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);
|
||||
|
||||
+30
-22
@@ -757,31 +757,34 @@ static int compose_open_fds(pid_t pid, char **ret) {
|
||||
* container parent (the pid's process isn't 'containerized').
|
||||
* Returns a negative number on errors.
|
||||
*/
|
||||
static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
|
||||
pid_t container_pid;
|
||||
static int get_process_container_parent_cmdline(PidRef *pid, char** ret_cmdline) {
|
||||
const char *proc_root_path;
|
||||
struct stat root_stat, proc_root_stat;
|
||||
int r;
|
||||
|
||||
assert(pidref_is_set(pid));
|
||||
assert(!pidref_is_remote(pid));
|
||||
|
||||
/* To compare inodes of / and /proc/[pid]/root */
|
||||
if (stat("/", &root_stat) < 0)
|
||||
return -errno;
|
||||
|
||||
proc_root_path = procfs_file_alloca(pid, "root");
|
||||
proc_root_path = procfs_file_alloca(pid->pid, "root");
|
||||
if (stat(proc_root_path, &proc_root_stat) < 0)
|
||||
return -errno;
|
||||
|
||||
/* The process uses system root. */
|
||||
if (stat_inode_same(&proc_root_stat, &root_stat)) {
|
||||
*cmdline = NULL;
|
||||
*ret_cmdline = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_(pidref_done) PidRef container_pid = PIDREF_NULL;
|
||||
r = namespace_get_leader(pid, NAMESPACE_MOUNT, &container_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pid_get_cmdline(container_pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, cmdline);
|
||||
r = pidref_get_cmdline(&container_pid, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, ret_cmdline);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1385,10 +1388,10 @@ static int gather_pid_metadata_from_procfs(struct iovec_wrapper *iovw, Context *
|
||||
if (cg_pid_get_user_unit(pid, &t) >= 0)
|
||||
(void) iovw_put_string_field_free(iovw, "COREDUMP_USER_UNIT=", t);
|
||||
|
||||
if (sd_pid_get_session(pid, &t) >= 0)
|
||||
if (cg_pidref_get_session(&context->pidref, &t) >= 0)
|
||||
(void) iovw_put_string_field_free(iovw, "COREDUMP_SESSION=", t);
|
||||
|
||||
if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) {
|
||||
if (cg_pidref_get_owner_uid(&context->pidref, &owner_uid) >= 0) {
|
||||
r = asprintf(&t, UID_FMT, owner_uid);
|
||||
if (r > 0)
|
||||
(void) iovw_put_string_field_free(iovw, "COREDUMP_OWNER_UID=", t);
|
||||
@@ -1451,7 +1454,7 @@ static int gather_pid_metadata_from_procfs(struct iovec_wrapper *iovw, Context *
|
||||
|
||||
/* If the process' root is "/", then there is a chance it has
|
||||
* mounted own root and hence being containerized. */
|
||||
if (proc_self_root_is_slash && get_process_container_parent_cmdline(pid, &t) > 0)
|
||||
if (proc_self_root_is_slash && get_process_container_parent_cmdline(&context->pidref, &t) > 0)
|
||||
(void) iovw_put_string_field_free(iovw, "COREDUMP_CONTAINER_CMDLINE=", t);
|
||||
}
|
||||
|
||||
@@ -1518,11 +1521,14 @@ static int receive_ucred(int transport_fd, struct ucred *ret_ucred) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int can_forward_coredump(pid_t pid) {
|
||||
static int can_forward_coredump(const PidRef *pid) {
|
||||
_cleanup_free_ char *cgroup = NULL, *path = NULL, *unit = NULL;
|
||||
int r;
|
||||
|
||||
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
|
||||
assert(pidref_is_set(pid));
|
||||
assert(!pidref_is_remote(pid));
|
||||
|
||||
r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1551,7 +1557,7 @@ static int can_forward_coredump(pid_t pid) {
|
||||
static int forward_coredump_to_container(Context *context) {
|
||||
_cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, netnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF;
|
||||
_cleanup_close_pair_ int pair[2] = EBADF_PAIR;
|
||||
pid_t leader_pid, child;
|
||||
pid_t child;
|
||||
struct ucred ucred = {
|
||||
.pid = context->pidref.pid,
|
||||
.uid = context->uid,
|
||||
@@ -1561,11 +1567,12 @@ static int forward_coredump_to_container(Context *context) {
|
||||
|
||||
assert(context);
|
||||
|
||||
r = namespace_get_leader(context->pidref.pid, NAMESPACE_PID, &leader_pid);
|
||||
_cleanup_(pidref_done) PidRef leader_pid = PIDREF_NULL;
|
||||
r = namespace_get_leader(&context->pidref, NAMESPACE_PID, &leader_pid);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get namespace leader: %m");
|
||||
|
||||
r = can_forward_coredump(leader_pid);
|
||||
r = can_forward_coredump(&leader_pid);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to check if coredump can be forwarded: %m");
|
||||
if (r == 0)
|
||||
@@ -1580,15 +1587,15 @@ static int forward_coredump_to_container(Context *context) {
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to set SO_PASSCRED: %m");
|
||||
|
||||
r = namespace_open(leader_pid, &pidnsfd, &mntnsfd, &netnsfd, &usernsfd, &rootfd);
|
||||
r = pidref_namespace_open(&leader_pid, &pidnsfd, &mntnsfd, &netnsfd, &usernsfd, &rootfd);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to join namespaces of PID " PID_FMT ": %m", leader_pid);
|
||||
return log_debug_errno(r, "Failed to open namespaces of PID " PID_FMT ": %m", leader_pid.pid);
|
||||
|
||||
r = namespace_fork("(sd-coredumpns)", "(sd-coredump)", NULL, 0,
|
||||
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM,
|
||||
pidnsfd, mntnsfd, netnsfd, usernsfd, rootfd, &child);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to fork into namespaces of PID " PID_FMT ": %m", leader_pid);
|
||||
return log_debug_errno(r, "Failed to fork into namespaces of PID " PID_FMT ": %m", leader_pid.pid);
|
||||
if (r == 0) {
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
@@ -1710,12 +1717,13 @@ static int acquire_pid_mount_tree_fd(const Context *context, int *ret_fd) {
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair) < 0)
|
||||
return log_error_errno(errno, "Failed to create socket pair: %m");
|
||||
|
||||
r = namespace_open(context->pidref.pid,
|
||||
/* ret_pidns_fd= */ NULL,
|
||||
&mntns_fd,
|
||||
/* ret_netns_fd= */ NULL,
|
||||
/* ret_userns_fd= */ NULL,
|
||||
&root_fd);
|
||||
r = pidref_namespace_open(
|
||||
&context->pidref,
|
||||
/* ret_pidns_fd= */ NULL,
|
||||
&mntns_fd,
|
||||
/* ret_netns_fd= */ NULL,
|
||||
/* ret_userns_fd= */ NULL,
|
||||
&root_fd);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open mount namespace of crashing process: %m");
|
||||
|
||||
|
||||
@@ -681,7 +681,7 @@ int machine_openpt(Machine *m, int flags, char **ret_peer) {
|
||||
if (!pidref_is_set(&m->leader))
|
||||
return -EINVAL;
|
||||
|
||||
return openpt_allocate_in_namespace(m->leader.pid, flags, ret_peer);
|
||||
return openpt_allocate_in_namespace(&m->leader, flags, ret_peer);
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
@@ -700,7 +700,7 @@ int machine_open_terminal(Machine *m, const char *path, int mode) {
|
||||
if (!pidref_is_set(&m->leader))
|
||||
return -EINVAL;
|
||||
|
||||
return open_terminal_in_namespace(m->leader.pid, path, mode);
|
||||
return open_terminal_in_namespace(&m->leader, path, mode);
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -1447,14 +1447,9 @@ int wipe_fully_visible_api_fs(int mntns_fd) {
|
||||
|
||||
log_debug("Wiping fully visible API FS");
|
||||
|
||||
r = namespace_open(0,
|
||||
/* ret_pidns_fd = */ NULL,
|
||||
&orig_mntns_fd,
|
||||
/* ret_netns_fd = */ NULL,
|
||||
/* ret_userns_fd = */ NULL,
|
||||
/* ret_root_fd = */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to pin originating mount namespace: %m");
|
||||
orig_mntns_fd = namespace_open_by_type(NAMESPACE_MOUNT);
|
||||
if (orig_mntns_fd < 0)
|
||||
return log_error_errno(orig_mntns_fd, "Failed to pin originating mount namespace: %m");
|
||||
|
||||
r = namespace_enter(/* pidns_fd = */ -EBADF,
|
||||
mntns_fd,
|
||||
|
||||
@@ -476,14 +476,9 @@ static int netns_child_begin(int netns_fd, int *ret_original_netns_fd) {
|
||||
assert(netns_fd >= 0);
|
||||
|
||||
if (ret_original_netns_fd) {
|
||||
r = namespace_open(0,
|
||||
/* ret_pidns_fd = */ NULL,
|
||||
/* ret_mntns_fd = */ NULL,
|
||||
&original_netns_fd,
|
||||
/* ret_userns_fd = */ NULL,
|
||||
/* ret_root_fd = */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open original network namespace: %m");
|
||||
original_netns_fd = namespace_open_by_type(NAMESPACE_NET);
|
||||
if (original_netns_fd < 0)
|
||||
return log_error_errno(original_netns_fd, "Failed to open original network namespace: %m");
|
||||
}
|
||||
|
||||
r = namespace_enter(/* pidns_fd = */ -EBADF,
|
||||
|
||||
+3
-8
@@ -4012,14 +4012,9 @@ static int outer_child(
|
||||
return r;
|
||||
|
||||
if (arg_userns_mode != USER_NAMESPACE_NO) {
|
||||
r = namespace_open(0,
|
||||
/* ret_pidns_fd = */ NULL,
|
||||
&mntns_fd,
|
||||
/* ret_netns_fd = */ NULL,
|
||||
/* ret_userns_fd = */ NULL,
|
||||
/* ret_root_fd = */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to pin outer mount namespace: %m");
|
||||
mntns_fd = namespace_open_by_type(NAMESPACE_MOUNT);
|
||||
if (mntns_fd < 0)
|
||||
return log_error_errno(mntns_fd, "Failed to pin outer mount namespace: %m");
|
||||
|
||||
l = send_one_fd(fd_outer_socket, mntns_fd, 0);
|
||||
if (l < 0)
|
||||
|
||||
@@ -301,14 +301,9 @@ int machine_id_commit(const char *root) {
|
||||
fd = safe_close(fd);
|
||||
|
||||
/* Store current mount namespace */
|
||||
r = namespace_open(0,
|
||||
/* ret_pidns_fd = */ NULL,
|
||||
&initial_mntns_fd,
|
||||
/* ret_netns_fd = */ NULL,
|
||||
/* ret_userns_fd = */ NULL,
|
||||
/* ret_root_fd = */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Can't fetch current mount namespace: %m");
|
||||
initial_mntns_fd = namespace_open_by_type(NAMESPACE_MOUNT);
|
||||
if (initial_mntns_fd < 0)
|
||||
return log_error_errno(initial_mntns_fd, "Can't fetch current mount namespace: %m");
|
||||
|
||||
/* Switch to a new mount namespace, isolate ourself and unmount etc_machine_id in our new namespace */
|
||||
r = detach_mount_namespace();
|
||||
|
||||
@@ -428,15 +428,9 @@ int netns_get_nsid(int netnsfd, uint32_t *ret) {
|
||||
int r;
|
||||
|
||||
if (netnsfd < 0) {
|
||||
r = namespace_open(
|
||||
0,
|
||||
/* ret_pidns_fd = */ NULL,
|
||||
/* ret_mntns_fd = */ NULL,
|
||||
&_netns_fd,
|
||||
/* ret_userns_fd = */ NULL,
|
||||
/* ret_root_fd = */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
_netns_fd = namespace_open_by_type(NAMESPACE_NET);
|
||||
if (_netns_fd < 0)
|
||||
return _netns_fd;
|
||||
|
||||
netnsfd = _netns_fd;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "namespace.h"
|
||||
#include "pidref.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
@@ -365,6 +366,54 @@ TEST(process_is_owned_by_uid) {
|
||||
ASSERT_OK(pidref_wait_for_terminate(&pid, /* ret= */ NULL));
|
||||
}
|
||||
|
||||
TEST(namespace_get_leader) {
|
||||
int r;
|
||||
|
||||
_cleanup_(pidref_done) PidRef original = PIDREF_NULL;
|
||||
ASSERT_OK(pidref_set_self(&original));
|
||||
|
||||
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
||||
r = pidref_safe_fork("(child)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_NEW_MOUNTNS|FORK_WAIT|FORK_LOG, &pid);
|
||||
ASSERT_OK(r);
|
||||
if (r == 0) {
|
||||
|
||||
_cleanup_(pidref_done) PidRef pid2 = PIDREF_NULL;
|
||||
r = pidref_safe_fork("(child)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_WAIT|FORK_LOG, &pid2);
|
||||
ASSERT_OK(r);
|
||||
|
||||
if (r == 0) {
|
||||
log_info("PID hierarchy: " PID_FMT " ← " PID_FMT " ← " PID_FMT, original.pid, pid.pid, pid2.pid);
|
||||
|
||||
_cleanup_(pidref_done) PidRef self = PIDREF_NULL;
|
||||
ASSERT_OK(pidref_set_self(&self));
|
||||
ASSERT_TRUE(pidref_equal(&self, &pid2));
|
||||
|
||||
_cleanup_(pidref_done) PidRef parent = PIDREF_NULL;
|
||||
ASSERT_OK(pidref_set_parent(&parent));
|
||||
ASSERT_TRUE(pidref_equal(&parent, &pid));
|
||||
ASSERT_TRUE(!pidref_equal(&self, &pid));
|
||||
ASSERT_TRUE(!pidref_equal(&self, &parent));
|
||||
|
||||
_cleanup_(pidref_done) PidRef grandparent = PIDREF_NULL;
|
||||
ASSERT_OK(pidref_get_ppid_as_pidref(&parent, &grandparent));
|
||||
ASSERT_TRUE(pidref_equal(&grandparent, &original));
|
||||
ASSERT_TRUE(!pidref_equal(&grandparent, &self));
|
||||
ASSERT_TRUE(!pidref_equal(&grandparent, &pid));
|
||||
ASSERT_TRUE(!pidref_equal(&grandparent, &pid2));
|
||||
ASSERT_TRUE(!pidref_equal(&grandparent, &parent));
|
||||
|
||||
_cleanup_(pidref_done) PidRef leader = PIDREF_NULL;
|
||||
ASSERT_OK(namespace_get_leader(&self, NAMESPACE_MOUNT, &leader));
|
||||
ASSERT_TRUE(pidref_equal(&parent, &leader));
|
||||
ASSERT_TRUE(pidref_equal(&pid, &leader));
|
||||
ASSERT_TRUE(!pidref_equal(&self, &leader));
|
||||
ASSERT_TRUE(!pidref_equal(&pid2, &leader));
|
||||
ASSERT_TRUE(!pidref_equal(&original, &leader));
|
||||
ASSERT_TRUE(!pidref_equal(&grandparent, &leader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
if (!have_namespaces())
|
||||
return log_tests_skipped("Don't have namespace support or lacking privileges");
|
||||
|
||||
@@ -848,6 +848,29 @@ TEST(pid_get_ppid) {
|
||||
|
||||
pid = ppid;
|
||||
}
|
||||
|
||||
/* the same via pidref */
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
ASSERT_OK(pidref_set_self(&pidref));
|
||||
for (;;) {
|
||||
_cleanup_free_ char *c1 = NULL, *c2 = NULL;
|
||||
_cleanup_(pidref_done) PidRef parent = PIDREF_NULL;
|
||||
r = pidref_get_ppid_as_pidref(&pidref, &parent);
|
||||
if (r == -EADDRNOTAVAIL) {
|
||||
log_info("No further parent PID");
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT_OK(r);
|
||||
|
||||
ASSERT_OK(pidref_get_cmdline(&pidref, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c1));
|
||||
ASSERT_OK(pidref_get_cmdline(&parent, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &c2));
|
||||
|
||||
log_info("Parent of " PID_FMT " (%s) is " PID_FMT " (%s).", pidref.pid, c1, parent.pid, c2);
|
||||
|
||||
pidref_done(&pidref);
|
||||
pidref = TAKE_PIDREF(parent);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(set_oom_score_adjust) {
|
||||
|
||||
Reference in New Issue
Block a user