udisks in systemd user-sessions (or kdbus in future)

Simon McVittie simon.mcvittie at collabora.co.uk
Mon Mar 9 05:32:47 PDT 2015


(udisks developers, please see
<http://lists.freedesktop.org/archives/systemd-devel/2015-January/027711.html>
if you need more background on login sessions vs. user-sessions.)

I'm developing a patch for udisks to fix its interaction with systemd
user-sessions (, and I would like to check that the behaviour I propose
is consistent with udisks' and systemd's security models.

Background
----------

In systemd user sessions, some of a user's processes can exist outside
the scope of any particular login session:

└─user.slice
  └─user-1000.slice
    ├─user at 1000.service
    │ ├─2089 /lib/systemd/systemd --user
    │ └─dbus.service
    │   ├─ 2233 /usr/bin/dbus-daemon …
    │   ├─ 2297 /usr/lib/gvfs/gvfsd
    │   …
    └─session-2.scope
      ├─ 2102 gnome-session
      ├─ 2376 /usr/bin/gnome-shell
      …

This model is currently a non-default opt-in thing if you use
dbus-daemon: you have to either use dbus 1.9.x and --enable-user-session
(e.g. the dbus-user-session package in Debian experimental), or install
third-party bits like user-session-units. However, I hope to make it the
default one day, and it is the only model supported by kdbus. The
systemd/kdbus developers have indicated that they have no interest in
supporting the traditional "D-Bus session bus per login session" model.

If processes outside login sessions don't have access to devices on
those login sessions' seats, then gvfsd won't be able to mount devices.
Conversely, there is no privilege boundary between the login sessions
and the same user's non-login-session processes - in particular, the
user's processes can usually ptrace each other and write to each other's
configuration files - so isolating them doesn't make a great deal of sense.

How udisks works now
--------------------

udisks currently has this pseudocode to determine whether I may mount a
device, and similar logic for other operations:

    let requesting_seat = requesting process->login_session->seat
    let device_seat = device->seat
    if (device_seat && requesting_seat &&
            requesting_seat == device_seat) {
        use a polkit rule like org.freedesktop.udisks2.filesystem-mount
            (by default, requires either an active login session or
            admin authentication)
    } else {
        use a polkit rule like
        org.freedesktop.udisks2.filesystem-mount-other-seat
            (by default, requires admin authentication regardless)
    }

However, that breaks down for the user-session model: in particular,
shared processes like gvfsd live outside the scope of any particular
login session. When gnome-disks asks gvfsd to ask udisks to mount a
disk, udisks sees that the request came from gvfsd, sees that gvfsd is
not in a login session, and uses the more strictly-controlled
filesystem-mount-other-seat action.

How I propose it should work
----------------------------

I propose to change it to this pseudocode, for which I'm developing a patch:

    let device_seat = device->seat

    if (device_seat) {
        let active_sessions = requesting uid's active login sessions

        foreach session in active_sessions {
            if session->seat && session->seat == device_seat {
                use a polkit rule like
                    org.freedesktop.udisks2.filesystem-mount
                return
            }
        }
    }

    use a polkit rule like
        org.freedesktop.udisks2.filesystem-mount-other-seat

(In practice I'd use sd_uid_is_on_seat() rather than looping over active
sessions myself.)

I'm specifically looking for one or more *active* sessions on the
device's seat because with fast-user-switching, you could in principle
encounter a situation like this:

user.slice
├─ alice
│  ├─ graphical session on seat0, tty7, active
│  └─ system --user
├─ bob
│  ├─ graphical session on seat0, tty8, inactive
│  ├─ graphical session on seat1, active
│  └─ systemd --user
└─ chris
   ├─ ssh session on no seat, active
   └─ systemd --user

In that situation, I think the desired behaviour is that alice controls
seat0 devices and bob controls seat1 devices, corresponding to their
respective physically-present locations; bob should not have control
over seat0 devices until he returns to seat0, and chris should not have
control over either.

udisks developers: is this consistent with how you think it should work?

systemd/kdbus developers: is this consistent with how you think
situations like this should work in the kdbus-based future?

(This sort of thing is one of the reasons I was keen to make D-Bus
support user sessions without requiring kdbus - if we can get this sort
of thing fixed now, in parallel with the kdbus developers getting it
through kernel review, then that's one less regression to fix when kdbus
eventually lands.)

Thanks,
    smcv

-- 
Simon McVittie
Collabora Ltd. <http://www.collabora.com/>


More information about the devkit-devel mailing list