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.
This commit is contained in:
Luca Boccassi
2023-01-20 12:18:05 +00:00
parent f840c7d58d
commit da20baaecc
6 changed files with 332 additions and 1 deletions
+8
View File
@@ -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;
+201
View File
@@ -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;
+32
View File
@@ -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)