diff --git a/include/uapi/linux/pidfd.h b/include/uapi/linux/pidfd.h index 4540f6301b8c..e0abd0b18841 100644 --- a/include/uapi/linux/pidfd.h +++ b/include/uapi/linux/pidfd.h @@ -23,6 +23,30 @@ #define PIDFD_INFO_SIZE_VER0 64 /* sizeof first published struct */ +/* + * The concept of process and threads in userland and the kernel is a confusing + * one - within the kernel every thread is a 'task' with its own individual PID, + * however from userland's point of view threads are grouped by a single PID, + * which is that of the 'thread group leader', typically the first thread + * spawned. + * + * To cut the Gideon knot, for internal kernel usage, we refer to + * PIDFD_SELF_THREAD to refer to the current thread (or task from a kernel + * perspective), and PIDFD_SELF_THREAD_GROUP to refer to the current thread + * group leader... + */ +#define PIDFD_SELF_THREAD -10000 /* Current thread. */ +#define PIDFD_SELF_THREAD_GROUP -20000 /* Current thread group leader. */ + +/* + * ...and for userland we make life simpler - PIDFD_SELF refers to the current + * thread, PIDFD_SELF_PROCESS refers to the process thread group leader. + * + * For nearly all practical uses, a user will want to use PIDFD_SELF. + */ +#define PIDFD_SELF PIDFD_SELF_THREAD +#define PIDFD_SELF_PROCESS PIDFD_SELF_THREAD_GROUP + struct pidfd_info { /* * This mask is similar to the request_mask in statx(2). diff --git a/kernel/pid.c b/kernel/pid.c index 924084713be8..22f5d2b2e290 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -564,15 +564,29 @@ struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags) */ struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags) { - unsigned int f_flags; + unsigned int f_flags = 0; struct pid *pid; struct task_struct *task; + enum pid_type type; - pid = pidfd_get_pid(pidfd, &f_flags); - if (IS_ERR(pid)) - return ERR_CAST(pid); + switch (pidfd) { + case PIDFD_SELF_THREAD: + type = PIDTYPE_PID; + pid = get_task_pid(current, type); + break; + case PIDFD_SELF_THREAD_GROUP: + type = PIDTYPE_TGID; + pid = get_task_pid(current, type); + break; + default: + pid = pidfd_get_pid(pidfd, &f_flags); + if (IS_ERR(pid)) + return ERR_CAST(pid); + type = PIDTYPE_TGID; + break; + } - task = get_pid_task(pid, PIDTYPE_TGID); + task = get_pid_task(pid, type); put_pid(pid); if (!task) return ERR_PTR(-ESRCH); diff --git a/kernel/signal.c b/kernel/signal.c index 875e97f6205a..081f19a24506 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -4009,56 +4009,12 @@ static struct pid *pidfd_to_pid(const struct file *file) (PIDFD_SIGNAL_THREAD | PIDFD_SIGNAL_THREAD_GROUP | \ PIDFD_SIGNAL_PROCESS_GROUP) -/** - * sys_pidfd_send_signal - Signal a process through a pidfd - * @pidfd: file descriptor of the process - * @sig: signal to send - * @info: signal info - * @flags: future flags - * - * Send the signal to the thread group or to the individual thread depending - * on PIDFD_THREAD. - * In the future extension to @flags may be used to override the default scope - * of @pidfd. - * - * Return: 0 on success, negative errno on failure - */ -SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig, - siginfo_t __user *, info, unsigned int, flags) +static int do_pidfd_send_signal(struct pid *pid, int sig, enum pid_type type, + siginfo_t __user *info, unsigned int flags) { - int ret; - struct pid *pid; kernel_siginfo_t kinfo; - enum pid_type type; - - /* Enforce flags be set to 0 until we add an extension. */ - if (flags & ~PIDFD_SEND_SIGNAL_FLAGS) - return -EINVAL; - - /* Ensure that only a single signal scope determining flag is set. */ - if (hweight32(flags & PIDFD_SEND_SIGNAL_FLAGS) > 1) - return -EINVAL; - - CLASS(fd, f)(pidfd); - if (fd_empty(f)) - return -EBADF; - - /* Is this a pidfd? */ - pid = pidfd_to_pid(fd_file(f)); - if (IS_ERR(pid)) - return PTR_ERR(pid); - - if (!access_pidfd_pidns(pid)) - return -EINVAL; switch (flags) { - case 0: - /* Infer scope from the type of pidfd. */ - if (fd_file(f)->f_flags & PIDFD_THREAD) - type = PIDTYPE_PID; - else - type = PIDTYPE_TGID; - break; case PIDFD_SIGNAL_THREAD: type = PIDTYPE_PID; break; @@ -4071,6 +4027,8 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig, } if (info) { + int ret; + ret = copy_siginfo_from_user_any(&kinfo, info); if (unlikely(ret)) return ret; @@ -4088,8 +4046,71 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig, if (type == PIDTYPE_PGID) return kill_pgrp_info(sig, &kinfo, pid); - else - return kill_pid_info_type(sig, &kinfo, pid, type); + + return kill_pid_info_type(sig, &kinfo, pid, type); +} + +/** + * sys_pidfd_send_signal - Signal a process through a pidfd + * @pidfd: file descriptor of the process + * @sig: signal to send + * @info: signal info + * @flags: future flags + * + * Send the signal to the thread group or to the individual thread depending + * on PIDFD_THREAD. + * In the future extension to @flags may be used to override the default scope + * of @pidfd. + * + * Return: 0 on success, negative errno on failure + */ +SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig, + siginfo_t __user *, info, unsigned int, flags) +{ + struct pid *pid; + enum pid_type type; + + /* Enforce flags be set to 0 until we add an extension. */ + if (flags & ~PIDFD_SEND_SIGNAL_FLAGS) + return -EINVAL; + + /* Ensure that only a single signal scope determining flag is set. */ + if (hweight32(flags & PIDFD_SEND_SIGNAL_FLAGS) > 1) + return -EINVAL; + + switch (pidfd) { + case PIDFD_SELF_THREAD: + pid = get_task_pid(current, PIDTYPE_PID); + type = PIDTYPE_PID; + break; + case PIDFD_SELF_THREAD_GROUP: + pid = get_task_pid(current, PIDTYPE_TGID); + type = PIDTYPE_TGID; + break; + default: { + CLASS(fd, f)(pidfd); + if (fd_empty(f)) + return -EBADF; + + /* Is this a pidfd? */ + pid = pidfd_to_pid(fd_file(f)); + if (IS_ERR(pid)) + return PTR_ERR(pid); + + if (!access_pidfd_pidns(pid)) + return -EINVAL; + + /* Infer scope from the type of pidfd. */ + if (fd_file(f)->f_flags & PIDFD_THREAD) + type = PIDTYPE_PID; + else + type = PIDTYPE_TGID; + + return do_pidfd_send_signal(pid, sig, type, info, flags); + } + } + + return do_pidfd_send_signal(pid, sig, type, info, flags); } static int