[systemd-commits] 7 commits - man/loginctl.xml src/bus-proxyd src/core src/login src/shared src/sysusers src/test

Lennart Poettering lennart at kemper.freedesktop.org
Fri Jan 9 09:35:44 PST 2015


 man/loginctl.xml                |   48 ++--
 src/bus-proxyd/bus-xml-policy.c |    5 
 src/core/execute.c              |  396 ++++++++++++++++++++--------------------
 src/login/loginctl.c            |   38 ++-
 src/login/logind-core.c         |    2 
 src/login/logind-dbus.c         |  220 +++++++++++++++-------
 src/login/logind-seat-dbus.c    |   22 +-
 src/login/logind-session-dbus.c |   19 +
 src/login/logind-session.c      |    2 
 src/login/logind-user-dbus.c    |   31 +--
 src/login/logind-user.c         |    4 
 src/login/logind.h              |    4 
 src/shared/macro.h              |    8 
 src/sysusers/sysusers.c         |    6 
 src/test/test-util.c            |   10 +
 15 files changed, 470 insertions(+), 345 deletions(-)

New commits:
commit fe21f16764147d51819a904d57ac36967f9913e3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 9 18:34:46 2015 +0100

    bus-proxy: make sure sure eavesdrop= XML attributes are properly handled

diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c
index cf39c52..9e4cc45 100644
--- a/src/bus-proxyd/bus-xml-policy.c
+++ b/src/bus-proxyd/bus-xml-policy.c
@@ -279,9 +279,8 @@ static int file_load(Policy *p, const char *path) {
                                         ic = POLICY_ITEM_GROUP;
                                 else if (streq(name, "eavesdrop")) {
                                         log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line);
-                                        i->class = POLICY_ITEM_IGNORE;
                                         state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE;
-                                        break;
+                                        ic = POLICY_ITEM_RECV; /* eavesdrop is a type of receive attribute match! */
                                 } else {
                                         log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line);
                                         state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE;
@@ -289,7 +288,7 @@ static int file_load(Policy *p, const char *path) {
                                 }
 
                                 if (i->class != _POLICY_ITEM_CLASS_UNSET && ic != i->class) {
-                                        log_error("send_ and receive_ fields mixed on same tag at %s:%u.", path, line);
+                                        log_error("send_, receive_/eavesdrop fields mixed on same tag at %s:%u.", path, line);
                                         return -EINVAL;
                                 }
 

commit 8cb4ab0058e51f1fba93683d145ef95f97c2fa86
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 9 16:25:47 2015 +0100

    logind: unify how we cast between uid_t and pointers for hashmap keys

diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index 88694f9..a6ff5ad 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -101,7 +101,7 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **
         assert(m);
         assert(name);
 
-        u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+        u = hashmap_get(m->users, UID_TO_PTR(uid));
         if (!u) {
                 u = user_new(m, uid, gid, name);
                 if (!u)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 3ff6cd3..bc985a3 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -92,7 +92,7 @@ int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid,
                         return r;
         }
 
-        user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+        user = hashmap_get(m->users, UID_TO_PTR(uid));
         if (!user)
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
 
@@ -1157,7 +1157,7 @@ static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *us
                 if (r < 0 && errno != ENOENT)
                         return -errno;
 
-                u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+                u = hashmap_get(m->users, UID_TO_PTR(uid));
                 if (u)
                         user_add_to_gc_queue(u);
         }
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index ea1831d..a51f9f3 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -355,7 +355,7 @@ int session_load(Session *s) {
                         return r;
                 }
 
-                user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
+                user = hashmap_get(s->manager->users, UID_TO_PTR(u));
                 if (!user) {
                         log_error("User of session %s not known.", s->id);
                         return -ENOENT;
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index 717740a..bff42e8 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -270,7 +270,7 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
         if (r < 0)
                 return 0;
 
-        user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+        user = hashmap_get(m->users, UID_TO_PTR(uid));
         if (!user)
                 return 0;
 
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 9ff1302..49c373b 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -56,7 +56,7 @@ User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
         if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
                 goto fail;
 
-        if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0)
+        if (hashmap_put(m->users, UID_TO_PTR(uid), u) < 0)
                 goto fail;
 
         u->manager = m;
