From dde2516304ac6b0edc1dfc6650f37d32fa62642c Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sun, 25 May 2025 19:50:06 +0900 Subject: [PATCH] dbus: handle bizarre dbus proxy behaviour There is a strange behaviour in xdg-dbus-proxy where if any interface string when stripped of a single ".*" suffix does not contain a '.' byte anywhere, the program will exit with code 1 without any output. This checks for such conditions to make the failure less confusing. Signed-off-by: Ophestra --- dbus/config.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++--- dbus/proxy.go | 16 ++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/dbus/config.go b/dbus/config.go index 26fce46..3f66b2b 100644 --- a/dbus/config.go +++ b/dbus/config.go @@ -5,6 +5,7 @@ import ( "errors" "io" "os" + "strings" ) // ProxyPair is an upstream dbus address and a downstream socket path. @@ -27,6 +28,61 @@ type Config struct { Filter bool `json:"filter"` } +func (c *Config) interfaces(yield func(string) bool) { + for _, iface := range c.See { + if !yield(iface) { + return + } + } + for _, iface := range c.Talk { + if !yield(iface) { + return + } + } + for _, iface := range c.Own { + if !yield(iface) { + return + } + } + + for iface := range c.Call { + if !yield(iface) { + return + } + } + for iface := range c.Broadcast { + if !yield(iface) { + return + } + } +} + +func (c *Config) checkInterfaces(segment string) error { + for iface := range c.interfaces { + /* + xdg-dbus-proxy fails without output when this condition is not met: + char *dot = strrchr (filter->interface, '.'); + if (dot != NULL) + { + *dot = 0; + if (strcmp (dot + 1, "*") != 0) + filter->member = g_strdup (dot + 1); + } + + trim ".*" since they are removed before searching for '.': + if (g_str_has_suffix (name, ".*")) + { + name[strlen (name) - 2] = 0; + wildcard = TRUE; + } + */ + if strings.IndexByte(strings.TrimSuffix(iface, ".*"), '.') == -1 { + return &BadInterfaceError{iface, segment} + } + } + return nil +} + func (c *Config) Args(bus ProxyPair) (args []string) { argc := 2 + len(c.See) + len(c.Talk) + len(c.Own) + len(c.Call) + len(c.Broadcast) if c.Log { @@ -63,9 +119,7 @@ func (c *Config) Args(bus ProxyPair) (args []string) { return } -func (c *Config) Load(r io.Reader) error { - return json.NewDecoder(r).Decode(&c) -} +func (c *Config) Load(r io.Reader) error { return json.NewDecoder(r).Decode(&c) } // NewConfigFromFile opens the target config file at path and parses its contents into *Config. func NewConfigFromFile(path string) (*Config, error) { diff --git a/dbus/proxy.go b/dbus/proxy.go index a18bf75..c44971e 100644 --- a/dbus/proxy.go +++ b/dbus/proxy.go @@ -2,6 +2,7 @@ package dbus import ( "context" + "fmt" "io" "os/exec" "sync" @@ -14,6 +15,15 @@ import ( // Overriding ProxyName will only affect Proxy instance created after the change. var ProxyName = "xdg-dbus-proxy" +type BadInterfaceError struct { + Interface string + Segment string +} + +func (e *BadInterfaceError) Error() string { + return fmt.Sprintf("bad interface string %q in %s bus configuration", e.Interface, e.Segment) +} + // Proxy holds the state of a xdg-dbus-proxy process, and should never be copied. type Proxy struct { helper helper.Helper @@ -66,9 +76,15 @@ func Finalise(sessionBus, systemBus ProxyPair, session, system *Config) (final * var args []string if session != nil { + if err = session.checkInterfaces("session"); err != nil { + return + } args = append(args, session.Args(sessionBus)...) } if system != nil { + if err = system.checkInterfaces("system"); err != nil { + return + } args = append(args, system.Args(systemBus)...) }