chiark / gitweb /
bus: add new sd_bus_creds object to encapsulate process credentials
authorLennart Poettering <lennart@poettering.net>
Thu, 28 Nov 2013 16:50:02 +0000 (17:50 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 28 Nov 2013 17:42:18 +0000 (18:42 +0100)
This way we can unify handling of credentials that are attached to
messages, or can be queried for bus name owners or connection peers.

This also adds the ability to extend incomplete credential information
with data from /proc,

Also, provide a convenience call that will automatically determine the
most appropriate credential object for an incoming message, by using the
the attached information if possible, the sending name information if
available and otherwise the peer's credentials.

33 files changed:
.gitignore
Makefile.am
src/core/dbus-manager.c
src/core/dbus.c
src/core/selinux-access.c
src/core/service.c
src/libsystemd-bus/bus-control.c
src/libsystemd-bus/bus-convenience.c
src/libsystemd-bus/bus-creds.c [new file with mode: 0644]
src/libsystemd-bus/bus-creds.h [new file with mode: 0644]
src/libsystemd-bus/bus-dump.c
src/libsystemd-bus/bus-dump.h
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-kernel.c
src/libsystemd-bus/bus-message.c
src/libsystemd-bus/bus-message.h
src/libsystemd-bus/bus-util.c
src/libsystemd-bus/bus-util.h
src/libsystemd-bus/busctl.c
src/libsystemd-bus/libsystemd-bus.sym
src/libsystemd-bus/sd-bus.c
src/libsystemd-bus/test-bus-chat.c
src/libsystemd-bus/test-bus-creds.c [new file with mode: 0644]
src/libsystemd-bus/test-bus-kernel.c
src/login/logind-dbus.c
src/login/logind-seat-dbus.c
src/login/logind-session-dbus.c
src/login/logind-user-dbus.c
src/machine/machine-dbus.c
src/machine/machined-dbus.c
src/shared/audit.c
src/shared/util.c
src/systemd/sd-bus.h

index f8f6c8ac3a0d03b697170db8e23357cf7edde79b..84c83a556c82fcd808e9a38bdc727f8f901d1558 100644 (file)
@@ -90,6 +90,7 @@
 /tags
 /test-boot-timestamp
 /test-bus-chat
+/test-bus-creds
 /test-bus-error
 /test-bus-introspect
 /test-bus-kernel
index 47b864cbf9b0f2f6a4b393b7e9e9e21a9a9c1580..90874dfb8efb2363bef165a74ea4eec6c4b56387 100644 (file)
@@ -769,7 +769,9 @@ libsystemd_shared_la_SOURCES = \
        src/shared/errno-list.c \
        src/shared/errno-list.h \
        src/shared/syscall-list.c \
-       src/shared/syscall-list.h
+       src/shared/syscall-list.h \
+       src/shared/audit.c \
+       src/shared/audit.h
 
 nodist_libsystemd_shared_la_SOURCES = \
        src/shared/errno-from-name.h \
@@ -842,14 +844,6 @@ libsystemd_capability_la_CFLAGS = \
 libsystemd_capability_la_LIBADD = \
        $(CAP_LIBS)
 
-# ------------------------------------------------------------------------------
-noinst_LTLIBRARIES += \
-       libsystemd-audit.la
-
-libsystemd_audit_la_SOURCES = \
-       src/shared/audit.c \
-       src/shared/audit.h
-
 # ------------------------------------------------------------------------------
 if HAVE_ACL
 noinst_LTLIBRARIES += \
@@ -1013,7 +1007,6 @@ libsystemd_core_la_LIBADD = \
        libsystemd-capability.la \
        libsystemd-units.la \
        libsystemd-label.la \
-       libsystemd-audit.la \
        libsystemd-id128-internal.la \
        libsystemd-daemon-internal.la \
        libudev-internal.la \
@@ -1957,6 +1950,8 @@ libsystemd_bus_la_SOURCES = \
        src/libsystemd-bus/bus-container.h \
        src/libsystemd-bus/bus-message.c \
        src/libsystemd-bus/bus-message.h \
+       src/libsystemd-bus/bus-creds.c \
+       src/libsystemd-bus/bus-creds.h \
        src/libsystemd-bus/bus-signature.c \
        src/libsystemd-bus/bus-signature.h \
        src/libsystemd-bus/bus-type.c \
@@ -2035,6 +2030,7 @@ tests += \
        test-bus-introspect \
        test-bus-objects \
        test-bus-error \
+       test-bus-creds \
        test-event
 
 bin_PROGRAMS += \
@@ -2119,6 +2115,17 @@ test_bus_error_LDADD = \
        libsystemd-daemon-internal.la \
        libsystemd-shared.la
 
+test_bus_creds_SOURCES = \
+       src/libsystemd-bus/test-bus-creds.c
+
+test_bus_creds_LDADD = \
+       libsystemd-bus-internal.la \
+       libsystemd-id128-internal.la \
+       libsystemd-daemon-internal.la \
+       libsystemd-shared.la \
+       libsystemd-bus-dump.la \
+       libsystemd-capability.la
+
 test_bus_match_SOURCES = \
        src/libsystemd-bus/test-bus-match.c
 
@@ -3086,7 +3093,6 @@ nodist_libsystemd_journal_core_la_SOURCES = \
 libsystemd_journal_core_la_LIBADD = \
        libsystemd-journal-internal.la \
        libudev-internal.la \
-       libsystemd-audit.la \
        libsystemd-capability.la \
        libsystemd-label.la \
        libsystemd-daemon-internal.la \
@@ -3778,7 +3784,6 @@ libsystemd_machine_core_la_SOURCES = \
 
 libsystemd_machine_core_la_LIBADD = \
        libsystemd-label.la \
-       libsystemd-audit.la \
        libsystemd-daemon-internal.la \
        libsystemd-bus-internal.la \
        libsystemd-id128-internal.la \
@@ -3933,7 +3938,6 @@ libsystemd_logind_core_la_SOURCES = \
 libsystemd_logind_core_la_LIBADD = \
        libsystemd-label.la \
        libsystemd-capability.la \
-       libsystemd-audit.la \
        libsystemd-daemon-internal.la \
        libsystemd-id128-internal.la \
        libsystemd-bus-internal.la \
@@ -4073,7 +4077,6 @@ pam_systemd_la_LDFLAGS = \
 
 pam_systemd_la_LIBADD = \
        libsystemd-capability.la \
-       libsystemd-audit.la \
        libsystemd-bus-internal.la \
        libsystemd-id128-internal.la \
        libsystemd-daemon-internal.la \
index b934624defd07d71abdbf21338bb80651d454437..8f637215713687f381bccb301901500239e42067 100644 (file)
@@ -338,7 +338,13 @@ static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *us
                 return r;
 
         if (pid == 0) {
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
                 if (r < 0)
                         return r;
         }
index d130e0974e92d30a15dc11d5a81defda8b8a9dd6..7d7c6cbddc8cf96e6101d7df11f16be8119c325a 100644 (file)
@@ -247,9 +247,14 @@ static int selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata,
         }
 
         if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 pid_t pid;
 
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                if (r < 0)
+                        return 0;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
                 if (r < 0)
                         return 0;
 
@@ -300,6 +305,7 @@ static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_
         assert(path);
 
         if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 pid_t pid;
 
