diff options
author | Luca Boccassi <bluca@debian.org> | 2023-01-19 23:20:55 +0000 |
---|---|---|
committer | Luca Boccassi <bluca@debian.org> | 2023-01-20 12:18:05 +0000 |
commit | da20baaeccbcca78350bf64bdc069dec685c95bc (patch) | |
tree | 85004b30d748e95c61fa1d1ac46b3836cde718ea | |
parent | f840c7d58dcd39fa98a887c50a9be5c35dbb599f (diff) | |
download | systemd-da20baaeccbcca78350bf64bdc069dec685c95bc.tar.gz |
sd-login: add sd_pidfd_* APIs
Same as the sd_pid_* counterparts, but take a pid file descriptor instead of
a pid, so that the callers can be sure that the returned values are really
about the process they asked for, and not about a recycled PID.
-rw-r--r-- | man/rules/meson.build | 10 | ||||
-rw-r--r-- | man/sd_pid_get_owner_uid.xml | 70 | ||||
-rw-r--r-- | src/libsystemd/libsystemd.sym | 8 | ||||
-rw-r--r-- | src/libsystemd/sd-login/sd-login.c | 201 | ||||
-rw-r--r-- | src/libsystemd/sd-login/test-login.c | 32 | ||||
-rw-r--r-- | src/systemd/sd-login.h | 12 |
6 files changed, 332 insertions, 1 deletions
diff --git a/man/rules/meson.build b/man/rules/meson.build index 90324fe1ec..194cc0b904 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -815,7 +815,15 @@ manpages = [ 'sd_pid_get_slice', 'sd_pid_get_unit', 'sd_pid_get_user_slice', - 'sd_pid_get_user_unit'], + 'sd_pid_get_user_unit', + 'sd_pidfd_get_cgroup', + 'sd_pidfd_get_machine_name', + 'sd_pidfd_get_owner_uid', + 'sd_pidfd_get_session', + 'sd_pidfd_get_slice', + 'sd_pidfd_get_unit', + 'sd_pidfd_get_user_slice', + 'sd_pidfd_get_user_unit'], 'HAVE_PAM'], ['sd_seat_get_active', '3', diff --git a/man/sd_pid_get_owner_uid.xml b/man/sd_pid_get_owner_uid.xml index c516083a5b..5ce5a19144 100644 --- a/man/sd_pid_get_owner_uid.xml +++ b/man/sd_pid_get_owner_uid.xml @@ -25,6 +25,14 @@ <refname>sd_pid_get_slice</refname> <refname>sd_pid_get_user_slice</refname> <refname>sd_pid_get_cgroup</refname> + <refname>sd_pidfd_get_owner_uid</refname> + <refname>sd_pidfd_get_session</refname> + <refname>sd_pidfd_get_user_unit</refname> + <refname>sd_pidfd_get_unit</refname> + <refname>sd_pidfd_get_machine_name</refname> + <refname>sd_pidfd_get_slice</refname> + <refname>sd_pidfd_get_user_slice</refname> + <refname>sd_pidfd_get_cgroup</refname> <refname>sd_peer_get_owner_uid</refname> <refname>sd_peer_get_session</refname> <refname>sd_peer_get_user_unit</refname> @@ -91,6 +99,54 @@ </funcprototype> <funcprototype> + <funcdef>int <function>sd_pidfd_get_owner_uid</function></funcdef> + <paramdef>int <parameter>pidfd</parameter></paramdef> + <paramdef>uid_t *<parameter>uid</parameter></paramdef> + </funcprototype> + + <funcprototype> + <funcdef>int <function>sd_pidfd_get_session</function></funcdef> + <paramdef>int <parameter>pidfd</parameter></paramdef> + <paramdef>char **<parameter>session</parameter></paramdef> + </funcprototype> + + <funcprototype> + <funcdef>int <function>sd_pidfd_get_user_unit</function></funcdef> + <paramdef>int <parameter>pidfd</parameter></paramdef> + <paramdef>char **<parameter>unit</parameter></paramdef> + </funcprototype> + + <funcprototype> + <funcdef>int <function>sd_pidfd_get_unit</function></funcdef> + <paramdef>int <parameter>pidfd</parameter></paramdef> + <paramdef>char **<parameter>unit</parameter></paramdef> + </funcprototype> + + <funcprototype> + <funcdef>int <function>sd_pidfd_get_machine_name</function></funcdef> + <paramdef>int <parameter>pidfd</parameter></paramdef> + <paramdef>char **<parameter>name</parameter></paramdef> + </funcprototype> + + <funcprototype> + <funcdef>int <function>sd_pidfd_get_slice</function></funcdef> + <paramdef>int <parameter>pidfd</parameter></paramdef> + <paramdef>char **<parameter>slice</parameter></paramdef> + </funcprototype> + + <funcprototype> + <funcdef>int <function>sd_pidfd_get_user_slice</function></funcdef> + <paramdef>int <parameter>pidfd</parameter></paramdef> + <paramdef>char **<parameter>slice</parameter></paramdef> + </funcprototype> + + <funcprototype> + <funcdef>int <function>sd_pidfd_get_cgroup</function></funcdef> + <paramdef>int <parameter>pidfd</parameter></paramdef> + <paramdef>char **<parameter>cgroup</parameter></paramdef> + </funcprototype> + + <funcprototype> <funcdef>int <function>sd_peer_get_owner_uid</function></funcdef> <paramdef>int <parameter>fd</parameter></paramdef> <paramdef>uid_t *<parameter>uid</parameter></paramdef> @@ -222,6 +278,20 @@ functions is passed as 0, the operation is executed for the calling process.</para> + <para>The <function>sd_pidfd_get_owner_uid()</function>, + <function>sd_pidfd_get_session()</function>, + <function>sd_pidfd_get_user_unit()</function>, + <function>sd_pidfd_get_unit()</function>, + <function>sd_pidfd_get_machine_name()</function>, + <function>sd_pidfd_get_slice()</function>, + <function>sd_pidfd_get_user_slice()</function> and + <function>sd_pidfd_get_cgroup()</function> calls operate similarly to their PID counterparts, but accept a + <constant>PIDFD</constant> instead of a <constant>PID</constant>, which means they are not subject to recycle + race conditions as the process is pinned by the file descriptor during the whole duration of the invocation. + Note that these require a kernel that supports <constant>PIDFD</constant>. A suitable file descriptor may be + acquired via + <citerefentry project='man-pages'><refentrytitle>pidfd_open</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para> + <para>The <function>sd_peer_get_owner_uid()</function>, <function>sd_peer_get_session()</function>, <function>sd_peer_get_user_unit()</function>, diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 07acb99271..0f2230a42f 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -802,4 +802,12 @@ global: sd_bus_emit_signal_to; sd_bus_emit_signal_tov; sd_bus_message_new_signal_to; + sd_pidfd_get_cgroup; + sd_pidfd_get_machine_name; + sd_pidfd_get_owner_uid; + sd_pidfd_get_session; + sd_pidfd_get_slice; + sd_pidfd_get_unit; + sd_pidfd_get_user_slice; + sd_pidfd_get_user_unit; } LIBSYSTEMD_252; diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c index 90b5ebb4b7..d483889fd1 100644 --- a/src/libsystemd/sd-login/sd-login.c +++ b/src/libsystemd/sd-login/sd-login.c @@ -22,6 +22,7 @@ #include "macro.h" #include "parse-util.h" #include "path-util.h" +#include "process-util.h" #include "socket-util.h" #include "stdio-util.h" #include "string-util.h" @@ -134,6 +135,206 @@ _public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) { return 0; } +_public_ int sd_pidfd_get_session(int pidfd, char **ret_session) { + _cleanup_free_ char *session = NULL; + pid_t pid; + int r; + + assert_return(pidfd >= 0, -EBADF); + assert_return(ret_session, -EINVAL); + + r = pidfd_get_pid(pidfd, &pid); + if (r < 0) + return r; + + r = sd_pid_get_session(pid, &session); + if (r < 0) + return r; + + r = pidfd_verify_pid(pidfd, pid); + if (r < 0) + return r; + + *ret_session = TAKE_PTR(session); + + return 0; +} + +_public_ int sd_pidfd_get_unit(int pidfd, char **ret_unit) { + _cleanup_free_ char *unit = NULL; + pid_t pid; + int r; + + assert_return(pidfd >= 0, -EBADF); + assert_return(ret_unit, -EINVAL); + + r = pidfd_get_pid(pidfd, &pid); + if (r < 0) + return r; + + r = sd_pid_get_unit(pid, &unit); + if (r < 0) + return r; + + r = pidfd_verify_pid(pidfd, pid); + if (r < 0) + return r; + + *ret_unit = TAKE_PTR(unit); + + return 0; +} + +_public_ int sd_pidfd_get_user_unit(int pidfd, char **ret_unit) { + _cleanup_free_ char *unit = NULL; + pid_t pid; + int r; + + assert_return(pidfd >= 0, -EBADF); + assert_return(ret_unit, -EINVAL); + + r = pidfd_get_pid(pidfd, &pid); + if (r < 0) + return r; + + r = sd_pid_get_user_unit(pid, &unit); + if (r < 0) + return r; + + r = pidfd_verify_pid(pidfd, pid); + if (r < 0) + return r; + + *ret_unit = TAKE_PTR(unit); + + return 0; +} + +_public_ int sd_pidfd_get_machine_name(int pidfd, char **ret_name) { + _cleanup_free_ char *name = NULL; + pid_t pid; + int r; + + assert_return(pidfd >= 0, -EBADF); + assert_return(ret_name, -EINVAL); + + r = pidfd_get_pid(pidfd, &pid); + if (r < 0) + return r; + + r = sd_pid_get_machine_name(pid, &name); + if (r < 0) + return r; + + r = pidfd_verify_pid(pidfd, pid); + if (r < 0) + return r; + + *ret_name = TAKE_PTR(name); + + return 0; +} + +_public_ int sd_pidfd_get_slice(int pidfd, char **ret_slice) { + _cleanup_free_ char *slice = NULL; + pid_t pid; + int r; + + assert_return(pidfd >= 0, -EBADF); + assert_return(ret_slice, -EINVAL); + + r = pidfd_get_pid(pidfd, &pid); + if (r < 0) + return r; + + r = sd_pid_get_slice(pid, &slice); + if (r < 0) + return r; + + r = pidfd_verify_pid(pidfd, pid); + if (r < 0) + return r; + + *ret_slice = TAKE_PTR(slice); + + return 0; +} + +_public_ int sd_pidfd_get_user_slice(int pidfd, char **ret_slice) { + _cleanup_free_ char *slice = NULL; + pid_t pid; + int r; + + assert_return(pidfd >= 0, -EBADF); + assert_return(ret_slice, -EINVAL); + + r = pidfd_get_pid(pidfd, &pid); + if (r < 0) + return r; + + r = sd_pid_get_user_slice(pid, &slice); + if (r < 0) + return r; + + r = pidfd_verify_pid(pidfd, pid); + if (r < 0) + return r; + + *ret_slice = TAKE_PTR(slice); + + return 0; +} + +_public_ int sd_pidfd_get_owner_uid(int pidfd, uid_t *ret_uid) { + uid_t uid; + pid_t pid; + int r; + + assert_return(pidfd >= 0, -EINVAL); + assert_return(ret_uid, -EINVAL); + + r = pidfd_get_pid(pidfd, &pid); + if (r < 0) + return r; + + r = sd_pid_get_owner_uid(pid, &uid); + if (r < 0) + return r; + + r = pidfd_verify_pid(pidfd, pid); + if (r < 0) + return r; + + *ret_uid = uid; + + return 0; +} + +_public_ int sd_pidfd_get_cgroup(int pidfd, char **ret_cgroup) { + _cleanup_free_ char *cgroup = NULL; + pid_t pid; + int r; + + assert_return(pidfd >= 0, -EBADF); + assert_return(ret_cgroup, -EINVAL); + + r = pidfd_get_pid(pidfd, &pid); + if (r < 0) + return r; + + r = sd_pid_get_cgroup(pid, &cgroup); + if (r < 0) + return r; + + r = pidfd_verify_pid(pidfd, pid); + if (r < 0) + return r; + + *ret_cgroup = TAKE_PTR(cgroup); + + return 0; +} + _public_ int sd_peer_get_session(int fd, char **session) { struct ucred ucred = UCRED_INVALID; int r; diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c index 96a8c567fc..1710cdeb91 100644 --- a/src/libsystemd/sd-login/test-login.c +++ b/src/libsystemd/sd-login/test-login.c @@ -9,6 +9,8 @@ #include "fd-util.h" #include "format-util.h" #include "log.h" +#include "missing_syscall.h" +#include "process-util.h" #include "string-util.h" #include "strv.h" #include "tests.h" @@ -44,6 +46,7 @@ TEST(login) { *type = NULL, *class = NULL, *state = NULL, *state2 = NULL, *seat = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *slice = NULL; + _cleanup_close_ int pidfd = -EBADFD; int r; uid_t u, u2 = UID_INVALID; char *t, **seats = NULL, **sessions = NULL; @@ -71,6 +74,35 @@ TEST(login) { log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup)); assert_se(IN_SET(r, 0, -ENOMEDIUM)); + pidfd = pidfd_open(getpid_cached(), 0); + if (pidfd >= 0) { + _cleanup_free_ char *cgroup2 = NULL, *session2 = NULL, + *unit2 = NULL, *user_unit2 = NULL, *slice2 = NULL; + + r = sd_pidfd_get_unit(pidfd, &unit2); + log_info("sd_pidfd_get_unit(pidfd, …) → %s / \"%s\"", e(r), strnull(unit2)); + assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pidfd_get_user_unit(pidfd, &user_unit2); + log_info("sd_pidfd_get_user_unit(pidfd, …) → %s / \"%s\"", e(r), strnull(user_unit2)); + assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pidfd_get_slice(pidfd, &slice2); + log_info("sd_pidfd_get_slice(pidfd, …) → %s / \"%s\"", e(r), strnull(slice2)); + assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pidfd_get_owner_uid(pidfd, &u2); + log_info("sd_pidfd_get_owner_uid(pidfd, …) → %s / "UID_FMT, e(r), u2); + assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pidfd_get_session(pidfd, &session2); + log_info("sd_pidfd_get_session(pidfd, …) → %s / \"%s\"", e(r), strnull(session2)); + + r = sd_pidfd_get_cgroup(pidfd, &cgroup2); + log_info("sd_pidfd_get_cgroup(pidfd, …) → %s / \"%s\"", e(r), strnull(cgroup2)); + assert_se(IN_SET(r, 0, -ENOMEDIUM)); + } + r = sd_uid_get_display(u2, &display_session); log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session)); if (u2 == UID_INVALID) diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h index 54970532ec..85dd086e2b 100644 --- a/src/systemd/sd-login.h +++ b/src/systemd/sd-login.h @@ -80,6 +80,18 @@ int sd_pid_get_machine_name(pid_t pid, char **machine); * hierarchy. */ int sd_pid_get_cgroup(pid_t pid, char **cgroup); +/* Equivalent to the corresponding sd_pid_get* functions, but take a + * PIDFD instead of a PID, to ensure there can be no possible PID + * recycle issues before/after the calls. */ +int sd_pidfd_get_session(pid_t pid, char **session); +int sd_pidfd_get_owner_uid(pid_t pid, uid_t *uid); +int sd_pidfd_get_unit(pid_t pid, char **unit); +int sd_pidfd_get_user_unit(pid_t pid, char **unit); +int sd_pidfd_get_slice(pid_t pid, char **slice); +int sd_pidfd_get_user_slice(pid_t pid, char **slice); +int sd_pidfd_get_machine_name(pid_t pid, char **machine); +int sd_pidfd_get_cgroup(pid_t pid, char **cgroup); + /* Similar to sd_pid_get_session(), but retrieves data about the peer * of a connected AF_UNIX socket */ int sd_peer_get_session(int fd, char **session); |