Messages in this thread | | | From | Mika Penttilä <> | Subject | Re: [PATCH 2/4] pid: add pidctl() | Date | Mon, 25 Mar 2019 17:20:54 +0000 |
| |
Hi!
> +SYSCALL_DEFINE5(pidctl, unsigned int, cmd, pid_t, pid, int, source, int, target, > + unsigned int, flags) > +{ > + struct pid_namespace *source_ns = NULL, *target_ns = NULL; > + struct pid *struct_pid; > + pid_t result; > + > + switch (cmd) { > + case PIDCMD_QUERY_PIDNS: > + if (pid != 0) > + return -EINVAL; > + pid = 1; > + /* fall through */ > + case PIDCMD_QUERY_PID: > + if (flags != 0) > + return -EINVAL; > + break; > + case PIDCMD_GET_PIDFD: > + if (flags & ~PIDCTL_CLOEXEC) > + return -EINVAL; > + break; > + default: > + return -EOPNOTSUPP; > + } > + > + source_ns = get_pid_ns_by_fd(source); > + result = PTR_ERR(source_ns); > + if (IS_ERR(source_ns)) > + goto err_source; > + > + target_ns = get_pid_ns_by_fd(target); > + result = PTR_ERR(target_ns); > + if (IS_ERR(target_ns)) > + goto err_target; > + > + if (cmd == PIDCMD_QUERY_PIDNS) { > + result = pidns_related(source_ns, target_ns); > + } else { > + rcu_read_lock(); > + struct_pid = find_pid_ns(pid, source_ns); > + result = struct_pid ? pid_nr_ns(struct_pid, target_ns) : -ESRCH;
Should you do get_pid(struct_pid) here to keep it alive till pidfd_create_fd() ?
> + rcu_read_unlock(); > + > + if (cmd == PIDCMD_GET_PIDFD) { > + int cloexec = (flags & PIDCTL_CLOEXEC) ? O_CLOEXEC : 0; > + if (result > 0) > + result = pidfd_create_fd(struct_pid, cloexec); > + else if (result == 0) > + result = -ENOENT; > + } > + } > + > + if (target) > + put_pid_ns(target_ns); > +err_target: > + if (source) > + put_pid_ns(source_ns); > +err_source: > + return result; > +} > + > void __init pid_idr_init(void) > { > /* Verify no one has done anything silly: */ > diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c > index aa6e72fb7c08..1c863fb3d55a 100644 > --- a/kernel/pid_namespace.c > +++ b/kernel/pid_namespace.c > @@ -429,6 +429,31 @@ static struct ns_common *pidns_get_parent(struct ns_common *ns) > return &get_pid_ns(pid_ns)->ns; > } > > +/** > + * pidnscmp - Determine if @ancestor is ancestor of @descendant > + * @ancestor: pidns suspected to be the ancestor of @descendant > + * @descendant: pidns suspected to be the descendant of @ancestor > + * > + * Returns -1 if @ancestor is not an ancestor of @descendant, > + * 0 if @ancestor is the same pidns as @descendant, 1 if @ancestor > + * is an ancestor of @descendant. > + */ > +int pidnscmp(struct pid_namespace *ancestor, struct pid_namespace *descendant) > +{ > + if (ancestor == descendant) > + return 0; > + > + for (;;) { > + if (!descendant) > + return -1; > + if (descendant == ancestor) > + break; > + descendant = descendant->parent; > + } > + > + return 1; > +} > + > static struct user_namespace *pidns_owner(struct ns_common *ns) > { > return to_pid_ns(ns)->user_ns;
| |