@@ -97,7 +97,7 @@ void user_free(User *u) {
 
         free(u->runtime_path);
 
-        hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
+        hashmap_remove(u->manager->users, UID_TO_PTR(u->uid));
 
         free(u->name);
         free(u->state_file);
diff --git a/src/shared/macro.h b/src/shared/macro.h
index 6a57428..daa42c4 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -275,6 +275,14 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
 #define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p)))
 #define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u)))
 
+/* The following macros add 1 when converting things, since UID 0 is a
+ * valid UID, while the pointer NULL is special */
+#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1))
+#define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
+
+#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1))
+#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
+
 #define memzero(x,l) (memset((x), 0, (l)))
 #define zero(x) (memzero(&(x), sizeof(x)))
 
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 5d5f5ea..f25ece0 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -81,12 +81,6 @@ static uid_t search_uid = UID_INVALID;
 static UidRange *uid_range = NULL;
 static unsigned n_uid_range = 0;
 
-#define UID_TO_PTR(u) (ULONG_TO_PTR(u+1))
-#define PTR_TO_UID(u) ((uid_t) (PTR_TO_ULONG(u)-1))
-
-#define GID_TO_PTR(g) (ULONG_TO_PTR(g+1))
-#define PTR_TO_GID(g) ((gid_t) (PTR_TO_ULONG(g)-1))
-
 #define fix_root(x) (arg_root ? strappenda(arg_root, x) : x)
 
 static int load_user_database(void) {
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 3c79f8f..d529a21 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -1415,6 +1415,15 @@ static void test_same_fd(void) {
         assert_se(same_fd(b, a) == 0);
 }
 
+static void test_uid_ptr(void) {
+
+        assert_se(UID_TO_PTR(0) != NULL);
+        assert_se(UID_TO_PTR(1000) != NULL);
+
+        assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
+        assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
+}
+
 int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
@@ -1490,6 +1499,7 @@ int main(int argc, char *argv[]) {
         test_parse_proc_cmdline();
         test_raw_clone();
         test_same_fd();
+        test_uid_ptr();
 
         return 0;
 }

commit 309a29dfd24f4175de334ca1593e3fe2436ab082
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 9 16:14:19 2015 +0100

    logind: when a bus call is done on a session, user or seat, optionally determine them from the caller credentials
    
    More specifically, if an operation is requested on a session with an
    empty name, the caller's session is used. If an operation is requested
    on a seat with an empty name, the seat of the caller's session is used.
    Finally, if an operation on the user with UID -1 is requested, the user
    of the client's session is used (and not the UID of the client!).

diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index bbb4ae2..3ff6cd3 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -44,6 +44,91 @@
 #include "selinux-util.h"
 #include "logind.h"
 
+int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        Session *session;
+        int r;
+
+        assert(m);
+        assert(message);
+        assert(ret);
+
+        if (isempty(name)) {
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_creds_get_session(creds, &name);
+                if (r < 0)
+                        return r;
+        }
+
+        session = hashmap_get(m->sessions, name);
+        if (!session)
+                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
+
+        *ret = session;
+        return 0;
+}
+
+int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
+        User *user;
+        int r;
+
+        assert(m);
+        assert(message);
+        assert(ret);
+
+        if (uid == UID_INVALID) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+
+                /* Note that we get the owner UID of the session, not the actual client UID here! */
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_creds_get_owner_uid(creds, &uid);
+                if (r < 0)
+                        return r;
+        }
+
+        user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+        if (!user)
+                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
+
+        *ret = user;
+        return 0;
+}
+
+int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
+        Seat *seat;
+        int r;
+
+        assert(m);
+        assert(message);
+        assert(ret);
+
+        if (isempty(name)) {
+                Session *session;
+
+                r = manager_get_session_from_creds(m, message, NULL, error, &session);
+                if (r < 0)
+                        return r;
+
+                seat = session->seat;
+
+                if (!seat)
+                        return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
+        } else {
+                seat = hashmap_get(m->seats, name);
+                if (!seat)
+                        return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
+        }
+
+        *ret = seat;
+        return 0;
+}
+
 static int property_get_idle_hint(
                 sd_bus *bus,
                 const char *path,
@@ -131,6 +216,7 @@ static int property_get_preparing(
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
 
 static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         _cleanup_free_ char *p = NULL;
         Manager *m = userdata;
         const char *name;
@@ -145,9 +231,9 @@ static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userda
         if (r < 0)
                 return r;
 
-        session = hashmap_get(m->sessions, name);
-        if (!session)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
+        r = manager_get_session_from_creds(m, message, name, error, &session);
+        if (r < 0)
+                return r;
 
         p = session_bus_path(session);
         if (!p)
@@ -173,23 +259,18 @@ static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void
         if (r < 0)
                 return r;
 
-        if (pid == 0) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-
-                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+        if (pid <= 0) {
+                r = manager_get_session_from_creds(m, message, NULL, error, &session);
                 if (r < 0)
                         return r;
-
-                r = sd_bus_creds_get_pid(creds, &pid);
+        } else {
+                r = manager_get_session_by_pid(m, pid, &session);
                 if (r < 0)
                         return r;
-        }
 
-        r = manager_get_session_by_pid(m, pid, &session);
-        if (r < 0)
-                return r;
-        if (!session)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
+                if (!session)
+                        return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
+        }
 
         p = session_bus_path(session);
         if (!p)
@@ -213,9 +294,9 @@ static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata,
         if (r < 0)
                 return r;
 
-        user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
-        if (!user)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
+        r = manager_get_user_from_creds(m, message, uid, error, &user);
+        if (r < 0)
+                return r;
 
         p = user_bus_path(user);
         if (!p)
@@ -241,24 +322,18 @@ static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *us
         if (r < 0)
                 return r;
 
-        if (pid == 0) {
-                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
-
-                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+        if (pid <= 0) {
+                r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
                 if (r < 0)
                         return r;
-
-                r = sd_bus_creds_get_pid(creds, &pid);
+        } else {
+                r = manager_get_user_by_pid(m, pid, &user);
                 if (r < 0)
                         return r;
+                if (!user)
+                        return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
         }
 
-        r = manager_get_user_by_pid(m, pid, &user);
-        if (r < 0)
-                return r;
-        if (!user)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
-
         p = user_bus_path(user);
         if (!p)
                 return -ENOMEM;
@@ -281,9 +356,9 @@ static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata,
         if (r < 0)
                 return r;
 
-        seat = hashmap_get(m->seats, name);
-        if (!seat)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
+        r = manager_get_seat_from_creds(m, message, name, error, &seat);
+        if (r < 0)
+                return r;
 
         p = seat_bus_path(seat);
         if (!p)
@@ -570,8 +645,6 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
                 if (r < 0)
                         return r;
 
-                assert_cc(sizeof(uint32_t) == sizeof(pid_t));
-
                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
                 if (r < 0)
                         return r;
@@ -755,9 +828,9 @@ static int method_release_session(sd_bus *bus, sd_bus_message *message, void *us
         if (r < 0)
                 return r;
 
-        session = hashmap_get(m->sessions, name);
-        if (!session)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
+        r = manager_get_session_from_creds(m, message, name, error, &session);
+        if (r < 0)
+                return r;
 
         session_release(session);
 
@@ -778,9 +851,9 @@ static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *u
         if (r < 0)
                 return r;
 
-        session = hashmap_get(m->sessions, name);
-        if (!session)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
+        r = manager_get_session_from_creds(m, message, name, error, &session);
+        if (r < 0)
+                return r;
 
         r = session_activate(session);
         if (r < 0)
@@ -807,13 +880,13 @@ static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message,
         if (r < 0)
                 return r;
 
-        session = hashmap_get(m->sessions, session_name);
-        if (!session)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", session_name);
+        r = manager_get_session_from_creds(m, message, session_name, error, &session);
+        if (r < 0)
+                return r;
 
-        seat = hashmap_get(m->seats, seat_name);
-        if (!seat)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", seat_name);
+        r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
+        if (r < 0)
+                return r;
 
         if (session->seat != seat)
                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
@@ -839,9 +912,9 @@ static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userd
         if (r < 0)
                 return r;
 
-        session = hashmap_get(m->sessions, name);
-        if (!session)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
+        r = manager_get_session_from_creds(m, message, name, error, &session);
+        if (r < 0)
+                return r;
 
         r = session_send_lock(session, streq(sd_bus_message_get_member(message), "LockSession"));
         if (r < 0)
@@ -866,6 +939,7 @@ static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *user
 }
 
 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         const char *name, *swho;
         Manager *m = userdata;
         Session *session;
@@ -892,9 +966,9 @@ static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userd
         if (signo <= 0 || signo >= _NSIG)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
 
-        session = hashmap_get(m->sessions, name);
-        if (!session)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
+        r = manager_get_session_from_creds(m, message, name, error, &session);
+        if (r < 0)
+                return r;
 
         r = session_kill(session, who, signo);
         if (r < 0)
@@ -921,9 +995,9 @@ static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata
         if (signo <= 0 || signo >= _NSIG)
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
 
-        user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
-        if (!user)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
+        r = manager_get_user_from_creds(m, message, uid, error, &user);
+        if (r < 0)
+                return r;
 
         r = user_kill(user, signo);
         if (r < 0)
@@ -933,6 +1007,7 @@ static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata
 }
 
 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         Manager *m = userdata;
         const char *name;
         Session *session;
@@ -946,9 +1021,9 @@ static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *
         if (r < 0)
                 return r;
 
-        session = hashmap_get(m->sessions, name);
-        if (!session)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
+        r = manager_get_session_from_creds(m, message, name, error, &session);
+        if (r < 0)
+                return r;
 
         r = session_stop(session, true);
         if (r < 0)
@@ -971,9 +1046,9 @@ static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *use
         if (r < 0)
                 return r;
 
-        user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
-        if (!user)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
+        r = manager_get_user_from_creds(m, message, uid, error, &user);
+        if (r < 0)
+                return r;
 
         r = user_stop(user, true);
         if (r < 0)
@@ -996,9 +1071,9 @@ static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *use
         if (r < 0)
                 return r;
 
-        seat = hashmap_get(m->seats, name);
-        if (!seat)
-                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
+        r = manager_get_seat_from_creds(m, message, name, error, &seat);
+        if (r < 0)
+                return r;
 
         r = seat_stop_sessions(seat, true);
         if (r < 0)
@@ -1024,6 +1099,19 @@ static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *us
         if (r < 0)
                 return r;
 
+        if (uid == UID_INVALID) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+
+                /* Note that we get the owner UID of the session, not the actual client UID here! */
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_creds_get_owner_uid(creds, &uid);
+                if (r < 0)
+                        return r;
+        }
+
         errno = 0;
         pw = getpwuid(uid);
         if (!pw)
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index fb32b13..ddf2cd8 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -326,25 +326,22 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 Session *session;
-                pid_t pid;
+                const char *name;
 
                 message = sd_bus_get_current_message(bus);
                 if (!message)
                         return 0;
 