@@ -307,9 +313,13 @@ static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_
                 if (!message)
                         return 0;
 
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
-                        return 0;
+                        return r;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
+                if (r < 0)
+                        return r;
 
                 u = manager_get_unit_by_pid(m, pid);
         } else {
index cca3df652ad483c2fd3b23db64cf281cc63ef057..21c7a8c5bcadd562419a70e22926dc88f347ff68 100644 (file)
 #include "audit.h"
 #include "selinux-util.h"
 #include "audit-fd.h"
+#include "strv.h"
 
 static bool initialized = false;
 
-struct auditstruct {
+struct audit_info {
+        sd_bus_creds *creds;
         const char *path;
-        char *cmdline;
-        uid_t loginuid;
-        uid_t uid;
-        gid_t gid;
+        const char *cmdline;
 };
 
-static int bus_get_selinux_security_context(
-                sd_bus *bus,
-                const char *name,
-                sd_bus_error *error,
-                char **ret) {
-
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        const void *p;
-        size_t sz;
-        char *b;
-        int r;
-
-        assert(bus);
-        assert(name);
-        assert(ret);
-
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.DBus",
-                        "/org/freedesktop/DBus",
-                        "org.freedesktop.DBus",
-                        "GetConnectionSELinuxSecurityContext",
-                        error, &m,
-                        "s", name);
-        if (r < 0)
-                return r;
-
-        r = sd_bus_message_read_array(m, 'y', &p, &sz);
-        if (r < 0)
-                return r;
-
-        b = strndup(p, sz);
-        if (!b)
-                return -ENOMEM;
-
-        *ret = b;
-        return 0;
-}
-
-static int bus_get_audit_data(
-                sd_bus *bus,
-                const char *name,
-                struct auditstruct *audit) {
-
-        pid_t pid;
-        int r;
-
-        assert(bus);
-        assert(name);
-        assert(audit);
-
-        r = sd_bus_get_owner_pid(bus, name, &pid);
-        if (r < 0)
-                return r;
-
-        r = audit_loginuid_from_pid(pid, &audit->loginuid);
-        if (r < 0)
-                return r;
-
-        r = get_process_uid(pid, &audit->uid);
-        if (r < 0)
-                return r;
-
-        r = get_process_gid(pid, &audit->gid);
-        if (r < 0)
-                return r;
-
-        r = get_process_cmdline(pid, 0, true, &audit->cmdline);
-        if (r < 0)
-                return r;
-
-        return 0;
-}
-
 /*
    Any time an access gets denied this callback will be called
    with the aduit data.  We then need to just copy the audit data into the msgbuf.
@@ -136,19 +61,19 @@ static int audit_callback(
                 char *msgbuf,
                 size_t msgbufsize) {
 
-        struct auditstruct *audit = (struct auditstruct *) auditdata;
+        const struct audit_info *audit = auditdata;
+        uid_t uid = 0, login_uid = 0;
+        gid_t gid = 0;
+
+        sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid);
+        sd_bus_creds_get_uid(audit->creds, &uid);
+        sd_bus_creds_get_gid(audit->creds, &gid);
 
         snprintf(msgbuf, msgbufsize,
                  "auid=%d uid=%d gid=%d%s%s%s%s%s%s",
-                 audit->loginuid,
-                 audit->uid,
-                 audit->gid,
-                 (audit->path ? " path=\"" : ""),
-                 strempty(audit->path),
-                 (audit->path ? "\"" : ""),
-                 (audit->cmdline ? " cmdline=\"" : ""),
-                 strempty(audit->cmdline),
-                 (audit->cmdline ? "\"" : ""));
+                 login_uid, uid, gid,
+                 audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "",
+                 audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : "");
 
         msgbuf[msgbufsize-1] = 0;
 
@@ -164,13 +89,12 @@ static int audit_callback(
 _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
         va_list ap;
 
-        va_start(ap, fmt);
-
 #ifdef HAVE_AUDIT
         if (get_audit_fd() >= 0) {
                 _cleanup_free_ char *buf = NULL;
                 int r;
 
+                va_start(ap, fmt);
                 r = vasprintf(&buf, fmt, ap);
                 va_end(ap);
 
@@ -178,10 +102,10 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
                         audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
                         return 0;
                 }
-
-                va_start(ap, fmt);
         }
 #endif
+
+        va_start(ap, fmt);
         log_metav(LOG_USER | LOG_INFO, __FILE__, __LINE__, __FUNCTION__, fmt, ap);
         va_end(ap);
 
@@ -238,76 +162,6 @@ void selinux_access_free(void) {
         initialized = false;
 }
 
-static int get_audit_data(
-                sd_bus *bus,
-                sd_bus_message *message,
-                struct auditstruct *audit) {
-
-        struct ucred ucred;
-        const char *sender;
-        socklen_t len;
-        int r, fd;
-
-        sender = sd_bus_message_get_sender(message);
-        if (sender)
-                return bus_get_audit_data(bus, sender, audit);
-
-        fd = sd_bus_get_fd(bus);
-        if (fd < 0)
-                return fd;
-
-        len = sizeof(ucred);
-        r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
-        if (r < 0)
-                return -errno;
-
-        audit->uid = ucred.uid;
-        audit->gid = ucred.gid;
-
-        r = audit_loginuid_from_pid(ucred.pid, &audit->loginuid);
-        if (r < 0)
-                return r;
-
-        r = get_process_cmdline(ucred.pid, 0, true, &audit->cmdline);
-        if (r < 0)
-                return r;
-
-        return 0;
-}
-
-/*
-   This function returns the security context of the remote end of the dbus
-   connections.  Whether it is on the bus or a local connection.
-*/
-static int get_calling_context(
-                sd_bus *bus,
-                sd_bus_message *message,
-                sd_bus_error *error,
-                security_context_t *ret) {
-
-        const char *sender;
-        int r, fd;
-
-        /*
-           If sender exists then
-           if sender is NULL this indicates a local connection.  Grab the fd
-           from dbus and do an getpeercon to peers process context
-        */
-        sender = sd_bus_message_get_sender(message);
-        if (sender)
-                return bus_get_selinux_security_context(bus, sender, error, ret);
-
-        fd = sd_bus_get_fd(bus);
-        if (fd < 0)
-                return fd;
-
-        r = getpeercon(fd, ret);
-        if (r < 0)
-                return -errno;
-
-        return 0;
-}
-
 /*
    This function communicates with the kernel to check whether or not it should
    allow the access.
@@ -321,9 +175,12 @@ int selinux_generic_access_check(
                 const char *permission,
                 sd_bus_error *error) {
 
-        security_context_t scon = NULL, fcon = NULL;
-        const char *tclass = NULL;
-        struct auditstruct audit;
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        const char *tclass = NULL, *scon = NULL;
+        struct audit_info audit_info = {};
+        _cleanup_free_ char *cl = NULL;
+        security_context_t fcon = NULL;
+        char **cmdline = NULL;
         int r = 0;
 
         assert(bus);
@@ -338,12 +195,16 @@ int selinux_generic_access_check(
         if (r < 0)
                 return r;
 
-        audit.uid = audit.loginuid = (uid_t) -1;
-        audit.gid = (gid_t) -1;
-        audit.cmdline = NULL;
-        audit.path = path;
+        r = sd_bus_query_sender_creds(
+                        message,
+                        SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|
+                        SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_AUDIT_LOGIN_UID|
+                        SD_BUS_CREDS_SELINUX_CONTEXT,
+                        &creds);
+        if (r < 0)
+                goto finish;
 
-        r = get_calling_context(bus, message, error, &scon);
+        r = sd_bus_creds_get_selinux_context(creds, &scon);
         if (r < 0)
                 goto finish;
 
@@ -367,21 +228,23 @@ int selinux_generic_access_check(
                 tclass = "system";
         }
 
-        get_audit_data(bus, message, &audit);
+        sd_bus_creds_get_cmdline(creds, &cmdline);
+        cl = strv_join(cmdline, " ");
+
+        audit_info.creds = creds;
+        audit_info.path = path;
+        audit_info.cmdline = cl;
 
-        errno = 0;
-        r = selinux_check_access(scon, fcon, tclass, permission, &audit);
+        r = selinux_check_access((security_context_t) scon, fcon, tclass, permission, &audit_info);
         if (r < 0)
                 r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
 
-        log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, audit.cmdline, r);
+        log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, cl, r);
 
 finish:
-        free(audit.cmdline);
-        freecon(scon);
         freecon(fcon);
 
-        if (r && security_getenforce() != 1) {
+        if (r < 0 && security_getenforce() != 1) {
                 sd_bus_error_free(error);
                 r = 0;
         }
index 5b41c36383e23e4f2e9668562311ddc663583b9a..cdbe4c83ee5ae2f5466fc00d588cd255a54340e3 100644 (file)
@@ -3673,11 +3673,14 @@ static void service_bus_name_owner_change(
                     s->state == SERVICE_RUNNING ||
                     s->state == SERVICE_RELOAD)) {
 
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 pid_t pid;
 
                 /* Try to acquire PID from bus service */
 
-                r = sd_bus_get_owner_pid(u->manager->api_bus, name, &pid);
+                r = sd_bus_get_owner_creds(u->manager->api_bus, name, SD_BUS_CREDS_PID, &creds);
+                if (r >= 0)
+                        r = sd_bus_creds_get_pid(creds, &pid);
                 if (r >= 0) {
                         log_debug_unit(u->id, "%s's D-Bus name %s is now owned by process %u", u->id, name, (unsigned) pid);
 
index f217269f79d29117fe5453df96a11b46ac26a952..43e2848ecc60b0e3f532445da5d7316d8025f8cb 100644 (file)
@@ -260,80 +260,114 @@ _public_ int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
         return 0;
 }
 
-_public_ int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) {
+_public_ int sd_bus_get_owner_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        uint32_t u;
+        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        pid_t pid = 0;
         int r;
 
-        if (!bus)
-                return -EINVAL;
-        if (!name)
-                return -EINVAL;
-        if (!uid)
-                return -EINVAL;
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
-        if (bus_pid_changed(bus))
-                return -ECHILD;
+        assert_return(bus, -EINVAL);
+        assert_return(name, -EINVAL);
+        assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
+        assert_return(creds, -EINVAL);
+        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
 
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.DBus",
-                        "/",
-                        "org.freedesktop.DBus",
-                        "GetConnectionUnixUser",
-                        NULL,
-                        &reply,
-                        "s",
-                        name);
-        if (r < 0)
-                return r;
+        c = bus_creds_new();
+        if (!c)
+                return -ENOMEM;
 
-        r = sd_bus_message_read(reply, "u", &u);
-        if (r < 0)
-                return r;
+        if ((mask & SD_BUS_CREDS_PID) ||
+            mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
+                uint32_t u;
 
-        *uid = (uid_t) u;
-        return 0;
-}
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.DBus",
+                                "/",
+                                "org.freedesktop.DBus",
+                                "GetConnectionUnixProcessID",
+                                NULL,
+                                &reply,
+                                "s",
+                                name);
+                if (r < 0)
+                        return r;
 
-_public_ int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        uint32_t u;
-        int r;
+                r = sd_bus_message_read(reply, "u", &u);
+                if (r < 0)
+                        return r;
 
-        if (!bus)
-                return -EINVAL;
-        if (!name)
-                return -EINVAL;
-        if (!pid)
-                return -EINVAL;
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
-        if (bus_pid_changed(bus))
-                return -ECHILD;
+                pid = u;
+                if (mask & SD_BUS_CREDS_PID) {
+                        c->pid = u;
+                        c->mask |= SD_BUS_CREDS_PID;
+                }
 
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.DBus",
-                        "/",
-                        "org.freedesktop.DBus",
-                        "GetConnectionUnixProcessID",
-                        NULL,
-                        &reply,
-                        "s",
-                        name);
-        if (r < 0)
-                return r;
+                reply = sd_bus_message_unref(reply);
+        }
+
+        if (mask & SD_BUS_CREDS_UID) {
+                uint32_t u;
+
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.DBus",
+                                "/",
+                                "org.freedesktop.DBus",
+                                "GetConnectionUnixUser",
+                                NULL,
+                                &reply,
+                                "s",
+                                name);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_read(reply, "u", &u);
+                if (r < 0)
+                        return r;
+
+                c->uid = u;
+                c->mask |= SD_BUS_CREDS_UID;
+
+                reply = sd_bus_message_unref(reply);
+        }
+
+        if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
+                const void *p;
+                size_t sz;
+
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.DBus",
+                                "/",
+                                "org.freedesktop.DBus",
+                                "GetConnectionSELinuxSecurityContext",
+                                NULL,
+                                &reply,
+                                "s",
+                                name);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_read_array(reply, 'y', &p, &sz);
+                if (r < 0)
+                        return r;
+
+                c->label = strndup(p, sz);
+                if (!c->label)
+                        return -ENOMEM;
+
+                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
+        }
 
-        r = sd_bus_message_read(reply, "u", &u);
+        r = bus_creds_add_more(c, mask, pid, 0);
         if (r < 0)
                 return r;
 
-        if (u == 0)
-                return -EIO;
+        *creds = c;
+        c = NULL;
 
-        *pid = (uid_t) u;
         return 0;
 }
 
index e765ddb21d47f925ee924cdd0481c3f1866c8eed..e57b26bf6b98e5cbb73331e369a08348b9577fe4 100644 (file)
@@ -410,3 +410,33 @@ _public_ int sd_bus_set_property(
 
         return sd_bus_call(bus, m, 0, error, NULL);
 }
