Comment 11 for bug 75602

Revision history for this message
In , Simon McVittie (smcv) wrote :

The problem here is that the Unix semantics of groups are rather non-obvious. Each Unix process has a primary group ID and an array of of supplementary group IDs; these are *normally* the group ID and supplementary groups of the process's owning user, but things like pam_group cause that not to be true.

dbus-daemon accesses the system group database via libc. On a GNU system, that means nsswitch (a module of glibc); you can access that database from the command line by running "getent groups" (which returns something that looks remarkably similar to /etc/group, but also contains information from LDAP or whatever).

When login(1), su(1) or whatever switches uid from root to a user, it reads from the system's group database, and assigns those groups to the process. This has some interesting side-effects; for instance, if you remove a user from, say, the audio group, but they have a background process like a screen(1) session, that process still has audio rights. Similarly, if you add a user to the audio group, any of their processes that are already running won't automatically get audio rights (until they run sg or newgrp or something).

pam_group doesn't add users to groups - it adds extra groups to processes. dbus-daemon starts from the uid and reads directly from the system group database to determine the groups, so it can't see those extra groups.

Using or not using the libdbus "userdb cache" won't fix this, because it's still reading from nsswitch and not looking at the requesting process's credentials directly.

Using or not using ncsd won't fix this either, because ncsd returns the same things as nsswitch (albeit perhaps an out-of-date version).

"Fixing" this would be not at all trivial. The D-Bus wire protocol normally uses a single Unix credential-passing message (on first connection to the bus) to get the user ID, but credential-passing can normally only carry one user ID and one group ID - so dbus-daemon never finds out the list of supplementary groups, only the primary group.

I'm inclined to say this is WONTFIX, because:

* using PolicyKit solves this for recent versions of HAL, upower, udisks,
  etc. as used in current GNOME (and presumably also KDE) distributions,
  removing the need for plugdev, powerdev, etc. group membership

* not directly related to D-Bus, but using ConsoleKit and udev also solves
  this for device-node ownership: on my Debian sid laptop, logging in to
  a local GNOME session automatically gives me rw access to appropriate
  device nodes via a POSIX ACL, for instance:

  # file: dev/snd/pcmC0D0p
  # owner: root
  # group: audio
  user::rw-
  user:smcv:rw-
  group::rw-
  mask::rw-
  other::---

* using pam_group for temporary group membership is generally insecure,
  in the sense that there's trivial privilege escalation from temporary
  to permanent group membership if users can write to any location that
  supports setgid executables:

  * log in at the console and be placed in the audio group

  * cd to anywhere that supports setgid executables (home directories
    are usually sufficient)

  * cp /bin/bash audiobash && chgrp audio audiobash && chmod g+s audiobash

  * log out

  * ssh in while another user is logged-in at the console

  * run audiobash, giving you a shell process in the audio group

  * use your new write access to /dev/snd to switch on the microphone and
    listen to the what the console user is doing