convert more code to PidRef (#35895)

This commit is contained in:
Lennart Poettering
2025-01-11 23:14:33 +01:00
committed by GitHub
15 changed files with 204 additions and 86 deletions
+23 -8
View File
@@ -351,31 +351,46 @@ int pidref_in_same_namespace(PidRef *pid1, PidRef *pid2, NamespaceType type) {
return fd_inode_same(ns1, ns2);
}
int namespace_get_leader(pid_t pid, NamespaceType type, pid_t *ret) {
int namespace_get_leader(PidRef *pidref, NamespaceType type, PidRef *ret) {
int r;
assert(pid >= 0);
/* Note: we don't bother with pidref_is_set()/pidref_is_remote() here, as the first call we do,
* pidref_get_ppid_as_pidref() calls those anyway */
assert(type >= 0 && type < _NAMESPACE_TYPE_MAX);
assert(ret);
for (;;) {
pid_t ppid;
_cleanup_(pidref_done) PidRef current = PIDREF_NULL;
PidRef *c = pidref;
r = pid_get_ppid(pid, &ppid);
for (;;) {
_cleanup_(pidref_done) PidRef parent = PIDREF_NULL;
r = pidref_get_ppid_as_pidref(c, &parent);
if (r < 0)
return r;
r = in_same_namespace(pid, ppid, type);
r = pidref_in_same_namespace(c, &parent, type);
if (r < 0)
return r;
if (r == 0) {
/* If the parent and the child are not in the same namespace, then the child is
* the leader we are looking for. */
*ret = pid;
if (pidref_is_set(&current))
*ret = TAKE_PIDREF(current);
else {
r = pidref_copy(c, ret);
if (r < 0)
return r;
}
return 0;
}
pid = ppid;
pidref_done(&current);
current = TAKE_PIDREF(parent);
c = &current;
}
}
+1 -1
View File
@@ -62,7 +62,7 @@ static inline int in_same_namespace(pid_t pid1, pid_t pid2, NamespaceType type)
type);
}
int namespace_get_leader(pid_t pid, NamespaceType type, pid_t *ret);
int namespace_get_leader(PidRef *pidref, NamespaceType type, PidRef *ret);
int detach_mount_namespace(void);
int detach_mount_namespace_harder(uid_t target_uid, gid_t target_gid);
+45 -3
View File
@@ -742,6 +742,44 @@ int pidref_get_ppid(const PidRef *pidref, pid_t *ret) {
return 0;
}
int pidref_get_ppid_as_pidref(const PidRef *pidref, PidRef *ret) {
pid_t ppid;
int r;
assert(ret);
r = pidref_get_ppid(pidref, &ppid);
if (r < 0)
return r;
for (unsigned attempt = 0; attempt < 16; attempt++) {
_cleanup_(pidref_done) PidRef parent = PIDREF_NULL;
r = pidref_set_pid(&parent, ppid);
if (r < 0)
return r;
/* If we have a pidfd of the original PID, let's verify that the process we acquired really
* is the parent still */
if (pidref->fd >= 0) {
r = pidref_get_ppid(pidref, &ppid);
if (r < 0)
return r;
/* Did the PPID change since we queried it? if so we might have pinned the wrong
* process, if its PID got reused by now. Let's try again */
if (parent.pid != ppid)
continue;
}
*ret = TAKE_PIDREF(parent);
return 0;
}
/* Give up after 16 tries */
return -ENOTRECOVERABLE;
}
int pid_get_start_time(pid_t pid, usec_t *ret) {
_cleanup_free_ char *line = NULL;
const char *p;
@@ -1745,12 +1783,16 @@ int pidref_safe_fork_full(
pid_t pid;
int r, q;
assert(!FLAGS_SET(flags, FORK_WAIT));
r = safe_fork_full(name, stdio_fds, except_fds, n_except_fds, flags, &pid);
if (r < 0)
if (r < 0 || !ret_pid)
return r;
if (r > 0 && FLAGS_SET(flags, FORK_WAIT)) {
/* If we are in the parent and successfully waited, then the process doesn't exist anymore */
*ret_pid = PIDREF_NULL;
return r;
}
q = pidref_set_pid(ret_pid, pid);
if (q < 0) /* Let's not fail for this, no matter what, the process exists after all, and that's key */
*ret_pid = PIDREF_MAKE_FROM_PID(pid);
+1
View File
@@ -54,6 +54,7 @@ int get_process_root(pid_t pid, char **ret);
int get_process_environ(pid_t pid, char **ret);
int pid_get_ppid(pid_t pid, pid_t *ret);
int pidref_get_ppid(const PidRef *pidref, pid_t *ret);
int pidref_get_ppid_as_pidref(const PidRef *pidref, PidRef *ret);
int pid_get_start_time(pid_t pid, usec_t *ret);
int pidref_get_start_time(const PidRef *pid, usec_t *ret);
int get_process_umask(pid_t pid, mode_t *ret);
+12 -7
View File
@@ -1355,14 +1355,16 @@ static int ptsname_namespace(int pty, char **ret) {
return 0;
}
int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_peer_path) {
int openpt_allocate_in_namespace(
const PidRef *pidref,
int flags,
char **ret_peer_path) {
_cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF, fd = -EBADF;
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
int r;
assert(pid > 0);
r = namespace_open(pid, &pidnsfd, &mntnsfd, /* ret_netns_fd = */ NULL, &usernsfd, &rootfd);
r = pidref_namespace_open(pidref, &pidnsfd, &mntnsfd, /* ret_netns_fd = */ NULL, &usernsfd, &rootfd);
if (r < 0)
return r;
@@ -1411,15 +1413,18 @@ int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_peer_path) {
return TAKE_FD(fd);
}
int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
int open_terminal_in_namespace(
const PidRef *pidref,
const char *name,
int mode) {
_cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF;
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
int r;
assert(pid > 0);
assert(name);
r = namespace_open(pid, &pidnsfd, &mntnsfd, /* ret_netns_fd= */ NULL, &usernsfd, &rootfd);
r = pidref_namespace_open(pidref, &pidnsfd, &mntnsfd, /* ret_netns_fd= */ NULL, &usernsfd, &rootfd);
if (r < 0)
return r;
+3 -2
View File
@@ -10,6 +10,7 @@
#include <unistd.h>
#include "macro.h"
#include "pidref.h"
#include "time-util.h"
/* Erase characters until the end of the line */
@@ -143,8 +144,8 @@ int getttyname_harder(int fd, char **ret);
int ptsname_malloc(int fd, char **ret);
int openpt_allocate(int flags, char **ret_peer);
int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_peer);
int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
int openpt_allocate_in_namespace(const PidRef *pidref, int flags, char **ret_peer);
int open_terminal_in_namespace(const PidRef *pidref, const char *name, int mode);
int vt_restore(int fd);
int vt_release(int fd, bool restore_vt);