+
+_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
+        sd_bus_creds *c;
+
+        assert_return(call, -EINVAL);
+        assert_return(call->sealed, -EPERM);
+        assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
+        assert_return(!bus_pid_changed(call->bus), -ECHILD);
+
+        c = sd_bus_message_get_creds(call);
+
+        /* All data we need? */
+        if (c && (mask & ~c->mask) == 0) {
+                *creds = sd_bus_creds_ref(c);
+                return 0;
+        }
+
+        /* No data passed? Or not enough data passed to retrieve the missing bits? */
+        if (!c || !(c->mask & SD_BUS_CREDS_PID)) {
+                /* We couldn't read anything from the call, let's try
+                 * to get it from the sender or peer */
+
+                if (call->sender)
+                        return sd_bus_get_owner_creds(call->bus, call->sender, mask, creds);
+                else
+                        return sd_bus_get_peer_creds(call->bus, mask, creds);
+        }
+
+        return sd_bus_creds_extend(c, mask, creds);
+}
diff --git a/src/libsystemd-bus/bus-creds.c b/src/libsystemd-bus/bus-creds.c
new file mode 100644 (file)
index 0000000..5ca70cc
--- /dev/null
@@ -0,0 +1,796 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdlib.h>
+
+#include "util.h"
+#include "cgroup-util.h"
+#include "fileio.h"
+#include "audit.h"
+#include "bus-message.h"
+#include "bus-util.h"
+#include "time-util.h"
+#include "bus-creds.h"
+
+enum {
+        CAP_OFFSET_INHERITABLE = 0,
+        CAP_OFFSET_PERMITTED = 1,
+        CAP_OFFSET_EFFECTIVE = 2,
+        CAP_OFFSET_BOUNDING = 3
+};
+
+void bus_creds_done(sd_bus_creds *c) {
+        assert(c);
+
+        /* For internal bus cred structures that are allocated by
+         * something else */
+
+        free(c->session);
+        free(c->unit);
+        free(c->user_unit);
+        free(c->slice);
+
+        free(c->cmdline_array);
+}
+
+_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
+        assert_return(c, NULL);
+
+        if (c->allocated) {
+                assert(c->n_ref > 0);
+                c->n_ref++;
+        } else {
+                sd_bus_message *m;
+
+                /* If this is an embedded creds structure, then
+                 * forward ref counting to the message */
+                m = container_of(c, sd_bus_message, creds);
+                sd_bus_message_ref(m);
+        }
+
+        return c;
+}
+
+_public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
+        assert_return(c, NULL);
+
+        if (c->allocated) {
+                assert(c->n_ref > 0);
+                c->n_ref--;
+
+                if (c->n_ref == 0) {
+                        bus_creds_done(c);
+
+                        free(c->comm);
+                        free(c->tid_comm);
+                        free(c->exe);
+                        free(c->cmdline);
+                        free(c->cgroup);
+                        free(c->capability);
+                        free(c->label);
+                        free(c);
+                }
+        } else {
+                sd_bus_message *m;
+
+                m = container_of(c, sd_bus_message, creds);
+                sd_bus_message_unref(m);
+        }
+
+
+        return NULL;
+}
+
+_public_ uint64_t sd_bus_creds_get_mask(sd_bus_creds *c) {
+        assert_return(c, 0);
+
+        return c->mask;
+}
+
+sd_bus_creds* bus_creds_new(void) {
+        sd_bus_creds *c;
+
+        c = new0(sd_bus_creds, 1);
+        if (!c)
+                return NULL;
+
+        c->allocated = true;
+        c->n_ref = 1;
+        return c;
+}
+
+_public_ int sd_bus_creds_new_from_pid(pid_t pid, uint64_t mask, sd_bus_creds **ret) {
+        sd_bus_creds *c;
+        int r;
+
+        assert_return(pid >= 0, -EINVAL);
+        assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
+        assert_return(ret, -EINVAL);
+
+        if (pid == 0)
+                pid = getpid();
+
+        c = bus_creds_new();
+        if (!c)
+                return -ENOMEM;
+
+        r = bus_creds_add_more(c, mask, pid, 0);
+        if (r < 0) {
+                free(c);
+                return r;
+        }
+
+        /* Check if the process existed at all, in case we haven't
+         * figured that out already */
+        if (kill(pid, 0) < 0 && errno == ESRCH) {
+                sd_bus_creds_unref(c);
+                return -ESRCH;
+        }
+
+        *ret = c;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
+        assert_return(c, -EINVAL);
+        assert_return(uid, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_UID, -ENODATA);
+
+        *uid = c->uid;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
+        assert_return(c, -EINVAL);
+        assert_return(gid, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_UID, -ENODATA);
+
+        *gid = c->gid;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
+        assert_return(c, -EINVAL);
+        assert_return(pid, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_PID, -ENODATA);
+
+        assert(c->pid > 0);
+        *pid = c->pid;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
+        assert_return(c, -EINVAL);
+        assert_return(tid, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_TID, -ENODATA);
+
+        assert(c->tid > 0);
+        *tid = c->tid;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_pid_starttime(sd_bus_creds *c, uint64_t *usec) {
+        assert_return(c, -EINVAL);
+        assert_return(usec, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_PID_STARTTIME, -ENODATA);
+
+        assert(c->pid_starttime > 0);
+        *usec = c->pid_starttime;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
+        assert_return(c, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT, -ENODATA);
+
+        assert(c->label);
+        *ret = c->label;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_COMM, -ENODATA);
+
+        assert(c->comm);
+        *ret = c->comm;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_TID_COMM, -ENODATA);
+
+        assert(c->tid_comm);
+        *ret = c->tid_comm;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_EXE, -ENODATA);
+
+        assert(c->exe);
+        *ret = c->exe;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_CGROUP, -ENODATA);
+
+        assert(c->cgroup);
+        *ret = c->cgroup;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
+        int r;
+
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_UNIT, -ENODATA);
+
+        assert(c->cgroup);
+
+        if (!c->unit) {
+                r = cg_path_get_unit(c->cgroup, (char**) &c->unit);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = c->unit;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
+        int r;
+
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_USER_UNIT, -ENODATA);
+
+        assert(c->cgroup);
+
+        if (!c->user_unit) {
+                r = cg_path_get_user_unit(c->cgroup, (char**) &c->user_unit);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = c->user_unit;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
+        int r;
+
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_SLICE, -ENODATA);
+
+        assert(c->cgroup);
+
+        if (!c->slice) {
+                r = cg_path_get_slice(c->cgroup, (char**) &c->slice);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = c->slice;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
+        int r;
+
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_SESSION, -ENODATA);
+
+        assert(c->cgroup);
+
+        if (!c->session) {
+                r = cg_path_get_session(c->cgroup, (char**) &c->session);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = c->session;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
+        assert_return(c, -EINVAL);
+        assert_return(uid, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_OWNER_UID, -ENODATA);
+
+        assert(c->cgroup);
+
+        return cg_path_get_owner_uid(c->cgroup, uid);
+}
+
+_public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
+        size_t n, i;
+        const char *p;
+        bool first;
+
+        assert_return(c, -EINVAL);
+        assert_return(c->cmdline, -ESRCH);
+        assert_return(c->mask & SD_BUS_CREDS_CMDLINE, -ENODATA);
+
+        assert(c->cmdline);
+
+        for (p = c->cmdline, n = 0; p < c->cmdline + c->cmdline_length; p++)
+                if (*p == 0)
+                        n++;
+
+        *(char***) &c->cmdline_array = new(char*, n + 1);
+        if (!c->cmdline_array)
+                return -ENOMEM;
+
+        for (p = c->cmdline, i = 0, first = true; p < c->cmdline + c->cmdline_length; p++) {
+                if (first)
+                        c->cmdline_array[i++] = (char*) p;
+
+                first = *p == 0;
+        }
+
+        c->cmdline_array[i] = NULL;
+        *cmdline = c->cmdline_array;
+
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
+        assert_return(c, -EINVAL);
+        assert_return(sessionid, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID, -ENODATA);
+
+        *sessionid = c->audit_session_id;
+        return 0;
+}
+
+_public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
+        assert_return(c, -EINVAL);
+        assert_return(uid, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID, -ENODATA);
+
+        *uid = c->audit_login_uid;
+        return 0;
+}
+
+static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
+        size_t sz;
+
+        assert(c);
+        assert(c->capability);
+
+        sz = c->capability_size / 4;
+        if ((size_t) capability >= sz*8)
+                return 0;
+
+        return !!(c->capability[offset * sz + (capability / 8)] & (1 << (capability % 8)));
+}
+
+_public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
+        assert_return(c, -EINVAL);
+        assert_return(capability >= 0, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS, -ENODATA);
+
+        return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
+}
+
+_public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
+        assert_return(c, -EINVAL);
+        assert_return(capability >= 0, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_PERMITTED_CAPS, -ENODATA);
+
+        return has_cap(c, CAP_OFFSET_PERMITTED, capability);
+}
+
+_public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
+        assert_return(c, -EINVAL);
+        assert_return(capability >= 0, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS, -ENODATA);
+
+        return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
+}
+
+_public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
+        assert_return(c, -EINVAL);
+        assert_return(capability >= 0, -EINVAL);
+        assert_return(c->mask & SD_BUS_CREDS_BOUNDING_CAPS, -ENODATA);
+
+        return has_cap(c, CAP_OFFSET_BOUNDING, capability);
+}
+
+static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
+        size_t sz;
+        unsigned i;
+
+        assert(c);
+        assert(p);
+
+        p += strspn(p, WHITESPACE);
+
+        sz = strlen(p);
+        if (sz % 2 != 0)
+                return -EINVAL;
+
+        sz /= 2;
+        if (!c->capability) {
+                c->capability = new0(uint8_t, sz * 4);
+                if (!c->capability)
+                        return -ENOMEM;
+
+                c->capability_size = sz * 4;
+        }
+
+        for (i = 0; i < sz; i ++) {
+                int x, y;
+
+                x = unhexchar(p[i*2]);
+                y = unhexchar(p[i*2+1]);
+
+                if (x < 0 || y < 0)
+                        return -EINVAL;
+
+                c->capability[offset * sz + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y;
+        }
+
+        return 0;
+}
+
+int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
+        uint64_t missing;
+        int r;
+
+        assert(c);
+        assert(c->allocated);
+
+        missing = mask & ~c->mask;
+        if (missing == 0)
+                return 0;
+
+        /* Try to retrieve PID from creds if it wasn't passed to us */
+        if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID))
+                pid = c->pid;
+
+        if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
+                tid = c->pid;
+
+        /* Without pid we cannot do much... */
+        if (pid <= 0)
+                return 0;
+
+        if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID |
+                       SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
+                       SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
+
+                _cleanup_fclose_ FILE *f = NULL;
+                char line[LINE_MAX];
+                const char *p;
+
+                p = procfs_file_alloca(pid, "status");
+
+                f = fopen(p, "re");
+                if (!f)
+                        return errno == ENOENT ? -ESRCH : -errno;
+
+                FOREACH_LINE(line, f, return -errno) {
+                        truncate_nl(line);
+
+                        if (missing & SD_BUS_CREDS_UID) {
+                                p = startswith(line, "Uid:");
+                                if (p) {
+                                        unsigned long uid;
+
+                                        p += strspn(p, WHITESPACE);
+                                        if (sscanf(p, "%lu", &uid) != 1)
+                                                return -EIO;
+
+                                        c->uid = (uid_t) uid;
+                                        c->mask |= SD_BUS_CREDS_UID;
+                                        continue;
+                                }
+                        }
+
+                        if (missing & SD_BUS_CREDS_GID) {
+                                p = startswith(line, "Gid:");
+                                if (p) {
+                                        unsigned long gid;
+
+                                        p += strspn(p, WHITESPACE);
+                                        if (sscanf(p, "%lu", &gid) != 1)
+                                                return -EIO;
+
+                                        c->gid = (uid_t) gid;
+                                        c->mask |= SD_BUS_CREDS_GID;
+                                        continue;
+                                }
+                        }
+
+                        if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
+                                p = startswith(line, "CapEff:");
+                                if (p) {
+                                        r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
+                                        if (r < 0)
+                                                return r;
+
+                                        c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
+                                        continue;
+                                }
+                        }
+
+                        if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
+                                p = startswith(line, "CapPrm:");
+                                if (p) {
+                                        r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
+                                        if (r < 0)
+                                                return r;
+
+                                        c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
+                                        continue;
+                                }
+                        }
+
+                        if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
+                                p = startswith(line, "CapInh:");
+                                if (p) {
+                                        r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
+                                        if (r < 0)
+                                                return r;
+
+                                        c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
+                                        continue;
+                                }
+                        }
+
+                        if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
+                                p = startswith(line, "CapBnd:");
+                                if (p) {
+                                        r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
+                                        if (r < 0)
+                                                return r;
+
+                                        c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
+                                        continue;
+                                }
+                        }
+                }
+        }
+
+        if (missing & (SD_BUS_CREDS_PID_STARTTIME)) {
+                unsigned long long st;
+
+                r = get_starttime_of_pid(pid, &st);
+                if (r < 0)
+                        return r;
+
+                c->pid_starttime = ((usec_t) st * USEC_PER_SEC) / (usec_t) sysconf(_SC_CLK_TCK);
+                c->mask |= SD_BUS_CREDS_PID_STARTTIME;
+        }
+
+        if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
+                const char *p;
+
+                p = procfs_file_alloca(pid, "attr/current");
+                r = read_one_line_file(p, &c->label);
+                if (r < 0 && r != -ENOENT)
+                        return r;
+                else if (r >= 0)
+                        c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
+        }
+
+        if (missing & SD_BUS_CREDS_COMM) {
+                r = get_process_comm(pid, &c->comm);
+                if (r < 0)
+                        return r;
+
+                c->mask |= SD_BUS_CREDS_COMM;
+        }
+
+        if (missing & SD_BUS_CREDS_EXE) {
+                r = get_process_exe(pid, &c->exe);
+                if (r < 0)
+                        return r;
+
+                c->mask |= SD_BUS_CREDS_EXE;
+        }
+
+        if (missing & SD_BUS_CREDS_CMDLINE) {
+                const char *p;
+
+                p = procfs_file_alloca(pid, "cmdline");
+                r = read_full_file(p, &c->cmdline, &c->cmdline_length);
+                if (r < 0)
+                        return r;
+
+                if (c->cmdline_length == 0) {
+                        free(c->cmdline);
+                        c->cmdline = NULL;
+                } else
+                        c->mask |= SD_BUS_CREDS_CMDLINE;
+        }
+
+        if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
+                _cleanup_free_ char *p = NULL;
+
+                if (asprintf(&p, "/proc/%lu/task/%lu/comm", (unsigned long) pid, (unsigned long) tid) < 0)
+                        return -ENOMEM;
+
+                r = read_one_line_file(p, &c->tid_comm);
+                if (r < 0)
+                        return r == -ENOENT ? -ESRCH : r;
+
+                c->mask |= SD_BUS_CREDS_TID_COMM;
+        }
+
+        if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
+
+                r = cg_pid_get_path(NULL, pid, &c->cgroup);
+                if (r < 0)
+                        return r;
+
+                c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
+        }
+
+        if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
+                r = audit_session_from_pid(pid, &c->audit_session_id);
+                if (r < 0 && r != -ENOTSUP && r != -ENXIO && r != ENOENT)
+                        return r;
+                else if (r >= 0)
+                        c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
+        }
+
+        if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
+                r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
+                if (r < 0 && r != -ENOTSUP && r != -ENXIO && r != ENOENT)
+                        return r;
+                else if (r >= 0)
+                        c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
+        }
+
+        return 0;
+}
+
+_public_ int sd_bus_creds_extend(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
+        int r;
+
+        assert_return(c, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        if ((mask & ~c->mask) == 0) {
+                /* There's already all data we need. */
+
+                *ret = sd_bus_creds_ref(c);
+                return 0;
+        }
+
+        n = bus_creds_new();
+        if (!n)
+                return -ENOMEM;
+
+        /* Copy the original data over */
+
+        if (c->mask & mask & SD_BUS_CREDS_UID) {
+                n->uid = c->uid;
+                n->mask |= SD_BUS_CREDS_UID;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_GID) {
+                n->gid = c->gid;
+                n->mask |= SD_BUS_CREDS_GID;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_PID) {
+                n->pid = c->pid;
+                n->mask |= SD_BUS_CREDS_PID;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_TID) {
+                n->tid = c->tid;
+                n->mask |= SD_BUS_CREDS_TID;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_PID_STARTTIME) {
+                n->pid_starttime = c->pid_starttime;
+                n->mask |= SD_BUS_CREDS_PID_STARTTIME;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_COMM) {
+                n->comm = strdup(c->comm);
+                if (!n->comm)
+                        return -ENOMEM;
+
+                n->mask |= SD_BUS_CREDS_COMM;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
+                n->tid_comm = strdup(c->tid_comm);
+                if (!n->tid_comm)
+                        return -ENOMEM;
+
+                n->mask |= SD_BUS_CREDS_TID_COMM;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_EXE) {
+                n->exe = strdup(c->exe);
+                if (!n->exe)
+                        return -ENOMEM;
+
+                n->mask |= SD_BUS_CREDS_EXE;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
+                n->cmdline = memdup(c->cmdline, c->cmdline_length);
+                if (!n->cmdline)
+                        return -ENOMEM;
+
+                n->cmdline_length = c->cmdline_length;
+                n->mask |= SD_BUS_CREDS_CMDLINE;
+        }
+
+        if (c->mask & mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_OWNER_UID)) {
+                n->cgroup = strdup(c->cgroup);
+                if (!n->cgroup)
+                        return -ENOMEM;
+
+                n->mask |= mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_OWNER_UID);
+        }
+
+        if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
+                n->capability = memdup(c->capability, c->capability_size);
+                if (!n->capability)
+                        return -ENOMEM;
+
+                n->capability_size = c->capability_size;
+                n->mask |= c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS);
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
+                n->audit_session_id = c->audit_session_id;
+                n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
+        }
+
+        if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
+                n->audit_login_uid = c->audit_login_uid;
+                n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
+        }
+
+        /* Get more data */
+
+        r = bus_creds_add_more(n, mask,
+                               c->mask & SD_BUS_CREDS_PID ? c->pid : 0,
+                               c->mask & SD_BUS_CREDS_TID ? c->tid : 0);
+        if (r < 0)
+                return r;
+
+        *ret = n;
+        n = NULL;
+        return 0;
+}
diff --git a/src/libsystemd-bus/bus-creds.h b/src/libsystemd-bus/bus-creds.h
new file mode 100644 (file)
index 0000000..e2416aa
--- /dev/null
@@ -0,0 +1,67 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+
+#include "sd-bus.h"
+#include "time-util.h"
+
+struct sd_bus_creds {
+        bool allocated;
+        unsigned n_ref;
+        uint64_t mask;
+
+        uid_t uid;
+        gid_t gid;
+        pid_t pid;
+        usec_t pid_starttime;
+        pid_t tid;
+
+        char *comm;
+        char *tid_comm;
+        char *exe;
+
+        char *cmdline;
+        size_t cmdline_length;
+        char **cmdline_array;
+
+        char *cgroup;
+        char *session;
+        char *unit;
+        char *user_unit;
+        char *slice;
+
+        uint8_t *capability;
+        size_t capability_size;
+
+        uint32_t audit_session_id;
+        uid_t audit_login_uid;
+
+        char *label;
+};
+
+sd_bus_creds* bus_creds_new(void);
+
+void bus_creds_done(sd_bus_creds *c);
+
+int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid);
index 8231cfabcd64220b145fd3fa0b80bf77cf2e9bd5..9545e181d8d1bab2af3b9b10d6c67f482a0d4ef5 100644 (file)
@@ -24,6 +24,7 @@
 #include "util.h"
 #include "capability.h"
 #include "strv.h"
