]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: make ReleaseSession "unprivileged" and allow closing of own session 32869/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 16 May 2024 15:06:24 +0000 (17:06 +0200)
committerLuca Boccassi <bluca@debian.org>
Mon, 20 May 2024 18:59:15 +0000 (20:59 +0200)
Fixes https://github.com/systemd/systemd/issues/28514.

Quoting https://github.com/systemd/systemd/issues/28514#issuecomment-1831781486:
> Whenever PAM is enabled for a service, we set up the PAM session and then
> fork off a process whose only job is to eventually close the PAM session when
> the service dies. That services we run with service privileges, both to
> minimize attack surface and because we want to use PR_SET_DEATHSIG to be get
> a notification via signal whenever the main process dies. But that only works
> if we have the same credentials as that main process.
>
> Now, if pam_systemd runs inside the PAM stack (which it normally does) it's
> session close hook will ask logind to synchronously end the session via a bus
> call. Currently that call is not accessible to unprivileged clients. And
> that's the part we need to relax: allow users to end their own sessions.

The check is implemented in a way that allows the kill if the sender is in
the target session.

I found 'sudo systemctl --user -M "zbyszek@" is-system-running' to
be a convenient reproducer.

Before:
May 16 16:25:26 x1c systemd[1]: run-u24754.service: Deactivated successfully.
May 16 16:25:26 x1c dbus-broker[1489]: A security policy denied :1.24757 to send method call /org/freedesktop/login1:org.freedesktop.login1.Manager.ReleaseSession to org.freedesktop.login1.
May 16 16:25:26 x1c (sd-pam)[3036470]: pam_systemd(login:session): Failed to release session: Access denied
May 16 16:25:26 x1c systemd[1]: Stopping session-114.scope...
May 16 16:25:26 x1c systemd[1]: session-114.scope: Deactivated successfully.
May 16 16:25:26 x1c systemd[1]: Stopped session-114.scope.
May 16 16:25:26 x1c systemd[1]: session-c151.scope: Deactivated successfully.
May 16 16:25:26 x1c systemd-logind[1513]: Session c151 logged out. Waiting for processes to exit.
May 16 16:25:26 x1c systemd-logind[1513]: Removed session c151.
After:
May 16 17:02:15 x1c systemd[1]: run-u24770.service: Deactivated successfully.
May 16 17:02:15 x1c systemd[1]: Stopping session-115.scope...
May 16 17:02:15 x1c systemd[1]: session-c153.scope: Deactivated successfully.
May 16 17:02:15 x1c systemd[1]: session-115.scope: Deactivated successfully.
May 16 17:02:15 x1c systemd[1]: Stopped session-115.scope.
May 16 17:02:15 x1c systemd-logind[1513]: Session c153 logged out. Waiting for processes to exit.
May 16 17:02:15 x1c systemd-logind[1513]: Removed session c153.

Edit: this seems to also fix https://github.com/systemd/systemd/issues/8598.
It seems that with the call to ReleaseSession, we wait for the pam session
close hooks to finish. I inserted a 'sleep(10)' after the call to ReleaseSession
in pam_systemd, and things block on that, nothing is killed prematurely.

man/org.freedesktop.login1.xml
src/login/logind-dbus.c
src/login/org.freedesktop.login1.conf

index dffd16e325639f254c0502775ed50d6b10915960..20936a693611e5f72811052a49ccbcd2c6f502f1 100644 (file)
@@ -104,7 +104,6 @@ node /org/freedesktop/login1 {
                              out s seat_id,
                              out u vtnr,
                              out b existing);
-      @org.freedesktop.systemd1.Privileged("true")
       ReleaseSession(in  s session_id);
       ActivateSession(in  s session_id);
       ActivateSessionOnSeat(in  s session_id,
index 70fc9aeebf3a5f3fbdbc1721fada92a3955c68f7..5fdf28ced07a43722357b719eb9d5f3ccdc6225f 100644 (file)
@@ -1172,7 +1172,7 @@ static int method_create_session_pidfd(sd_bus_message *message, void *userdata,
 
 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Manager *m = ASSERT_PTR(userdata);
-        Session *session;
+        Session *session, *sender_session;
         const char *name;
         int r;
 
@@ -1186,6 +1186,13 @@ static int method_release_session(sd_bus_message *message, void *userdata, sd_bu
         if (r < 0)
                 return r;
 
+        r = get_sender_session(m, message, /* consult_display= */ false, error, &sender_session);
+        if (r < 0)
+                return r;
+
+        if (session != sender_session)
+                return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
+
         r = session_release(session);
         if (r < 0)
                 return r;
@@ -3767,7 +3774,7 @@ static const sd_bus_vtable manager_vtable[] = {
                                 SD_BUS_ARGS("s", session_id),
                                 SD_BUS_NO_RESULT,
                                 method_release_session,
-                                0),
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("ActivateSession",
                                 SD_BUS_ARGS("s", session_id),
                                 SD_BUS_NO_RESULT,
index dd6e3651e3ef537c1074f14fe2ddd9ac24ec8309..dff944f172d8bec79d675b75aec63d77f9773f5f 100644 (file)
                        send_interface="org.freedesktop.login1.Manager"
                        send_member="FlushDevices"/>
 
+                <allow send_destination="org.freedesktop.login1"
+                       send_interface="org.freedesktop.login1.Manager"
+                       send_member="ReleaseSession"/>
+
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Seat"
                        send_member="Terminate"/>