chiark / gitweb /
logind: properly handle if two session with identical loginuids are attempted to...
[elogind.git] / src / logind-dbus.c
index 0f3de41fff2ab1046c16a0580f21f17f0ea2ec01..d48d68c2bb70b4b64d5bdd3fc63c7a54dc43e134 100644 (file)
@@ -176,7 +176,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
         Seat *s;
         DBusMessageIter iter;
         int r;
-        char *id, *p;
+        char *id = NULL, *p;
         int vtnr = -1;
         int pipe_fds[2] = { -1, -1 };
         DBusMessage *reply = NULL;
@@ -306,19 +306,74 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
 
         audit_session_from_pid(leader, &audit_id);
 
-        if (audit_id > 0)
+        if (audit_id > 0) {
                 asprintf(&id, "%lu", (unsigned long) audit_id);
-        else
-                asprintf(&id, "c%lu", ++m->session_counter);
 
-        if (!id) {
-                r = -ENOMEM;
-                goto fail;
-        }
+                if (!id) {
+                        r = -ENOMEM;
+                        goto fail;
+                }
 
-        if (hashmap_get(m->sessions, id)) {
-                r = -EEXIST;
-                goto fail;
+                session = hashmap_get(m->sessions, id);
+
+                if (session) {
+
+                        /* Session already exists, client is probably
+                         * something like "su" which changes uid but
+                         * is still the same audit session */
+
+                        reply = dbus_message_new_method_return(message);
+                        if (!reply) {
+                                r = -ENOMEM;
+                                goto fail;
+                        }
+
+                        /* Create a throw-away fd */
+                        if (pipe(pipe_fds) < 0) {
+                                r = -errno;
+                                goto fail;
+                        }
+
+                        close_nointr_nofail(pipe_fds[0]);
+                        pipe_fds[0] = -1;
+
+                        p = session_bus_path(session);
+                        if (!p) {
+                                r = -ENOMEM;
+                                goto fail;
+                        }
+
+                        b = dbus_message_append_args(
+                                        reply,
+                                        DBUS_TYPE_STRING, &session->id,
+                                        DBUS_TYPE_OBJECT_PATH, &p,
+                                        DBUS_TYPE_STRING, &session->user->runtime_path,
+                                        DBUS_TYPE_UNIX_FD, &pipe_fds[1],
+                                        DBUS_TYPE_INVALID);
+                        free(p);
+
+                        if (!b) {
+                                r = -ENOMEM;
+                                goto fail;
+                        }
+
+                        close_nointr_nofail(pipe_fds[1]);
+                        *_reply = reply;
+
+                        return 0;
+                }
+
+        } else {
+                do {
+                        free(id);
+                        asprintf(&id, "c%lu", ++m->session_counter);
+
+                        if (!id) {
+                                r = -ENOMEM;
+                                goto fail;
+                        }
+
+                } while (hashmap_get(m->sessions, id));
         }
 
         r = manager_add_session(m, user, id, &session);