+#include "audit.h"
 
 #include "bus-message.h"
 #include "bus-internal.h"
@@ -45,13 +46,8 @@ static char *indent(unsigned level) {
 }
 
 int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
-        const char *u = NULL, *uu = NULL, *s = NULL;
-        char **cmdline = NULL;
         unsigned level = 1;
         int r;
-        uid_t owner, audit_loginuid;
-        uint32_t audit_sessionid;
-        bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
 
         assert(m);
 
@@ -96,23 +92,6 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
                                 ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
                                 ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
 
-                if (m->pid != 0)
-                        fprintf(f, "  PID=%lu", (unsigned long) m->pid);
-                if (m->pid_starttime != 0)
-                        fprintf(f, "  PIDStartTime=%llu", (unsigned long long) m->pid_starttime);
-                if (m->tid != 0)
-                        fprintf(f, "  TID=%lu", (unsigned long) m->tid);
-                if (m->uid_valid)
-                        fprintf(f, "  UID=%lu", (unsigned long) m->uid);
-                r = sd_bus_message_get_owner_uid(m, &owner);
-                if (r >= 0)
-                        fprintf(f, "  OwnerUID=%lu", (unsigned long) owner);
-                if (m->gid_valid)
-                        fprintf(f, "  GID=%lu", (unsigned long) m->gid);
-
-                if (m->pid != 0 || m->pid_starttime != 0 || m->tid != 0 || m->uid_valid || r >= 0 || m->gid_valid)
-                        fputs("\n", f);
-
                 if (m->monotonic != 0)
                         fprintf(f, "  Monotonic=%llu", (unsigned long long) m->monotonic);
                 if (m->realtime != 0)
@@ -121,70 +100,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
                 if (m->monotonic != 0 || m->realtime != 0)
                         fputs("\n", f);
 
-                if (m->exe)
-                        fprintf(f, "  Exe=%s", m->exe);
-                if (m->comm)
-                        fprintf(f, "  Comm=%s", m->comm);
-                if (m->tid_comm)
-                        fprintf(f, "  TIDComm=%s", m->tid_comm);
-                if (m->label)
-                        fprintf(f, "  Label=%s", m->label);
-
-                if (m->exe || m->comm || m->tid_comm || m->label)
-                        fputs("\n", f);
-
-                if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
-                        char **c;
-
-                        fputs("  CommandLine=[", f);
-                        STRV_FOREACH(c, cmdline) {
-                                if (c != cmdline)
-                                        fputc(' ', f);
-
-                                fputs(*c, f);
-                        }
-
-                        fputs("]\n", f);
-                }
-
-                if (m->cgroup)
-                        fprintf(f, "  CGroup=%s\n", m->cgroup);
-
-                sd_bus_message_get_unit(m, &u);
-                if (u)
-                        fprintf(f, "  Unit=%s", u);
-                sd_bus_message_get_user_unit(m, &uu);
-                if (uu)
-                        fprintf(f, "  UserUnit=%s", uu);
-                sd_bus_message_get_session(m, &s);
-                if (s)
-                        fprintf(f, "  Session=%s", s);
-                if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0) {
-                        audit_loginuid_is_set = true;
-                        fprintf(f, "  AuditLoginUID=%lu", (unsigned long) audit_loginuid);
-                }
-                if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0) {
-                        audit_sessionid_is_set = true;
-                        fprintf(f, "  AuditSessionID=%lu", (unsigned long) audit_sessionid);
-                }
-
-                if (u || uu || s || audit_loginuid_is_set || audit_sessionid_is_set)
-                        fputs("\n", f);
-
-                r = sd_bus_message_has_effective_cap(m, 0);
-                if (r >= 0) {
-                        unsigned long c, last_cap;
-
-                        fprintf(f, "  Capabilities=%s", r ? cap_to_name(0) : "");
-
-                        last_cap = cap_last_cap();
-                        for (c = 0; c < last_cap; c++) {
-                                r = sd_bus_message_has_effective_cap(m, c);
-                                if (r > 0)
-                                        fprintf(f, "|%s", cap_to_name(c));
-                        }
-                        fputs("\n", f);
-                }
+                bus_creds_dump(&m->creds, f);
         }
 
         r = sd_bus_message_rewind(m, true);
@@ -333,3 +249,142 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
         fprintf(f, "  };\n\n");
         return 0;
 }
+
+static void dump_capabilities(
+                sd_bus_creds *c,
+                FILE *f,
+                const char *name,
+                int (*has)(sd_bus_creds *c, int capability)) {
+
+        unsigned long i, last_cap;
+        unsigned n = 0;
+        int r;
+
+        assert(c);
+        assert(f);
+        assert(name);
+        assert(has);
+
+        i = 0;
+        r = has(c, i);
+        if (r < 0)
+                return;
+
+        fprintf(f, "  %s=", name);
+        last_cap = cap_last_cap();
+
+        for (;;) {
+                if (r > 0) {
+                        if (n > 0)
+                                fputc(' ', f);
+                        if (n % 4 == 3)
+                                fputs("\n          ", f);
+
+                        fputs(cap_to_name(i), f);
+                        n++;
+                }
+
+                i++;
+
+                if (i > last_cap)
+                        break;
+
+                r = has(c, i);
+        }
+
+        fputs("\n", f);
+}
+
+int bus_creds_dump(sd_bus_creds *c, FILE *f) {
+        bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
+        const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
+        uid_t owner, audit_loginuid;
+        uint32_t audit_sessionid;
+        char **cmdline = NULL;
+        int r;
+
+        assert(c);
+
+        if (!f)
+                f = stdout;
+
+        if (c->mask & SD_BUS_CREDS_PID)
+                fprintf(f, "  PID=%lu", (unsigned long) c->pid);
+        if (c->mask & SD_BUS_CREDS_PID_STARTTIME)
+                fprintf(f, "  PIDStartTime=%llu", (unsigned long long) c->pid_starttime);
+        if (c->mask & SD_BUS_CREDS_TID)
+                fprintf(f, "  TID=%lu", (unsigned long) c->tid);
+        if (c->mask & SD_BUS_CREDS_UID)
+                fprintf(f, "  UID=%lu", (unsigned long) c->uid);
+        r = sd_bus_creds_get_owner_uid(c, &owner);
+        if (r >= 0)
+                fprintf(f, "  OwnerUID=%lu", (unsigned long) owner);
+        if (c->mask & SD_BUS_CREDS_GID)
+                fprintf(f, "  GID=%lu", (unsigned long) c->gid);
+
+        if ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID)) || r >= 0)
+                fputs("\n", f);
+
+        if (c->mask & SD_BUS_CREDS_EXE)
+                fprintf(f, "  Exe=%s", c->exe);
+        if (c->mask & SD_BUS_CREDS_COMM)
+                fprintf(f, "  Comm=%s", c->comm);
+        if (c->mask & SD_BUS_CREDS_TID_COMM)
+                fprintf(f, "  TIDComm=%s", c->tid_comm);
+        if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
+                fprintf(f, "  Label=%s", c->label);
+
+        if (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_SELINUX_CONTEXT))
+                fputs("\n", f);
+
+        if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
+                char **i;
+
+                fputs("  CommandLine=", f);
+                STRV_FOREACH(i, cmdline) {
+                        if (i != cmdline)
+                                fputc(' ', f);
+
+                        fputs(*i, f);
+                }
+
+                fputs("\n", f);
+        }
+
+        if (c->mask & SD_BUS_CREDS_CGROUP)
+                fprintf(f, "  CGroup=%s", c->cgroup);
+        sd_bus_creds_get_unit(c, &u);
+        if (u)
+                fprintf(f, "  Unit=%s", u);
+        sd_bus_creds_get_user_unit(c, &uu);
+        if (uu)
+                fprintf(f, "  UserUnit=%s", uu);
+        sd_bus_creds_get_slice(c, &sl);
+        if (sl)
+                fprintf(f, "  Slice=%s", sl);
+        sd_bus_creds_get_session(c, &s);
+        if (s)
+                fprintf(f, "  Session=%s", s);
+
+        if ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s)
+                fputs("\n", f);
+
+        if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
+                audit_loginuid_is_set = true;
+                fprintf(f, "  AuditLoginUID=%lu", (unsigned long) audit_loginuid);
+        }
+        if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
+                audit_sessionid_is_set = true;
+                fprintf(f, "  AuditSessionID=%lu", (unsigned long) audit_sessionid);
+        }
+
+        if (audit_loginuid_is_set || audit_sessionid_is_set)
+                fputs("\n", f);
+
+        dump_capabilities(c, f, "EffectiveCapabilities", sd_bus_creds_has_effective_cap);
+        dump_capabilities(c, f, "PermittedCapabilities", sd_bus_creds_has_permitted_cap);
+        dump_capabilities(c, f, "InheritableCapabilities", sd_bus_creds_has_inheritable_cap);
+        dump_capabilities(c, f, "BoundingCapabilities", sd_bus_creds_has_bounding_cap);
+
+        return 0;
+}
index 51aa6aad4a2f58e3bde6b4c9b95d6473189f0475..bb1d25dc4284872cfa4bb12994fbc16c84973a39 100644 (file)
@@ -27,3 +27,5 @@
 #include "sd-bus.h"
 
 int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header);
