diff --git a/fs/nsfs.c b/fs/nsfs.c index af352dadffe1..ad6bb91a3e23 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -124,9 +125,12 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { struct user_namespace *user_ns; + struct pid_namespace *pid_ns; + struct task_struct *tsk; struct ns_common *ns = get_proc_ns(file_inode(filp)); uid_t __user *argp; uid_t uid; + int ret; switch (ioctl) { case NS_GET_USERNS: @@ -157,9 +161,56 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl, id = mnt_ns->seq; return put_user(id, idp); } + case NS_GET_PID_FROM_PIDNS: + fallthrough; + case NS_GET_TGID_FROM_PIDNS: + fallthrough; + case NS_GET_PID_IN_PIDNS: + fallthrough; + case NS_GET_TGID_IN_PIDNS: + if (ns->ops->type != CLONE_NEWPID) + return -EINVAL; + + ret = -ESRCH; + pid_ns = container_of(ns, struct pid_namespace, ns); + + rcu_read_lock(); + + if (ioctl == NS_GET_PID_IN_PIDNS || + ioctl == NS_GET_TGID_IN_PIDNS) + tsk = find_task_by_vpid(arg); + else + tsk = find_task_by_pid_ns(arg, pid_ns); + if (!tsk) + break; + + switch (ioctl) { + case NS_GET_PID_FROM_PIDNS: + ret = task_pid_vnr(tsk); + break; + case NS_GET_TGID_FROM_PIDNS: + ret = task_tgid_vnr(tsk); + break; + case NS_GET_PID_IN_PIDNS: + ret = task_pid_nr_ns(tsk, pid_ns); + break; + case NS_GET_TGID_IN_PIDNS: + ret = task_tgid_nr_ns(tsk, pid_ns); + break; + default: + ret = 0; + break; + } + rcu_read_unlock(); + + if (!ret) + ret = -ESRCH; + break; default: - return -ENOTTY; + ret = -ENOTTY; } + + return ret; } int ns_get_name(char *buf, size_t size, struct task_struct *task, diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h index 56e8b1639b98..b133211331f6 100644 --- a/include/uapi/linux/nsfs.h +++ b/include/uapi/linux/nsfs.h @@ -17,5 +17,13 @@ #define NS_GET_OWNER_UID _IO(NSIO, 0x4) /* Get the id for a mount namespace */ #define NS_GET_MNTNS_ID _IO(NSIO, 0x5) +/* Translate pid from target pid namespace into the caller's pid namespace. */ +#define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x6, int) +/* Return thread-group leader id of pid in the callers pid namespace. */ +#define NS_GET_TGID_FROM_PIDNS _IOR(NSIO, 0x7, int) +/* Translate pid from caller's pid namespace into a target pid namespace. */ +#define NS_GET_PID_IN_PIDNS _IOR(NSIO, 0x8, int) +/* Return thread-group leader id of pid in the target pid namespace. */ +#define NS_GET_TGID_IN_PIDNS _IOR(NSIO, 0x9, int) #endif /* __LINUX_NSFS_H */