How to use the DBus system in a container with docker root-less

2.5k Views Asked by At

I would like to use DBus in a container with docker in root-less mode. I use Ubuntu 22.10 :

host$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.10
Release:    22.10
Codename:   kinetic

and docker root-less :

host$ docker info
Client:
 Context:    rootless
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
  compose: Docker Compose (Docker Inc., v2.12.2)
  scan: Docker Scan (Docker Inc., v0.21.0)

Server:
 Containers: 1
  Running: 1
  Paused: 0
  Stopped: 0
 Images: 3
 Server Version: 20.10.21
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: false
  userxattr: true
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: d986545181c905378b0f90faa9c5eae3cbfa3755
 runc version: v1.1.4-0-g5fd4c4d
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
  rootless
  cgroupns
 Kernel Version: 5.19.0-26-generic
 Operating System: Ubuntu 22.10
 OSType: linux
 Architecture: x86_64
 CPUs: 12
 Total Memory: 31.23GiB
 Name: ****************
 ID: LAEG:NBQE:RME5:OPHR:TT4C:PHA3:25FE:7DPW:46PD:E2VI:6FB6:HQ2P
 Docker Root Dir: /home/*******/.local/share/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

I tried to create a container with the dbus socket mounted in it :

docker run -it --rm -v /var/run/dbus:/var/run/dbus ubuntu:latest bash

In my case I need to launch the container with a user different from root. Then I created a test user with the uid 1000:

root@163974703e4c:/# adduser test
Adding user `test' ...
Adding new group `test' (1000) ...
Adding new user `test' (1000) with group `test' ...
Creating home directory `/home/test' ...
Copying files from `/etc/skel' ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information for test
Enter the new value, or press ENTER for the default
    Full Name []: 
    Room Number []: 
    Work Phone []: 
    Home Phone []: 
    Other []: 
Is the information correct? [Y/n] Y

I switch to this new user :

root@163974703e4c:/# su test
test@163974703e4c:/$ id
uid=1000(test) gid=1000(test) groups=1000(test)

As I have a user other than root, he has on my host a subuid. My /etc/subuid:

user:100000:65536

Therefore I put an acl on my dbus socket to allow my sub user to use the socket:

host$ sudo setfacl -R -m u:100999:rwx /run/dbus/system_bus_socket

So I have the DBus socket with an access to this socket in the container:

test@163974703e4c:/$ ls -lan /run/dbus/system_bus_socket 
srw-rwxrw-+ 1 65534 65534 0 Dec  9 17:46 /run/dbus/system_bus_socket

test@163974703e4c:/$ getfacl /run/dbus/system_bus_socket 
getfacl: Removing leading '/' from absolute path names
# file: run/dbus/system_bus_socket
# owner: nobody
# group: nogroup
user::rw-
user:test:rwx
group::rw-
mask::rwx
other::rw-

I test the command dbus-monitor --system but I have this output :

$ dbus-monitor --system
Failed to open connection to system bus: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.

Can you help me please?

I tried to launch my container in privileged mode, with --add-cap ALL, but I still get this error message.

I tried to use strace to show all system call nothing more information :

prctl(PR_CAPBSET_READ, CAP_MAC_OVERRIDE) = 0
prctl(PR_CAPBSET_READ, 0x30 /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, CAP_CHECKPOINT_RESTORE) = 0
prctl(PR_CAPBSET_READ, 0x2c /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, 0x2a /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, 0x29 /* CAP_??? */) = -1 EINVAL (Invalid argument)
getresuid([1000], [1000], [1000])       = 0
getresgid([1000], [1000], [1000])       = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/run/dbus/system_bus_socket"}, 29) = 0
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK)    = 0
geteuid()                               = 1000
getsockname(3, {sa_family=AF_UNIX}, [128 => 2]) = 0
poll([{fd=3, events=POLLOUT}], 1, 0)    = 1 ([{fd=3, revents=POLLOUT}])
sendto(3, "\0", 1, MSG_NOSIGNAL, NULL, 0) = 1
sendto(3, "AUTH EXTERNAL 31303030\r\n", 24, MSG_NOSIGNAL, NULL, 0) = 24
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
read(3, "REJECTED EXTERNAL\r\n", 2048)  = 19
close(3)                                = 0
write(2, "Failed to open connection to sys"..., 252Failed to open connection to system bus: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
) = 252
exit_group(1)                           = ?
+++ exited with 1 +++