+
+int bus_creds_dump(sd_bus_creds *c, FILE *f);
index 7a695c7b93e53667db84bc231ce8940b88e820fa..accb83849b32ae3be3005cf90f1fce3daba53cda 100644 (file)
@@ -213,6 +213,8 @@ struct sd_bus {
         struct ucred ucred;
         char label[NAME_MAX];
 
+        uint64_t creds_mask;
+
         int *fds;
         unsigned n_fds;
 
index da9474dc51e51cd04cf0065bbd98070dd1e8e185..84d84df59dab4971e98d9d3c90fe85e53000754f 100644 (file)
@@ -548,31 +548,48 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess
                         idx += d->memfd.size;
 
                 } else if (d->type == KDBUS_MSG_SRC_CREDS) {
-                        m->pid_starttime = d->creds.starttime / NSEC_PER_USEC;
-                        m->uid = d->creds.uid;
-                        m->gid = d->creds.gid;
-                        m->pid = d->creds.pid;
-                        m->tid = d->creds.tid;
-                        m->uid_valid = m->gid_valid = true;
+                        m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
+                        m->creds.uid = d->creds.uid;
+                        m->creds.gid = d->creds.gid;
+                        m->creds.pid = d->creds.pid;
+                        m->creds.tid = d->creds.tid;
+                        m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID) & bus->creds_mask;
+
                 } else if (d->type == KDBUS_MSG_TIMESTAMP) {
                         m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
                         m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
-                } else if (d->type == KDBUS_MSG_SRC_PID_COMM)
-                        m->comm = d->str;
-                else if (d->type == KDBUS_MSG_SRC_TID_COMM)
-                        m->tid_comm = d->str;
-                else if (d->type == KDBUS_MSG_SRC_EXE)
-                        m->exe = d->str;
-                else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
-                        m->cmdline = d->str;
-                        m->cmdline_length = l;
-                } else if (d->type == KDBUS_MSG_SRC_CGROUP)
-                        m->cgroup = d->str;
-                else if (d->type == KDBUS_MSG_SRC_AUDIT)
-                        m->audit = &d->audit;
-                else if (d->type == KDBUS_MSG_SRC_CAPS) {
-                        m->capability = d->data;
-                        m->capability_size = l;
+
+                } else if (d->type == KDBUS_MSG_SRC_PID_COMM) {
+                        m->creds.comm = d->str;
+                        m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
+
+                } else if (d->type == KDBUS_MSG_SRC_TID_COMM) {
+                        m->creds.tid_comm = d->str;
+                        m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
+
+                } else if (d->type == KDBUS_MSG_SRC_EXE) {
+                        m->creds.exe = d->str;
+                        m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
+
+                } else if (d->type == KDBUS_MSG_SRC_CMDLINE) {
+                        m->creds.cmdline = d->str;
+                        m->creds.cmdline_length = l;
+                        m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
+
+                } else if (d->type == KDBUS_MSG_SRC_CGROUP) {
+                        m->creds.cgroup = d->str;
+                        m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
+
+                } else if (d->type == KDBUS_MSG_SRC_AUDIT) {
+                        m->creds.audit_session_id = d->audit.sessionid;
+                        m->creds.audit_login_uid = d->audit.loginuid;
+                        m->creds.mask |= (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID) & bus->creds_mask;
+
+                } else if (d->type == KDBUS_MSG_SRC_CAPS) {
+                        m->creds.capability = d->data;
+                        m->creds.capability_size = l;
+                        m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
+
                 } else if (d->type == KDBUS_MSG_DST_NAME)
                         destination = d->str;
                 else if (d->type != KDBUS_MSG_FDS &&
index 132426f6fdc1d4a47ab446857a904be5fbf80fe1..dd058e72c426b3c10d8ddd2b41b23688e7b22c31 100644 (file)
@@ -143,16 +143,12 @@ static void message_free(sd_bus_message *m) {
         if (m->iovec != m->iovec_fixed)
                 free(m->iovec);
 
-        free(m->cmdline_array);
-
         message_reset_containers(m);
         free(m->root_container.signature);
 
         free(m->peeked_signature);
 
-        free(m->unit);
-        free(m->user_unit);
-        free(m->session);
+        bus_creds_done(&m->creds);
         free(m);
 }
 
@@ -358,15 +354,17 @@ int bus_message_from_header(
         m->n_fds = n_fds;
 
         if (ucred) {
-                m->uid = ucred->uid;
-                m->pid = ucred->pid;
-                m->gid = ucred->gid;
-                m->uid_valid = m->gid_valid = true;
+                m->creds.uid = ucred->uid;
+                m->creds.pid = ucred->pid;
+                m->creds.gid = ucred->gid;
+                m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
         }
 
         if (label) {
-                m->label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
-                memcpy(m->label, label, label_sz + 1);
+                m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
+                memcpy(m->creds.label, label, label_sz + 1);
+
+                m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
         }
 
         if (bus)
@@ -811,63 +809,10 @@ _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
         return &m->error;
 }
 
-_public_ int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
-        assert_return(m, -EINVAL);
-        assert_return(uid, -EINVAL);
-        assert_return(m->uid_valid, -ESRCH);
-
-        *uid = m->uid;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
-        assert_return(m, -EINVAL);
-        assert_return(gid, -EINVAL);
-        assert_return(m->gid_valid, -ESRCH);
-
-        *gid = m->gid;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
-        assert_return(m, -EINVAL);
-        assert_return(pid, -EINVAL);
-        assert_return(m->pid > 0, -ESRCH);
-
-        *pid = m->pid;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
-        assert_return(m, -EINVAL);
-        assert_return(tid, -EINVAL);
-        assert_return(m->tid > 0, -ESRCH);
-
-        *tid = m->tid;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) {
-        assert_return(m, -EINVAL);
-        assert_return(usec, -EINVAL);
-        assert_return(m->pid_starttime > 0, -ESRCH);
-
-        *usec = m->pid_starttime;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) {
-        assert_return(m, -EINVAL);
-        assert_return(m->label, -ESRCH);
-
-        *ret = m->label;
-        return 0;
-}
-
 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
         assert_return(m, -EINVAL);
         assert_return(usec, -EINVAL);
-        assert_return(m->monotonic > 0, -ESRCH);
+        assert_return(m->monotonic > 0, -ENODATA);
 
         *usec = m->monotonic;
         return 0;
@@ -876,166 +821,19 @@ _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t
 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
         assert_return(m, -EINVAL);
         assert_return(usec, -EINVAL);
-        assert_return(m->realtime > 0, -ESRCH);
+        assert_return(m->realtime > 0, -ENODATA);
 
         *usec = m->realtime;
         return 0;
 }
 
