From b2206fe514d1ef3b917f2e5b64d9d1e5fad3e408 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Nov 2024 16:35:48 +0100 Subject: [PATCH 1/4] socket-util: introduce getpeerpidref() This combines getpeercred() and getpeerpidfd() and returns a PidRef --- src/basic/socket-util.c | 22 ++++++++++++++++++++++ src/basic/socket-util.h | 2 ++ src/test/test-socket-util.c | 21 +++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 94089323b4..9190072f4e 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -975,6 +975,28 @@ int getpeerpidfd(int fd) { return pidfd; } +int getpeerpidref(int fd, PidRef *ret) { + int r; + + assert(fd >= 0); + assert(ret); + + int pidfd = getpeerpidfd(fd); + if (pidfd < 0) { + if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd)) + return pidfd; + + struct ucred ucred; + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return pidref_set_pid(ret, ucred.pid); + } + + return pidref_set_pidfd_consume(ret, pidfd); +} + ssize_t send_many_fds_iov_sa( int transport_fd, int *fds_array, size_t n_fds_array, diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 874e559a4b..e21a4427f0 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -20,6 +20,7 @@ #include "macro.h" #include "missing_network.h" #include "missing_socket.h" +#include "pidref.h" #include "sparse-endian.h" union sockaddr_union { @@ -154,6 +155,7 @@ int getpeercred(int fd, struct ucred *ucred); int getpeersec(int fd, char **ret); int getpeergroups(int fd, gid_t **ret); int getpeerpidfd(int fd); +int getpeerpidref(int fd, PidRef *ret); ssize_t send_many_fds_iov_sa( int transport_fd, diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index f7b31aeb46..63bbb1d1d2 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -584,4 +584,25 @@ TEST(sockaddr_un_set_path) { assert_se(connect(fd2, &sa.sa, SOCKADDR_LEN(sa)) >= 0); } +TEST(getpeerpidref) { + _cleanup_close_pair_ int fd[2] = EBADF_PAIR; + + ASSERT_OK(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fd)); + + _cleanup_(pidref_done) PidRef pidref0 = PIDREF_NULL, pidref1 = PIDREF_NULL, pidref_self = PIDREF_NULL, pidref_pid1 = PIDREF_NULL; + ASSERT_OK(getpeerpidref(fd[0], &pidref0)); + ASSERT_OK(getpeerpidref(fd[1], &pidref1)); + + ASSERT_OK(pidref_set_self(&pidref_self)); + ASSERT_OK(pidref_set_pid(&pidref_pid1, 1)); + + ASSERT_TRUE(pidref_equal(&pidref0, &pidref1)); + ASSERT_TRUE(pidref_equal(&pidref0, &pidref_self)); + ASSERT_TRUE(pidref_equal(&pidref1, &pidref_self)); + + ASSERT_TRUE(!pidref_equal(&pidref_self, &pidref_pid1)); + ASSERT_TRUE(!pidref_equal(&pidref1, &pidref_pid1)); + ASSERT_TRUE(!pidref_equal(&pidref0, &pidref_pid1)); +} + DEFINE_TEST_MAIN(LOG_DEBUG); From 92d78966fd604d818fba86e65ef6693983178acd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Nov 2024 16:35:26 +0100 Subject: [PATCH 2/4] cgroup-util: add pidref counterparts for cg_pid_get_session() + cg_pid_get_owner_uid() --- src/basic/cgroup-util.c | 45 +++++++++++++++++++++++++++++++++++++ src/basic/cgroup-util.h | 2 ++ src/test/test-cgroup-util.c | 4 ++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 8247b0c25f..9d41db2883 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1402,6 +1402,28 @@ int cg_pid_get_session(pid_t pid, char **ret_session) { return cg_path_get_session(cgroup, ret_session); } +int cg_pidref_get_session(const PidRef *pidref, char **ret) { + int r; + + if (!pidref_is_set(pidref)) + return -ESRCH; + if (pidref_is_remote(pidref)) + return -EREMOTE; + + _cleanup_free_ char *session = NULL; + r = cg_pid_get_session(pidref->pid, &session); + if (r < 0) + return r; + + r = pidref_verify(pidref); + if (r < 0) + return r; + + if (ret) + *ret = TAKE_PTR(session); + return 0; +} + int cg_path_get_owner_uid(const char *path, uid_t *ret_uid) { _cleanup_free_ char *slice = NULL; char *start, *end; @@ -1439,6 +1461,29 @@ int cg_pid_get_owner_uid(pid_t pid, uid_t *ret_uid) { return cg_path_get_owner_uid(cgroup, ret_uid); } +int cg_pidref_get_owner_uid(const PidRef *pidref, uid_t *ret) { + int r; + + if (!pidref_is_set(pidref)) + return -ESRCH; + if (pidref_is_remote(pidref)) + return -EREMOTE; + + uid_t uid; + r = cg_pid_get_owner_uid(pidref->pid, &uid); + if (r < 0) + return r; + + r = pidref_verify(pidref); + if (r < 0) + return r; + + if (ret) + *ret = uid; + + return 0; +} + int cg_path_get_slice(const char *p, char **ret_slice) { const char *e = NULL; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index d471aee0c3..23aa84f100 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -286,7 +286,9 @@ int cg_shift_path(const char *cgroup, const char *cached_root, const char **ret_ int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **ret_cgroup); int cg_pid_get_session(pid_t pid, char **ret_session); +int cg_pidref_get_session(const PidRef *pidref, char **ret); int cg_pid_get_owner_uid(pid_t pid, uid_t *ret_uid); +int cg_pidref_get_owner_uid(const PidRef *pidref, uid_t *ret); int cg_pid_get_unit(pid_t pid, char **ret_unit); int cg_pidref_get_unit(const PidRef *pidref, char **ret); int cg_pid_get_user_unit(pid_t pid, char **ret_unit); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 1d8f99cc6e..9fa3ddf9d1 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -212,8 +212,8 @@ TEST(proc) { cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid.pid, &path); cg_pid_get_path_shifted(pid.pid, NULL, &path_shifted); - cg_pid_get_owner_uid(pid.pid, &uid); - cg_pid_get_session(pid.pid, &session); + cg_pidref_get_owner_uid(&pid, &uid); + cg_pidref_get_session(&pid, &session); cg_pid_get_unit(pid.pid, &unit); cg_pid_get_user_unit(pid.pid, &user_unit); cg_pid_get_machine_name(pid.pid, &machine); From 1740d3e04b90da828789f91c6e37ec35cfb57bf0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Nov 2024 16:37:10 +0100 Subject: [PATCH 3/4] sd-login: make use of getpeerpidref() and cg_pidref_get_*() --- src/libsystemd/sd-login/sd-login.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c index 3aca593622..b2c67c9d09 100644 --- a/src/libsystemd/sd-login/sd-login.c +++ b/src/libsystemd/sd-login/sd-login.c @@ -334,46 +334,46 @@ _public_ int sd_pidfd_get_cgroup(int pidfd, char **ret_cgroup) { return 0; } -_public_ int sd_peer_get_session(int fd, char **session) { - struct ucred ucred = UCRED_INVALID; +_public_ int sd_peer_get_session(int fd, char **ret) { int r; assert_return(fd >= 0, -EBADF); - assert_return(session, -EINVAL); + assert_return(ret, -EINVAL); - r = getpeercred(fd, &ucred); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = getpeerpidref(fd, &pidref); if (r < 0) return r; - return cg_pid_get_session(ucred.pid, session); + return cg_pidref_get_session(&pidref, ret); } -_public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) { - struct ucred ucred; +_public_ int sd_peer_get_owner_uid(int fd, uid_t *ret) { int r; assert_return(fd >= 0, -EBADF); - assert_return(uid, -EINVAL); + assert_return(ret, -EINVAL); - r = getpeercred(fd, &ucred); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = getpeerpidref(fd, &pidref); if (r < 0) return r; - return cg_pid_get_owner_uid(ucred.pid, uid); + return cg_pidref_get_owner_uid(&pidref, ret); } -_public_ int sd_peer_get_unit(int fd, char **unit) { - struct ucred ucred; +_public_ int sd_peer_get_unit(int fd, char **ret) { int r; assert_return(fd >= 0, -EBADF); - assert_return(unit, -EINVAL); + assert_return(ret, -EINVAL); - r = getpeercred(fd, &ucred); + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + r = getpeerpidref(fd, &pidref); if (r < 0) return r; - return cg_pid_get_unit(ucred.pid, unit); + return cg_pidref_get_unit(&pidref, ret); } _public_ int sd_peer_get_user_unit(int fd, char **unit) { From dd445d6e99a5aa62caa272174d3577c0f7e49c03 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 6 Jan 2025 09:54:13 +0100 Subject: [PATCH 4/4] cgroup-util: add remoteness checks to all cg_pidref_get_xyz() calls --- src/basic/cgroup-util.c | 4 ++++ src/test/test-cgroup-util.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 9d41db2883..25dcab91fc 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -839,6 +839,8 @@ int cg_pidref_get_path(const char *controller, const PidRef *pidref, char **ret_ if (!pidref_is_set(pidref)) return -ESRCH; + if (pidref_is_remote(pidref)) + return -EREMOTE; r = cg_pid_get_path(controller, pidref->pid, &path); if (r < 0) @@ -1204,6 +1206,8 @@ int cg_pidref_get_unit(const PidRef *pidref, char **ret) { if (!pidref_is_set(pidref)) return -ESRCH; + if (pidref_is_remote(pidref)) + return -EREMOTE; r = cg_pid_get_unit(pidref->pid, &unit); if (r < 0) diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 9fa3ddf9d1..0170cb279b 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -210,11 +210,11 @@ TEST(proc) { if (pidref_is_kernel_thread(&pid) != 0) continue; - cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid.pid, &path); + cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, &pid, &path); cg_pid_get_path_shifted(pid.pid, NULL, &path_shifted); cg_pidref_get_owner_uid(&pid, &uid); cg_pidref_get_session(&pid, &session); - cg_pid_get_unit(pid.pid, &unit); + cg_pidref_get_unit(&pid, &unit); cg_pid_get_user_unit(pid.pid, &user_unit); cg_pid_get_machine_name(pid.pid, &machine); cg_pid_get_slice(pid.pid, &slice);