[systemd-devel] RFC: user session lifetimes vs. $DISPLAY
lennart at poettering.net
Wed Mar 6 07:55:40 PST 2013
On Wed, 06.03.13 15:12, Simon McVittie (simon.mcvittie at collabora.co.uk) wrote:
> On 05/03/13 21:23, Lennart Poettering wrote:
> > Kay actually wants to get rid of
> > the session bus entirely. My own idea was to use it only for gdm to
> > support the multi-seat case, where the same gdm user might need to run
> > multiple gdm sessions in parallel, one for each display. However, that
> > idea is definitely flawed, and it might be better to fix this for good
> > and do dynamic user ids or so for this case, so that the gdm sessions
> > are actually properly isolated from each other...
> Is there any security benefit in having each gdm greeter run under a
> different uid, or is this just working around the conflict between "no
> more than one GUI per user" and "gdm needs several GUIs"?
It is a security benefit. Currently the greeter and its stack are run
under the same fixed UID, so if a user manages to exploit his, he could
read passwords from all other login screens on the system. Also, things
like PA are currently broken in this context, since they try to be
per-user, so they try to share all accessible sound cards between all
login screens -- and that's definitely broken: i.e. we should try very
hard that the screen reader audio from login screen #1 cannot be
influenced by the login screen #2 on another seat.
> Presumably this would need a reasonably large UID range reserved by the
> sysadmin or distribution (e.g. Debian reserves uids 60000-64999 for
> allocation by the base-passwd maintainer and could reserve a sub-range
> in here for its gdm), and a NSS module or something that synthesizes
> appropriate user information?
Yes, something like this.
But this also has a couple of more issues. For example, if you do
dynamic UIDs you really really want to avoid that the user can write
anything to disk, so that no trace of this UID remains. Now, as it turns
out we can actually do this nicely via namespaces and tmpfs. i.e. for
the environment one of these dynamic UIDs run under we'd mount
everything read-only, and only give write access to its own /tmp,
/dev/shm, and XDG_RUNTIME_DIR, but mount a new tmpfs into it, that is
only visible to this user and goes away automatically when the namespace
I think this would be a pretty good approach, but then again, I figure
the UNIX lover crowd would be up in arms against dynamically allocated
UIDs and suchlike.
> How does "no more than one XDG_RUNTIME_DIR per uid" interact with uid
> namespaces? :-)
I doubt UID namespaces will fly in the long run...
> > And here are our options:
> Terminology: do we have a good piece of jargon for the thing represented
> by a login1.User and an XDG_RUNTIME_DIR?
logind tracks a "state" enum for each user. It is either offline,
lingerung, online, active, closing.
offline = not logged in at all
lingering = not logged in, but the user at .service for the user is
running, which is only allowed for very specific users, see "loginctl
enable-linger" for more information.
online = actually logged in
active = actually loggined in but has at least one session in the
closing = the user is being logged out right now, but hasn't finished
logging out yet, i.e. because some processes didn't respond to SIGTERM
So, following this terminology I'd just call the user "online" in the
context you were asking about.
> The fact that it's dbus-daemon --session is not particularly important,
> because systemd --user's dbus.service can easily run whatever it wants
> to. I think the things that are important for continuity/compatibility
> are that asking for DBUS_BUS_SESSION (or the equivalent in other
> libraries) gets you onto a bus that isn't a privilege boundary, can be
> relied on to exist at least when you're in a "normal" X11 session (via
> distributions' X11 startup scripts or X11 autolaunching), and reads
> services from /usr/share/dbus-1/services (which is currently a mixture
> of things that want to be login-session-scoped, and things that ought to
> be login1.User-scoped - mostly the latter, probably).
> Approximately in order of my preference:
> > 4) Introduce --user, and always redirect --session to it. This way
> > --user would be pretty much identical to --sessin, except for where
> > the socket is stored and how it is communicated.
> > Approach 4 is the arguably the "cleanest one", but current gdm is
> > incompatible with it.
> If you're going this route, I don't think there'd be much point in
> introducing dbus-daemon --user, DBUS_BUS_USER, DBUS_USER_BUS_ADDRESS and
> so on, just to be aliases for the session equivalents - just say "on
> systems where it is managed by systemd, the 'session bus' is actually a
> per-login1.User bus" and be done with it.
That sounds like an OK approach, but might be confusing?
> In practice, the definition of the session bus is currently something
> like "one per login1.Session, except when it's not". Processes in a ssh
> login session can easily "join" an X11 session's bus by setting $DISPLAY
> and $DBUS_SESSION_BUS_ADDRESS; processes in an X11 session can start a
> new mini-session (typically for regression tests) with dbus-launch or
> In a "user bus" world, it'll still be necessary for, e.g. regression
> tests to start an isolated mini-environment, the same way they currently
> start an isolated D-Bus session - I'd be inclined to do that by setting
> the regression test's $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR. I
> think it's OK if doing that requires you to also reset $HOME and $XDG_*
> to avoid conflicts with the real home directory - regression tests have
> to do that anyway, in practice - but I'm not willing to try to enforce
> the letter of the XDG_RUNTIME_DIR spec if that means we can't have sane
> regression tests for D-Bus services without being root.
WE have "--session --address=" already, so doing env var tricks might
not even be necessary.
> The remaining problems with this are:
> 1. Finding the X11 display: patching libX11 (well, really xcb) to try
> $XDG_RUNTIME_DIR/X11-display before giving up would resolve this.
> 2. Multiple X11 displays: if you want to say that systemd doesn't
> support this then that's your prerogative, but I don't think "this is
> difficult, and in practice there are bugs" necessarily implies "we
> should make it architecturally impossible to ever support this".
Yes, I agree.
> One way to resolve the "multiple X11 displays" issue without ruling it
> out forever would be to say "if you do want to support multiple X11
> displays, you'll have to make your service instanced-by-display or
> something" - instancing is something systemd already knows how to do.
Yes, I agree.
> The AT-SPI bus-starter (org.a11y.Bus.service) is one example of a D-Bus
> session service that, if multiple X11 displays are supported, really
> does want one instance per X11 display.
> It does occur to me that if there isn't a real security boundary between
> greeters, gdm could treat each greeter as a lot like the "regression
> test" use-case - separate *everything*, including HOME and
> XDG_RUNTIME_DIR, while keeping the same uid. Perhaps pam_systemd could
> even grow an "isolate" option which does that, including resetting HOME
> to a new empty (or even inaccessible) directory? I realise that
> contradicts the spec for XDG_RUNTIME_DIR, but the spec for
> XDG_RUNTIME_DIR only says what it does because you wrote it that way for
> a reason - and AFAICS, not sharing HOME avoids that reason.
Well, some bits cannot be isolated like this. For example PulseAudio
takes possession of any sound card it can access. It runs as user, and
relies on udev's ACL management to give the foreground session access to
the sound card and none other. This works fine as long as there's only
one PA instance running per user. But as soon as you have multiple, then
things get weird, as then multiple users might get access at the same
time, and they'd fight for the soundcard, and it would be undefined
which one wins. And I am pretty sure PA is just one of the instances of
this problem here.
Hence, I am pretty sure gdm should have different UIDs for different
greeters, which kinda implies dynamically allocated users for it.
> 3. Remote X11. D-Bus has some level of support for being configured to
> listen on TCP on a trusted network and be used with remote X11 in
> conjunction with NFS home directories (it was designed back when that
> was a thing, and in particular to replace KDE's DCOP, which was
> transported over X11). None of the current maintainers ever use it like
> this, and even Havoc doesn't really know which use-cases are meant to
> work, which in practice means that whenever we change anything, someone
> pops up on the mailing list complaining that we broke their pet use-case.
> I think it would be reasonable to say that D-Bus without systemd
> semi-supports this (and you get to keep both pieces), but if you're
> doing that, you can't use systemd --user (or alternatively, you can use
> it, but you have to mask dbus.socket and dbus.service, and tell it to
> pass DBUS_SESSION_BUS_ADDRESS=autolaunch: to all services).
I was always of the opinion on that busses should stay local, and only
very specific busses should ever become networked (such as what mango
lassi has been doing).
Note that with the kdbus stuff I assume that apps would soonishly stop
working across networked dbus anyway. For example, the new "Portals"
stuff from the apps context we want to use kdbus to exchange actual
payload data, and that wouldn't scale at all in a networked environment.
So, I'd really suggest to ignore the networked case. It doesn't really
work right now, and it will work even less in the future. I am ready to
take the heat for this...
> > 2) Add dbus --user, and keep it separate from --session, i.e. thus
> > confusing developers with three distinct busses.
> I'd rather not. AIUI, your assertion is that "most" D-Bus services
> really want to be login1.User-scoped? I don't want to go round every
> D-Bus service doing s/session/user/ for no good reason.
> > 3) Same as 2) but do actually keep it separate only for the gdm case,
> > otherwise redirect --session to --user.
> I don't like the sound of this one either. If having them be separate
> dbus-daemons is only used for gdm and similarly odd situations, then in
> practice it won't be tested, which means in practice it won't work.
But that'd be OK, since the only case where it would matter would be
gdm, which has a very well defined set of bus clients.
But dunno, maybe going for approach 4) is the better option after
all. It would certainly be the quickest to get of the ground, except for
the gdm issue...
Lennart Poettering - Red Hat, Inc.
More information about the systemd-devel