-_public_ int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) {
-        assert_return(m, -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(m->comm, -ESRCH);
-
-        *ret = m->comm;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) {
-        assert_return(m, -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(m->tid_comm, -ESRCH);
-
-        *ret = m->tid_comm;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) {
-        assert_return(m, -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(m->exe, -ESRCH);
-
-        *ret = m->exe;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_cgroup(sd_bus_message *m, const char **ret) {
-        assert_return(m, -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(m->cgroup, -ESRCH);
-
-        *ret = m->cgroup;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_unit(sd_bus_message *m, const char **ret) {
-        int r;
-
-        assert_return(m, -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(m->cgroup, -ESRCH);
-
-        if (!m->unit) {
-                r = cg_path_get_unit(m->cgroup, &m->unit);
-                if (r < 0)
-                        return r;
-        }
-
-        *ret = m->unit;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_user_unit(sd_bus_message *m, const char **ret) {
-        int r;
-
-        assert_return(m, -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(m->cgroup, -ESRCH);
-
-        if (!m->user_unit) {
-                r = cg_path_get_user_unit(m->cgroup, &m->user_unit);
-                if (r < 0)
-                        return r;
-        }
-
-        *ret = m->user_unit;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_session(sd_bus_message *m, const char **ret) {
-        int r;
-
-        assert_return(m, -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(m->cgroup, -ESRCH);
-
-        if (!m->session) {
-                r = cg_path_get_session(m->cgroup, &m->session);
-                if (r < 0)
-                        return r;
-        }
-
-        *ret = m->session;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_owner_uid(sd_bus_message *m, uid_t *uid) {
-        assert_return(m, -EINVAL);
-        assert_return(uid, -EINVAL);
-        assert_return(m->cgroup, -ESRCH);
-
-        return cg_path_get_owner_uid(m->cgroup, uid);
-}
-
-_public_ int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) {
-        size_t n, i;
-        const char *p;
-        bool first;
-
-        assert_return(m, -EINVAL);
-        assert_return(m->cmdline, -ESRCH);
-
-        for (p = m->cmdline, n = 0; p < m->cmdline + m->cmdline_length; p++)
-                if (*p == 0)
-                        n++;
-
-        m->cmdline_array = new(char*, n + 1);
-        if (!m->cmdline_array)
-                return -ENOMEM;
-
-        for (p = m->cmdline, i = 0, first = true; p < m->cmdline + m->cmdline_length; p++) {
-                if (first)
-                        m->cmdline_array[i++] = (char*) p;
-
-                first = *p == 0;
-        }
-
-        m->cmdline_array[i] = NULL;
-        *cmdline = m->cmdline_array;
-
-        return 0;
-}
-
-_public_ int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid) {
-        assert_return(m, -EINVAL);
-        assert_return(sessionid, -EINVAL);
-        assert_return(m->audit, -ESRCH);
-
-        *sessionid = m->audit->sessionid;
-        return 0;
-}
-
-_public_ int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *uid) {
-        assert_return(m, -EINVAL);
-        assert_return(uid, -EINVAL);
-        assert_return(m->audit, -ESRCH);
-
-        *uid = m->audit->loginuid;
-        return 0;
-}
-
-_public_ int sd_bus_message_has_effective_cap(sd_bus_message *m, int capability) {
-        unsigned sz;
-
-        assert_return(m, -EINVAL);
-        assert_return(capability < 0, -EINVAL);
-        assert_return(!m->capability, -ESRCH);
+_public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
+        assert_return(m, NULL);
 
-        sz = m->capability_size / 4;
-        if ((unsigned) capability >= sz*8)
-                return 0;
+        if (m->creds.mask == 0)
+                return NULL;
 
-        return !!(m->capability[2 * sz + (capability / 8)] & (1 << (capability % 8)));
+        return &m->creds;
 }
 
 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
index 8c0ba862135500277ea9d9bb8035c53455323d5a..72a79f792b4276b568e316187f5f750cf4151785 100644 (file)
@@ -29,6 +29,7 @@
 #include "sd-bus.h"
 #include "kdbus.h"
 #include "time-util.h"
+#include "bus-creds.h"
 
 struct bus_container {
         char enclosing;
@@ -78,19 +79,14 @@ struct sd_bus_message {
 
         sd_bus_error error;
 
-        uid_t uid;
-        gid_t gid;
-        pid_t pid;
-        pid_t tid;
-        usec_t pid_starttime;
+        sd_bus_creds creds;
+
         usec_t monotonic;
         usec_t realtime;
 
         bool sealed:1;
         bool dont_send:1;
         bool allow_fds:1;
-        bool uid_valid:1;
-        bool gid_valid:1;
         bool free_header:1;
         bool free_kdbus:1;
         bool free_fds:1;
@@ -102,8 +98,6 @@ struct sd_bus_message {
         struct bus_body_part *body_end;
         unsigned n_body_parts;
 
-        char *label;
-
         size_t rindex;
         struct bus_body_part *cached_rindex_part;
         size_t cached_rindex_part_begin;
@@ -126,24 +120,6 @@ struct sd_bus_message {
 
         char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
         char destination_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
-
-        const char *exe;
-        const char *comm;
-        const char *tid_comm;
-        const char *cgroup;
-
-        const char *cmdline;
-        size_t cmdline_length;
-        char **cmdline_array;
-
-        char *session;
-        char *unit;
-        char *user_unit;
-
-        struct kdbus_audit *audit;
-
-        uint8_t *capability;
-        size_t capability_size;
 };
 
 #define BUS_MESSAGE_NEED_BSWAP(m) ((m)->header->endian != SD_BUS_NATIVE_ENDIAN)
index 7a2197509254500f007b37eda785a49d69afd18d..5069aaaaba87c809d838a5a1721639181e313fe5 100644 (file)
@@ -20,6 +20,7 @@
 ***/
 
 #include <sys/socket.h>
+#include <sys/capability.h>
 
 #include "util.h"
 #include "strv.h"
@@ -137,7 +138,7 @@ int bus_verify_polkit(
                 bool *_challenge,
                 sd_bus_error *e) {
 
-        const char *sender;
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         uid_t uid;
         int r;
 
@@ -145,11 +146,11 @@ int bus_verify_polkit(
         assert(m);
         assert(action);
 
-        sender = sd_bus_message_get_sender(m);
-        if (!sender)
-                return -EBADMSG;
+        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
+        if (r < 0)
+                return r;
 
-        r = sd_bus_get_owner_uid(bus, sender, &uid);
+        r = sd_bus_creds_get_uid(creds, &uid);
         if (r < 0)
                 return r;
 
@@ -160,6 +161,11 @@ int bus_verify_polkit(
         else {
                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
                 int authorized = false, challenge = false;
+                const char *sender;
+
+                sender = sd_bus_message_get_sender(m);
+                if (!sender)
+                        return -EBADMSG;
 
                 r = sd_bus_call_method(
                                 bus,
@@ -271,8 +277,9 @@ int bus_verify_polkit_async(
 #ifdef ENABLE_POLKIT
         _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
         AsyncPolkitQuery *q;
-#endif
         const char *sender;
+#endif
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         uid_t uid;
         int r;
 
@@ -319,17 +326,21 @@ int bus_verify_polkit_async(
         }
 #endif
 
-        sender = sd_bus_message_get_sender(m);
-        if (!sender)
-                return -EBADMSG;
+        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
+        if (r < 0)
+                return r;
 
-        r = sd_bus_get_owner_uid(bus, sender, &uid);
+        r = sd_bus_creds_get_uid(creds, &uid);
         if (r < 0)
                 return r;
 
         if (uid == 0)
                 return 1;
+
 #ifdef ENABLE_POLKIT
+        sender = sd_bus_message_get_sender(m);
+        if (!sender)
+                return -EBADMSG;
 
         r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
         if (r < 0)
index 38d468edada426e53a020281539a6af76ba6c9c8..9d4923794dbcfb08afaa50181c4e56fd21a5d03d 100644 (file)
@@ -137,9 +137,11 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref);
 
 #define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp)
 #define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp)
+#define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp)
 #define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free)
 
 #define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type)              \
index 4204adb5bc0d2f00bd412016049b8ef76fe6398c..24db48a7e62c9f7e540ec63cf7a270576204176d 100644 (file)
@@ -75,41 +75,47 @@ static int list_bus_names(sd_bus *bus, char **argv) {
                (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 20, "CONNECTION");
 
         STRV_FOREACH(i, l) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 _cleanup_free_ char *owner = NULL;
                 sd_id128_t mid;
-                pid_t pid;
-                uid_t uid;
 
                 if (arg_no_unique && (*i)[0] == ':')
                         continue;
 
                 printf("%-*s", (int) max_i, *i);
 
-                r = sd_bus_get_owner_pid(bus, *i, &pid);
+                r = sd_bus_get_owner_creds(bus, *i, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM, &creds);
                 if (r >= 0) {
-                        _cleanup_free_ char *comm = NULL;
+                        pid_t pid;
+                        uid_t uid;
 
-                        printf(" %10lu", (unsigned long) pid);
+                        r = sd_bus_creds_get_pid(creds, &pid);
+                        if (r >= 0) {
+                                const char *comm = NULL;
 
-                        get_process_comm(pid, &comm);
-                        printf(" %-15s", strna(comm));
-                } else
-                        printf("          - -              ");
+                                sd_bus_creds_get_comm(creds, &comm);
 
-                r = sd_bus_get_owner_uid(bus, *i, &uid);
-                if (r >= 0) {
-                        _cleanup_free_ char *u = NULL;
+                                printf(" %10lu %-15s", (unsigned long) pid, strna(comm));
+                        } else
+                                printf("          - -              ");
 
-                        u = uid_to_name(uid);
-                        if (!u)
-                                return log_oom();
+                        r = sd_bus_creds_get_uid(creds, &uid);
+                        if (r >= 0) {
+                                _cleanup_free_ char *u = NULL;
 
-                        if (strlen(u) > 16)
-                                u[16] = 0;
+                                u = uid_to_name(uid);
+                                if (!u)
+                                        return log_oom();
 
-                        printf(" %-16s", u);
+                                if (strlen(u) > 16)
+                                        u[16] = 0;
+
+                                printf(" %-16s", u);
+                        } else
+                                printf(" -               ");
                 } else
-                        printf(" -               ");
+                        printf("          - -               -               ");
+
 
                 r = sd_bus_get_owner(bus, *i, &owner);
                 if (r >= 0)
index 9cf06c44dde003b83276b5b3d288985b2885f29f..435c794b14047523e961b81787b6708fca33fa7d 100644 (file)
@@ -28,13 +28,6 @@ global:
         sd_bus_negotiate_fds;
         sd_bus_negotiate_attach_timestamp;
         sd_bus_negotiate_attach_creds;
-        sd_bus_negotiate_attach_comm;
-        sd_bus_negotiate_attach_exe;
-        sd_bus_negotiate_attach_cmdline;
-        sd_bus_negotiate_attach_cgroup;
-        sd_bus_negotiate_attach_caps;
-        sd_bus_negotiate_attach_selinux_context;
-        sd_bus_negotiate_attach_audit;
         sd_bus_start;
         sd_bus_close;
         sd_bus_ref;
@@ -42,6 +35,7 @@ global:
         sd_bus_is_open;
         sd_bus_can_send;
         sd_bus_get_server_id;
+        sd_bus_get_peer_creds;
         sd_bus_send;
         sd_bus_send_to;
         sd_bus_get_fd;
@@ -82,6 +76,7 @@ global:
         sd_bus_message_new_method_errnof;
         sd_bus_message_ref;
         sd_bus_message_unref;
+        sd_bus_message_get_bus;
         sd_bus_message_get_type;
         sd_bus_message_get_serial;
         sd_bus_message_get_reply_serial;
@@ -95,27 +90,9 @@ global:
         sd_bus_message_get_sender;
         sd_bus_message_get_error;
         sd_bus_message_get_errno;
-        sd_bus_message_get_bus;
         sd_bus_message_get_monotonic_timestamp;
         sd_bus_message_get_realtime_timestamp;
-        sd_bus_message_get_uid;
-        sd_bus_message_get_gid;
-        sd_bus_message_get_pid;
-        sd_bus_message_get_tid;
-        sd_bus_message_get_pid_starttime;
-        sd_bus_message_get_selinux_context;
-        sd_bus_message_get_comm;
-        sd_bus_message_get_tid_comm;
-        sd_bus_message_get_exe;
-        sd_bus_message_get_cgroup;
-        sd_bus_message_get_cmdline;
-        sd_bus_message_get_unit;
-        sd_bus_message_get_user_unit;
-        sd_bus_message_get_session;
-        sd_bus_message_get_owner_uid;
-        sd_bus_message_get_audit_sessionid;
-        sd_bus_message_get_audit_loginuid;
-        sd_bus_message_has_effective_cap;
+        sd_bus_message_get_creds;
         sd_bus_message_is_signal;
         sd_bus_message_is_method_call;
         sd_bus_message_is_method_error;
@@ -147,6 +124,15 @@ global:
         sd_bus_message_at_end;
         sd_bus_message_rewind;
 
+        /* Bus management */
+        sd_bus_get_unique_name;
+        sd_bus_request_name;
+        sd_bus_release_name;
+        sd_bus_list_names;
+        sd_bus_get_owner;
+        sd_bus_get_owner_creds;
+        sd_bus_get_owner_machine_id;
+
         /* Convenience calls */
         sd_bus_call_method;
         sd_bus_get_property;
@@ -166,16 +152,36 @@ global:
         sd_bus_emit_interfaces_added;
         sd_bus_emit_interfaces_removed_strv;
         sd_bus_emit_interfaces_removed;
+        sd_bus_query_sender_creds;
 
-        /* Bus management */
-        sd_bus_get_unique_name;
-        sd_bus_request_name;
-        sd_bus_release_name;
-        sd_bus_list_names;
-        sd_bus_get_owner;
-        sd_bus_get_owner_uid;
-        sd_bus_get_owner_pid;
-        sd_bus_get_owner_machine_id;
+        /* Credentials */
+        sd_bus_creds_new_from_pid;
+        sd_bus_creds_ref;
+        sd_bus_creds_unref;
+        sd_bus_creds_extend;
+        sd_bus_creds_get_mask;
+        sd_bus_creds_get_uid;
+        sd_bus_creds_get_gid;
+        sd_bus_creds_get_pid;
+        sd_bus_creds_get_pid_starttime;
+        sd_bus_creds_get_tid;
+        sd_bus_creds_get_comm;
+        sd_bus_creds_get_tid_comm;
+        sd_bus_creds_get_exe;
+        sd_bus_creds_get_cmdline;
+        sd_bus_creds_get_cgroup;
+        sd_bus_creds_get_unit;
+        sd_bus_creds_get_user_unit;
+        sd_bus_creds_get_slice;
+        sd_bus_creds_get_session;
+        sd_bus_creds_get_owner_uid;
+        sd_bus_creds_has_effective_cap;
+        sd_bus_creds_has_permitted_cap;
+        sd_bus_creds_has_inheritable_cap;
+        sd_bus_creds_has_bounding_cap;
+        sd_bus_creds_get_selinux_context;
+        sd_bus_creds_get_audit_session_id;
+        sd_bus_creds_get_audit_login_uid;
 
         /* Error structures */
         sd_bus_error_free;
index 49a2abc73b8182f1c17ca6169ade10abcb87f6b2..97a8c683bb04decf169c86648f700e13900df416 100644 (file)
@@ -283,75 +283,38 @@ _public_ int sd_bus_negotiate_attach_timestamp(sd_bus *bus, int b) {
         return 0;
 }
 
-_public_ int sd_bus_negotiate_attach_creds(sd_bus *bus, int b) {
+_public_ int sd_bus_negotiate_attach_creds(sd_bus *bus, uint64_t mask) {
         assert_return(bus, -EINVAL);
+        assert_return(mask <= _SD_BUS_CREDS_MAX, -EINVAL);
         assert_return(bus->state == BUS_UNSET, -EPERM);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
-        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CREDS, b);
-        return 0;
-}
+        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CREDS,
+                 !!(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID)));
 
-_public_ int sd_bus_negotiate_attach_comm(sd_bus *bus, int b) {
-        assert_return(bus, -EINVAL);
-        assert_return(bus->state == BUS_UNSET, -EPERM);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_COMM,
+                 !!(mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)));
 
-        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_COMM, b);
-        return 0;
-}
+        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_EXE,
+                 !!(mask & SD_BUS_CREDS_EXE));
 
-_public_ int sd_bus_negotiate_attach_exe(sd_bus *bus, int b) {
-        assert_return(bus, -EINVAL);
-        assert_return(bus->state == BUS_UNSET, -EPERM);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CMDLINE,
+                 !!(mask & SD_BUS_CREDS_CMDLINE));
 
-        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_EXE, b);
-        return 0;
-}
+        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP,
+                 !!(mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)));
 
-_public_ int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b) {
-        assert_return(bus, -EINVAL);
-        assert_return(bus->state == BUS_UNSET, -EPERM);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CAPS,
+                 !!(mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)));
 
-        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CMDLINE, b);
-        return 0;
-}
+        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_SECLABEL,
+                 !!(mask & SD_BUS_CREDS_SELINUX_CONTEXT));
 
-_public_ int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b) {
-        assert_return(bus, -EINVAL);
-        assert_return(bus->state == BUS_UNSET, -EPERM);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP, b);
-        return 0;
-}
-
-_public_ int sd_bus_negotiate_attach_caps(sd_bus *bus, int b) {
-        assert_return(bus, -EINVAL);
-        assert_return(bus->state == BUS_UNSET, -EPERM);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CAPS, b);
-        return 0;
-}
+        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_AUDIT,
+                 !!(mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
 
-_public_ int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b) {
-        assert_return(bus, -EINVAL);
-        assert_return(bus->state == BUS_UNSET, -EPERM);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        bus->creds_mask = mask;
 
-        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_SECLABEL, b);
-        return 0;
-}
-
-_public_ int sd_bus_negotiate_attach_audit(sd_bus *bus, int b) {
-        assert_return(bus, -EINVAL);
-        assert_return(bus->state == BUS_UNSET, -EPERM);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_AUDIT, b);
         return 0;
 }
 
