[systemd-devel] Running pam-enabled /bin/login sessions in unprivileged terminal emulators

Pekka Paalanen ppaalanen at gmail.com
Mon May 24 07:56:44 UTC 2021


On Sat, 22 May 2021 16:18:35 -0400
nerdopolis <bluescreen_avenger at verizon.net> wrote:

> On Saturday, May 22, 2021 3:14:27 PM EDT Pekka Paalanen wrote:
> > On Sat, 22 May 2021 09:04:42 -0400
> > nerdopolis <bluescreen_avenger at verizon.net> wrote:
> >   
> > > On Saturday, May 22, 2021 6:50:09 AM EDT Pekka Paalanen wrote:  
> > > > On Fri, 21 May 2021 21:29:09 -0400
> > > > nerdopolis <bluescreen_avenger at verizon.net> wrote:
> > > >     
> > > > > Sorry, I got the terminology mixed up again. I am still using TTYs to run the
> > > > > instances of `cage`. It's the kernel mode VT emulators I am replacing with the
> > > > > user mode terminal emulators (running under a fullscreen Wayland compositor)    
> > > > 
> > > > Hi,
> > > > 
> > > > I'm trying to clarify things for everyone here, since I think I can
> > > > guess what you want to achieve, but you have a hard time explaining
> > > > your original goal. I hope you don't mind.
> > > > 
> > > >     
> > > That's fine. Thanks!  
> > > > Starting from the outermost "layer" and going inwards:
> > > > 
> > > > 1.a Have a system service, that takes over VT 1, changes user to
> > > >     'vtty', and runs 'cage' which is a Wayland compositor, mostly
> > > >     unprivileged.
> > > > 
> > > > OR
> > > > 
> > > > 1.b Have a system service, that takes over a seat directly, as the
> > > >     kernel has the VT system disabled (or the seat is not seat0).
> > > >     Changes user to 'vtty' and runs 'cage' mostly unprivileged.
> > > > 
> > > > 
> > > > 2. Inside cage, you run a Wayland terminal emulator as user 'vtty',
> > > >    so mostly unprivileged. The terminal emulator creates a PTY.
> > > > 
> > > > 3. Inside that terminal emulator, that is, connecting to that PTY,
> > > >    you want to be able log in with any user. Therefore the program
> > > >    running on the PTY should present a login prompt and succeed
> > > >    in logging a user in and setting up his session, and switching
> > > >    to a shell running as that user.
> > > > 
> > > > All in all, this stack would replace the usual stack where
> > > > /bin/login runs directly on the TTY of a VT, allowing to use a more
> > > > featureful terminal, custom display modes, multi-output support,
> > > > maybe multiple parallel sessions for different users a la fast user
> > > > switching, and more.
> > > >     
> > > 
> > > Not to mention, getting Shift+PgUp back, (and now on multiseat systems,
> > > keyboard input from non-seat0 seats will no longer bleed into seat0 when VT 1-6
> > > are active) :)  
> > > > Am I guessing right?    
> > > 
> > > You are guessing correct. Thanks!  
> > > > 
> > > > Then the question is, how to organize all this so that it works,
> > > > and what program(s) should be used in step 3, and how?
> > > > 
> > > > 
> > > > My own proposal for this would be to run everything as systemd
> > > > system services:
> > > > 
> > > > 1. Cage runs as a system service, as user 'vtty'. Cage will require
> > > >    systemd integration so that it can tell systemd when it is ready
> > > >    to accept Wayland clients.
> > > > 
> > > > 2. The Wayland terminal runs as another systemd system service,
> > > >    depending on the cage service, as user 'vtty'.
> > > >     
> > > That's close to what I was trying, but cage is pretty cool in this regard, you
> > > can start
> > >     cage -- vte
> > > and cage starts VTE as its only client, so the complexity of starting the
> > > wayland client externally, don't have to worry about that.  
> > 
> > But if cage starts the terminal, then systemd does not know when
> > the terminal is ready to accept a login program, or is there a way
> > to watch PTYs?
> > 
> > Ideally the terminal too would integrate with systemd start-up
> > notification IPC. Perhaps let systemd control which PTY to use, so
> > the login program/service knows to connect to the right one.
> > 
> > There's also auto-respawn, shutdown, cgroups, and more that systemd
> > can do.
> >   
> > > > 3. The login program runs as a third systemd system service,
> > > >    depending on the terminal service, as user 'root' because it
> > > >    needs to be able log in a user and set up a session for them.
> > > > 
> > > > That would solve the problem of how to get the necessary privileges
> > > > to log in a user, but all the other details I'm not sure.
> > > >     
> > > That's what I was aiming to do, wasn't sure how to connect to the service until
> > > I found I can do that with socat a few days after I sent that first email to 
> > > the list, but I still feel I should still clarify here.  
> > 
> > The socat thing for "connection" sounds quite wild to me. Instead,
> > I would expect to start a login program with the PTY as its std
> > in/out/err, just like it works with normal VT TTY logins.
> >   
> 
> Sounds like you would need to make VTE start up with nothing running, and have
> VTE report the PTY that it got?

