diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 133 |
1 files changed, 127 insertions, 6 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 5d53183e2705..b7953934aa99 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -19,7 +19,9 @@ | |||
19 | #include <linux/sched/task.h> | 19 | #include <linux/sched/task.h> |
20 | #include <linux/sched/task_stack.h> | 20 | #include <linux/sched/task_stack.h> |
21 | #include <linux/sched/cputime.h> | 21 | #include <linux/sched/cputime.h> |
22 | #include <linux/file.h> | ||
22 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
24 | #include <linux/proc_fs.h> | ||
23 | #include <linux/tty.h> | 25 | #include <linux/tty.h> |
24 | #include <linux/binfmts.h> | 26 | #include <linux/binfmts.h> |
25 | #include <linux/coredump.h> | 27 | #include <linux/coredump.h> |
@@ -3487,6 +3489,16 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait_time32, compat_sigset_t __user *, uthese, | |||
3487 | #endif | 3489 | #endif |
3488 | #endif | 3490 | #endif |
3489 | 3491 | ||
3492 | static inline void prepare_kill_siginfo(int sig, struct kernel_siginfo *info) | ||
3493 | { | ||
3494 | clear_siginfo(info); | ||
3495 | info->si_signo = sig; | ||
3496 | info->si_errno = 0; | ||
3497 | info->si_code = SI_USER; | ||
3498 | info->si_pid = task_tgid_vnr(current); | ||
3499 | info->si_uid = from_kuid_munged(current_user_ns(), current_uid()); | ||
3500 | } | ||
3501 | |||
3490 | /** | 3502 | /** |
3491 | * sys_kill - send a signal to a process | 3503 | * sys_kill - send a signal to a process |
3492 | * @pid: the PID of the process | 3504 | * @pid: the PID of the process |
@@ -3496,16 +3508,125 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) | |||
3496 | { | 3508 | { |
3497 | struct kernel_siginfo info; | 3509 | struct kernel_siginfo info; |
3498 | 3510 | ||
3499 | clear_siginfo(&info); | 3511 | prepare_kill_siginfo(sig, &info); |
3500 | info.si_signo = sig; | ||
3501 | info.si_errno = 0; | ||
3502 | info.si_code = SI_USER; | ||
3503 | info.si_pid = task_tgid_vnr(current); | ||
3504 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); | ||
3505 | 3512 | ||
3506 | return kill_something_info(sig, &info, pid); | 3513 | return kill_something_info(sig, &info, pid); |
3507 | } | 3514 | } |
3508 | 3515 | ||
3516 | #ifdef CONFIG_PROC_FS | ||
3517 | /* | ||
3518 | * Verify that the signaler and signalee either are in the same pid namespace | ||
3519 | * or that the signaler's pid namespace is an ancestor of the signalee's pid | ||
3520 | * namespace. | ||
3521 | */ | ||
3522 | static bool access_pidfd_pidns(struct pid *pid) | ||
3523 | { | ||
3524 | struct pid_namespace *active = task_active_pid_ns(current); | ||
3525 | struct pid_namespace *p = ns_of_pid(pid); | ||
3526 | |||
3527 | for (;;) { | ||
3528 | if (!p) | ||
3529 | return false; | ||
3530 | if (p == active) | ||
3531 | break; | ||
3532 | p = p->parent; | ||
3533 | } | ||
3534 | |||
3535 | return true; | ||
3536 | } | ||
3537 | |||
3538 | static int copy_siginfo_from_user_any(kernel_siginfo_t *kinfo, siginfo_t *info) | ||
3539 | { | ||
3540 | #ifdef CONFIG_COMPAT | ||
3541 | /* | ||
3542 | * Avoid hooking up compat syscalls and instead handle necessary | ||
3543 | * conversions here. Note, this is a stop-gap measure and should not be | ||
3544 | * considered a generic solution. | ||
3545 | */ | ||
3546 | if (in_compat_syscall()) | ||
3547 | return copy_siginfo_from_user32( | ||
3548 | kinfo, (struct compat_siginfo __user *)info); | ||
3549 | #endif | ||
3550 | return copy_siginfo_from_user(kinfo, info); | ||
3551 | } | ||
3552 | |||
3553 | /** | ||
3554 | * sys_pidfd_send_signal - send a signal to a process through a task file | ||
3555 | * descriptor | ||
3556 | * @pidfd: the file descriptor of the process | ||
3557 | * @sig: signal to be sent | ||
3558 | * @info: the signal info | ||
3559 | * @flags: future flags to be passed | ||
3560 | * | ||
3561 | * The syscall currently only signals via PIDTYPE_PID which covers | ||
3562 | * kill(<positive-pid>, <signal>. It does not signal threads or process | ||
3563 | * groups. | ||
3564 | * In order to extend the syscall to threads and process groups the @flags | ||
3565 | * argument should be used. In essence, the @flags argument will determine | ||
3566 | * what is signaled and not the file descriptor itself. Put in other words, | ||
3567 | * grouping is a property of the flags argument not a property of the file | ||
3568 | * descriptor. | ||
3569 | * | ||
3570 | * Return: 0 on success, negative errno on failure | ||
3571 | */ | ||
3572 | SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig, | ||
3573 | siginfo_t __user *, info, unsigned int, flags) | ||
3574 | { | ||
3575 | int ret; | ||
3576 | struct fd f; | ||
3577 | struct pid *pid; | ||
3578 | kernel_siginfo_t kinfo; | ||
3579 | |||
3580 | /* Enforce flags be set to 0 until we add an extension. */ | ||
3581 | if (flags) | ||
3582 | return -EINVAL; | ||
3583 | |||
3584 | f = fdget_raw(pidfd); | ||
3585 | if (!f.file) | ||
3586 | return -EBADF; | ||
3587 | |||
3588 | /* Is this a pidfd? */ | ||
3589 | pid = tgid_pidfd_to_pid(f.file); | ||
3590 | if (IS_ERR(pid)) { | ||
3591 | ret = PTR_ERR(pid); | ||
3592 | goto err; | ||
3593 | } | ||
3594 | |||
3595 | ret = -EINVAL; | ||
3596 | if (!access_pidfd_pidns(pid)) | ||
3597 | goto err; | ||
3598 | |||
3599 | if (info) { | ||
3600 | ret = copy_siginfo_from_user_any(&kinfo, info); | ||
3601 | if (unlikely(ret)) | ||
3602 | goto err; | ||
3603 | |||
3604 | ret = -EINVAL; | ||
3605 | if (unlikely(sig != kinfo.si_signo)) | ||
3606 | goto err; | ||
3607 | |||
3608 | if ((task_pid(current) != pid) && | ||
3609 | (kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL)) { | ||
3610 | /* Only allow sending arbitrary signals to yourself. */ | ||
3611 | ret = -EPERM; | ||
3612 | if (kinfo.si_code != SI_USER) | ||
3613 | goto err; | ||
3614 | |||
3615 | /* Turn this into a regular kill signal. */ | ||
3616 | prepare_kill_siginfo(sig, &kinfo); | ||
3617 | } | ||
3618 | } else { | ||
3619 | prepare_kill_siginfo(sig, &kinfo); | ||
3620 | } | ||
3621 | |||
3622 | ret = kill_pid_info(sig, &kinfo, pid); | ||
3623 | |||
3624 | err: | ||
3625 | fdput(f); | ||
3626 | return ret; | ||
3627 | } | ||
3628 | #endif /* CONFIG_PROC_FS */ | ||
3629 | |||
3509 | static int | 3630 | static int |
3510 | do_send_specific(pid_t tgid, pid_t pid, int sig, struct kernel_siginfo *info) | 3631 | do_send_specific(pid_t tgid, pid_t pid, int sig, struct kernel_siginfo *info) |
3511 | { | 3632 | { |