I want to get the same output as on my host in my container :

dbus-monitor --system
dbus-monitor: unable to enable new-style monitoring: org.freedesktop.DBus.Error.AccessDenied: "Rejected send message, 1 matched rules; type="method_call", sender=":1.544" (uid=1000 pid=32723 comm="dbus-monitor --system" label="unconfined") interface="org.freedesktop.DBus.Monitoring" member="BecomeMonitor" error name="(unset)" requested_reply="0" destination="org.freedesktop.DBus" (bus)". Falling back to eavesdropping.
signal time=1670624207.443897 sender=org.freedesktop.DBus -> destination=:1.544 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
   string ":1.544"
signal time=1670624214.344658 sender=:1.12 -> destination=(null destination) serial=47 path=/org/freedesktop/UDisks2/drives/ST2000DM008_2FR102_ZFL3HVF7; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
   string "org.freedesktop.UDisks2.Drive.Ata"
   array [
      dict entry(
         string "SmartUpdated"
         variant             uint64 1670624214
      )
   ]
   array [
   ]
1

There are 1 best solutions below

0
On

The issue is the EXTERNAL authentication used by libdbus which leads t0 discrepancy crossing user-namespace boundaries. Described here https://bugreports.qt.io/browse/QTBUG-108408.

If you can afford to patch libdbus in your project or at least in your containers then you should be good to go by this patch.

From 0d18f455194924ffb100bc980239082187b48301 Mon Sep 1

7 00:00:00 2001
From: =?UTF-8?q?=F0=9F=98=8
Date: Sun, 13 Nov 2022 20:08:02 +0100
Subject: [PATCH] fix: Do not send UID by External Auth
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

sending the UID per EXTERNAL authentication crossing user-namespace would cause
mismatch with out-of-band credentials acquired over UDS
An empty "AUTH EXTERNAL" is still a valid implementation of EXTERNAL authentication

Upstream-ticket: https://gitlab.freedesktop.org/dbus/dbus/-/issues/195

---
 dbus/dbus-auth.c | 37 ++++++++++++++-----------------------
 1 file changed, 14 insertions(+), 23 deletions(-)

diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index d4faa737..1d8f3b53 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -1231,31 +1231,22 @@ static dbus_bool_t
 handle_client_initial_response_external_mech (DBusAuth         *auth,
                                               DBusString       *response)
 {
-  /* We always append our UID as an initial response, so the server
-   * doesn't have to send back an empty challenge to check whether we
-   * want to specify an identity. i.e. this avoids a round trip that
-   * the spec for the EXTERNAL mechanism otherwise requires.
-   */
-  DBusString plaintext;
-
-  if (!_dbus_string_init (&plaintext))
+  /* We don't send the UID as crossing user-namespace would cause
+     mismatch with out-of-band credentials acquired over UDS
+     it is still a valid implementation of EXTERNAL authentication
+     check related tickets in sd-bus
+     https://github.com/systemd/systemd/commit/1ed4723d38cd0d1423c8fe650f90fa86007ddf55
+     and gdbus
+     https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2832
+
+     Upstream ticket for proper fix: https://gitlab.freedesktop.org/dbus/dbus/-/issues/195
+  */
+  if (!_dbus_string_append (response,
+                          "\r\nDATA"))
+  {
     return FALSE;
-
-  if (!_dbus_append_user_from_current_process (&plaintext))
-    goto failed;
-
-  if (!_dbus_string_hex_encode (&plaintext, 0,
-               response,
-               _dbus_string_get_length (response)))
-    goto failed;
-
-  _dbus_string_free (&plaintext);
-  
+  }
   return TRUE;
-
- failed:
-  _dbus_string_free (&plaintext);
-  return FALSE;  
 }
 
 static dbus_bool_t
-- 
2.38.1