From: Nick Rosbrook Date: Fri, 8 Sep 2023 21:03:56 +0000 (-0400) Subject: process-util: introduce namespace_get_leader helper X-Git-Tag: v255-rc1~231^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ade39d9ab849a6e8ae0f182a09e33b670463169c;p=thirdparty%2Fsystemd.git process-util: introduce namespace_get_leader helper For a given PID and namespace type, this helper function gives the PID of the leader of the namespace containing the given PID. Use this in systemd-coredump instead of using the existing get_mount_namespace_leader. This helper will be used again in a later commit. --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 4928379bd75..7cebbe1cc10 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -318,6 +318,33 @@ int container_get_leader(const char *machine, pid_t *pid) { return 0; } +int namespace_get_leader(pid_t pid, NamespaceType type, pid_t *ret) { + int r; + + assert(ret); + + for (;;) { + pid_t ppid; + + r = get_process_ppid(pid, &ppid); + if (r < 0) + return r; + + r = in_same_namespace(pid, ppid, 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; + return 0; + } + + pid = ppid; + } +} + int is_kernel_thread(pid_t pid) { _cleanup_free_ char *line = NULL; unsigned long long flags; diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 8f87fdc2ae7..7acc102f40c 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -14,6 +14,7 @@ #include "alloc-util.h" #include "format-util.h" #include "macro.h" +#include "namespace-util.h" #include "time-util.h" #define procfs_file_alloca(pid, field) \ @@ -53,6 +54,8 @@ int get_process_umask(pid_t pid, mode_t *ret); int container_get_leader(const char *machine, pid_t *pid); +int namespace_get_leader(pid_t pid, NamespaceType type, pid_t *ret); + int wait_for_terminate(pid_t pid, siginfo_t *status); typedef enum WaitFlags { diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 3a82a717428..e9b1f64e4f3 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -713,56 +713,6 @@ static int compose_open_fds(pid_t pid, char **ret) { return memstream_finalize(&m, ret, NULL); } -static int get_process_ns(pid_t pid, const char *namespace, ino_t *ns) { - const char *p; - struct stat stbuf; - _cleanup_close_ int proc_ns_dir_fd = -EBADF; - - p = procfs_file_alloca(pid, "ns"); - - proc_ns_dir_fd = open(p, O_DIRECTORY | O_CLOEXEC | O_RDONLY); - if (proc_ns_dir_fd < 0) - return -errno; - - if (fstatat(proc_ns_dir_fd, namespace, &stbuf, /* flags */0) < 0) - return -errno; - - *ns = stbuf.st_ino; - return 0; -} - -static int get_mount_namespace_leader(pid_t pid, pid_t *ret) { - ino_t proc_mntns; - int r; - - r = get_process_ns(pid, "mnt", &proc_mntns); - if (r < 0) - return r; - - for (;;) { - ino_t parent_mntns; - pid_t ppid; - - r = get_process_ppid(pid, &ppid); - if (r == -EADDRNOTAVAIL) /* Reached the top (i.e. typically PID 1, but could also be a process - * whose parent is not in our pidns) */ - return -ENOENT; - if (r < 0) - return r; - - r = get_process_ns(ppid, "mnt", &parent_mntns); - if (r < 0) - return r; - - if (proc_mntns != parent_mntns) { - *ret = ppid; - return 0; - } - - pid = ppid; - } -} - /* Returns 1 if the parent was found. * Returns 0 if there is not a process we can call the pid's * container parent (the pid's process isn't 'containerized'). @@ -788,7 +738,7 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) { return 0; } - r = get_mount_namespace_leader(pid, &container_pid); + r = namespace_get_leader(pid, NAMESPACE_MOUNT, &container_pid); if (r < 0) return r;