@@ -2812,3 +2775,48 @@ _public_ char *sd_bus_label_unescape(const char *f) {
 
         return r;
 }
+
+_public_ int sd_bus_get_peer_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
+        sd_bus_creds *c;
+        pid_t pid = 0;
+        int r;
+
+        assert_return(bus, -EINVAL);
+        assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
+        assert_return(ret, -EINVAL);
+        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
+        assert_return(!bus->is_kernel, -ENOTSUP);
+
+        if (!bus->ucred_valid && !isempty(bus->label))
+                return -ENODATA;
+
+        c = bus_creds_new();
+        if (!c)
+                return -ENOMEM;
+
+        if (bus->ucred_valid) {
+                pid = c->pid = bus->ucred.pid;
+                c->uid = bus->ucred.uid;
+                c->gid = bus->ucred.gid;
+
+                c->mask |= ((SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask) & bus->creds_mask;
+        }
+
+        if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
+                c->label = strdup(bus->label);
+                if (!c->label) {
+                        sd_bus_creds_unref(c);
+                        return -ENOMEM;
+                }
+
+                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT | bus->creds_mask;
+        }
+
+        r = bus_creds_add_more(c, mask, pid, 0);
+        if (r < 0)
+                return r;
+
+        *ret = c;
+        return 0;
+}
index 66a5df9b575a8b90c53a9e7588089e8cec492e28..021379f0b0dadb54fa8842e3c36160a4ce867910 100644 (file)
@@ -158,8 +158,8 @@ static int server(sd_bus *bus) {
                 if (!m)
                         continue;
 
-                sd_bus_message_get_pid(m, &pid);
-                sd_bus_message_get_selinux_context(m, &label);
+                sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid);
+                sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label);
                 log_info("Got message! member=%s pid=%lu label=%s",
                          strna(sd_bus_message_get_member(m)),
                          (unsigned long) pid,
diff --git a/src/libsystemd-bus/test-bus-creds.c b/src/libsystemd-bus/test-bus-creds.c
new file mode 100644 (file)
index 0000000..0a9b2ca
--- /dev/null
@@ -0,0 +1,46 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "sd-bus.h"
+#include "bus-dump.h"
+#include "bus-util.h"
+#include "util.h"
+
+int main(int argc, char *argv[]) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+        int r;
+
+        r = sd_bus_creds_new_from_pid(0, _SD_BUS_CREDS_MAX, &creds);
+        assert_se(r >= 0);
+
+        bus_creds_dump(creds, NULL);
+
+        creds = sd_bus_creds_unref(creds);
+
+        r = sd_bus_creds_new_from_pid(1, _SD_BUS_CREDS_MAX, &creds);
+        if (r != -EACCES) {
+                assert_se(r >= 0);
+                putchar('\n');
+                bus_creds_dump(creds, NULL);
+        }
+
+        return 0;
+}
index 44d2fa7247fa1b9f6df8934dffaec9ae19dc3f64..f970ca5ca4b5f10bcb9746974608824ecdb59672 100644 (file)
@@ -63,24 +63,10 @@ int main(int argc, char *argv[]) {
         assert_se(r >= 0);
 
         assert_se(sd_bus_negotiate_attach_timestamp(a, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_creds(a, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_comm(a, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_exe(a, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_cmdline(a, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_cgroup(a, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_caps(a, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_selinux_context(a, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_audit(a, 1) >= 0);
+        assert_se(sd_bus_negotiate_attach_creds(a, _SD_BUS_CREDS_MAX) >= 0);
 
         assert_se(sd_bus_negotiate_attach_timestamp(b, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_creds(b, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_comm(b, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_exe(b, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_cmdline(b, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_cgroup(b, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_caps(b, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_selinux_context(b, 1) >= 0);
-        assert_se(sd_bus_negotiate_attach_audit(b, 1) >= 0);
+        assert_se(sd_bus_negotiate_attach_creds(b, _SD_BUS_CREDS_MAX) >= 0);
 
         r = sd_bus_start(a);
         assert_se(r >= 0);
index a4bdf5f28cf9cc8e19e69c471f32c2c4984a48c1..0461d1877e7b2d22caa5588d6d2efa4adfbe41ce 100644 (file)
@@ -172,7 +172,13 @@ static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void
                 return r;
 
         if (pid == 0) {
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
                 if (r < 0)
                         return r;
         }
@@ -234,7 +240,13 @@ static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *us
                 return r;
 
         if (pid == 0) {
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
                 if (r < 0)
                         return r;
         }
@@ -543,9 +555,15 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
         }
 
         if (leader <= 0) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                if (r < 0)
+                        return r;
+
                 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
 
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), (pid_t*) &leader);
+                r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
                 if (r < 0)
                         return r;
         }
@@ -1424,6 +1442,7 @@ static int method_do_shutdown_or_sleep(
                 sd_bus_message_handler_t method,
                 sd_bus_error *error) {
 
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         bool multiple_sessions, blocked;
         int interactive, r;
         uid_t uid;
@@ -1455,7 +1474,11 @@ static int method_do_shutdown_or_sleep(
                         return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
         }
 
-        r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_creds_get_uid(creds, &uid);
         if (r < 0)
                 return r;
 
@@ -1579,6 +1602,7 @@ static int method_can_shutdown_or_sleep(
                 const char *sleep_verb,
                 sd_bus_error *error) {
 
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         bool multiple_sessions, challenge, blocked;
         const char *result = NULL;
         uid_t uid;
@@ -1600,7 +1624,11 @@ static int method_can_shutdown_or_sleep(
                         return sd_bus_reply_method_return(message, "s", "na");
         }
 
-        r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_creds_get_uid(creds, &uid);
         if (r < 0)
                 return r;
 
@@ -1722,6 +1750,7 @@ static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *u
 }
 
 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         const char *who, *why, *what, *mode;
         _cleanup_free_ char *id = NULL;
         _cleanup_close_ int fifo_fd = -1;
@@ -1774,11 +1803,15 @@ static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata,
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
-        r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID, &creds);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_creds_get_uid(creds, &uid);
         if (r < 0)
                 return r;
 
-        r = sd_bus_get_owner_pid(m->bus, sd_bus_message_get_sender(message), &pid);
+        r = sd_bus_creds_get_pid(creds, &pid);
         if (r < 0)
                 return r;
 
index f274c0d6396f47f804235788af7c166d79968bcd..76158e501bbabd0461232d5888b0028b3247f60c 100644 (file)
@@ -266,6 +266,7 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
         assert(m);
 
         if (streq(path, "/org/freedesktop/login1/seat/self")) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 Session *session;
                 pid_t pid;
@@ -274,9 +275,13 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
                 if (!message)
                         return 0;
 
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
-                        return 0;
+                        return r;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
+                if (r < 0)
+                        return r;
 
                 r = manager_get_session_by_pid(m, pid, &session);
                 if (r <= 0)
index bb62b26ce4bc6d80f05e7c7f2827dfb4d90d2a64..4bbe75e428cc7b5a5b8408fd96945c596cf324f0 100644 (file)
@@ -225,6 +225,7 @@ static int method_lock(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
 }
 
 static int method_set_idle_hint(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         Session *s = userdata;
         uid_t uid;
         int r, b;
@@ -237,7 +238,11 @@ static int method_set_idle_hint(sd_bus *bus, sd_bus_message *message, void *user
         if (r < 0)
                 return r;
 
-        r = sd_bus_get_owner_uid(bus, sd_bus_message_get_sender(message), &uid);
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_creds_get_uid(creds, &uid);
         if (r < 0)
                 return r;
 
@@ -283,6 +288,7 @@ static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
 }
 
 static int method_take_control(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         Session *s = userdata;
         int r, force;
         uid_t uid;
@@ -295,7 +301,11 @@ static int method_take_control(sd_bus *bus, sd_bus_message *message, void *userd
         if (r < 0)
                 return r;
 
-        r = sd_bus_get_owner_uid(bus, sd_bus_message_get_sender(message), &uid);
+        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_creds_get_uid(creds, &uid);
         if (r < 0)
                 return r;
 
@@ -477,6 +487,7 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
         assert(m);
 
         if (streq(path, "/org/freedesktop/login1/session/self")) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 pid_t pid;
 
@@ -484,9 +495,13 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
                 if (!message)
                         return 0;
 
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
-                        return 0;
+                        return r;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
+                if (r < 0)
+                        return r;
 
                 r = manager_get_session_by_pid(m, pid, &session);
                 if (r <= 0)
index 6a77e33eeae453ad3f2915ad573e5c7e7aa6551c..b034515203465e548c6da9d9c8b4a95cd75130b1 100644 (file)
@@ -247,6 +247,7 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
         assert(m);
 
         if (streq(path, "/org/freedesktop/login1/user/self")) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 pid_t pid;
 
@@ -254,9 +255,13 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
                 if (!message)
                         return 0;
 
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
-                        return 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)
index c6a794b5e838f483b1ca5cade04ef48d1ebaa814..1f24b11197c022036e19383d97682bc4e8c45335 100644 (file)
@@ -154,6 +154,7 @@ int machine_object_find(sd_bus *bus, const char *path, const char *interface, vo
         assert(m);
 
         if (streq(path, "/org/freedesktop/machine1/machine/self")) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 sd_bus_message *message;
                 pid_t pid;
 
@@ -161,9 +162,13 @@ int machine_object_find(sd_bus *bus, const char *path, const char *interface, vo
                 if (!message)
                         return 0;
 
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                 if (r < 0)
-                        return 0;
+                        return r;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
+                if (r < 0)
+                        return r;
 
                 r = manager_get_machine_by_pid(m, pid, &machine);
                 if (r <= 0)
index 34cd61d667edfc357060cbbe3901c1e11dfd9e41..726cc4cbc73c52992168190f53dd91f9fada173c 100644 (file)
@@ -102,7 +102,13 @@ static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void
                 return r;
 
         if (pid == 0) {
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_creds_get_pid(creds, &pid);
                 if (r < 0)
                         return r;
         }
@@ -216,9 +222,15 @@ static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *use
                 return r;
 
         if (leader == 0) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+
+                r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
+                if (r < 0)
+                        return r;
+
                 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
 
-                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), (pid_t*) &leader);
+                r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
                 if (r < 0)
                         return r;
         }
index 97560cc9a3f462e9461b250914baf8778af16294..9ab46408da43ff99fa099ba838e300f90aabe75d 100644 (file)
@@ -26,8 +26,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <ctype.h>
-#include <sys/prctl.h>
-#include <sys/capability.h>
 
 #include "macro.h"
 #include "audit.h"
 #include "virt.h"
 
 int audit_session_from_pid(pid_t pid, uint32_t *id) {
-        char *s;
+        _cleanup_free_ char *s = NULL;
+        const char *p;
         uint32_t u;
         int r;
 
         assert(id);
 
-        if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
-                return -ENOENT;
-
         /* Audit doesn't support containers right now */
         if (detect_container(NULL) > 0)
                 return -ENOTSUP;
 
         if (pid == 0)
-                r = read_one_line_file("/proc/self/sessionid", &s);
-        else {
-                char *p;
-
-                if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
-                        return -ENOMEM;
-
-                r = read_one_line_file(p, &s);
-                free(p);
-        }
+                p = "/proc/self/sessionid";
+        else
+                p = procfs_file_alloca(pid, "sessionid");
 
+        r = read_one_line_file(p, &s);
         if (r < 0)
                 return r;
 
         r = safe_atou32(s, &u);
-        free(s);
-
         if (r < 0)
                 return r;
 
         if (u == (uint32_t) -1 || u <= 0)
-                return -ENOENT;
+                return -ENXIO;
 
         *id = u;
         return 0;
 }
 
 int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
-        char *s;
+        _cleanup_free_ char *s = NULL;
+        const char *p;
         uid_t u;
         int r;
 
         assert(uid);
 
-        /* Only use audit login uid if we are executed with sufficient
-         * capabilities so that pam_loginuid could do its job. If we
-         * are lacking the CAP_AUDIT_CONTROL capabality we most likely
-         * are being run in a container and /proc/self/loginuid is
-         * useless since it probably contains a uid of the host
-         * system. */
-
-        if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
-                return -ENOENT;
-
         /* Audit doesn't support containers right now */
         if (detect_container(NULL) > 0)
                 return -ENOTSUP;
 
         if (pid == 0)
-                r = read_one_line_file("/proc/self/loginuid", &s);
-        else {
-                char *p;
-
-                if (asprintf(&p, "/proc/%lu/loginuid", (unsigned long) pid) < 0)
-                        return -ENOMEM;
-
-                r = read_one_line_file(p, &s);
-                free(p);
-        }
+                p = "/proc/self/loginuid";
+        else
+                p = procfs_file_alloca(pid, "loginuid");
 
+        r = read_one_line_file(p, &s);
         if (r < 0)
                 return r;
 
         r = parse_uid(s, &u);
-        free(s);
-
         if (r < 0)
                 return r;
 
         if (u == (uid_t) -1)
-                return -ENOENT;
+                return -ENXIO;
 
         *uid = (uid_t) u;
         return 0;
index 0fce2537da1c77ae225668c50bcba4290597af62..38134ae521b61963de65667dc7920dffc9d9bf32 100644 (file)
@@ -430,7 +430,7 @@ char *split_quoted(const char *c, size_t *l, char **state) {
                 *state = (char*) e;
         }
 
-        return current;
+        return (char*) current;
 }
 
 int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
@@ -497,7 +497,7 @@ int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
 
         f = fopen(p, "re");
         if (!f)
-                return -errno;
+                return errno == ENOENT ? -ESRCH : -errno;
 
         if (!fgets(line, sizeof(line), f)) {
                 if (ferror(f))
@@ -563,6 +563,7 @@ char *truncate_nl(char *s) {
 
 int get_process_comm(pid_t pid, char **name) {
         const char *p;
+        int r;
 
         assert(name);
         assert(pid >= 0);
@@ -572,7 +573,11 @@ int get_process_comm(pid_t pid, char **name) {
         else
                 p = procfs_file_alloca(pid, "comm");
 
-        return read_one_line_file(p, name);
+        r = read_one_line_file(p, name);
+        if (r == -ENOENT)
+                return -ESRCH;
+
+        return r;
 }
 
 int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
@@ -729,7 +734,7 @@ int get_process_exe(pid_t pid, char **name) {
 
         r = readlink_malloc(p, name);
         if (r < 0)
-                return r;
+                return r == -ENOENT ? -ESRCH : r;
 
         d = endswith(*name, " (deleted)");
         if (d)
index 9c001b11f4c1e153611d4716835b20994155cdea..202fdb87bec389229c93dc4b692731b9f1bfb880 100644 (file)
@@ -37,6 +37,7 @@ _SD_BEGIN_DECLARATIONS;
 
 typedef struct sd_bus sd_bus;
 typedef struct sd_bus_message sd_bus_message;
+typedef struct sd_bus_creds sd_bus_creds;
 
 typedef struct {
         const char *name;
@@ -44,6 +45,34 @@ typedef struct {
         int need_free;
 } sd_bus_error;
 
+/* Flags */
+
+enum {
+        SD_BUS_CREDS_UID              = 1ULL << 0,
+        SD_BUS_CREDS_GID              = 1ULL << 1,
+        SD_BUS_CREDS_PID              = 1ULL << 2,
+        SD_BUS_CREDS_PID_STARTTIME    = 1ULL << 3,
+        SD_BUS_CREDS_TID              = 1ULL << 4,
+        SD_BUS_CREDS_COMM             = 1ULL << 5,
+        SD_BUS_CREDS_TID_COMM         = 1ULL << 6,
+        SD_BUS_CREDS_EXE              = 1ULL << 7,
+        SD_BUS_CREDS_CMDLINE          = 1ULL << 8,
+        SD_BUS_CREDS_CGROUP           = 1ULL << 9,
+        SD_BUS_CREDS_UNIT             = 1ULL << 10,
+        SD_BUS_CREDS_USER_UNIT        = 1ULL << 11,
+        SD_BUS_CREDS_SLICE            = 1ULL << 12,
+        SD_BUS_CREDS_SESSION          = 1ULL << 13,
+        SD_BUS_CREDS_OWNER_UID        = 1ULL << 14,
+        SD_BUS_CREDS_EFFECTIVE_CAPS   = 1ULL << 15,
+        SD_BUS_CREDS_PERMITTED_CAPS   = 1ULL << 16,
+        SD_BUS_CREDS_INHERITABLE_CAPS = 1ULL << 17,
+        SD_BUS_CREDS_BOUNDING_CAPS    = 1ULL << 18,
+        SD_BUS_CREDS_SELINUX_CONTEXT  = 1ULL << 19,
+        SD_BUS_CREDS_AUDIT_SESSION_ID = 1ULL << 20,
+        SD_BUS_CREDS_AUDIT_LOGIN_UID  = 1ULL << 21,
+        _SD_BUS_CREDS_MAX             = (1ULL << 22) -1,
+};
+
 /* Callbacks */
 
 typedef int (*sd_bus_message_handler_t)(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error);
@@ -74,14 +103,7 @@ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id);
 int sd_bus_set_anonymous(sd_bus *bus, int b);
 int sd_bus_negotiate_fds(sd_bus *bus, int b);
 int sd_bus_negotiate_attach_timestamp(sd_bus *bus, int b);
-int sd_bus_negotiate_attach_creds(sd_bus *bus, int b);
-int sd_bus_negotiate_attach_comm(sd_bus *bus, int b);
-int sd_bus_negotiate_attach_exe(sd_bus *bus, int b);
-int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b);
-int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b);
-int sd_bus_negotiate_attach_caps(sd_bus *bus, int b);
-int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b);
-int sd_bus_negotiate_attach_audit(sd_bus *bus, int b);
+int sd_bus_negotiate_attach_creds(sd_bus *bus, uint64_t creds_mask);
 int sd_bus_start(sd_bus *ret);
 
 void sd_bus_close(sd_bus *bus);
@@ -92,6 +114,7 @@ sd_bus *sd_bus_unref(sd_bus *bus);
 int sd_bus_is_open(sd_bus *bus);
 int sd_bus_can_send(sd_bus *bus, char type);
 int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *peer);
+int sd_bus_get_peer_creds(sd_bus *bus, uint64_t creds_mask, sd_bus_creds **ret);
 
 int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial);
 int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *serial);
@@ -149,6 +172,8 @@ int sd_bus_message_new_method_errnof(sd_bus_message *call, sd_bus_message **m, i
 sd_bus_message* sd_bus_message_ref(sd_bus_message *m);
 sd_bus_message* sd_bus_message_unref(sd_bus_message *m);
 
+sd_bus* sd_bus_message_get_bus(sd_bus_message *m);
+
 int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type);
 int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial);
 int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial);
@@ -164,28 +189,9 @@ const char *sd_bus_message_get_sender(sd_bus_message *m);
 const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m);
 int sd_bus_message_get_errno(sd_bus_message *m);
 
-sd_bus* sd_bus_message_get_bus(sd_bus_message *m);
-
 int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec);
 int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec);
-int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid);
-int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid);
-int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid);
-int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid);
-int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec);
-int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **r);
-int sd_bus_message_get_comm(sd_bus_message *m, const char **r);
-int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **r);
-int sd_bus_message_get_exe(sd_bus_message *m, const char **r);
-int sd_bus_message_get_cgroup(sd_bus_message *m, const char **r);
-int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline);
-int sd_bus_message_get_unit(sd_bus_message *m, const char **unit);
-int sd_bus_message_get_user_unit(sd_bus_message *m, const char **unit);
-int sd_bus_message_get_session(sd_bus_message *m, const char **session);
-int sd_bus_message_get_owner_uid(sd_bus_message *m, uid_t *uid);
-int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid);
-int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *loginuid);
-int sd_bus_message_has_effective_cap(sd_bus_message *m, int capability);
+sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m); /* do not unref the result */
 
 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member);
 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member);
