b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 2) /*
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 3) * fs/signalfd.c
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 4) *
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 5) * Copyright (C) 2003 Linus Torvalds
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 6) *
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 7) * Mon Mar 5, 2007: Davide Libenzi <davidel@xmailserver.org>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 8) * Changed ->read() to return a siginfo strcture instead of signal number.
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 9) * Fixed locking in ->poll().
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 10) * Added sighand-detach notification.
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 11) * Added fd re-use in sys_signalfd() syscall.
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 12) * Now using anonymous inode source.
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 13) * Thanks to Oleg Nesterov for useful code review and suggestions.
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 14) * More comments and suggestions from Arnd Bergmann.
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 15) * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br>
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 16) * Retrieve multiple signals with one read() call
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 17) * Sun Jul 15, 2007: Davide Libenzi <davidel@xmailserver.org>
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 18) * Attach to the sighand only during read() and poll().
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 19) */
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 20)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 21) #include <linux/file.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 22) #include <linux/poll.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 23) #include <linux/init.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 24) #include <linux/fs.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 25) #include <linux/sched.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 26) #include <linux/slab.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 27) #include <linux/kernel.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 28) #include <linux/signal.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 29) #include <linux/list.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 30) #include <linux/anon_inodes.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 31) #include <linux/signalfd.h>
7ec37dfd4d282 (Adrian Bunk 2008-02-06 01:36:48 -0800 32) #include <linux/syscalls.h>
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 33) #include <linux/proc_fs.h>
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 34) #include <linux/compat.h>
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 35)
d80e731ecab42 (Oleg Nesterov 2012-02-24 20:07:11 +0100 36) void signalfd_cleanup(struct sighand_struct *sighand)
d80e731ecab42 (Oleg Nesterov 2012-02-24 20:07:11 +0100 37) {
d80e731ecab42 (Oleg Nesterov 2012-02-24 20:07:11 +0100 38) wait_queue_head_t *wqh = &sighand->signalfd_wqh;
971316f0503a5 (Oleg Nesterov 2012-02-24 20:07:29 +0100 39) /*
971316f0503a5 (Oleg Nesterov 2012-02-24 20:07:29 +0100 40) * The lockless check can race with remove_wait_queue() in progress,
971316f0503a5 (Oleg Nesterov 2012-02-24 20:07:29 +0100 41) * but in this case its caller should run under rcu_read_lock() and
5f0d5a3ae7cff (Paul E. McKenney 2017-01-18 02:53:44 -0800 42) * sighand_cachep is SLAB_TYPESAFE_BY_RCU, we can safely return.
971316f0503a5 (Oleg Nesterov 2012-02-24 20:07:29 +0100 43) */
d80e731ecab42 (Oleg Nesterov 2012-02-24 20:07:11 +0100 44) if (likely(!waitqueue_active(wqh)))
d80e731ecab42 (Oleg Nesterov 2012-02-24 20:07:11 +0100 45) return;
d80e731ecab42 (Oleg Nesterov 2012-02-24 20:07:11 +0100 46)
ac6424b981bce (Ingo Molnar 2017-06-20 12:06:13 +0200 47) /* wait_queue_entry_t->func(POLLFREE) should do remove_wait_queue() */
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 48) wake_up_poll(wqh, EPOLLHUP | POLLFREE);
d80e731ecab42 (Oleg Nesterov 2012-02-24 20:07:11 +0100 49) }
d80e731ecab42 (Oleg Nesterov 2012-02-24 20:07:11 +0100 50)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 51) struct signalfd_ctx {
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 52) sigset_t sigmask;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 53) };
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 54)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 55) static int signalfd_release(struct inode *inode, struct file *file)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 56) {
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 57) kfree(file->private_data);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 58) return 0;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 59) }
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 60)
076ccb76e1a6c (Al Viro 2017-07-03 01:02:18 -0400 61) static __poll_t signalfd_poll(struct file *file, poll_table *wait)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 62) {
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 63) struct signalfd_ctx *ctx = file->private_data;
076ccb76e1a6c (Al Viro 2017-07-03 01:02:18 -0400 64) __poll_t events = 0;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 65)
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 66) poll_wait(file, ¤t->sighand->signalfd_wqh, wait);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 67)
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 68) spin_lock_irq(¤t->sighand->siglock);
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 69) if (next_signal(¤t->pending, &ctx->sigmask) ||
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 70) next_signal(¤t->signal->shared_pending,
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 71) &ctx->sigmask))
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 72) events |= EPOLLIN;
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 73) spin_unlock_irq(¤t->sighand->siglock);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 74)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 75) return events;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 76) }
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 77)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 78) /*
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 79) * Copied from copy_siginfo_to_user() in kernel/signal.c
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 80) */
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 81) static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
ae7795bc6187a (Eric W. Biederman 2018-09-25 11:27:20 +0200 82) kernel_siginfo_t const *kinfo)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 83) {
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 84) struct signalfd_siginfo new;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 85)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 86) BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 87)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 88) /*
14e4a0f2bb242 (Robert P. J. Day 2008-02-03 15:12:15 +0200 89) * Unused members should be zero ...
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 90) */
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 91) memset(&new, 0, sizeof(new));
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 92)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 93) /*
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 94) * If you change siginfo_t structure, please be sure
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 95) * this code is fixed accordingly.
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 96) */
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 97) new.ssi_signo = kinfo->si_signo;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 98) new.ssi_errno = kinfo->si_errno;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 99) new.ssi_code = kinfo->si_code;
cc731525f26af (Eric W. Biederman 2017-07-16 22:36:59 -0500 100) switch (siginfo_layout(kinfo->si_signo, kinfo->si_code)) {
cc731525f26af (Eric W. Biederman 2017-07-16 22:36:59 -0500 101) case SIL_KILL:
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 102) new.ssi_pid = kinfo->si_pid;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 103) new.ssi_uid = kinfo->si_uid;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 104) break;
cc731525f26af (Eric W. Biederman 2017-07-16 22:36:59 -0500 105) case SIL_TIMER:
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 106) new.ssi_tid = kinfo->si_tid;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 107) new.ssi_overrun = kinfo->si_overrun;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 108) new.ssi_ptr = (long) kinfo->si_ptr;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 109) new.ssi_int = kinfo->si_int;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 110) break;
cc731525f26af (Eric W. Biederman 2017-07-16 22:36:59 -0500 111) case SIL_POLL:
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 112) new.ssi_band = kinfo->si_band;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 113) new.ssi_fd = kinfo->si_fd;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 114) break;
31931c93dfe05 (Eric W. Biederman 2018-04-24 20:59:47 -0500 115) case SIL_FAULT_BNDERR:
31931c93dfe05 (Eric W. Biederman 2018-04-24 20:59:47 -0500 116) case SIL_FAULT_PKUERR:
922e3013046b7 (Eric W. Biederman 2021-05-03 12:52:43 -0500 117) case SIL_PERF_EVENT:
31931c93dfe05 (Eric W. Biederman 2018-04-24 20:59:47 -0500 118) /*
922e3013046b7 (Eric W. Biederman 2021-05-03 12:52:43 -0500 119) * Fall through to the SIL_FAULT case. SIL_FAULT_BNDERR,
922e3013046b7 (Eric W. Biederman 2021-05-03 12:52:43 -0500 120) * SIL_FAULT_PKUERR, and SIL_PERF_EVENT are only
922e3013046b7 (Eric W. Biederman 2021-05-03 12:52:43 -0500 121) * generated by faults that deliver them synchronously to
922e3013046b7 (Eric W. Biederman 2021-05-03 12:52:43 -0500 122) * userspace. In case someone injects one of these signals
922e3013046b7 (Eric W. Biederman 2021-05-03 12:52:43 -0500 123) * and signalfd catches it treat it as SIL_FAULT.
31931c93dfe05 (Eric W. Biederman 2018-04-24 20:59:47 -0500 124) */
cc731525f26af (Eric W. Biederman 2017-07-16 22:36:59 -0500 125) case SIL_FAULT:
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 126) new.ssi_addr = (long) kinfo->si_addr;
9abcabe311181 (Eric W. Biederman 2021-04-30 17:29:36 -0500 127) break;
9abcabe311181 (Eric W. Biederman 2021-04-30 17:29:36 -0500 128) case SIL_FAULT_TRAPNO:
9abcabe311181 (Eric W. Biederman 2021-04-30 17:29:36 -0500 129) new.ssi_addr = (long) kinfo->si_addr;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 130) new.ssi_trapno = kinfo->si_trapno;
31931c93dfe05 (Eric W. Biederman 2018-04-24 20:59:47 -0500 131) break;
31931c93dfe05 (Eric W. Biederman 2018-04-24 20:59:47 -0500 132) case SIL_FAULT_MCEERR:
31931c93dfe05 (Eric W. Biederman 2018-04-24 20:59:47 -0500 133) new.ssi_addr = (long) kinfo->si_addr;
31931c93dfe05 (Eric W. Biederman 2018-04-24 20:59:47 -0500 134) new.ssi_addr_lsb = (short) kinfo->si_addr_lsb;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 135) break;
cc731525f26af (Eric W. Biederman 2017-07-16 22:36:59 -0500 136) case SIL_CHLD:
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 137) new.ssi_pid = kinfo->si_pid;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 138) new.ssi_uid = kinfo->si_uid;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 139) new.ssi_status = kinfo->si_status;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 140) new.ssi_utime = kinfo->si_utime;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 141) new.ssi_stime = kinfo->si_stime;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 142) break;
cc731525f26af (Eric W. Biederman 2017-07-16 22:36:59 -0500 143) case SIL_RT:
0859ab59a8a48 (Davide Libenzi 2008-04-10 21:29:29 -0700 144) /*
0859ab59a8a48 (Davide Libenzi 2008-04-10 21:29:29 -0700 145) * This case catches also the signals queued by sigqueue().
0859ab59a8a48 (Davide Libenzi 2008-04-10 21:29:29 -0700 146) */
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 147) new.ssi_pid = kinfo->si_pid;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 148) new.ssi_uid = kinfo->si_uid;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 149) new.ssi_ptr = (long) kinfo->si_ptr;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 150) new.ssi_int = kinfo->si_int;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 151) break;
76b7f670730e8 (Eric W. Biederman 2018-04-24 20:48:32 -0500 152) case SIL_SYS:
76b7f670730e8 (Eric W. Biederman 2018-04-24 20:48:32 -0500 153) new.ssi_call_addr = (long) kinfo->si_call_addr;
76b7f670730e8 (Eric W. Biederman 2018-04-24 20:48:32 -0500 154) new.ssi_syscall = kinfo->si_syscall;
76b7f670730e8 (Eric W. Biederman 2018-04-24 20:48:32 -0500 155) new.ssi_arch = kinfo->si_arch;
76b7f670730e8 (Eric W. Biederman 2018-04-24 20:48:32 -0500 156) break;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 157) }
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 158)
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 159) if (copy_to_user(uinfo, &new, sizeof(struct signalfd_siginfo)))
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 160) return -EFAULT;
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 161)
5611f55ee4df7 (Eric W. Biederman 2018-04-24 20:39:16 -0500 162) return sizeof(*uinfo);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 163) }
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 164)
ae7795bc6187a (Eric W. Biederman 2018-09-25 11:27:20 +0200 165) static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info,
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 166) int nonblock)
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 167) {
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 168) ssize_t ret;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 169) DECLARE_WAITQUEUE(wait, current);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 170)
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 171) spin_lock_irq(¤t->sighand->siglock);
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 172) ret = dequeue_signal(current, &ctx->sigmask, info);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 173) switch (ret) {
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 174) case 0:
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 175) if (!nonblock)
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 176) break;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 177) ret = -EAGAIN;
df561f6688fef (Gustavo A. R. Silva 2020-08-23 17:36:59 -0500 178) fallthrough;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 179) default:
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 180) spin_unlock_irq(¤t->sighand->siglock);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 181) return ret;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 182) }
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 183)
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 184) add_wait_queue(¤t->sighand->signalfd_wqh, &wait);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 185) for (;;) {
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 186) set_current_state(TASK_INTERRUPTIBLE);
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 187) ret = dequeue_signal(current, &ctx->sigmask, info);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 188) if (ret != 0)
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 189) break;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 190) if (signal_pending(current)) {
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 191) ret = -ERESTARTSYS;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 192) break;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 193) }
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 194) spin_unlock_irq(¤t->sighand->siglock);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 195) schedule();
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 196) spin_lock_irq(¤t->sighand->siglock);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 197) }
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 198) spin_unlock_irq(¤t->sighand->siglock);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 199)
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 200) remove_wait_queue(¤t->sighand->signalfd_wqh, &wait);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 201) __set_current_state(TASK_RUNNING);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 202)
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 203) return ret;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 204) }
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 205)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 206) /*
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 207) * Returns a multiple of the size of a "struct signalfd_siginfo", or a negative
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 208) * error code. The "count" parameter must be at least the size of a
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 209) * "struct signalfd_siginfo".
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 210) */
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 211) static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 212) loff_t *ppos)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 213) {
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 214) struct signalfd_ctx *ctx = file->private_data;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 215) struct signalfd_siginfo __user *siginfo;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 216) int nonblock = file->f_flags & O_NONBLOCK;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 217) ssize_t ret, total = 0;
ae7795bc6187a (Eric W. Biederman 2018-09-25 11:27:20 +0200 218) kernel_siginfo_t info;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 219)
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 220) count /= sizeof(struct signalfd_siginfo);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 221) if (!count)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 222) return -EINVAL;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 223)
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 224) siginfo = (struct signalfd_siginfo __user *) buf;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 225) do {
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 226) ret = signalfd_dequeue(ctx, &info, nonblock);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 227) if (unlikely(ret <= 0))
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 228) break;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 229) ret = signalfd_copyinfo(siginfo, &info);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 230) if (ret < 0)
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 231) break;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 232) siginfo++;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 233) total += ret;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 234) nonblock = 1;
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 235) } while (--count);
b3762bfc8d046 (Davi Arnaut 2007-05-23 13:58:04 -0700 236)
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 237) return total ? total: ret;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 238) }
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 239)
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 240) #ifdef CONFIG_PROC_FS
a3816ab0e8fe5 (Joe Perches 2014-09-29 16:08:25 -0700 241) static void signalfd_show_fdinfo(struct seq_file *m, struct file *f)
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 242) {
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 243) struct signalfd_ctx *ctx = f->private_data;
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 244) sigset_t sigmask;
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 245)
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 246) sigmask = ctx->sigmask;
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 247) signotset(&sigmask);
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 248) render_sigset_t(m, "sigmask:\t", &sigmask);
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 249) }
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 250) #endif
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 251)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 252) static const struct file_operations signalfd_fops = {
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 253) #ifdef CONFIG_PROC_FS
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 254) .show_fdinfo = signalfd_show_fdinfo,
138d22b58696c (Cyrill Gorcunov 2012-12-17 16:05:02 -0800 255) #endif
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 256) .release = signalfd_release,
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 257) .poll = signalfd_poll,
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 258) .read = signalfd_read,
6038f373a3dc1 (Arnd Bergmann 2010-08-15 18:52:59 +0200 259) .llseek = noop_llseek,
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 260) };
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 261)
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 262) static int do_signalfd4(int ufd, sigset_t *mask, int flags)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 263) {
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 264) struct signalfd_ctx *ctx;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 265)
e38b36f325153 (Ulrich Drepper 2008-07-23 21:29:42 -0700 266) /* Check the SFD_* constants for consistency. */
e38b36f325153 (Ulrich Drepper 2008-07-23 21:29:42 -0700 267) BUILD_BUG_ON(SFD_CLOEXEC != O_CLOEXEC);
e38b36f325153 (Ulrich Drepper 2008-07-23 21:29:42 -0700 268) BUILD_BUG_ON(SFD_NONBLOCK != O_NONBLOCK);
e38b36f325153 (Ulrich Drepper 2008-07-23 21:29:42 -0700 269)
5fb5e04926a54 (Ulrich Drepper 2008-07-23 21:29:37 -0700 270) if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
9deb27baedb79 (Ulrich Drepper 2008-07-23 21:29:24 -0700 271) return -EINVAL;
9deb27baedb79 (Ulrich Drepper 2008-07-23 21:29:24 -0700 272)
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 273) sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 274) signotset(mask);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 275)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 276) if (ufd == -1) {
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 277) ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 278) if (!ctx)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 279) return -ENOMEM;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 280)
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 281) ctx->sigmask = *mask;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 282)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 283) /*
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 284) * When we call this, the initialization must be complete, since
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 285) * anon_inode_getfd() will install the fd.
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 286) */
7d9dbca34240e (Ulrich Drepper 2008-07-23 21:29:22 -0700 287) ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
628ff7c1d8d84 (Roland Dreier 2009-12-18 09:41:24 -0800 288) O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK)));
2030a42cecd4d (Al Viro 2008-02-23 06:46:49 -0500 289) if (ufd < 0)
2030a42cecd4d (Al Viro 2008-02-23 06:46:49 -0500 290) kfree(ctx);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 291) } else {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 292) struct fd f = fdget(ufd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 293) if (!f.file)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 294) return -EBADF;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 295) ctx = f.file->private_data;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 296) if (f.file->f_op != &signalfd_fops) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 297) fdput(f);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 298) return -EINVAL;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 299) }
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 300) spin_lock_irq(¤t->sighand->siglock);
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 301) ctx->sigmask = *mask;
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 302) spin_unlock_irq(¤t->sighand->siglock);
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 303)
b8fceee17a310 (Davide Libenzi 2007-09-20 12:40:16 -0700 304) wake_up(¤t->sighand->signalfd_wqh);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 305) fdput(f);
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 306) }
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 307)
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 308) return ufd;
fba2afaaec790 (Davide Libenzi 2007-05-10 22:23:13 -0700 309) }
9deb27baedb79 (Ulrich Drepper 2008-07-23 21:29:24 -0700 310)
52fb6db0fd6f5 (Dominik Brodowski 2018-03-11 11:34:36 +0100 311) SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
52fb6db0fd6f5 (Dominik Brodowski 2018-03-11 11:34:36 +0100 312) size_t, sizemask, int, flags)
52fb6db0fd6f5 (Dominik Brodowski 2018-03-11 11:34:36 +0100 313) {
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 314) sigset_t mask;
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 315)
a089e3fd5a82a (Helge Deller 2020-08-11 18:36:04 -0700 316) if (sizemask != sizeof(sigset_t))
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 317) return -EINVAL;
a089e3fd5a82a (Helge Deller 2020-08-11 18:36:04 -0700 318) if (copy_from_user(&mask, user_mask, sizeof(mask)))
a089e3fd5a82a (Helge Deller 2020-08-11 18:36:04 -0700 319) return -EFAULT;
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 320) return do_signalfd4(ufd, &mask, flags);
52fb6db0fd6f5 (Dominik Brodowski 2018-03-11 11:34:36 +0100 321) }
52fb6db0fd6f5 (Dominik Brodowski 2018-03-11 11:34:36 +0100 322)
836f92adf121f (Heiko Carstens 2009-01-14 14:14:33 +0100 323) SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask,
836f92adf121f (Heiko Carstens 2009-01-14 14:14:33 +0100 324) size_t, sizemask)
9deb27baedb79 (Ulrich Drepper 2008-07-23 21:29:24 -0700 325) {
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 326) sigset_t mask;
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 327)
a089e3fd5a82a (Helge Deller 2020-08-11 18:36:04 -0700 328) if (sizemask != sizeof(sigset_t))
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 329) return -EINVAL;
a089e3fd5a82a (Helge Deller 2020-08-11 18:36:04 -0700 330) if (copy_from_user(&mask, user_mask, sizeof(mask)))
a089e3fd5a82a (Helge Deller 2020-08-11 18:36:04 -0700 331) return -EFAULT;
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 332) return do_signalfd4(ufd, &mask, 0);
9deb27baedb79 (Ulrich Drepper 2008-07-23 21:29:24 -0700 333) }
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 334)
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 335) #ifdef CONFIG_COMPAT
570484bfe813f (Dominik Brodowski 2018-03-20 19:36:46 +0100 336) static long do_compat_signalfd4(int ufd,
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 337) const compat_sigset_t __user *user_mask,
570484bfe813f (Dominik Brodowski 2018-03-20 19:36:46 +0100 338) compat_size_t sigsetsize, int flags)
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 339) {
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 340) sigset_t mask;
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 341)
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 342) if (sigsetsize != sizeof(compat_sigset_t))
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 343) return -EINVAL;
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 344) if (get_compat_sigset(&mask, user_mask))
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 345) return -EFAULT;
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 346) return do_signalfd4(ufd, &mask, flags);
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 347) }
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 348)
570484bfe813f (Dominik Brodowski 2018-03-20 19:36:46 +0100 349) COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd,
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 350) const compat_sigset_t __user *, user_mask,
570484bfe813f (Dominik Brodowski 2018-03-20 19:36:46 +0100 351) compat_size_t, sigsetsize,
570484bfe813f (Dominik Brodowski 2018-03-20 19:36:46 +0100 352) int, flags)
570484bfe813f (Dominik Brodowski 2018-03-20 19:36:46 +0100 353) {
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 354) return do_compat_signalfd4(ufd, user_mask, sigsetsize, flags);
570484bfe813f (Dominik Brodowski 2018-03-20 19:36:46 +0100 355) }
570484bfe813f (Dominik Brodowski 2018-03-20 19:36:46 +0100 356)
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 357) COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd,
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 358) const compat_sigset_t __user *, user_mask,
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 359) compat_size_t, sigsetsize)
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 360) {
5ed0127fc3619 (Al Viro 2018-05-27 08:35:50 -0400 361) return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0);
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 362) }
7d197ed4a68e7 (Al Viro 2013-02-24 01:41:39 -0500 363) #endif