-                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
                 if (r < 0)
                         return r;
 
-                r = sd_bus_creds_get_pid(creds, &pid);
+                r = sd_bus_creds_get_session(creds, &name);
                 if (r < 0)
                         return r;
 
-                r = manager_get_session_by_pid(m, pid, &session);
-                if (r <= 0)
-                        return 0;
-
-                if (!session->seat)
+                session = hashmap_get(m->sessions, name);
+                if (!session)
                         return 0;
 
                 seat = session->seat;
@@ -361,10 +358,11 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
                         return -ENOMEM;
 
                 seat = hashmap_get(m->seats, e);
-                if (!seat)
-                        return 0;
         }
 
+        if (!seat)
+                return 0;
+
         *found = seat;
         return 1;
 }
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index a6b15f2..d341131 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -490,23 +490,21 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
         if (streq(path, "/org/freedesktop/login1/session/self")) {
                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
-                pid_t pid;
+                const char *name;
 
                 message = sd_bus_get_current_message(bus);
                 if (!message)
                         return 0;
 
-                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
                 if (r < 0)
                         return r;
 
-                r = sd_bus_creds_get_pid(creds, &pid);
+                r = sd_bus_creds_get_session(creds, &name);
                 if (r < 0)
                         return r;
 
-                r = manager_get_session_by_pid(m, pid, &session);
-                if (r <= 0)
-                        return 0;
+                session = hashmap_get(m->sessions, name);
         } else {
                 _cleanup_free_ char *e = NULL;
                 const char *p;
@@ -520,10 +518,11 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
                         return -ENOMEM;
 
                 session = hashmap_get(m->sessions, e);
-                if (!session)
-                        return 0;
         }
 
+        if (!session)
+                return 0;
+
         *found = session;
         return 1;
 }
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index e811b37..717740a 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -235,6 +235,7 @@ const sd_bus_vtable user_vtable[] = {
 
 int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
         Manager *m = userdata;
+        uid_t uid;
         User *user;
         int r;
 
@@ -247,39 +248,31 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
         if (streq(path, "/org/freedesktop/login1/user/self")) {
                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
-                pid_t pid;
 
                 message = sd_bus_get_current_message(bus);
                 if (!message)
                         return 0;
 
-                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
                 if (r < 0)
                         return r;
 
-                r = sd_bus_creds_get_pid(creds, &pid);
-                if (r < 0)
-                        return r;
-
-                r = manager_get_user_by_pid(m, pid, &user);
-                if (r <= 0)
-                        return 0;
+                r = sd_bus_creds_get_owner_uid(creds, &uid);
         } else {
-                unsigned long lu;
                 const char *p;
 
                 p = startswith(path, "/org/freedesktop/login1/user/_");
                 if (!p)
                         return 0;
 
-                r = safe_atolu(p, &lu);
-                if (r < 0)
-                        return 0;
-
-                user = hashmap_get(m->users, ULONG_TO_PTR(lu));
-                if (!user)
-                        return 0;
+                r = parse_uid(p, &uid);
         }
+        if (r < 0)
+                return 0;
+
+        user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+        if (!user)
+                return 0;
 
         *found = user;
         return 1;
diff --git a/src/login/logind.h b/src/login/logind.h
index 2f76572..e0cb7d0 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -193,3 +193,7 @@ void manager_drop_busname(Manager *manager, const char *name);
 int manager_set_lid_switch_ignore(Manager *m, usec_t until);
 
 int config_parse_tmpfs_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
+int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
+int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret);

commit 3909ba34ec9b2c63d9938b6ba37af54a214fcff3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 9 01:47:03 2015 +0100

    man: document that 'loginctl activate' only takes a single argument

diff --git a/man/loginctl.xml b/man/loginctl.xml
index 095ba05..8056310 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -250,14 +250,13 @@
                         </varlistentry>
 
                         <varlistentry>
-                                <term><command>activate</command> <replaceable>ID</replaceable>...</term>
-
-                                <listitem><para>Activate one or more
-                                sessions. This brings one or more
-                                sessions into the foreground, if
-                                another session is currently in the
-                                foreground on the respective
-                                seat.</para></listitem>
+                                <term><command>activate</command> <replaceable>ID</replaceable></term>
+
+                                <listitem><para>Activate a
+                                session. This brings a session into
+                                the foreground, if another session is
+                                currently in the foreground on the
+                                respective seat.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>

commit b298e98413a8bd112f0f7bd91a0dff3e7e931424
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 9 01:44:40 2015 +0100

    logind: include "self" object links in dbus introspection
    
    Makes "busctl introspect" a lot more fun.

diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index a99d008..fb32b13 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -404,6 +404,10 @@ int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
                         return r;
         }
 
+        r = strv_extend(&l, "/org/freedesktop/login1/seat/self");
+        if (r < 0)
+                return r;
+
         *nodes = l;
         l = NULL;
 
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index 4e75d5b..a6b15f2 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -563,6 +563,10 @@ int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
                         return r;
         }
 