Yes, almost. Hack VTE to use only the PTY you set via systemd. Let VTE
keep on running even if nothing has the PTY open. Systemd will take
care of shutting down the terminal when appropriate (another reason why
let systemd launch the terminal and not cage).

And yes, the whole point is that you *don't* start a login program
from inside cage or the terminal. Cage and terminal are unprivileged
processes, and login requires privileges so you have the problem of
needing to elevate privileges as they have been dropped already.

Instead, letting systemd start the login program directly avoids the
need to raise privileges, because systemd already runs with full
privileges and simply not drop them when starting the login process.

> > But then you do need to know which PTY it is. I think it would be
> > best to configure that as the parameter for templatated systemd
> > units: the terminal unit gets the PTY to listen on, and the login
> > unit gets the PTY to use as its controlling terminal and std
> > in/out/err. And the dependency between the two.
> >   
> 
> Seems like I would need to elevate to have an unprivileged parameterized
> service start a dependant with a _different_ parameter? 

Elevate? No, nothing should need to elevate.

System service *units* are not unprivileged. System service *processes*
might be. I don't think there is any problem making dependencies
between system services, regardless of what they run and how. The thing
you cannot do is to make system services depend on user services, but
that's not a problem here because you only have system services for
this.

> With this, it seems you would have frontend at .service
> where frontend at .service replaces autovt at .service
> (frontend at .service runs as the system user)
> 
> If I have it dependant on backend at .service, it automatically starts it with the
> same parameter. (from there I just use a socket with the parameter name)

Yes, I believe you can use the template parameters with Requires/Before
directives, so the terminal service gets auto-launched when you start
the login service for a PTY.

> Not sure how frontend at tty1.service would start backend@/dev/pts/0.service ?
> And if you start backend first, it's going to need to know the pty still...

Not tty1, but my-login@<PTY>.service, depending on
my-terminal@%i.service which depends on cage.service.

tty1 would be for cage only and can be hardcoded in the unit assuming
VTs even exist.

> > One problem here is how are you going to lock a terminal when
> > switching to another with a different user logged in. So maybe this
> > whole model is flawed, and you need authentication to work through
> > the Wayland compositor which is in charge of which terminal is
> > active.
> >   
> 
> Wait, do normal TTYs do locking? CTRL+ALT+FX or chvt, and I've never seen a
> lock on them...

They don't do locking, that's a big problem I think would be good to
solve. :-)

> > > and if you're really curious, I have the .service files I made public
> > > https://github.com/n3rdopolis/fakekmscon/tree/master/usr/lib/systemd/system  
> > 
> > I looked at the service files, and they don't seem to have much. I
> > looked at your libexec scripts, and they are much more complicated
> > than I expected, doing a lot more than I'm willing to try to
> > understand at this hour. :-)
> > 
> >   
> 
> Sorry, one hint, Ignore the SIG_WINCH stuff and ptycommandproxy. That's a
> separate FIFO for allowing the unprivileged account for using stty to set 
> the size of the server pty to be the same as the frontend pty so text mode
> applications like nmtui and text editors work correctly...
> 
> Those do make the script more complex

I do think using socat here is a problem, not a solution. Look at how
normal gettys and logins connect to the VT TTYs and serial terminals?

AFAIU, they do not so much "connect" but start with their standard
input/output/error streams already connected to the right *TY device
which also becomes their "controlling terminal". That way, they are
directly using the *TY device and can issue tty ioctls (stty etc.)
directly.


Disclaimer: this is all based on my theoretical understanding, not
experience, so I may have got something wrong. Hopefully others on this
mailing list point out any mistakes.


Thanks,
pq
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/systemd-devel/attachments/20210524/9a938c45/attachment.sig>


More information about the systemd-devel mailing list