diff --git a/.gitignore b/.gitignore
index f8f6c8ac3a..84c83a556c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,6 +90,7 @@
/tags
/test-boot-timestamp
/test-bus-chat
+/test-bus-creds
/test-bus-error
/test-bus-introspect
/test-bus-kernel
diff --git a/Makefile.am b/Makefile.am
index 47b864cbf9..90874dfb8e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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 \
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index b934624def..8f63721571 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -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;
}
diff --git a/src/core/dbus.c b/src/core/dbus.c
index d130e0974e..7d7c6cbddc 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -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 {
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index cca3df652a..21c7a8c5bc 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -41,91 +41,16 @@
#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, " ");
- errno = 0;
- r = selinux_check_access(scon, fcon, tclass, permission, &audit);
+ audit_info.creds = creds;
+ audit_info.path = path;
+ audit_info.cmdline = cl;
+
+ 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;
}
diff --git a/src/core/service.c b/src/core/service.c
index 5b41c36383..cdbe4c83ee 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -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);
diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c
index f217269f79..43e2848ecc 100644
--- a/src/libsystemd-bus/bus-control.c
+++ b/src/libsystemd-bus/bus-control.c
@@ -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);
+ c = bus_creds_new();
+ if (!c)
+ return -ENOMEM;
+
+ if ((mask & SD_BUS_CREDS_PID) ||
+ mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
+ uint32_t u;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.DBus",
+ "/",
+ "org.freedesktop.DBus",
+ "GetConnectionUnixProcessID",
+ NULL,
+ &reply,
+ "s",
+ name);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(reply, "u", &u);
+ if (r < 0)
+ return r;
+
+ pid = u;
+ if (mask & SD_BUS_CREDS_PID) {
+ c->pid = u;
+ c->mask |= SD_BUS_CREDS_PID;
+ }
+
+ 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 = bus_creds_add_more(c, mask, pid, 0);
if (r < 0)
return r;
- r = sd_bus_message_read(reply, "u", &u);
- if (r < 0)
- return r;
+ *creds = c;
+ c = NULL;
- *uid = (uid_t) u;
- return 0;
-}
-
-_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;
-
- 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;
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/",
- "org.freedesktop.DBus",
- "GetConnectionUnixProcessID",
- NULL,
- &reply,
- "s",
- name);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(reply, "u", &u);
- if (r < 0)
- return r;
-
- if (u == 0)
- return -EIO;
-
- *pid = (uid_t) u;
return 0;
}
diff --git a/src/libsystemd-bus/bus-convenience.c b/src/libsystemd-bus/bus-convenience.c
index e765ddb21d..e57b26bf6b 100644
--- a/src/libsystemd-bus/bus-convenience.c
+++ b/src/libsystemd-bus/bus-convenience.c
@@ -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
index 0000000000..5ca70ccafa
--- /dev/null
+++ b/src/libsystemd-bus/bus-creds.c
@@ -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 .
+***/
+
+#include
+
+#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
index 0000000000..e2416aa501
--- /dev/null
+++ b/src/libsystemd-bus/bus-creds.h
@@ -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 .
+***/
+
+#include
+
+#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);
diff --git a/src/libsystemd-bus/bus-dump.c b/src/libsystemd-bus/bus-dump.c
index 8231cfabcd..9545e181d8 100644
--- a/src/libsystemd-bus/bus-dump.c
+++ b/src/libsystemd-bus/bus-dump.c
@@ -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;
+}
diff --git a/src/libsystemd-bus/bus-dump.h b/src/libsystemd-bus/bus-dump.h
index 51aa6aad4a..bb1d25dc42 100644
--- a/src/libsystemd-bus/bus-dump.h
+++ b/src/libsystemd-bus/bus-dump.h
@@ -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);
diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h
index 7a695c7b93..accb83849b 100644
--- a/src/libsystemd-bus/bus-internal.h
+++ b/src/libsystemd-bus/bus-internal.h
@@ -213,6 +213,8 @@ struct sd_bus {
struct ucred ucred;
char label[NAME_MAX];
+ uint64_t creds_mask;
+
int *fds;
unsigned n_fds;
diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c
index da9474dc51..84d84df59d 100644
--- a/src/libsystemd-bus/bus-kernel.c
+++ b/src/libsystemd-bus/bus-kernel.c
@@ -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 &&
diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c
index 132426f6fd..dd058e72c4 100644
--- a/src/libsystemd-bus/bus-message.c
+++ b/src/libsystemd-bus/bus-message.c
@@ -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);
+_public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
+ assert_return(m, NULL);
- *ret = m->comm;
- return 0;
-}
+ if (m->creds.mask == 0)
+ return NULL;
-_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);
-
- sz = m->capability_size / 4;
- if ((unsigned) capability >= sz*8)
- return 0;
-
- return !!(m->capability[2 * sz + (capability / 8)] & (1 << (capability % 8)));
+ return &m->creds;
}
_public_ int sd_bus_message_is_signal(sd_bus_message *m,
diff --git a/src/libsystemd-bus/bus-message.h b/src/libsystemd-bus/bus-message.h
index 8c0ba86213..72a79f792b 100644
--- a/src/libsystemd-bus/bus-message.h
+++ b/src/libsystemd-bus/bus-message.h
@@ -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)
diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c
index 7a21975092..5069aaaaba 100644
--- a/src/libsystemd-bus/bus-util.c
+++ b/src/libsystemd-bus/bus-util.c
@@ -20,6 +20,7 @@
***/
#include
+#include
#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)
diff --git a/src/libsystemd-bus/bus-util.h b/src/libsystemd-bus/bus-util.h
index 38d468edad..9d4923794d 100644
--- a/src/libsystemd-bus/bus-util.h
+++ b/src/libsystemd-bus/bus-util.h
@@ -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) \
diff --git a/src/libsystemd-bus/busctl.c b/src/libsystemd-bus/busctl.c
index 4204adb5bc..24db48a7e6 100644
--- a/src/libsystemd-bus/busctl.c
+++ b/src/libsystemd-bus/busctl.c
@@ -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));
+ sd_bus_creds_get_comm(creds, &comm);
+
+ printf(" %10lu %-15s", (unsigned long) pid, strna(comm));
+ } else
+ printf(" - - ");
+
+ r = sd_bus_creds_get_uid(creds, &uid);
+ if (r >= 0) {
+ _cleanup_free_ char *u = NULL;
+
+ u = uid_to_name(uid);
+ if (!u)
+ return log_oom();
+
+ if (strlen(u) > 16)
+ u[16] = 0;
+
+ printf(" %-16s", u);
+ } else
+ printf(" - ");
} else
- printf(" - - ");
+ printf(" - - - ");
- r = sd_bus_get_owner_uid(bus, *i, &uid);
- if (r >= 0) {
- _cleanup_free_ char *u = NULL;
-
- u = uid_to_name(uid);
- if (!u)
- return log_oom();
-
- if (strlen(u) > 16)
- u[16] = 0;
-
- printf(" %-16s", u);
- } else
- printf(" - ");
r = sd_bus_get_owner(bus, *i, &owner);
if (r >= 0)
diff --git a/src/libsystemd-bus/libsystemd-bus.sym b/src/libsystemd-bus/libsystemd-bus.sym
index 9cf06c44dd..435c794b14 100644
--- a/src/libsystemd-bus/libsystemd-bus.sym
+++ b/src/libsystemd-bus/libsystemd-bus.sym
@@ -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;
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index 49a2abc73b..97a8c683bb 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -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_AUDIT,
+ !!(mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
- SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP, b);
- return 0;
-}
+ bus->creds_mask = mask;
-_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;
-}
-
-_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);
-
- 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;
+}
diff --git a/src/libsystemd-bus/test-bus-chat.c b/src/libsystemd-bus/test-bus-chat.c
index 66a5df9b57..021379f0b0 100644
--- a/src/libsystemd-bus/test-bus-chat.c
+++ b/src/libsystemd-bus/test-bus-chat.c
@@ -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
index 0000000000..0a9b2ca466
--- /dev/null
+++ b/src/libsystemd-bus/test-bus-creds.c
@@ -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 .
+***/
+
+#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;
+}
diff --git a/src/libsystemd-bus/test-bus-kernel.c b/src/libsystemd-bus/test-bus-kernel.c
index 44d2fa7247..f970ca5ca4 100644
--- a/src/libsystemd-bus/test-bus-kernel.c
+++ b/src/libsystemd-bus/test-bus-kernel.c
@@ -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);
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index a4bdf5f28c..0461d1877e 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -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_get_owner_pid(m->bus, sd_bus_message_get_sender(message), &pid);
+ r = sd_bus_creds_get_uid(creds, &uid);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index f274c0d639..76158e501b 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -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)
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index bb62b26ce4..4bbe75e428 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -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)
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index 6a77e33eea..b034515203 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -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)
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index c6a794b5e8..1f24b11197 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -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)
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 34cd61d667..726cc4cbc7 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -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;
}
diff --git a/src/shared/audit.c b/src/shared/audit.c
index 97560cc9a3..9ab46408da 100644
--- a/src/shared/audit.c
+++ b/src/shared/audit.c
@@ -26,8 +26,6 @@
#include
#include
#include
-#include
-#include
#include "macro.h"
#include "audit.h"
@@ -37,91 +35,64 @@
#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;
diff --git a/src/shared/util.c b/src/shared/util.c
index 0fce2537da..38134ae521 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -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)
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 9c001b11f4..202fdb87be 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -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_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds);
-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);
+/* 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);