+        r = strv_extend(&l, "/org/freedesktop/login1/session/self");
+        if (r < 0)
+                return r;
+
         *nodes = l;
         l = NULL;
 
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index 812a19f..e811b37 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -319,6 +319,10 @@ int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
                         return r;
         }
 
+        r = strv_extend(&l, "/org/freedesktop/login1/user/self");
+        if (r < 0)
+                return r;
+
         *nodes = l;
         l = NULL;
 

commit 86e1f46f92ff4c447ea32a6892ea394c6e6ef541
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 9 01:43:53 2015 +0100

    loginctl: make "loginctl session-status" without session ID show the caller's session status
    
    Similar for user-status and seat-status.

diff --git a/man/loginctl.xml b/man/loginctl.xml
index 7a6cc15..095ba05 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -209,16 +209,20 @@
                         </varlistentry>
 
                         <varlistentry>
-                                <term><command>session-status</command> <replaceable>ID</replaceable>...</term>
+                                <term><command>session-status</command> <optional><replaceable>ID</replaceable>...</optional></term>
 
                                 <listitem><para>Show terse runtime
                                 status information about one or more
                                 sessions, followed by the most recent
-                                log data from the journal. This
-                                function is intended to generate
-                                human-readable output. If you are
-                                looking for computer-parsable output,
-                                use <command>show-session</command>
+                                log data from the journal. Takes one
+                                or more session identifiers as
+                                parameters. If no session identifiers
+                                are passed the status of the caller's
+                                session is shown. This function is
+                                intended to generate human-readable
+                                output. If you are looking for
+                                computer-parsable output, use
+                                <command>show-session</command>
                                 instead.</para></listitem>
                         </varlistentry>
 
@@ -307,12 +311,16 @@
                         </varlistentry>
 
                         <varlistentry>
-                                <term><command>user-status</command> <replaceable>USER</replaceable>...</term>
+                                <term><command>user-status</command> <optional><replaceable>USER</replaceable>...</optional></term>
 
                                 <listitem><para>Show terse runtime
                                 status information about one or more
                                 logged in users, followed by the most
-                                recent log data from the journal. This
+                                recent log data from the
+                                journal. Takes one or more user names
+                                or numeric user IDs as parameters. If
+                                no parameters are passed the status of
+                                the caller's user is shown. This
                                 function is intended to generate
                                 human-readable output. If you are
                                 looking for computer-parsable output,
@@ -390,12 +398,15 @@
                         </varlistentry>
 
                         <varlistentry>
-                                <term><command>seat-status</command> <replaceable>NAME</replaceable>...</term>
+                                <term><command>seat-status</command> <optional><replaceable>NAME</replaceable>...</optional></term>
 
                                 <listitem><para>Show terse runtime
                                 status information about one or more
