[systemd-devel] Crond session, pam_access and pam_systemd

Mantas Mikulėnas grawity at gmail.com
Fri Oct 16 11:22:27 UTC 2020


On Fri, Oct 16, 2020 at 1:41 PM Thomas HUMMEL <thomas.hummel at pasteur.fr>
wrote:

> Hello,
>
> if I try to sum up all of your answers, I come to the following
> understanding :
>
> - sessions are always created via the pam_systemd module
> - which is, in my case called (sshd, crond) via the password-auth stack
> include
> - so crond, through pam_systemd will cause a session to be created
>

If you specifically mean systemd-logind sessions, yes.

But I think you're still confusing the two different kinds of "sessions"
that exist here. PAM open_session creates a PAM session, which eventually
*causes* a systemd-logind session to be created, but isn't 100% the same
thing.


> - such session is created via the sd-pam helper responsible for
> pam_open_session() and pam_close_session() calls
>

Not exactly. For cron and sshd, all those PAM functions are called directly
by cron or sshd themselves.

The sd-pam helper only does this task when systemd pid1 (the service
manager) needs to call PAM for a service that has PAMName= set in its unit.

As far as I could figure out, the entire process works like this:

sshd (listener)
└ sshd (connection worker)
  ├ pam_start(sshd, ...)
  ├ pam_acct_mgmt()
  │ └ pam_access.so
  ├ pam_open_session()
  │ └ pam_systemd.so
  │   └ DBus call to systemd-logind: CreateSession(service=sshd, uid=1000)
  ├ fork login shell
  │ └ /bin/bash
  └ pam_close_session()

systemd-logind
└ receives CreateSession(uid=1000)
  ├ DBus call to systemd: Start(user at 1000.service)
  └ DBus call to systemd: StartTransientUnit(session-1234.scope)

systemd (pid1)
└ user at 1000.service
  └ sd-pam
    ├ pam_start(systemd-user, ...)
    ├ pam_acct_mgmt()
    │ └ pam_access.so
    ├ pam_open_session()
    ├ fork sd-pam child
    │ └ sd-pam (waits for parent to exit)
    │   └ pam_close_session()
    └ exec systemd --user



> - such a worker is started by a systemd --user instance
>

No, it's actually started by the systemd system manager itself, because
user at .service has PAMName= set. It only *appears* to be a child of systemd
--user, because it is a child of the process which first forked sd-pam,
then exec'd systemd --user.

Most tools (sudo, sshd, crond) handle all PAM calls in the parent process,
just forking your shell or cronjob as a child, then waiting for the child
to exit before they can call pam_close_session(). Systemd does it the other
way around – it also forks, but the *child* waits for the parent to exit
before calling pam_close_session(), whereas the parent directly execs the
ExecStart command.

So if you had a basic unit with "ExecStart=/bin/sleep 1h", if it also had
User= and PAMName=, then you would see 'sd-pam' as a child of 'sleep 1h'.


> - so a user crontab will ultimately cause the use of the already running
> systemd --user instance of the user (because his logged in or is
> lingered) OR the creation of a systemd --user instance for the purpose
> of the crond session creation
>

Yes, more or less.


>
> What I still don't quite get is :
>
> - is it sd-pam or systemd --user or user@<uid>.service holding them
> which uses the systemd-user pam service name ?
>

user@<uid>.service is where the name is configured, but sd-pam is the
process which actually calls PAM for that service name.

systemd --user on its own doesn't talk to PAM at all. (See what I wrote
above about the sd-pam worker.)


>
> - my understanding was that pam service name is passed to pam_start() :
> in the user crontab case, my guess is that crond does this call with the
> crond service name (so pam knows what module stacks to run).
> So this would mean something like the user@<uid>.service (or sd-pam)
> would itself call pam_start(systemd-user, ...) when called by pam_systemd ?
>

Yes.


>
> So basically pam_systemd module would trigger another service which
> itself would go through pam with the systemd-user service name ?
>

Yes.


>
> - again, why is a first ssh login session able to create the user
> session without the user having to be listed for systemd-user in
> access.conf whereas crond semmes to need it (givent no systemd --user
> was previously running in both cases) ?
>

I don't know why you're seeing the different behavior between crond and
sshd.

However, a systemd-logind session doesn't actually *need* user at .service
(systemd --user), it can be created without. So even if user@<uid>.service
could not be started due to PAM not authorizing it (or due to some other
reason), this will still not prevent pam_systemd from registering the
session and creating user-<uid>.slice and making it appear in `loginctl`.

-- 
Mantas Mikulėnas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/systemd-devel/attachments/20201016/2da8655b/attachment.htm>


More information about the systemd-devel mailing list