@@ -221,6 +227,16 @@ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *content
 int sd_bus_message_at_end(sd_bus_message *m, int complete);
 int sd_bus_message_rewind(sd_bus_message *m, int complete);
 
+/* Bus management */
+
+int sd_bus_get_unique_name(sd_bus *bus, const char **unique);
+int sd_bus_request_name(sd_bus *bus, const char *name, int flags);
+int sd_bus_release_name(sd_bus *bus, const char *name);
+int sd_bus_list_names(sd_bus *bus, char ***l);
+int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner); /* free the result! */
+int sd_bus_get_owner_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds); /* unref the result! */
+int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine);
+
 /* Convenience calls */
 
 int sd_bus_call_method(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, ...);
@@ -246,16 +262,39 @@ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *inte
 int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces);
 int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_;
 
-/* Bus management */
-
-int sd_bus_get_unique_name(sd_bus *bus, const char **unique);
-int sd_bus_request_name(sd_bus *bus, const char *name, int flags);
-int sd_bus_release_name(sd_bus *bus, const char *name);
-int sd_bus_list_names(sd_bus *bus, char ***l);
-int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner); /* free the result! */
-int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid);
-int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid);
-int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine);
+int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds);
+
+/* Credential handling */
+
+int sd_bus_creds_new_from_pid(pid_t pid, uint64_t creds_mask, sd_bus_creds **ret);
+sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c);
+sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c);
+uint64_t sd_bus_creds_get_mask(sd_bus_creds *c);
+
+int sd_bus_creds_extend(sd_bus_creds *c, uint64_t creds_mask, sd_bus_creds **ret); /* unref the result */
+
+int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid);
+int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid);
+int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid);
+int sd_bus_creds_get_pid_starttime(sd_bus_creds *c, uint64_t *usec);
+int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid);
+int sd_bus_creds_get_comm(sd_bus_creds *c, const char **r);
+int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **r);
+int sd_bus_creds_get_exe(sd_bus_creds *c, const char **r);
+int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline);
+int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **r);
+int sd_bus_creds_get_unit(sd_bus_creds *c, const char **unit);
+int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **unit);
+int sd_bus_creds_get_slice(sd_bus_creds *c, const char **slice);
+int sd_bus_creds_get_session(sd_bus_creds *c, const char **session);
+int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid);
+int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability);
+int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability);
+int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability);
+int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability);
+int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **r);
+int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid);
+int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *loginuid);
 
 /* Error structures */
 
@@ -273,6 +312,8 @@ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e);
 int sd_bus_error_is_set(const sd_bus_error *e);
 int sd_bus_error_has_name(const sd_bus_error *e, const char *name);
 
+/* Auxiliary macros */
+
 #define SD_BUS_MESSAGE_APPEND_ID128(x) 16,                              \
                 (x).bytes[0],  (x).bytes[1],  (x).bytes[2],  (x).bytes[3], \
                 (x).bytes[4],  (x).bytes[5],  (x).bytes[6],  (x).bytes[7], \
@@ -285,6 +326,8 @@ int sd_bus_error_has_name(const sd_bus_error *e, const char *name);
                 &(x).bytes[8],  &(x).bytes[9],  &(x).bytes[10], &(x).bytes[11], \
                 &(x).bytes[12], &(x).bytes[13], &(x).bytes[14], &(x).bytes[15]
 
+/* Label escaping */
+
 char *sd_bus_label_escape(const char *s);
 char *sd_bus_label_unescape(const char *f);