convert more code to PidRef (#35895)
This commit is contained in:
@@ -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(¤t))
|
||||
*ret = TAKE_PIDREF(current);
|
||||
else {
|
||||
r = pidref_copy(c, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid = ppid;
|
||||
pidref_done(¤t);
|
||||
current = TAKE_PIDREF(parent);
|
||||
c = ¤t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user