1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #31106 from poettering/bus-creds-pidref

sd-bus: port "sd_bus_creds" object to pidfds and use it everywhere
This commit is contained in:
Luca Boccassi 2024-01-29 19:19:17 +00:00 committed by GitHub
commit 17f3e91e81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 603 additions and 349 deletions

1
TODO
View File

@ -379,7 +379,6 @@ Features:
- actually wait for POLLIN on pidref's pidfd in service logic
- exec_spawn() + safe_fork()
- openpt_allocate_in_namespace()
- sd_bus_creds
- unit_attach_pid_to_cgroup_via_bus()
- cg_attach() requires new kernel feature

View File

@ -202,6 +202,7 @@ manpages = [
'sd_bus_creds_get_fsuid',
'sd_bus_creds_get_gid',
'sd_bus_creds_get_owner_uid',
'sd_bus_creds_get_pidfd_dup',
'sd_bus_creds_get_ppid',
'sd_bus_creds_get_selinux_context',
'sd_bus_creds_get_session',
@ -227,6 +228,7 @@ manpages = [
'3',
['sd_bus_creds_get_augmented_mask',
'sd_bus_creds_get_mask',
'sd_bus_creds_new_from_pidfd',
'sd_bus_creds_ref',
'sd_bus_creds_unref',
'sd_bus_creds_unrefp'],

View File

@ -17,6 +17,7 @@
<refnamediv>
<refname>sd_bus_creds_get_pid</refname>
<refname>sd_bus_creds_get_pidfd_dup</refname>
<refname>sd_bus_creds_get_ppid</refname>
<refname>sd_bus_creds_get_tid</refname>
<refname>sd_bus_creds_get_uid</refname>
@ -64,6 +65,12 @@
<paramdef>pid_t *<parameter>pid</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_bus_creds_get_pidfd_dup</function></funcdef>
<paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
<paramdef>int *<parameter>ret_fd</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_bus_creds_get_ppid</function></funcdef>
<paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
@ -289,11 +296,14 @@
<citerefentry><refentrytitle>sd_bus_creds_get_mask</refentrytitle><manvolnum>3</manvolnum></citerefentry>
to determine the mask of fields available.</para>
<para><function>sd_bus_creds_get_pid()</function> will retrieve
the PID (process identifier). Similarly,
<function>sd_bus_creds_get_ppid()</function> will retrieve the
parent PID. Note that PID 1 has no parent process, in which case
-ENXIO is returned.</para>
<para><function>sd_bus_creds_get_pid()</function> will retrieve the PID (process identifier). Similarly,
<function>sd_bus_creds_get_ppid()</function> will retrieve the parent PID. Note that PID 1 has no parent
process, in which case -ENXIO is returned.</para>
<para><function>sd_bus_creds_get_pidfd_dup()</function> will retrieve the PID file descriptor (pidfd),
see <citerefentry
project='man-pages'><refentrytitle>pidfd_open</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
details. The file descriptor is duplicated and thus must be closed by the caller.</para>
<para><function>sd_bus_creds_get_tid()</function> will retrieve the
TID (thread identifier).</para>
@ -543,6 +553,7 @@
<function>sd_bus_creds_get_tty()</function>, and
<function>sd_bus_creds_get_description()</function> were added in version 220.</para>
<para><function>sd_bus_creds_get_user_slice()</function> was added in version 223.</para>
<para><function>sd_bus_creds_get_pidfd_dup()</function> was added in version 256.</para>
</refsect1>
<refsect1>

View File

@ -17,6 +17,7 @@
<refnamediv>
<refname>sd_bus_creds_new_from_pid</refname>
<refname>sd_bus_creds_new_from_pidfd</refname>
<refname>sd_bus_creds_get_mask</refname>
<refname>sd_bus_creds_get_augmented_mask</refname>
<refname>sd_bus_creds_ref</refname>
@ -37,6 +38,13 @@
<paramdef>sd_bus_creds **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_bus_creds_new_from_pidfd</function></funcdef>
<paramdef>int <parameter>pidfd</parameter></paramdef>
<paramdef>uint64_t <parameter>creds_mask</parameter></paramdef>
<paramdef>sd_bus_creds **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>uint64_t <function>sd_bus_creds_get_mask</function></funcdef>
<paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
@ -98,6 +106,7 @@
<constant>SD_BUS_CREDS_UNIQUE_NAME</constant>,
<constant>SD_BUS_CREDS_WELL_KNOWN_NAMES</constant>,
<constant>SD_BUS_CREDS_DESCRIPTION</constant>,
<constant>SD_BUS_CREDS_PIDFD</constant>,
<constant>SD_BUS_CREDS_AUGMENT</constant>,
<constant>_SD_BUS_CREDS_ALL</constant>
</para>
@ -116,91 +125,65 @@
and
<citerefentry><refentrytitle>sd_bus_message_get_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>The information that will be stored is determined by
<parameter>creds_mask</parameter>. It may contain a subset of ORed
constants <constant>SD_BUS_CREDS_PID</constant>,
<constant>SD_BUS_CREDS_PPID</constant>,
<constant>SD_BUS_CREDS_TID</constant>,
<constant>SD_BUS_CREDS_UID</constant>,
<constant>SD_BUS_CREDS_EUID</constant>,
<constant>SD_BUS_CREDS_SUID</constant>,
<constant>SD_BUS_CREDS_FSUID</constant>,
<constant>SD_BUS_CREDS_GID</constant>,
<constant>SD_BUS_CREDS_EGID</constant>,
<constant>SD_BUS_CREDS_SGID</constant>,
<constant>SD_BUS_CREDS_FSGID</constant>,
<constant>SD_BUS_CREDS_SUPPLEMENTARY_GIDS</constant>,
<constant>SD_BUS_CREDS_COMM</constant>,
<constant>SD_BUS_CREDS_TID_COMM</constant>,
<constant>SD_BUS_CREDS_EXE</constant>,
<constant>SD_BUS_CREDS_CMDLINE</constant>,
<constant>SD_BUS_CREDS_CGROUP</constant>,
<constant>SD_BUS_CREDS_UNIT</constant>,
<constant>SD_BUS_CREDS_SLICE</constant>,
<constant>SD_BUS_CREDS_USER_UNIT</constant>,
<constant>SD_BUS_CREDS_USER_SLICE</constant>,
<constant>SD_BUS_CREDS_SESSION</constant>,
<constant>SD_BUS_CREDS_OWNER_UID</constant>,
<constant>SD_BUS_CREDS_EFFECTIVE_CAPS</constant>,
<constant>SD_BUS_CREDS_PERMITTED_CAPS</constant>,
<constant>SD_BUS_CREDS_INHERITABLE_CAPS</constant>,
<constant>SD_BUS_CREDS_BOUNDING_CAPS</constant>,
<constant>SD_BUS_CREDS_SELINUX_CONTEXT</constant>,
<constant>SD_BUS_CREDS_AUDIT_SESSION_ID</constant>,
<constant>SD_BUS_CREDS_AUDIT_LOGIN_UID</constant>,
<constant>SD_BUS_CREDS_TTY</constant>,
<constant>SD_BUS_CREDS_UNIQUE_NAME</constant>,
<constant>SD_BUS_CREDS_WELL_KNOWN_NAMES</constant>, and
<constant>SD_BUS_CREDS_DESCRIPTION</constant>. Use the special
value <constant>_SD_BUS_CREDS_ALL</constant> to request all
supported fields. The <constant>SD_BUS_CREDS_AUGMENT</constant>
constant may not be ORed into the mask for invocations of
<function>sd_bus_creds_new_from_pid()</function>.</para>
<para><function>sd_bus_creds_new_from_pidfd()</function> is identical to
<function>sd_bus_creds_new_from_pid()</function>, but takes a PID file descriptor rather than a numeric
PID as reference to the process. See <citerefentry
project='man-pages'><refentrytitle>pidfd_open</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para>
<para>The information that will be stored is determined by <parameter>creds_mask</parameter>. It may
contain a subset of ORed constants <constant>SD_BUS_CREDS_PID</constant>,
<constant>SD_BUS_CREDS_PPID</constant>, <constant>SD_BUS_CREDS_TID</constant>,
<constant>SD_BUS_CREDS_UID</constant>, <constant>SD_BUS_CREDS_EUID</constant>,
<constant>SD_BUS_CREDS_SUID</constant>, <constant>SD_BUS_CREDS_FSUID</constant>,
<constant>SD_BUS_CREDS_GID</constant>, <constant>SD_BUS_CREDS_EGID</constant>,
<constant>SD_BUS_CREDS_SGID</constant>, <constant>SD_BUS_CREDS_FSGID</constant>,
<constant>SD_BUS_CREDS_SUPPLEMENTARY_GIDS</constant>, <constant>SD_BUS_CREDS_COMM</constant>,
<constant>SD_BUS_CREDS_TID_COMM</constant>, <constant>SD_BUS_CREDS_EXE</constant>,
<constant>SD_BUS_CREDS_CMDLINE</constant>, <constant>SD_BUS_CREDS_CGROUP</constant>,
<constant>SD_BUS_CREDS_UNIT</constant>, <constant>SD_BUS_CREDS_SLICE</constant>,
<constant>SD_BUS_CREDS_USER_UNIT</constant>, <constant>SD_BUS_CREDS_USER_SLICE</constant>,
<constant>SD_BUS_CREDS_SESSION</constant>, <constant>SD_BUS_CREDS_OWNER_UID</constant>,
<constant>SD_BUS_CREDS_EFFECTIVE_CAPS</constant>, <constant>SD_BUS_CREDS_PERMITTED_CAPS</constant>,
<constant>SD_BUS_CREDS_INHERITABLE_CAPS</constant>, <constant>SD_BUS_CREDS_BOUNDING_CAPS</constant>,
<constant>SD_BUS_CREDS_SELINUX_CONTEXT</constant>, <constant>SD_BUS_CREDS_AUDIT_SESSION_ID</constant>,
<constant>SD_BUS_CREDS_AUDIT_LOGIN_UID</constant>, <constant>SD_BUS_CREDS_TTY</constant>,
<constant>SD_BUS_CREDS_UNIQUE_NAME</constant>, <constant>SD_BUS_CREDS_WELL_KNOWN_NAMES</constant>,
<constant>SD_BUS_CREDS_DESCRIPTION</constant>, and <constant>SD_BUS_CREDS_PIDFD</constant>. Use the
special value <constant>_SD_BUS_CREDS_ALL</constant> to request all supported fields. The
<constant>SD_BUS_CREDS_AUGMENT</constant> constant may not be ORed into the mask for invocations of
<function>sd_bus_creds_new_from_pid()</function> or
<function>sd_bus_creds_new_from_pidfd()</function>.</para>
<para>Fields can be retrieved from the credentials object using
<citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and other functions which correspond directly to the constants
listed above.</para>
<para>A mask of fields which were actually successfully retrieved
can be retrieved with
<function>sd_bus_creds_get_mask()</function>. If the credentials
object was created with
<function>sd_bus_creds_new_from_pid()</function>, this will be a
subset of fields requested in <parameter>creds_mask</parameter>.
<para>A mask of fields which were actually successfully retrieved can be retrieved with
<function>sd_bus_creds_get_mask()</function>. If the credentials object was created with
<function>sd_bus_creds_new_from_pid()</function> or <function>sd_bus_creds_new_from_pidfd()</function>,
this will be a subset of fields requested in <parameter>creds_mask</parameter>.
</para>
<para>Similar to <function>sd_bus_creds_get_mask()</function>, the
function <function>sd_bus_creds_get_augmented_mask()</function>
returns a bitmask of field constants. The mask indicates which
credential fields have been retrieved in a non-atomic fashion. For
credential objects created via
<function>sd_bus_creds_new_from_pid()</function>, this mask will be
identical to the mask returned by
<function>sd_bus_creds_get_mask()</function>. However, for
credential objects retrieved via
<function>sd_bus_get_name_creds()</function>, this mask will be set
for the credential fields that could not be determined atomically
at peer connection time, and which were later added by reading
augmenting credential data from
<filename>/proc/</filename>. Similarly, for credential objects
retrieved via <function>sd_bus_get_owner_creds()</function>, the
mask is set for the fields that could not be determined atomically
at bus creation time, but have been augmented. Similarly, for
credential objects retrieved via
<function>sd_bus_message_get_creds()</function>, the mask is set
for the fields that could not be determined atomically at message
sending time, but have been augmented. The mask returned by
<function>sd_bus_creds_get_augmented_mask()</function> is always a
subset of (or identical to) the mask returned by
<function>sd_bus_creds_get_mask()</function> for the same
object. The latter call hence returns all credential fields
available in the credential object, the former then marks the
subset of those that have been augmented. Note that augmented
fields are unsuitable for authorization decisions, as they may be
retrieved at different times, thus being subject to races. Hence,
augmented fields should be used exclusively for informational
purposes.
<para>Similar to <function>sd_bus_creds_get_mask()</function>, the function
<function>sd_bus_creds_get_augmented_mask()</function> returns a bitmask of field constants. The mask
indicates which credential fields have been retrieved in a non-atomic fashion. For credential objects
created via <function>sd_bus_creds_new_from_pid()</function> or
<function>sd_bus_creds_new_from_pidfd()</function>, this mask will be identical to the mask returned by
<function>sd_bus_creds_get_mask()</function>. However, for credential objects retrieved via
<function>sd_bus_get_name_creds()</function>, this mask will be set for the credential fields that could
not be determined atomically at peer connection time, and which were later added by reading augmenting
credential data from <filename>/proc/</filename>. Similarly, for credential objects retrieved via
<function>sd_bus_get_owner_creds()</function>, the mask is set for the fields that could not be
determined atomically at bus creation time, but have been augmented. Similarly, for credential objects
retrieved via <function>sd_bus_message_get_creds()</function>, the mask is set for the fields that could
not be determined atomically at message sending time, but have been augmented. The mask returned by
<function>sd_bus_creds_get_augmented_mask()</function> is always a subset of (or identical to) the mask
returned by <function>sd_bus_creds_get_mask()</function> for the same object. The latter call hence
returns all credential fields available in the credential object, the former then marks the subset of
those that have been augmented. Note that augmented fields are unsuitable for authorization decisions, as
they may be retrieved at different times, thus being subject to races. Hence, augmented fields should be
used exclusively for informational purposes.
</para>
<para><function>sd_bus_creds_ref()</function> creates a new
@ -234,9 +217,9 @@
<refsect1>
<title>Return Value</title>
<para>On success, <function>sd_bus_creds_new_from_pid()</function>
returns 0 or a positive integer. On failure, it returns a negative
errno-style error code.</para>
<para>On success, <function>sd_bus_creds_new_from_pid()</function> and
<function>sd_bus_creds_new_from_pidfd()</function> return 0 or a positive integer. On failure, they return
a negative errno-style error code.</para>
<para><function>sd_bus_creds_get_mask()</function> returns the
mask of successfully acquired fields.</para>
@ -256,9 +239,9 @@
<refsect1>
<title>Reference ownership</title>
<para>Function <function>sd_bus_creds_new_from_pid()</function>
creates a new object and the caller owns the sole reference. When
not needed anymore, this reference should be destroyed with
<para>The functions <function>sd_bus_creds_new_from_pid()</function> and
<function>sd_bus_creds_new_from_pidfd()</function> create a new object and the caller owns the sole
reference. When not needed anymore, this reference should be destroyed with
<citerefentry><refentrytitle>sd_bus_creds_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
@ -307,6 +290,7 @@
<function>sd_bus_creds_unref()</function> were added in version 209.</para>
<para><function>sd_bus_creds_get_augmented_mask()</function> was added in version 223.</para>
<para><function>sd_bus_creds_unrefp()</function> was added in version 229.</para>
<para><function>sd_bus_creds_new_from_pidfd()</function> was added in version 256.</para>
</refsect1>
<refsect1>

View File

@ -930,12 +930,14 @@ int getpeersec(int fd, char **ret) {
}
int getpeergroups(int fd, gid_t **ret) {
socklen_t n = sizeof(gid_t) * 64;
_cleanup_free_ gid_t *d = NULL;
assert(fd >= 0);
assert(ret);
long ngroups_max = sysconf(_SC_NGROUPS_MAX);
socklen_t n = sizeof(gid_t) * MAX((socklen_t) ngroups_max, 64U);
for (;;) {
d = malloc(n);
if (!d)
@ -953,7 +955,7 @@ int getpeergroups(int fd, gid_t **ret) {
assert_se(n % sizeof(gid_t) == 0);
n /= sizeof(gid_t);
if ((socklen_t) (int) n != n)
if (n > INT_MAX)
return -E2BIG;
*ret = TAKE_PTR(d);

View File

@ -11,6 +11,7 @@
#include "bus-common-errors.h"
#include "bus-get-properties.h"
#include "bus-log-control-api.h"
#include "bus-util.h"
#include "chase.h"
#include "confidential-virt.h"
#include "data-fd-util.h"
@ -464,18 +465,13 @@ static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char
* its sleeve: if the name is specified empty we use the client's unit. */
if (isempty(name)) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
r = bus_query_sender_pidref(message, &pidref);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
u = manager_get_unit_by_pid(m, pid);
u = manager_get_unit_by_pidref(m, &pidref);
if (!u)
return sd_bus_error_set(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");
} else {
@ -542,7 +538,7 @@ static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error
static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = ASSERT_PTR(userdata);
pid_t pid;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
Unit *u;
int r;
@ -552,27 +548,20 @@ static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bu
/* Anyone can call this method */
r = sd_bus_message_read(message, "u", &pid);
r = sd_bus_message_read(message, "u", &pidref.pid);
if (r < 0)
return r;
if (pid < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pid);
if (pid == 0) {
_cleanup_(sd_bus_creds_unrefp) 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 (pidref.pid < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pidref.pid);
if (pidref.pid == 0) {
r = bus_query_sender_pidref(message, &pidref);
if (r < 0)
return r;
}
u = manager_get_unit_by_pid(m, pid);
u = manager_get_unit_by_pidref(m, &pidref);
if (!u)
return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid);
return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pidref.pid);
return reply_unit_path(u, message, error);
}
@ -601,21 +590,16 @@ static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userd
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid invocation ID");
if (sd_id128_is_null(id)) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
r = bus_query_sender_pidref(message, &pidref);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
u = manager_get_unit_by_pid(m, pid);
u = manager_get_unit_by_pidref(m, &pidref);
if (!u)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT,
"Client " PID_FMT " not member of any unit.", pid);
"Client " PID_FMT " not member of any unit.", pidref.pid);
} else {
u = hashmap_get(m->units_by_invocation_id, &id);
if (!u)
@ -2934,7 +2918,7 @@ static int method_dump_unit_descriptor_store(sd_bus_message *message, void *user
}
static int aux_scope_from_message(Manager *m, sd_bus_message *message, Unit **ret_scope, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_(pidref_done) PidRef sender_pidref = PIDREF_NULL;
_cleanup_free_ PidRef *pidrefs = NULL;
const char *name;
Unit *from, *scope;
@ -2942,20 +2926,15 @@ static int aux_scope_from_message(Manager *m, sd_bus_message *message, Unit **re
CGroupContext *cc;
size_t n_pids = 0;
uint64_t flags;
pid_t pid;
int r;
assert(ret_scope);
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
r = bus_query_sender_pidref(message, &sender_pidref);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
from = manager_get_unit_by_pid(m, pid);
from = manager_get_unit_by_pidref(m, &sender_pidref);
if (!from)
return sd_bus_error_set(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");

View File

@ -3,6 +3,7 @@
#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-get-properties.h"
#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-kill.h"
#include "dbus-manager.h"
@ -84,7 +85,7 @@ static int bus_scope_set_transient_property(
return bus_set_transient_oom_policy(u, name, &s->oom_policy, message, flags, error);
if (streq(name, "PIDs")) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_(pidref_done) PidRef sender_pidref = PIDREF_NULL;
unsigned n = 0;
r = sd_bus_message_enter_container(message, 'a', "u");
@ -94,7 +95,7 @@ static int bus_scope_set_transient_property(
for (;;) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
uint32_t upid;
pid_t pid;
PidRef *p;
r = sd_bus_message_read(message, "u", &upid);
if (r < 0)
@ -103,28 +104,27 @@ static int bus_scope_set_transient_property(
break;
if (upid == 0) {
if (!creds) {
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
if (!pidref_is_set(&sender_pidref)) {
r = bus_query_sender_pidref(message, &sender_pidref);
if (r < 0)
return r;
}
r = sd_bus_creds_get_pid(creds, &pid);
p = &sender_pidref;
} else {
r = pidref_set_pid(&pidref, upid);
if (r < 0)
return r;
} else
pid = (uid_t) upid;
r = pidref_set_pid(&pidref, pid);
if (r < 0)
return r;
p = &pidref;
}
r = unit_pid_attachable(u, &pidref, error);
r = unit_pid_attachable(u, p, error);
if (r < 0)
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
r = unit_watch_pidref(u, &pidref, /* exclusive= */ false);
r = unit_watch_pidref(u, p, /* exclusive= */ false);
if (r < 0 && r != -EEXIST)
return r;
}

View File

@ -7,6 +7,7 @@
#include "bus-common-errors.h"
#include "bus-get-properties.h"
#include "bus-polkit.h"
#include "bus-util.h"
#include "cgroup-util.h"
#include "condition.h"
#include "dbus-job.h"
@ -1485,7 +1486,7 @@ int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not active, refusing.");
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PIDFD, &creds);
if (r < 0)
return r;
@ -1496,7 +1497,6 @@ int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd
_cleanup_(pidref_freep) PidRef *pidref = NULL;
uid_t process_uid, sender_uid;
uint32_t upid;
pid_t pid;
r = sd_bus_message_read(message, "u", &upid);
if (r < 0)
@ -1505,13 +1505,14 @@ int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd
break;
if (upid == 0) {
r = sd_bus_creds_get_pid(creds, &pid);
_cleanup_(pidref_done) PidRef p = PIDREF_NULL;
r = bus_creds_get_pidref(creds, &p);
if (r < 0)
return r;
} else
pid = (uid_t) upid;
r = pidref_new_from_pid(pid, &pidref);
r = pidref_dup(&p, &pidref);
} else
r = pidref_new_from_pid(upid, &pidref);
if (r < 0)
return r;
@ -1537,9 +1538,9 @@ int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd
return sd_bus_error_set_errnof(error, r, "Failed to retrieve process UID: %m");
if (process_uid != sender_uid)
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by client's UID. Refusing.", pid);
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by client's UID. Refusing.", pidref->pid);
if (process_uid != u->ref_uid)
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by target unit's UID. Refusing.", pid);
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by target unit's UID. Refusing.", pidref->pid);
}
r = set_ensure_consume(&pids, &pidref_hash_ops_free, TAKE_PTR(pidref));

View File

@ -232,6 +232,8 @@ static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_er
return 0;
path = sd_bus_message_get_path(message);
if (!path)
return 0;
if (object_path_startswith("/org/freedesktop/systemd1", path)) {
r = mac_selinux_access_check(message, verb, error);
@ -241,25 +243,20 @@ static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_er
return 0;
}
if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
if (streq(path, "/org/freedesktop/systemd1/unit/self")) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
r = bus_query_sender_pidref(message, &pidref);
if (r < 0)
return 0;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return 0;
u = manager_get_unit_by_pid(m, pid);
u = manager_get_unit_by_pidref(m, &pidref);
} else {
r = manager_get_job_from_dbus_path(m, path, &j);
if (r >= 0)
u = j->unit;
else
manager_load_unit_from_dbus_path(m, path, NULL, &u);
(void) manager_load_unit_from_dbus_path(m, path, NULL, &u);
}
if (!u)
return 0;
@ -280,24 +277,19 @@ static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_
assert(bus);
assert(path);
if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
if (streq(path, "/org/freedesktop/systemd1/unit/self")) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
sd_bus_message *message;
pid_t pid;
message = sd_bus_get_current_message(bus);
if (!message)
return 0;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
r = bus_query_sender_pidref(message, &pidref);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
u = manager_get_unit_by_pid(m, pid);
u = manager_get_unit_by_pidref(m, &pidref);
if (!u)
return 0;
} else {

View File

@ -248,7 +248,7 @@ int mac_selinux_access_check_internal(
tclass = "system";
}
sd_bus_creds_get_cmdline(creds, &cmdline);
(void) sd_bus_creds_get_cmdline(creds, &cmdline);
cl = strv_join(cmdline, " ");
struct audit_info audit_info = {

View File

@ -834,3 +834,9 @@ global:
sd_id128_get_app_specific;
sd_device_enumerator_add_match_property_required;
} LIBSYSTEMD_254;
LIBSYSTEMD_256 {
global:
sd_bus_creds_get_pidfd_dup;
sd_bus_creds_new_from_pidfd;
} LIBSYSTEMD_255;

View File

@ -14,6 +14,7 @@
#include "bus-internal.h"
#include "bus-message.h"
#include "capability-util.h"
#include "fd-util.h"
#include "process-util.h"
#include "stdio-util.h"
#include "string-util.h"
@ -430,7 +431,6 @@ _public_ int sd_bus_get_name_creds(
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
const char *unique;
pid_t pid = 0;
int r;
assert_return(bus, -EINVAL);
@ -483,8 +483,9 @@ _public_ int sd_bus_get_name_creds(
}
if (mask != 0) {
bool need_pid, need_uid, need_gids, need_selinux, need_separate_calls, need_pidfd, need_augment;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool need_pid, need_uid, need_selinux, need_separate_calls;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
c = bus_creds_new();
if (!c)
@ -498,20 +499,25 @@ _public_ int sd_bus_get_name_creds(
c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
}
need_pid = (mask & SD_BUS_CREDS_PID) ||
((mask & SD_BUS_CREDS_AUGMENT) &&
(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
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|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
SD_BUS_CREDS_SELINUX_CONTEXT|
SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
need_uid = mask & SD_BUS_CREDS_EUID;
need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT;
need_augment =
(mask & SD_BUS_CREDS_AUGMENT) &&
(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
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|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
SD_BUS_CREDS_SELINUX_CONTEXT|
SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID|
SD_BUS_CREDS_PIDFD));
if (need_pid + need_uid + need_selinux > 1) {
need_pid = (mask & SD_BUS_CREDS_PID) || need_augment;
need_uid = mask & SD_BUS_CREDS_EUID;
need_gids = mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT;
need_pidfd = (mask & SD_BUS_CREDS_PIDFD) || need_augment;
if (need_pid + need_uid + need_selinux + need_pidfd + need_gids > 1) {
/* If we need more than one of the credentials, then use GetConnectionCredentials() */
@ -572,7 +578,9 @@ _public_ int sd_bus_get_name_creds(
if (r < 0)
return r;
pid = p;
if (!pidref_is_set(&pidref))
pidref = PIDREF_MAKE_FROM_PID(p);
if (mask & SD_BUS_CREDS_PID) {
c->pid = p;
c->mask |= SD_BUS_CREDS_PID;
@ -599,6 +607,69 @@ _public_ int sd_bus_get_name_creds(
r = sd_bus_message_exit_container(reply);
if (r < 0)
return r;
} else if (need_pidfd && streq(m, "ProcessFD")) {
int fd;
r = sd_bus_message_read(reply, "v", "h", &fd);
if (r < 0)
return r;
pidref_done(&pidref);
r = pidref_set_pidfd(&pidref, fd);
if (r < 0)
return r;
if (mask & SD_BUS_CREDS_PIDFD) {
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (fd < 0)
return -errno;
close_and_replace(c->pidfd, fd);
c->mask |= SD_BUS_CREDS_PIDFD;
}
} else if (need_gids && streq(m, "UnixGroupIDs")) {
/* Note that D-Bus actualy only gives us a combined list of
* primary gid and supplementary gids. And we don't know
* which one the primary one is. We'll take the whole shebang
* hence and use it as the supplementary group list, and not
* initialize the primary gid field. This is slightly
* incorrect of course, but only slightly, as in effect if
* the primary gid is also listed in the supplementary gid
* it has zero effect. */
r = sd_bus_message_enter_container(reply, 'v', "au");
if (r < 0)
return r;
r = sd_bus_message_enter_container(reply, 'a', "u");
if (r < 0)
return r;
for (;;) {
uint32_t u;
r = sd_bus_message_read(reply, "u", &u);
if (r < 0)
return r;
if (r == 0)
break;
if (!GREEDY_REALLOC(c->supplementary_gids, c->n_supplementary_gids+1))
return -ENOMEM;
c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) u;
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return r;
r = sd_bus_message_exit_container(reply);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
} else {
r = sd_bus_message_skip(reply, "v");
if (r < 0)
@ -614,7 +685,7 @@ _public_ int sd_bus_get_name_creds(
if (r < 0)
return r;
if (need_pid && pid == 0)
if (need_pid && !pidref_is_set(&pidref))
return -EPROTO;
}
@ -642,7 +713,9 @@ _public_ int sd_bus_get_name_creds(
if (r < 0)
return r;
pid = u;
if (!pidref_is_set(&pidref))
pidref = PIDREF_MAKE_FROM_PID(u);
if (mask & SD_BUS_CREDS_PID) {
c->pid = u;
c->mask |= SD_BUS_CREDS_PID;
@ -710,9 +783,11 @@ _public_ int sd_bus_get_name_creds(
}
}
r = bus_creds_add_more(c, mask, pid, 0);
if (r < 0 && r != -ESRCH) /* Return the error, but ignore ESRCH which just means the process is already gone */
return r;
if (pidref_is_set(&pidref)) {
r = bus_creds_add_more(c, mask, &pidref, 0);
if (r < 0 && r != -ESRCH) /* Return the error, but ignore ESRCH which just means the process is already gone */
return r;
}
}
if (creds)
@ -765,8 +840,8 @@ not_found:
_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
bool do_label, do_groups, do_sockaddr_peer;
pid_t pid = 0;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
bool do_label, do_groups, do_sockaddr_peer, do_pidfd;
int r;
assert_return(bus, -EINVAL);
@ -786,9 +861,10 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
do_sockaddr_peer = bus->sockaddr_size_peer >= offsetof(struct sockaddr_un, sun_path) + 1 &&
bus->sockaddr_peer.sa.sa_family == AF_UNIX &&
bus->sockaddr_peer.un.sun_path[0] == 0;
do_pidfd = bus->pidfd >= 0 && (mask & SD_BUS_CREDS_PIDFD);
/* Avoid allocating anything if we have no chance of returning useful data */
if (!bus->ucred_valid && !do_label && !do_groups && !do_sockaddr_peer)
if (!bus->ucred_valid && !do_label && !do_groups && !do_sockaddr_peer && !do_pidfd)
return -ENODATA;
c = bus_creds_new();
@ -797,8 +873,10 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
if (bus->ucred_valid) {
if (pid_is_valid(bus->ucred.pid)) {
pid = c->pid = bus->ucred.pid;
c->pid = bus->ucred.pid;
c->mask |= SD_BUS_CREDS_PID & mask;
pidref = PIDREF_MAKE_FROM_PID(c->pid);
}
if (uid_is_valid(bus->ucred.uid)) {
@ -859,7 +937,20 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
}
}
r = bus_creds_add_more(c, mask, pid, 0);
if (do_pidfd) {
c->pidfd = fcntl(bus->pidfd, F_DUPFD_CLOEXEC, 3);
if (c->pidfd < 0)
return -errno;
pidref_done(&pidref);
r = pidref_set_pidfd(&pidref, bus->pidfd);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_PIDFD;
}
r = bus_creds_add_more(c, mask, &pidref, 0);
if (r < 0 && r != -ESRCH) /* If the process vanished, then don't complain, just return what we got */
return r;

View File

@ -640,8 +640,8 @@ _public_ int sd_bus_set_property(
}
_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **ret) {
uint64_t missing;
sd_bus_creds *c;
int r;
assert_return(call, -EINVAL);
assert_return(call->sealed, -EPERM);
@ -653,36 +653,22 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
return -ENOTCONN;
c = sd_bus_message_get_creds(call);
/* All data we need? */
if (c && (mask & ~SD_BUS_CREDS_AUGMENT & ~c->mask) == 0) {
if (c)
missing = mask & ~SD_BUS_CREDS_AUGMENT & ~c->mask;
else
missing = mask & ~SD_BUS_CREDS_AUGMENT;
if (missing == 0) { /* All data we need? */
*ret = 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. */
/* There's a sender, use that */
if (call->sender && call->bus->bus_client)
return sd_bus_get_name_creds(call->bus, call->sender, mask, ret);
if (call->sender)
/* There's a sender, but the creds are missing. */
return sd_bus_get_name_creds(call->bus, call->sender, mask, ret);
else
/* There's no sender. For direct connections
* the credentials of the AF_UNIX peer matter,
* which may be queried via sd_bus_get_owner_creds(). */
return sd_bus_get_owner_creds(call->bus, mask, ret);
}
r = bus_creds_extend_by_pid(c, mask, ret);
if (r == -ESRCH) {
/* Process doesn't exist anymore? propagate the few things we have */
*ret = sd_bus_creds_ref(c);
return 0;
}
return r;
/* There's no sender. For direct connections the credentials of the AF_UNIX peer matter, which may be
* queried via sd_bus_get_owner_creds(). */
return sd_bus_get_owner_creds(call->bus, mask, ret);
}
_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {

View File

@ -53,6 +53,8 @@ void bus_creds_done(sd_bus_creds *c) {
* below. */
strv_free(c->cmdline_array);
safe_close(c->pidfd);
}
_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
@ -129,44 +131,70 @@ _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
sd_bus_creds* bus_creds_new(void) {
sd_bus_creds *c;
c = new0(sd_bus_creds, 1);
c = new(sd_bus_creds, 1);
if (!c)
return NULL;
c->allocated = true;
c->n_ref = 1;
*c = (sd_bus_creds) {
.allocated = true,
.n_ref = 1,
SD_BUS_CREDS_INIT_FIELDS,
};
return c;
}
_public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
static int bus_creds_new_from_pidref(sd_bus_creds **ret, PidRef *pidref, uint64_t mask) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
int r;
assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
assert_return(ret, -EINVAL);
c = bus_creds_new();
if (!c)
return -ENOMEM;
r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pidref, 0);
if (r < 0)
return r;
r = pidref_verify(pidref);
if (r < 0)
return r;
*ret = TAKE_PTR(c);
return 0;
}
_public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
int r;
assert_return(pid >= 0, -EINVAL);
assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
assert_return(ret, -EINVAL);
if (pid == 0)
pid = getpid_cached();
c = bus_creds_new();
if (!c)
return -ENOMEM;
r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
r = pidref_set_pid(&pidref, pid);
if (r < 0)
return r;
/* Check if the process existed at all, in case we haven't
* figured that out already */
r = pid_is_alive(pid);
return bus_creds_new_from_pidref(ret, &pidref, mask);
}
_public_ int sd_bus_creds_new_from_pidfd(sd_bus_creds **ret, int pidfd, uint64_t mask) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
int r;
assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
assert_return(ret, -EINVAL);
assert_return(pidfd >= 0, -EBADF);
r = pidref_set_pidfd(&pidref, pidfd);
if (r < 0)
return r;
if (r == 0)
return -ESRCH;
*ret = TAKE_PTR(c);
return 0;
return bus_creds_new_from_pidref(ret, &pidref, mask);
}
_public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
@ -280,6 +308,23 @@ _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
return 0;
}
_public_ int sd_bus_creds_get_pidfd_dup(sd_bus_creds *c, int *ret_fd) {
_cleanup_close_ int copy = -EBADF;
assert_return(c, -EINVAL);
assert_return(ret_fd, -EINVAL);
if (!(c->mask & SD_BUS_CREDS_PIDFD))
return -ENODATA;
copy = fcntl(c->pidfd, F_DUPFD_CLOEXEC, 3);
if (copy < 0)
return -errno;
*ret_fd = TAKE_FD(copy);
return 0;
}
_public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
assert_return(c, -EINVAL);
assert_return(ppid, -EINVAL);
@ -750,7 +795,8 @@ static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
return 0;
}
int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, PidRef *pidref, pid_t tid) {
_cleanup_(pidref_done) PidRef pidref_buf = PIDREF_NULL;
uint64_t missing;
int r;
@ -761,12 +807,26 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
return 0;
/* Try to retrieve PID from creds if it wasn't passed to us */
if (pid > 0) {
c->pid = pid;
if (pidref_is_set(pidref)) {
if ((c->mask & SD_BUS_CREDS_PID) && c->pid != pidref->pid) /* Insist that things match if already set */
return -EBUSY;
c->pid = pidref->pid;
c->mask |= SD_BUS_CREDS_PID;
} else if (c->mask & SD_BUS_CREDS_PID)
pid = c->pid;
else
} else if (c->mask & SD_BUS_CREDS_PIDFD) {
r = pidref_set_pidfd(&pidref_buf, c->pidfd);
if (r < 0)
return r;
pidref = &pidref_buf;
} else if (c->mask & SD_BUS_CREDS_PID) {
r = pidref_set_pid(&pidref_buf, c->pid);
if (r < 0)
return r;
pidref = &pidref_buf;
} else
/* Without pid we cannot do much... */
return 0;
@ -784,6 +844,14 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
c->mask |= SD_BUS_CREDS_TID;
}
if ((missing & SD_BUS_CREDS_PIDFD) && pidref->fd >= 0) {
c->pidfd = fcntl(pidref->fd, F_DUPFD_CLOEXEC, 3);
if (c->pidfd < 0)
return -errno;
c->mask |= SD_BUS_CREDS_PIDFD;
}
if (missing & (SD_BUS_CREDS_PPID |
SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
@ -794,13 +862,13 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
_cleanup_fclose_ FILE *f = NULL;
const char *p;
p = procfs_file_alloca(pid, "status");
p = procfs_file_alloca(pidref->pid, "status");
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
else if (!ERRNO_IS_PRIVILEGE(errno))
if (!ERRNO_IS_PRIVILEGE(errno))
return -errno;
} else {
@ -958,7 +1026,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
const char *p;
p = procfs_file_alloca(pid, "attr/current");
p = procfs_file_alloca(pidref->pid, "attr/current");
r = read_one_line_file(p, &c->label);
if (r < 0) {
if (!IN_SET(r, -ENOENT, -EINVAL, -EPERM, -EACCES))
@ -968,7 +1036,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
}
if (missing & SD_BUS_CREDS_COMM) {
r = pid_get_comm(pid, &c->comm);
r = pid_get_comm(pidref->pid, &c->comm);
if (r < 0) {
if (!ERRNO_IS_PRIVILEGE(r))
return r;
@ -977,7 +1045,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
}
if (missing & SD_BUS_CREDS_EXE) {
r = get_process_exe(pid, &c->exe);
r = get_process_exe(pidref->pid, &c->exe);
if (r == -ESRCH) {
/* Unfortunately we cannot really distinguish
* the case here where the process does not
@ -998,7 +1066,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (missing & SD_BUS_CREDS_CMDLINE) {
const char *p;
p = procfs_file_alloca(pid, "cmdline");
p = procfs_file_alloca(pidref->pid, "cmdline");
r = read_full_virtual_file(p, &c->cmdline, &c->cmdline_size);
if (r == -ENOENT)
return -ESRCH;
@ -1016,7 +1084,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
_cleanup_free_ char *p = NULL;
if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pidref->pid, tid) < 0)
return -ENOMEM;
r = read_one_line_file(p, &c->tid_comm);
@ -1032,7 +1100,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
if (!c->cgroup) {
r = cg_pid_get_path(NULL, pid, &c->cgroup);
r = cg_pid_get_path(NULL, pidref->pid, &c->cgroup);
if (r < 0) {
if (!ERRNO_IS_PRIVILEGE(r))
return r;
@ -1050,7 +1118,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
}
if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
r = audit_session_from_pid(pid, &c->audit_session_id);
r = audit_session_from_pid(pidref->pid, &c->audit_session_id);
if (r == -ENODATA) {
/* ENODATA means: no audit session id assigned */
c->audit_session_id = AUDIT_SESSION_INVALID;
@ -1063,7 +1131,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
}
if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
r = audit_loginuid_from_pid(pidref->pid, &c->audit_login_uid);
if (r == -ENODATA) {
/* ENODATA means: no audit login uid assigned */
c->audit_login_uid = UID_INVALID;
@ -1076,7 +1144,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
}
if (missing & SD_BUS_CREDS_TTY) {
r = get_ctty(pid, NULL, &c->tty);
r = get_ctty(pidref->pid, NULL, &c->tty);
if (r == -ENXIO) {
/* ENXIO means: process has no controlling TTY */
c->tty = NULL;
@ -1088,16 +1156,12 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
c->mask |= SD_BUS_CREDS_TTY;
}
/* In case only the exe path was to be read we cannot distinguish the case where the exe path was
* unreadable because the process was a kernel thread, or when the process didn't exist at
* all. Hence, let's do a final check, to be sure. */
r = pid_is_alive(pid);
r = pidref_verify(pidref);
if (r < 0)
return r;
if (r == 0)
return -ESRCH;
if (tid > 0 && tid != pid && pid_is_unwaited(tid) == 0)
/* Validate tid is still valid, too */
if (tid > 0 && tid != pidref->pid && pid_is_unwaited(tid) == 0)
return -ESRCH;
c->augmented = missing & c->mask;
@ -1131,6 +1195,13 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
n->mask |= SD_BUS_CREDS_PID;
}
if (c->mask & mask & SD_BUS_CREDS_PIDFD) {
n->pidfd = fcntl(c->pidfd, F_DUPFD_CLOEXEC, 3);
if (n->pidfd < 0)
return -errno;
n->mask |= SD_BUS_CREDS_PIDFD;
}
if (c->mask & mask & SD_BUS_CREDS_TID) {
n->tid = c->tid;
n->mask |= SD_BUS_CREDS_TID;

View File

@ -5,6 +5,9 @@
#include "sd-bus.h"
#include "pidref.h"
#include "user-util.h"
struct sd_bus_creds {
bool allocated;
unsigned n_ref;
@ -27,6 +30,7 @@ struct sd_bus_creds {
pid_t ppid;
pid_t pid;
pid_t tid;
int pidfd;
char *comm;
char *tid_comm;
@ -63,10 +67,22 @@ struct sd_bus_creds {
char *description, *unescaped_description;
};
#define SD_BUS_CREDS_INIT_FIELDS \
.uid = UID_INVALID, \
.euid = UID_INVALID, \
.suid = UID_INVALID, \
.fsuid = UID_INVALID, \
.gid = GID_INVALID, \
.egid = GID_INVALID, \
.sgid = GID_INVALID, \
.fsgid = GID_INVALID, \
.pidfd = -EBADF, \
.audit_login_uid = UID_INVALID
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);
int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, PidRef *pidref, pid_t tid);
int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret);

View File

@ -355,6 +355,8 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
if (c->mask & SD_BUS_CREDS_PID)
fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix);
if (c->mask & SD_BUS_CREDS_PIDFD)
fprintf(f, "%sPIDFD=%syes%s", prefix, color, suffix);
if (c->mask & SD_BUS_CREDS_TID)
fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix);
if (c->mask & SD_BUS_CREDS_PPID) {

View File

@ -269,6 +269,7 @@ struct sd_bus {
size_t n_groups;
union sockaddr_union sockaddr_peer;
socklen_t sockaddr_size_peer;
int pidfd;
uint64_t creds_mask;

View File

@ -373,6 +373,7 @@ static int message_from_header(
if (!m)
return -ENOMEM;
m->creds = (sd_bus_creds) { SD_BUS_CREDS_INIT_FIELDS };
m->sealed = true;
m->header = buffer;
@ -469,6 +470,7 @@ _public_ int sd_bus_message_new(
return -ENOMEM;
t->n_ref = 1;
t->creds = (sd_bus_creds) { SD_BUS_CREDS_INIT_FIELDS };
t->bus = sd_bus_ref(bus);
t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
t->header->endian = BUS_NATIVE_ENDIAN;

View File

@ -643,14 +643,20 @@ static void bus_get_peercred(sd_bus *b) {
/* Get the SELinux context of the peer */
r = getpeersec(b->input_fd, &b->label);
if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
log_debug_errno(r, "Failed to determine peer security context: %m");
log_debug_errno(r, "Failed to determine peer security context, ignoring: %m");
/* Get the list of auxiliary groups of the peer */
r = getpeergroups(b->input_fd, &b->groups);
if (r >= 0)
b->n_groups = (size_t) r;
else if (!IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
log_debug_errno(r, "Failed to determine peer's group list: %m");
log_debug_errno(r, "Failed to determine peer's group list, ignoring: %m");
r = getpeerpidfd(b->input_fd);
if (r < 0)
log_debug_errno(r, "Failed to determin peer pidfd, ignoring: %m");
else
close_and_replace(b->pidfd, r);
/* Let's query the peers socket address, it might carry information such as the peer's comm or
* description string */

View File

@ -256,6 +256,7 @@ _public_ int sd_bus_new(sd_bus **ret) {
.n_groups = SIZE_MAX,
.close_on_exit = true,
.ucred = UCRED_INVALID,
.pidfd = -EBADF,
.runtime_scope = _RUNTIME_SCOPE_INVALID,
};

View File

@ -4,6 +4,7 @@
#include "bus-dump.h"
#include "cgroup-util.h"
#include "errno-util.h"
#include "tests.h"
int main(int argc, char *argv[]) {
@ -24,11 +25,30 @@ int main(int argc, char *argv[]) {
creds = sd_bus_creds_unref(creds);
r = sd_bus_creds_new_from_pid(&creds, 1, _SD_BUS_CREDS_ALL);
if (r != -EACCES) {
if (!ERRNO_IS_NEG_PRIVILEGE(r)) {
assert_se(r >= 0);
putchar('\n');
bus_creds_dump(creds, NULL, true);
}
creds = sd_bus_creds_unref(creds);
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
r = sd_bus_default_system(&bus);
if (r < 0)
log_warning_errno(r, "Unable to connect to system bus, skipping rest of test.");
else {
const char *unique;
assert_se(sd_bus_get_unique_name(bus, &unique) >= 0);
r = sd_bus_get_name_creds(bus, unique, _SD_BUS_CREDS_ALL, &creds);
log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_get_name_creds: %m");
assert_se(r >= 0);
putchar('\n');
bus_creds_dump(creds, NULL, true);
}
return 0;
}

View File

@ -5,10 +5,39 @@
#include "sd-bus.h"
#include "bus-dump.h"
#include "bus-util.h"
#include "fd-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "sort-util.h"
#include "tests.h"
#include "user-util.h"
static bool gid_list_contained(const gid_t *a, size_t n, const gid_t *b, size_t m) {
assert_se(a || n == 0);
assert_se(b || m == 0);
/* Checks if every entry in a[] is also in b[] */
for (size_t i = 0; i < n; i++) {
size_t j;
for (j = 0; j < m; j++)
if (a[i] == b[j])
break;
if (j >= m)
return false;
}
return true;
}
static bool gid_list_same(const gid_t *a, size_t n, const gid_t *b, size_t m) {
return gid_list_contained(a, n, b, m) &&
gid_list_contained(b, m, a, n);
}
static void *server(void *p) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
@ -27,11 +56,13 @@ static void *server(void *p) {
assert_se(sd_bus_set_fd(bus, fd, fd) >= 0);
TAKE_FD(fd);
assert_se(sd_bus_set_server(bus, true, id) >= 0);
assert_se(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION) >= 0);
assert_se(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS) >= 0);
assert_se(sd_bus_start(bus) >= 0);
assert_se(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION, &c) >= 0);
assert_se(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS, &c) >= 0);
bus_creds_dump(c, /* f= */ NULL, /* terse= */ false);
uid_t u;
assert_se(sd_bus_creds_get_euid(c, &u) >= 0);
@ -45,6 +76,26 @@ static void *server(void *p) {
assert_se(sd_bus_creds_get_pid(c, &pid) >= 0);
assert_se(pid == getpid_cached());
int pidfd = -EBADF;
if (sd_bus_creds_get_pidfd_dup(c, &pidfd) >= 0) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
assert_se(pidref_set_pidfd_take(&pidref, pidfd) >= 0);
assert_se(pidref.pid == getpid_cached());
}
const gid_t *gl = NULL;
int n;
n = sd_bus_creds_get_supplementary_gids(c, &gl);
if (n >= 0) {
_cleanup_free_ gid_t *gg = NULL;
r = getgroups_alloc(&gg);
assert_se(r >= 0);
assert_se(gid_list_same(gl, n, gg, r));
}
const char *comm;
assert_se(sd_bus_creds_get_comm(c, &comm) >= 0);
assert_se(pid_get_comm(0, &our_comm) >= 0);

View File

@ -759,8 +759,8 @@ static int create_session(
void *userdata,
sd_bus_error *error,
uid_t uid,
pid_t pid,
int pidfd,
pid_t leader_pid,
int leader_pidfd,
const char *service,
const char *type,
const char *class,
@ -793,32 +793,18 @@ static int create_session(
if (flags != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Flags must be zero.");
if (pidfd >= 0) {
r = pidref_set_pidfd(&leader, pidfd);
if (r < 0)
return r;
} else if (pid == 0) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t p;
if (leader_pidfd >= 0)
r = pidref_set_pidfd(&leader, leader_pidfd);
else if (leader_pid == 0)
r = bus_query_sender_pidref(message, &leader);
else {
if (leader_pid < 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Leader PID is not valid");
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &p);
if (r < 0)
return r;
r = pidref_set_pid(&leader, p);
if (r < 0)
return r;
} else {
assert(pid > 0);
r = pidref_set_pid(&leader, pid);
if (r < 0)
return r;
r = pidref_set_pid(&leader, leader_pid);
}
if (r < 0)
return r;
if (leader.pid == 1 || leader.pid == getpid_cached())
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
@ -1096,32 +1082,32 @@ fail:
static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
pid_t leader;
pid_t leader_pid;
uint32_t vtnr;
uid_t uid;
int remote;
uint32_t vtnr = 0;
int r;
int remote, r;
assert(message);
assert_cc(sizeof(pid_t) == sizeof(uint32_t));
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
r = sd_bus_message_read(message,
"uusssssussbss",
&uid,
&leader,
&service,
&type,
&class,
&desktop,
&cseat,
&vtnr,
&tty,
&display,
&remote,
&remote_user,
&remote_host);
r = sd_bus_message_read(
message,
"uusssssussbss",
&uid,
&leader_pid,
&service,
&type,
&class,
&desktop,
&cseat,
&vtnr,
&tty,
&display,
&remote,
&remote_user,
&remote_host);
if (r < 0)
return r;
@ -1130,7 +1116,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
userdata,
error,
uid,
leader,
leader_pid,
/* pidfd = */ -EBADF,
service,
type,
@ -1148,29 +1134,28 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
static int method_create_session_pidfd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
int leaderfd = -EBADF;
uid_t uid;
int remote;
uint32_t vtnr = 0;
uint64_t flags;
int r;
uint32_t vtnr;
uid_t uid;
int leader_fd = -EBADF, remote, r;
r = sd_bus_message_read(message,
"uhsssssussbsst",
&uid,
&leaderfd,
&service,
&type,
&class,
&desktop,
&cseat,
&vtnr,
&tty,
&display,
&remote,
&remote_user,
&remote_host,
&flags);
r = sd_bus_message_read(
message,
"uhsssssussbsst",
&uid,
&leader_fd,
&service,
&type,
&class,
&desktop,
&cseat,
&vtnr,
&tty,
&display,
&remote,
&remote_user,
&remote_host,
&flags);
if (r < 0)
return r;
@ -1179,8 +1164,8 @@ static int method_create_session_pidfd(sd_bus_message *message, void *userdata,
userdata,
error,
uid,
/* pid = */ 0,
leaderfd,
/* leader_pid = */ 0,
leader_fd,
service,
type,
class,
@ -3506,7 +3491,6 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error
Manager *m = ASSERT_PTR(userdata);
InhibitMode mm;
InhibitWhat w;
pid_t pid;
uid_t uid;
int r;
@ -3557,7 +3541,7 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error
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_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PIDFD, &creds);
if (r < 0)
return r;
@ -3565,14 +3549,10 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
r = bus_creds_get_pidref(creds, &pidref);
if (r < 0)
return r;
r = pidref_set_pid(&pidref, pid);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed pin source process "PID_FMT": %m", pid);
if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED,
"Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.",

View File

@ -710,3 +710,47 @@ int bus_property_get_string_set(
return bus_message_append_string_set(reply, *s);
}
int bus_creds_get_pidref(
sd_bus_creds *c,
PidRef *ret) {
int pidfd = -EBADF;
pid_t pid;
int r;
assert(c);
assert(ret);
r = sd_bus_creds_get_pid(c, &pid);
if (r < 0)
return r;
r = sd_bus_creds_get_pidfd_dup(c, &pidfd);
if (r < 0 && r != -ENODATA)
return r;
*ret = (PidRef) {
.pid = pid,
.fd = pidfd,
};
return 0;
}
int bus_query_sender_pidref(
sd_bus_message *m,
PidRef *ret) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
int r;
assert(m);
assert(ret);
r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_PID|SD_BUS_CREDS_PIDFD, &creds);
if (r < 0)
return r;
return bus_creds_get_pidref(creds, ret);
}

View File

@ -11,6 +11,7 @@
#include "errno-util.h"
#include "macro.h"
#include "pidref.h"
#include "runtime-scope.h"
#include "set.h"
#include "string-util.h"
@ -73,3 +74,6 @@ extern const struct hash_ops bus_message_hash_ops;
int bus_message_append_string_set(sd_bus_message *m, Set *s);
int bus_property_get_string_set(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_creds_get_pidref(sd_bus_creds *c, PidRef *ret);
int bus_query_sender_pidref(sd_bus_message *m, PidRef *ret);

View File

@ -90,8 +90,9 @@ __extension__ enum {
SD_BUS_CREDS_UNIQUE_NAME = 1ULL << 31,
SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 32,
SD_BUS_CREDS_DESCRIPTION = 1ULL << 33,
SD_BUS_CREDS_PIDFD = 1ULL << 34,
SD_BUS_CREDS_AUGMENT = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */
_SD_BUS_CREDS_ALL = (1ULL << 34) -1
_SD_BUS_CREDS_ALL = (1ULL << 35) -1
};
__extension__ enum {
@ -402,12 +403,14 @@ int sd_bus_match_signal_async(sd_bus *bus, sd_bus_slot **ret, const char *sender
/* Credential handling */
int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t creds_mask);
int sd_bus_creds_new_from_pidfd(sd_bus_creds **ret, int pidfd, uint64_t creds_mask);
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(const sd_bus_creds *c);
uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c);
int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid);
int sd_bus_creds_get_pidfd_dup(sd_bus_creds *c, int *ret_fd);
int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid);
int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid);
int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid);