mirror of
https://github.com/systemd/systemd.git
synced 2025-03-11 20:58:27 +03:00
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.
This commit is contained in:
parent
9764bca98e
commit
ade39d9ab8
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user