[systemd-devel] Support `systemd-run --machine M --user` for running unprivileged
Vito Caputo
vcaputo at pengaru.com
Tue Mar 19 19:43:03 UTC 2019
On Tue, Mar 19, 2019 at 12:06:15PM +0100, Lennart Poettering wrote:
> On Mo, 18.03.19 17:04, Vito Caputo (vcaputo at pengaru.com) wrote:
>
> > I'd personally appreciate being able to wire things up in my window
> > manager where I can run things via hotkeys like:
> >
> > `systemd-run --machine finance --user firefox`
> > `systemd-run --machine entertainment --user firefox`
> >
> > etc.
> >
> > These containers are already configured using systemd-nspawn, with the X
> > socket bind-mounted.
> >
> > I'm not using user namespaces, so this is just trying to run things as
> > the same uid inside the container as outside the container without root
> > or polkit kludges.
> >
> > I can do this already using ssh and ssh keys, but it seems completely
> > unnecessary - systemd is already running everywhere, and I can use the
> > logind set-linger option to get the user instance up @ container boot.
> >
> > Has anyone taken a look at what the technical barriers are? I can't be
> > the only person wanting this kind of functionality.
>
> Hmm, I think supporting this would make sense indeed. It should
> probably feel like the ssh thing, i.e. so that
>
> "systemd-run --machine=lennart at foobar --user firefox" does the right
> thing. In fact, people keep asking for a way to connect to the user
> bus of another local user all the time, and this could be a way to
> safely provide that too (think: "systemd-run --machine=otheruser at .host
> --user firefox"; making use of the ".host" alias which refers to the
> local host system always).
>
> A clean implementation would probably involve this:
>
> 1. Add an OpenUserBus() call to systemd-machined's bus API, like we
> already have OpenPTY(), OpenLogin(), OpenShell(),
> OpenRootDirectory() to get specific resources from a
> container. Most likely this new call should be implemented very
> similar to OpenShell() but instead of invoking $SHELL should call
> systemd-stdio-bridge running inside the container. It would return
> a connected AF_UNIX socket fd to the client.
>
> 2. Create a new host-side tiny binary that wraps this OpenUserBus()
> call: when invoked it calls it, and passes the AF_UNIX socket it
> acquires that way to its parent somehow.
>
> 3. Tweak sd-bus to call this new binary when connecting this way.
>
> 4. Expose this in systemd-run.
>
> Why bother with systemd-machined here? We need a privileged component
> somewhere, since entering the container requires privs.
>
> Why bother with systemd-stdio-bridge inside the container? First of
> all, this would match how the SSH case is handled: there too we call
> systemd-stdio-bridge on the other side. The main reason though is
> this: when connecting to the user bus we really should go through PAM
> I think, so that a full PAM session is started (and thus systemd
> --user potentially started, and thus dbus-daemon), limits applied and
> $XDG_RUNTIME_DIR and $DBUS_SESSION_BUS_ADDRESS set in whatever way
> desired. But if we to call PAM we need to go through PID 1 in the
> container, and then we somehow need to call something there that then
> propagates the dbus traffic to us. Ideally that could be a short
> binary included in the container payload that simply passes a
> connected socket back, but this means we'd have to have it already in
> the container image included (otherwise we'd have to do it with some
> statically compiled, inserted binary, which is ugly and
> messy). systemd-stdio-bridge OTOH already exists, and does something
> very similar. Only drawback: traffic is bumped off another process
> instead of passing the naked AF_UNIX socket through. (But there are
> some niceties by doing it this way too: the fact that
> systemd-stdio-bridge is continously running inside a PAM session keeps
> the user at .service instance inside the container – and its dbus
> instance — pinned as long as the connection is going on.)
>
> Why have the new tiny binary wrapping OpenUserBus()? We could also do
> this inside the sd-bus library code, in-process. I think doing this
> out of process is a bit nicer though, otherwise we'd have to use an
> sd-bus connection to set up another sd-bus connection all hidden
> behind the same sd-bus API, and I am not sure I like that kind of
> recursive asynchronicity too much if it happens inside the same
> process. But this is mostly a matter of taste, as it keeps things
> simpler I think to just fork something off that does its own work and
> then dies quickly.
>
> Does that make sense?
>
Yes, on a high-level it makes sense, and thank you for the detailed
response. I think what's here is sufficient guidance to try out an
implementation.
> Would love to review/merge patches for this (or something similar)!
>
If I have some time in the coming months I'll take a look at
implementing this, if nobody beats me to it. For now I'm a little busy
as I need to finish a bunch of desert construction projects in the
physical world, preferably well before summer arrives.
Thanks,
Vito Caputo
More information about the systemd-devel
mailing list