-                                seats. This function is
-                                intended to generate human-readable
+                                seats. Takes one or more seat names as
+                                parameters. If no seat names are
+                                passed the status of the caller's
+                                session's seat is shown. This function
+                                is intended to generate human-readable
                                 output. If you are looking for
                                 computer-parsable output, use
                                 <command>show-seat</command>
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 0fdd42b..c62ae32 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -684,10 +684,14 @@ static int show_session(int argc, char *argv[], void *userdata) {
 
         pager_open_if_enabled();
 
-        if (properties && argc <= 1) {
+        if (argc <= 1) {
                 /* If not argument is specified inspect the manager
                  * itself */
-                return show_properties(bus, "/org/freedesktop/login1", &new_line);
+                if (properties)
+                        return show_properties(bus, "/org/freedesktop/login1", &new_line);
+
+                /* And in the pretty case, show data of the calling session */
+                return print_session_status_info(bus, "/org/freedesktop/login1/session/self", &new_line);
         }
 
         for (i = 1; i < argc; i++) {
@@ -736,10 +740,13 @@ static int show_user(int argc, char *argv[], void *userdata) {
 
         pager_open_if_enabled();
 
-        if (properties && argc <= 1) {
+        if (argc <= 1) {
                 /* If not argument is specified inspect the manager
                  * itself */
-                return show_properties(bus, "/org/freedesktop/login1", &new_line);
+                if (properties)
+                        return show_properties(bus, "/org/freedesktop/login1", &new_line);
+
+                return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line);
         }
 
         for (i = 1; i < argc; i++) {
@@ -793,10 +800,13 @@ static int show_seat(int argc, char *argv[], void *userdata) {
 
         pager_open_if_enabled();
 
-        if (properties && argc <= 1) {
+        if (argc <= 1) {
                 /* If not argument is specified inspect the manager
                  * itself */
-                return show_properties(bus, "/org/freedesktop/login1", &new_line);
+                if (properties)
+                        return show_properties(bus, "/org/freedesktop/login1", &new_line);
+
+                return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line);
         }
 
         for (i = 1; i < argc; i++) {
@@ -1133,7 +1143,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "                           verbose, export, json, json-pretty, json-sse, cat)\n\n"
                "Session Commands:\n"
                "  list-sessions            List sessions\n"
-               "  session-status ID...     Show session status\n"
+               "  session-status [ID...]   Show session status\n"
                "  show-session [ID...]     Show properties of sessions or the manager\n"
                "  activate ID              Activate a session\n"
                "  lock-session ID...       Screen lock one or more sessions\n"
@@ -1144,7 +1154,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "  kill-session ID...       Send signal to processes of a session\n\n"
                "User Commands:\n"
                "  list-users               List users\n"
-               "  user-status USER...      Show user status\n"
+               "  user-status [USER...]    Show user status\n"
                "  show-user [USER...]      Show properties of users or the manager\n"
                "  enable-linger USER...    Enable linger state of one or more users\n"
                "  disable-linger USER...   Disable linger state of one or more users\n"
@@ -1152,8 +1162,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "  kill-user USER...        Send signal to processes of a user\n\n"
                "Seat Commands:\n"
                "  list-seats               List seats\n"
-               "  seat-status NAME...      Show seat status\n"
-               "  show-seat NAME...        Show properties of one or more seats\n"
+               "  seat-status [NAME...]    Show seat status\n"
+               "  show-seat [NAME...]      Show properties of seats or the manager\n"
                "  attach NAME DEVICE...    Attach one or more devices to a seat\n"
                "  flush-devices            Flush all device associations\n"
                "  terminate-seat NAME...   Terminate all sessions on one or more seats\n"
@@ -1292,7 +1302,7 @@ static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
         static const Verb verbs[] = {
                 { "help",              VERB_ANY, VERB_ANY, 0,            help              },
                 { "list-sessions",     VERB_ANY, 1,        VERB_DEFAULT, list_sessions     },
-                { "session-status",    2,        VERB_ANY, 0,            show_session      },
+                { "session-status",    VERB_ANY, VERB_ANY, 0,            show_session      },
                 { "show-session",      VERB_ANY, VERB_ANY, 0,            show_session      },
                 { "activate",          2,        2,        0,            activate          },
                 { "lock-session",      2,        VERB_ANY, 0,            activate          },
@@ -1302,15 +1312,15 @@ static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
                 { "terminate-session", 2,        VERB_ANY, 0,            activate          },
                 { "kill-session",      2,        VERB_ANY, 0,            kill_session      },
                 { "list-users",        VERB_ANY, 1,        0,            list_users        },
-                { "user-status",       2,        VERB_ANY, 0,            show_user         },
+                { "user-status",       VERB_ANY, VERB_ANY, 0,            show_user         },
                 { "show-user",         VERB_ANY, VERB_ANY, 0,            show_user         },
                 { "enable-linger",     2,        VERB_ANY, 0,            enable_linger     },
                 { "disable-linger",    2,        VERB_ANY, 0,            enable_linger     },
                 { "terminate-user",    2,        VERB_ANY, 0,            terminate_user    },
                 { "kill-user",         2,        VERB_ANY, 0,            kill_user         },
                 { "list-seats",        VERB_ANY, 1,        0,            list_seats        },
-                { "seat-status",       2,        VERB_ANY, 0,            show_seat         },
-                { "show-seat",         VERB_ANY, 1,        0,            show_seat         },
+                { "seat-status",       VERB_ANY, VERB_ANY, 0,            show_seat         },
+                { "show-seat",         VERB_ANY, VERB_ANY, 0,            show_seat         },
                 { "attach",            3,        VERB_ANY, 0,            attach            },
                 { "flush-devices",     VERB_ANY, 1,        0,            flush_devices     },
                 { "terminate-seat",    2,        VERB_ANY, 0,            terminate_seat    },

commit ff0af2a1660bb122f29713c9b2aff8179f165bb7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 9 00:13:33 2015 +0100

    core: modernize execution code a bit
    
    Among other things, avoid log_struct() unless we really need it.
    
    Also, use "r" as variable to store function errors in, instead of "err".
    "r" is pretty much what we use everywhere else, hence using the same
    here make sense.
    
    FInally, in the child, when we want to log, make sure to open the
    logging framework first, since it is explicitly closed in preparation
    for the exec().

diff --git a/src/core/execute.c b/src/core/execute.c
index 67a69b7..12a96a7 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1266,15 +1266,16 @@ static int build_environment(
         return 0;
 }
 
-static int exec_child(ExecCommand *command,
-                      const ExecContext *context,
-                      const ExecParameters *params,
-                      ExecRuntime *runtime,
-                      char **argv,
-                      int socket_fd,
-                      int *fds, unsigned n_fds,
-                      char **files_env,
-                      int *error) {
+static int exec_child(
+                ExecCommand *command,
+                const ExecContext *context,
+                const ExecParameters *params,
+                ExecRuntime *runtime,
+                char **argv,
+                int socket_fd,
+                int *fds, unsigned n_fds,
+                char **files_env,
+                int *exit_status) {
 
         _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
         _cleanup_free_ char *mac_selinux_context_net = NULL;
@@ -1283,12 +1284,12 @@ static int exec_child(ExecCommand *command,
         int dont_close[n_fds + 4];
         uid_t uid = UID_INVALID;
         gid_t gid = GID_INVALID;
-        int i, err;
+        int i, r;
 
         assert(command);
         assert(context);
         assert(params);
-        assert(error);
+        assert(exit_status);
 
         rename_process_from_path(command->path);
 
@@ -1303,10 +1304,10 @@ static int exec_child(ExecCommand *command,
         if (context->ignore_sigpipe)
                 ignore_signals(SIGPIPE, -1);
 
-        err = reset_signal_mask();
-        if (err < 0) {
-                *error = EXIT_SIGNAL_MASK;
-                return err;
+        r = reset_signal_mask();
+        if (r < 0) {
+                *exit_status = EXIT_SIGNAL_MASK;
+                return r;
         }
 
         if (params->idle_pipe)
@@ -1315,6 +1316,7 @@ static int exec_child(ExecCommand *command,
         /* Close sockets very early to make sure we don't
          * block init reexecution because it cannot bind its
          * sockets */
+
         log_forget_fds();
 
         if (socket_fd >= 0)
@@ -1332,15 +1334,15 @@ static int exec_child(ExecCommand *command,
                         dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
         }
 
-        err = close_all_fds(dont_close, n_dont_close);
-        if (err < 0) {
-                *error = EXIT_FDS;
-                return err;
+        r = close_all_fds(dont_close, n_dont_close);
+        if (r < 0) {
+                *exit_status = EXIT_FDS;
+                return r;
         }
 
         if (!context->same_pgrp)
                 if (setsid() < 0) {
-                        *error = EXIT_SETSID;
+                        *exit_status = EXIT_SETSID;
                         return -errno;
                 }
 
@@ -1349,28 +1351,28 @@ static int exec_child(ExecCommand *command,
         if (params->confirm_spawn) {
                 char response;
 
-                err = ask_for_confirmation(&response, argv);
-                if (err == -ETIMEDOUT)
+                r = ask_for_confirmation(&response, argv);
+                if (r == -ETIMEDOUT)
                         write_confirm_message("Confirmation question timed out, assuming positive response.\n");
-                else if (err < 0)
-                        write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-err));
+                else if (r < 0)
+                        write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-r));
                 else if (response == 's') {
                         write_confirm_message("Skipping execution.\n");
-                        *error = EXIT_CONFIRM;
+                        *exit_status = EXIT_CONFIRM;
                         return -ECANCELED;
                 } else if (response == 'n') {
                         write_confirm_message("Failing execution.\n");
-                        *error = 0;
+                        *exit_status = 0;
                         return 0;
                 }
         }
 
         if (context->user) {
                 username = context->user;
-                err = get_user_creds(&username, &uid, &gid, &home, &shell);
-                if (err < 0) {
-                        *error = EXIT_USER;
-                        return err;
+                r = get_user_creds(&username, &uid, &gid, &home, &shell);
+                if (r < 0) {
+                        *exit_status = EXIT_USER;
+                        return r;
                 }
         }
 
@@ -1379,29 +1381,29 @@ static int exec_child(ExecCommand *command,
         if (socket_fd >= 0)
                 fd_nonblock(socket_fd, false);
 
-        err = setup_input(context, socket_fd, params->apply_tty_stdin);
-        if (err < 0) {
-                *error = EXIT_STDIN;
-                return err;
+        r = setup_input(context, socket_fd, params->apply_tty_stdin);
+        if (r < 0) {
+                *exit_status = EXIT_STDIN;
+                return r;
         }
 
-        err = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin, uid, gid);
-        if (err < 0) {
-                *error = EXIT_STDOUT;
-                return err;
+        r = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin, uid, gid);
+        if (r < 0) {
+                *exit_status = EXIT_STDOUT;
+                return r;
         }
 
-        err = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin, uid, gid);
-        if (err < 0) {
-                *error = EXIT_STDERR;
-                return err;
+        r = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin, uid, gid);
+        if (r < 0) {
+                *exit_status = EXIT_STDERR;
+                return r;
         }
 
         if (params->cgroup_path) {
-                err = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0, NULL, NULL);
-                if (err < 0) {
-                        *error = EXIT_CGROUP;
-                        return err;
+                r = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0, NULL, NULL);
+                if (r < 0) {
+                        *exit_status = EXIT_CGROUP;
+                        return r;
                 }
         }
 
@@ -1414,16 +1416,20 @@ static int exec_child(ExecCommand *command,
                  * shouldn't trip up over that. */
 
                 sprintf(t, "%i", context->oom_score_adjust);
-                err = write_string_file("/proc/self/oom_score_adj", t);
-                if (err < 0 && err != -EPERM && err != EACCES) {
-                        *error = EXIT_OOM_ADJUST;
+                r = write_string_file("/proc/self/oom_score_adj", t);
+                if (r == -EPERM || r == EACCES) {
+                        log_open();
+                        log_unit_debug_errno(params->unit_id, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
+                        log_close();
+                } else if (r < 0) {
+                        *exit_status = EXIT_OOM_ADJUST;
                         return -errno;
                 }
         }
 
         if (context->nice_set)
                 if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
-                        *error = EXIT_NICE;
+                        *exit_status = EXIT_NICE;
                         return -errno;
                 }
 
@@ -1432,38 +1438,38 @@ static int exec_child(ExecCommand *command,
                         .sched_priority = context->cpu_sched_priority,
                 };
 
-                err = sched_setscheduler(0,
-                                         context->cpu_sched_policy |
-                                         (context->cpu_sched_reset_on_fork ?
-                                          SCHED_RESET_ON_FORK : 0),
-                                         &param);
-                if (err < 0) {
-                        *error = EXIT_SETSCHEDULER;
+                r = sched_setscheduler(0,
+                                       context->cpu_sched_policy |
+                                       (context->cpu_sched_reset_on_fork ?
+                                        SCHED_RESET_ON_FORK : 0),
+                                       &param);
+                if (r < 0) {
+                        *exit_status = EXIT_SETSCHEDULER;
                         return -errno;
                 }
         }
 
         if (context->cpuset)
                 if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
-                        *error = EXIT_CPUAFFINITY;
+                        *exit_status = EXIT_CPUAFFINITY;
                         return -errno;
                 }
 
         if (context->ioprio_set)
                 if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
-                        *error = EXIT_IOPRIO;
+                        *exit_status = EXIT_IOPRIO;
                         return -errno;
                 }
 
         if (context->timer_slack_nsec != NSEC_INFINITY)
                 if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
-                        *error = EXIT_TIMERSLACK;
+                        *exit_status = EXIT_TIMERSLACK;
                         return -errno;
                 }
 
         if (context->personality != 0xffffffffUL)
                 if (personality(context->personality) < 0) {
-                        *error = EXIT_PERSONALITY;
+                        *exit_status = EXIT_PERSONALITY;
                         return -errno;
                 }
 
@@ -1471,10 +1477,10 @@ static int exec_child(ExecCommand *command,
                 utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path);
 
         if (context->user && is_terminal_input(context->std_input)) {
-                err = chown_terminal(STDIN_FILENO, uid);
-                if (err < 0) {
-                        *error = EXIT_STDIN;
-                        return err;
+                r = chown_terminal(STDIN_FILENO, uid);
+                if (r < 0) {
+                        *exit_status = EXIT_STDIN;
+                        return r;
                 }
         }
 
@@ -1482,10 +1488,10 @@ static int exec_child(ExecCommand *command,
         if (params->bus_endpoint_fd >= 0 && context->bus_endpoint) {
                 uid_t ep_uid = (uid == UID_INVALID) ? 0 : uid;
 
-                err = bus_kernel_set_endpoint_policy(params->bus_endpoint_fd, ep_uid, context->bus_endpoint);
-                if (err < 0) {
-                        *error = EXIT_BUS_ENDPOINT;
-                        return err;
+                r = bus_kernel_set_endpoint_policy(params->bus_endpoint_fd, ep_uid, context->bus_endpoint);
+                if (r < 0) {
+                        *exit_status = EXIT_BUS_ENDPOINT;
+                        return r;
                 }
         }
 #endif
@@ -1494,17 +1500,17 @@ static int exec_child(ExecCommand *command,
          * (but only in systemd's own controller hierarchy!) to the
          * user of the new process. */
         if (params->cgroup_path && context->user && params->cgroup_delegate) {
-                err = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0644, uid, gid);
-                if (err < 0) {
-                        *error = EXIT_CGROUP;
-                        return err;
+                r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0644, uid, gid);
+                if (r < 0) {
+                        *exit_status = EXIT_CGROUP;
+                        return r;
                 }
 
 
-                err = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0755, uid, gid);
-                if (err < 0) {
-                        *error = EXIT_CGROUP;
-                        return err;
+                r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0755, uid, gid);
+                if (r < 0) {
+                        *exit_status = EXIT_CGROUP;
+                        return r;
                 }
         }
 
@@ -1516,23 +1522,23 @@ static int exec_child(ExecCommand *command,
 
                         p = strjoin(params->runtime_prefix, "/", *rt, NULL);
                         if (!p) {
-                                *error = EXIT_RUNTIME_DIRECTORY;
+                                *exit_status = EXIT_RUNTIME_DIRECTORY;
                                 return -ENOMEM;
                         }
 
-                        err = mkdir_safe(p, context->runtime_directory_mode, uid, gid);
-                        if (err < 0) {
-                                *error = EXIT_RUNTIME_DIRECTORY;
-                                return err;
+                        r = mkdir_safe(p, context->runtime_directory_mode, uid, gid);
+                        if (r < 0) {
+                                *exit_status = EXIT_RUNTIME_DIRECTORY;
+                                return r;
                         }
                 }
         }
 
         if (params->apply_permissions) {
-                err = enforce_groups(context, username, gid);
-                if (err < 0) {
-                        *error = EXIT_GROUP;
-                        return err;
+                r = enforce_groups(context, username, gid);
+                if (r < 0) {
+                        *exit_status = EXIT_GROUP;
+                        return r;
                 }
         }
 
@@ -1540,19 +1546,19 @@ static int exec_child(ExecCommand *command,
 
 #ifdef HAVE_PAM
         if (params->apply_permissions && context->pam_name && username) {
-                err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
-                if (err < 0) {
-                        *error = EXIT_PAM;
-                        return err;
+                r = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
+                if (r < 0) {
+                        *exit_status = EXIT_PAM;
+                        return r;
                 }
         }
 #endif
 
         if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) {
-                err = setup_netns(runtime->netns_storage_socket);
-                if (err < 0) {
-                        *error = EXIT_NETWORK;
-                        return err;
+                r = setup_netns(runtime->netns_storage_socket);
+                if (r < 0) {
+                        *exit_status = EXIT_NETWORK;
+                        return r;
                 }
         }
 
@@ -1581,7 +1587,7 @@ static int exec_child(ExecCommand *command,
                                 var = strappenda(runtime->var_tmp_dir, "/tmp");
                 }
 
-                err = setup_namespace(
+                r = setup_namespace(
                                 context->read_write_dirs,
                                 context->read_only_dirs,
                                 context->inaccessible_dirs,
@@ -1593,23 +1599,28 @@ static int exec_child(ExecCommand *command,
                                 context->protect_system,
                                 context->mount_flags);
 
-                if (err == -EPERM)
-                        log_unit_warning_errno(params->unit_id, err, "Failed to set up file system namespace due to lack of privileges. Execution sandbox will not be in effect: %m");
-                else if (err < 0) {
-                        *error = EXIT_NAMESPACE;
-                        return err;
+                /* If we couldn't set up the namespace this is
+                 * probably due to a missing capability. In this case,
+                 * silently proceeed. */
+                if (r == -EPERM || r == -EACCES) {
+                        log_open();
+                        log_unit_debug_errno(params->unit_id, r, "Failed to set up namespace, assuming containerized execution, ignoring: %m");
+                        log_close();
+                } else if (r < 0) {
+                        *exit_status = EXIT_NAMESPACE;
+                        return r;
                 }
         }
 
         if (params->apply_chroot) {
                 if (context->root_directory)
                         if (chroot(context->root_directory) < 0) {
-                                *error = EXIT_CHROOT;
+                                *exit_status = EXIT_CHROOT;
                                 return -errno;
                         }
 
                 if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
-                        *error = EXIT_CHDIR;
+                        *exit_status = EXIT_CHDIR;
                         return -errno;
                 }
         } else {
@@ -1618,22 +1629,22 @@ static int exec_child(ExecCommand *command,
                 if (asprintf(&d, "%s/%s",
                              context->root_directory ? context->root_directory : "",
                              context->working_directory ? context->working_directory : "") < 0) {
-                        *error = EXIT_MEMORY;
+                        *exit_status = EXIT_MEMORY;
                         return -ENOMEM;
                 }
 
                 if (chdir(d) < 0) {
-                        *error = EXIT_CHDIR;
+                        *exit_status = EXIT_CHDIR;
                         return -errno;
                 }
         }
 
 #ifdef HAVE_SELINUX
         if (params->apply_permissions && mac_selinux_use() && params->selinux_context_net && socket_fd >= 0) {
-                err = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net);
-                if (err < 0) {
-                        *error = EXIT_SELINUX_CONTEXT;
-                        return err;
+                r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net);
+                if (r < 0) {
+                        *exit_status = EXIT_SELINUX_CONTEXT;
+                        return r;
                 }
         }
 #endif
@@ -1644,14 +1655,14 @@ static int exec_child(ExecCommand *command,
          * and the netns fds we don't need anymore. The custom
          * endpoint fd was needed to upload the policy and can
          * now be closed as well. */
-        err = close_all_fds(fds, n_fds);
-        if (err >= 0)
-                err = shift_fds(fds, n_fds);
-        if (err >= 0)
-                err = flags_fds(fds, n_fds, context->non_blocking);
-        if (err < 0) {
-                *error = EXIT_FDS;
-                return err;
+        r = close_all_fds(fds, n_fds);
+        if (r >= 0)
+                r = shift_fds(fds, n_fds);
+        if (r >= 0)
+                r = flags_fds(fds, n_fds, context->non_blocking);
+        if (r < 0) {
+                *exit_status = EXIT_FDS;
+                return r;
         }
 
         if (params->apply_permissions) {
@@ -1661,34 +1672,34 @@ static int exec_child(ExecCommand *command,
                                 continue;
 
                         if (setrlimit_closest(i, context->rlimit[i]) < 0) {
-                                *error = EXIT_LIMITS;
+                                *exit_status = EXIT_LIMITS;
                                 return -errno;
                         }
                 }
 
                 if (context->capability_bounding_set_drop) {
-                        err = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
-                        if (err < 0) {
-                                *error = EXIT_CAPABILITIES;
-                                return err;
+                        r = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
+                        if (r < 0) {
+                                *exit_status = EXIT_CAPABILITIES;
+                                return r;
                         }
                 }
 
 #ifdef HAVE_SMACK
                 if (context->smack_process_label) {
-                        err = mac_smack_apply_pid(0, context->smack_process_label);
-                        if (err < 0) {
-                                *error = EXIT_SMACK_PROCESS_LABEL;
-                                return err;
+                        r = mac_smack_apply_pid(0, context->smack_process_label);
+                        if (r < 0) {
+                                *exit_status = EXIT_SMACK_PROCESS_LABEL;
+                                return r;
                         }
                 }
 #endif
 
                 if (context->user) {
-                        err = enforce_user(context, uid);
-                        if (err < 0) {
-                                *error = EXIT_USER;
-                                return err;
+                        r = enforce_user(context, uid);
+                        if (r < 0) {
+                                *exit_status = EXIT_USER;
+                                return r;
                         }
                 }
 
@@ -1698,39 +1709,39 @@ static int exec_child(ExecCommand *command,
                  * PR_SET_SECUREBITS unless necessary. */
                 if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
                         if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
-                                *error = EXIT_SECUREBITS;
+                                *exit_status = EXIT_SECUREBITS;
                                 return -errno;
                         }
 
                 if (context->capabilities)
                         if (cap_set_proc(context->capabilities) < 0) {
-                                *error = EXIT_CAPABILITIES;
+                                *exit_status = EXIT_CAPABILITIES;
                                 return -errno;
                         }
 
                 if (context->no_new_privileges)
                         if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
-                                *error = EXIT_NO_NEW_PRIVILEGES;
+                                *exit_status = EXIT_NO_NEW_PRIVILEGES;
                                 return -errno;
                         }
 
 #ifdef HAVE_SECCOMP
                 if (context->address_families_whitelist ||
                     !set_isempty(context->address_families)) {
-                        err = apply_address_families(context);
-                        if (err < 0) {
-                                *error = EXIT_ADDRESS_FAMILIES;
-                                return err;
+                        r = apply_address_families(context);
+                        if (r < 0) {
+                                *exit_status = EXIT_ADDRESS_FAMILIES;
+                                return r;
                         }
                 }
 
                 if (context->syscall_whitelist ||
                     !set_isempty(context->syscall_filter) ||
                     !set_isempty(context->syscall_archs)) {
-                        err = apply_seccomp(context);
-                        if (err < 0) {
-                                *error = EXIT_SECCOMP;
-                                return err;
+                        r = apply_seccomp(context);
+                        if (r < 0) {
+                                *exit_status = EXIT_SECCOMP;
+                                return r;
                         }
                 }
 #endif
@@ -1740,10 +1751,10 @@ static int exec_child(ExecCommand *command,
                         char *exec_context = mac_selinux_context_net ?: context->selinux_context;
 
                         if (exec_context) {
-                                err = setexeccon(exec_context);
-                                if (err < 0) {
-                                        *error = EXIT_SELINUX_CONTEXT;
-                                        return err;
+                                r = setexeccon(exec_context);
+                                if (r < 0) {
+                                        *exit_status = EXIT_SELINUX_CONTEXT;
+                                        return r;
                                 }
                         }
                 }
@@ -1751,19 +1762,19 @@ static int exec_child(ExecCommand *command,
 
 #ifdef HAVE_APPARMOR
                 if (context->apparmor_profile && mac_apparmor_use()) {
-                        err = aa_change_onexec(context->apparmor_profile);
-                        if (err < 0 && !context->apparmor_profile_ignore) {
-                                *error = EXIT_APPARMOR_PROFILE;
+                        r = aa_change_onexec(context->apparmor_profile);
+                        if (r < 0 && !context->apparmor_profile_ignore) {
+                                *exit_status = EXIT_APPARMOR_PROFILE;
                                 return -errno;
                         }
                 }
 #endif
         }
 
-        err = build_environment(context, n_fds, params->watchdog_usec, home, username, shell, &our_env);
-        if (err < 0) {
-                *error = EXIT_MEMORY;
-                return err;
+        r = build_environment(context, n_fds, params->watchdog_usec, home, username, shell, &our_env);
+        if (r < 0) {
+                *exit_status = EXIT_MEMORY;
+                return r;
         }
 
         final_env = strv_env_merge(5,
@@ -1774,13 +1785,13 @@ static int exec_child(ExecCommand *command,
                                    pam_env,
                                    NULL);
         if (!final_env) {
-                *error = EXIT_MEMORY;
+                *exit_status = EXIT_MEMORY;
                 return -ENOMEM;
         }
 
         final_argv = replace_env_argv(argv, final_env);
         if (!final_argv) {
-                *error = EXIT_MEMORY;
+                *exit_status = EXIT_MEMORY;
                 return -ENOMEM;
         }
 
@@ -1801,7 +1812,7 @@ static int exec_child(ExecCommand *command,
                 }
         }
         execve(command->path, final_argv, final_env);
-        *error = EXIT_EXEC;
+        *exit_status = EXIT_EXEC;
         return -errno;
 }
 
@@ -1813,10 +1824,10 @@ int exec_spawn(ExecCommand *command,
 
         _cleanup_strv_free_ char **files_env = NULL;
         int *fds = NULL; unsigned n_fds = 0;
-        char *line, **argv;
-        int socket_fd;
+        _cleanup_free_ char *line = NULL;
+        int socket_fd, r;
+        char **argv;
         pid_t pid;
-        int err;
 
         assert(command);
         assert(context);
@@ -1828,8 +1839,10 @@ int exec_spawn(ExecCommand *command,
             context->std_output == EXEC_OUTPUT_SOCKET ||
             context->std_error == EXEC_OUTPUT_SOCKET) {
 
-                if (params->n_fds != 1)
+                if (params->n_fds != 1) {
+                        log_unit_error(params->unit_id, "Got more than one socket.");
                         return -EINVAL;
+                }
 
                 socket_fd = params->fds[0];
         } else {
@@ -1838,18 +1851,11 @@ int exec_spawn(ExecCommand *command,
                 n_fds = params->n_fds;
         }
 
-        err = exec_context_load_environment(context, params->unit_id, &files_env);
-        if (err < 0) {
-                log_unit_struct(params->unit_id,
-                                LOG_ERR,
-                                LOG_MESSAGE("Failed to load environment files: %s", strerror(-err)),
-                                LOG_ERRNO(-err),
-                                NULL);
-                return err;
-        }
+        r = exec_context_load_environment(context, params->unit_id, &files_env);
+        if (r < 0)
+                return log_unit_error_errno(params->unit_id, r, "Failed to load environment files: %m");
 
         argv = params->argv ?: command->argv;
-
         line = exec_command_line(argv);
         if (!line)
                 return log_oom();
@@ -1859,45 +1865,39 @@ int exec_spawn(ExecCommand *command,
                         "EXECUTABLE=%s", command->path,
                         LOG_MESSAGE("About to execute: %s", line),
                         NULL);
-        free(line);
-
         pid = fork();
         if (pid < 0)
-                return -errno;
+                return log_unit_error_errno(params->unit_id, r, "Failed to fork: %m");
 
         if (pid == 0) {
-                int r;
-
-                err = exec_child(command,
-                                 context,
-                                 params,
-                                 runtime,
-                                 argv,
-                                 socket_fd,
-                                 fds, n_fds,
-                                 files_env,
-                                 &r);
-                if (r != 0) {
+                int exit_status;
+
+                r = exec_child(command,
+                               context,
+                               params,
+                               runtime,
+                               argv,
+                               socket_fd,
+                               fds, n_fds,
+                               files_env,
+                               &exit_status);
+                if (r < 0) {
                         log_open();
-                        log_struct(LOG_ERR,
-                                   LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
-                                   "EXECUTABLE=%s", command->path,
-                                   LOG_MESSAGE("Failed at step %s spawning %s: %s",
-                                               exit_status_to_string(r, EXIT_STATUS_SYSTEMD),
-                                               command->path, strerror(-err)),
-                                   LOG_ERRNO(-err),
-                                   NULL);
-                        log_close();
+                        log_unit_struct(params->unit_id,
+                                        LOG_ERR,
+                                        LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
+                                        "EXECUTABLE=%s", command->path,
+                                        LOG_MESSAGE("Failed at step %s spawning %s: %s",
+                                                    exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD),
+                                                    command->path, strerror(-r)),
+                                        LOG_ERRNO(r),
+                                        NULL);
                 }
 
-                _exit(r);
+                _exit(exit_status);
         }
 
-        log_unit_struct(params->unit_id,
-                        LOG_DEBUG,
-                        LOG_MESSAGE("Forked %s as "PID_FMT,
-                                    command->path, pid),
-                        NULL);
+        log_unit_debug(params->unit_id, "Forked %s as "PID_FMT, command->path, pid);
 
         /* We add the new process to the cgroup both in the child (so
          * that we can be sure that no user code is ever executed



More information about the systemd-commits mailing list