chiark / gitweb /
login: fix user@.service case, so we don't allow nested sessions (#8051)
authorAlan Jenkins <alan.christopher.jenkins@gmail.com>
Thu, 22 Feb 2018 20:38:44 +0000 (20:38 +0000)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:59:04 +0000 (07:59 +0200)
> logind sessions are mostly bound to the audit session concept, and audit
> sessions remain unaffected by "su", in fact they are defined to be
> "sealed off", i.e. in a way that if a process entered a session once, it
> will always stay with it, and so will its children, i.e. the only way to
> get a new session is by forking off something off PID 1 (or something
> similar) that never has been part of a session.

The code had a gap.  user@.service is a special case PAM session which does
not create a logind session.  Let's remember to check for it.

Fixes #8021

src/login/logind-dbus.c

index ee3a1e919aa93f6cfbcfc3a95fbce11f3531b203..f444ad9b4bf49bc5da987aeffbc81cb6d695d13a 100644 (file)
@@ -41,6 +41,7 @@
 #include "mkdir.h"
 #include "path-util.h"
 #include "process-util.h"
+//#include "cgroup-util.h"
 #include "selinux-util.h"
 #include "sleep-config.h"
 //#include "special.h"
@@ -660,6 +661,7 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu
 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
         uint32_t audit_id = 0;
+        _cleanup_free_ char *unit = NULL;
         _cleanup_free_ char *id = NULL;
         Session *session = NULL;
         Manager *m = userdata;
@@ -789,8 +791,15 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
                         return r;
         }
 
-        r = manager_get_session_by_pid(m, leader, NULL);
-        if (r > 0)
+        /*
+         * Check if we are already in a logind session.  Or if we are in user@.service
+         * which is a special PAM session that avoids creating a logind session.
+         */
+        r = cg_pid_get_unit(leader, &unit);
+        if (r < 0)
+                return r;
+        if (hashmap_get(m->session_units, unit) ||
+            hashmap_get(m->user_units, unit))
                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
 
         /*