162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/signalfd.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2003 Linus Torvalds 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Mon Mar 5, 2007: Davide Libenzi <davidel@xmailserver.org> 862306a36Sopenharmony_ci * Changed ->read() to return a siginfo strcture instead of signal number. 962306a36Sopenharmony_ci * Fixed locking in ->poll(). 1062306a36Sopenharmony_ci * Added sighand-detach notification. 1162306a36Sopenharmony_ci * Added fd re-use in sys_signalfd() syscall. 1262306a36Sopenharmony_ci * Now using anonymous inode source. 1362306a36Sopenharmony_ci * Thanks to Oleg Nesterov for useful code review and suggestions. 1462306a36Sopenharmony_ci * More comments and suggestions from Arnd Bergmann. 1562306a36Sopenharmony_ci * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br> 1662306a36Sopenharmony_ci * Retrieve multiple signals with one read() call 1762306a36Sopenharmony_ci * Sun Jul 15, 2007: Davide Libenzi <davidel@xmailserver.org> 1862306a36Sopenharmony_ci * Attach to the sighand only during read() and poll(). 1962306a36Sopenharmony_ci */ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/file.h> 2262306a36Sopenharmony_ci#include <linux/poll.h> 2362306a36Sopenharmony_ci#include <linux/init.h> 2462306a36Sopenharmony_ci#include <linux/fs.h> 2562306a36Sopenharmony_ci#include <linux/sched.h> 2662306a36Sopenharmony_ci#include <linux/slab.h> 2762306a36Sopenharmony_ci#include <linux/kernel.h> 2862306a36Sopenharmony_ci#include <linux/signal.h> 2962306a36Sopenharmony_ci#include <linux/list.h> 3062306a36Sopenharmony_ci#include <linux/anon_inodes.h> 3162306a36Sopenharmony_ci#include <linux/signalfd.h> 3262306a36Sopenharmony_ci#include <linux/syscalls.h> 3362306a36Sopenharmony_ci#include <linux/proc_fs.h> 3462306a36Sopenharmony_ci#include <linux/compat.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_civoid signalfd_cleanup(struct sighand_struct *sighand) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci wake_up_pollfree(&sighand->signalfd_wqh); 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistruct signalfd_ctx { 4262306a36Sopenharmony_ci sigset_t sigmask; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic int signalfd_release(struct inode *inode, struct file *file) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci kfree(file->private_data); 4862306a36Sopenharmony_ci return 0; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic __poll_t signalfd_poll(struct file *file, poll_table *wait) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct signalfd_ctx *ctx = file->private_data; 5462306a36Sopenharmony_ci __poll_t events = 0; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci poll_wait(file, ¤t->sighand->signalfd_wqh, wait); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci spin_lock_irq(¤t->sighand->siglock); 5962306a36Sopenharmony_ci if (next_signal(¤t->pending, &ctx->sigmask) || 6062306a36Sopenharmony_ci next_signal(¤t->signal->shared_pending, 6162306a36Sopenharmony_ci &ctx->sigmask)) 6262306a36Sopenharmony_ci events |= EPOLLIN; 6362306a36Sopenharmony_ci spin_unlock_irq(¤t->sighand->siglock); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return events; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * Copied from copy_siginfo_to_user() in kernel/signal.c 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_cistatic int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, 7262306a36Sopenharmony_ci kernel_siginfo_t const *kinfo) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct signalfd_siginfo new; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* 7962306a36Sopenharmony_ci * Unused members should be zero ... 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci memset(&new, 0, sizeof(new)); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* 8462306a36Sopenharmony_ci * If you change siginfo_t structure, please be sure 8562306a36Sopenharmony_ci * this code is fixed accordingly. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci new.ssi_signo = kinfo->si_signo; 8862306a36Sopenharmony_ci new.ssi_errno = kinfo->si_errno; 8962306a36Sopenharmony_ci new.ssi_code = kinfo->si_code; 9062306a36Sopenharmony_ci switch (siginfo_layout(kinfo->si_signo, kinfo->si_code)) { 9162306a36Sopenharmony_ci case SIL_KILL: 9262306a36Sopenharmony_ci new.ssi_pid = kinfo->si_pid; 9362306a36Sopenharmony_ci new.ssi_uid = kinfo->si_uid; 9462306a36Sopenharmony_ci break; 9562306a36Sopenharmony_ci case SIL_TIMER: 9662306a36Sopenharmony_ci new.ssi_tid = kinfo->si_tid; 9762306a36Sopenharmony_ci new.ssi_overrun = kinfo->si_overrun; 9862306a36Sopenharmony_ci new.ssi_ptr = (long) kinfo->si_ptr; 9962306a36Sopenharmony_ci new.ssi_int = kinfo->si_int; 10062306a36Sopenharmony_ci break; 10162306a36Sopenharmony_ci case SIL_POLL: 10262306a36Sopenharmony_ci new.ssi_band = kinfo->si_band; 10362306a36Sopenharmony_ci new.ssi_fd = kinfo->si_fd; 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci case SIL_FAULT_BNDERR: 10662306a36Sopenharmony_ci case SIL_FAULT_PKUERR: 10762306a36Sopenharmony_ci case SIL_FAULT_PERF_EVENT: 10862306a36Sopenharmony_ci /* 10962306a36Sopenharmony_ci * Fall through to the SIL_FAULT case. SIL_FAULT_BNDERR, 11062306a36Sopenharmony_ci * SIL_FAULT_PKUERR, and SIL_FAULT_PERF_EVENT are only 11162306a36Sopenharmony_ci * generated by faults that deliver them synchronously to 11262306a36Sopenharmony_ci * userspace. In case someone injects one of these signals 11362306a36Sopenharmony_ci * and signalfd catches it treat it as SIL_FAULT. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci case SIL_FAULT: 11662306a36Sopenharmony_ci new.ssi_addr = (long) kinfo->si_addr; 11762306a36Sopenharmony_ci break; 11862306a36Sopenharmony_ci case SIL_FAULT_TRAPNO: 11962306a36Sopenharmony_ci new.ssi_addr = (long) kinfo->si_addr; 12062306a36Sopenharmony_ci new.ssi_trapno = kinfo->si_trapno; 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci case SIL_FAULT_MCEERR: 12362306a36Sopenharmony_ci new.ssi_addr = (long) kinfo->si_addr; 12462306a36Sopenharmony_ci new.ssi_addr_lsb = (short) kinfo->si_addr_lsb; 12562306a36Sopenharmony_ci break; 12662306a36Sopenharmony_ci case SIL_CHLD: 12762306a36Sopenharmony_ci new.ssi_pid = kinfo->si_pid; 12862306a36Sopenharmony_ci new.ssi_uid = kinfo->si_uid; 12962306a36Sopenharmony_ci new.ssi_status = kinfo->si_status; 13062306a36Sopenharmony_ci new.ssi_utime = kinfo->si_utime; 13162306a36Sopenharmony_ci new.ssi_stime = kinfo->si_stime; 13262306a36Sopenharmony_ci break; 13362306a36Sopenharmony_ci case SIL_RT: 13462306a36Sopenharmony_ci /* 13562306a36Sopenharmony_ci * This case catches also the signals queued by sigqueue(). 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_ci new.ssi_pid = kinfo->si_pid; 13862306a36Sopenharmony_ci new.ssi_uid = kinfo->si_uid; 13962306a36Sopenharmony_ci new.ssi_ptr = (long) kinfo->si_ptr; 14062306a36Sopenharmony_ci new.ssi_int = kinfo->si_int; 14162306a36Sopenharmony_ci break; 14262306a36Sopenharmony_ci case SIL_SYS: 14362306a36Sopenharmony_ci new.ssi_call_addr = (long) kinfo->si_call_addr; 14462306a36Sopenharmony_ci new.ssi_syscall = kinfo->si_syscall; 14562306a36Sopenharmony_ci new.ssi_arch = kinfo->si_arch; 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci if (copy_to_user(uinfo, &new, sizeof(struct signalfd_siginfo))) 15062306a36Sopenharmony_ci return -EFAULT; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return sizeof(*uinfo); 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info, 15662306a36Sopenharmony_ci int nonblock) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci enum pid_type type; 15962306a36Sopenharmony_ci ssize_t ret; 16062306a36Sopenharmony_ci DECLARE_WAITQUEUE(wait, current); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci spin_lock_irq(¤t->sighand->siglock); 16362306a36Sopenharmony_ci ret = dequeue_signal(current, &ctx->sigmask, info, &type); 16462306a36Sopenharmony_ci switch (ret) { 16562306a36Sopenharmony_ci case 0: 16662306a36Sopenharmony_ci if (!nonblock) 16762306a36Sopenharmony_ci break; 16862306a36Sopenharmony_ci ret = -EAGAIN; 16962306a36Sopenharmony_ci fallthrough; 17062306a36Sopenharmony_ci default: 17162306a36Sopenharmony_ci spin_unlock_irq(¤t->sighand->siglock); 17262306a36Sopenharmony_ci return ret; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci add_wait_queue(¤t->sighand->signalfd_wqh, &wait); 17662306a36Sopenharmony_ci for (;;) { 17762306a36Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 17862306a36Sopenharmony_ci ret = dequeue_signal(current, &ctx->sigmask, info, &type); 17962306a36Sopenharmony_ci if (ret != 0) 18062306a36Sopenharmony_ci break; 18162306a36Sopenharmony_ci if (signal_pending(current)) { 18262306a36Sopenharmony_ci ret = -ERESTARTSYS; 18362306a36Sopenharmony_ci break; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci spin_unlock_irq(¤t->sighand->siglock); 18662306a36Sopenharmony_ci schedule(); 18762306a36Sopenharmony_ci spin_lock_irq(¤t->sighand->siglock); 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci spin_unlock_irq(¤t->sighand->siglock); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci remove_wait_queue(¤t->sighand->signalfd_wqh, &wait); 19262306a36Sopenharmony_ci __set_current_state(TASK_RUNNING); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci return ret; 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci/* 19862306a36Sopenharmony_ci * Returns a multiple of the size of a "struct signalfd_siginfo", or a negative 19962306a36Sopenharmony_ci * error code. The "count" parameter must be at least the size of a 20062306a36Sopenharmony_ci * "struct signalfd_siginfo". 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_cistatic ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, 20362306a36Sopenharmony_ci loff_t *ppos) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct signalfd_ctx *ctx = file->private_data; 20662306a36Sopenharmony_ci struct signalfd_siginfo __user *siginfo; 20762306a36Sopenharmony_ci int nonblock = file->f_flags & O_NONBLOCK; 20862306a36Sopenharmony_ci ssize_t ret, total = 0; 20962306a36Sopenharmony_ci kernel_siginfo_t info; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci count /= sizeof(struct signalfd_siginfo); 21262306a36Sopenharmony_ci if (!count) 21362306a36Sopenharmony_ci return -EINVAL; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci siginfo = (struct signalfd_siginfo __user *) buf; 21662306a36Sopenharmony_ci do { 21762306a36Sopenharmony_ci ret = signalfd_dequeue(ctx, &info, nonblock); 21862306a36Sopenharmony_ci if (unlikely(ret <= 0)) 21962306a36Sopenharmony_ci break; 22062306a36Sopenharmony_ci ret = signalfd_copyinfo(siginfo, &info); 22162306a36Sopenharmony_ci if (ret < 0) 22262306a36Sopenharmony_ci break; 22362306a36Sopenharmony_ci siginfo++; 22462306a36Sopenharmony_ci total += ret; 22562306a36Sopenharmony_ci nonblock = 1; 22662306a36Sopenharmony_ci } while (--count); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci return total ? total: ret; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 23262306a36Sopenharmony_cistatic void signalfd_show_fdinfo(struct seq_file *m, struct file *f) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci struct signalfd_ctx *ctx = f->private_data; 23562306a36Sopenharmony_ci sigset_t sigmask; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci sigmask = ctx->sigmask; 23862306a36Sopenharmony_ci signotset(&sigmask); 23962306a36Sopenharmony_ci render_sigset_t(m, "sigmask:\t", &sigmask); 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci#endif 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic const struct file_operations signalfd_fops = { 24462306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 24562306a36Sopenharmony_ci .show_fdinfo = signalfd_show_fdinfo, 24662306a36Sopenharmony_ci#endif 24762306a36Sopenharmony_ci .release = signalfd_release, 24862306a36Sopenharmony_ci .poll = signalfd_poll, 24962306a36Sopenharmony_ci .read = signalfd_read, 25062306a36Sopenharmony_ci .llseek = noop_llseek, 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic int do_signalfd4(int ufd, sigset_t *mask, int flags) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct signalfd_ctx *ctx; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* Check the SFD_* constants for consistency. */ 25862306a36Sopenharmony_ci BUILD_BUG_ON(SFD_CLOEXEC != O_CLOEXEC); 25962306a36Sopenharmony_ci BUILD_BUG_ON(SFD_NONBLOCK != O_NONBLOCK); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK)) 26262306a36Sopenharmony_ci return -EINVAL; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP)); 26562306a36Sopenharmony_ci signotset(mask); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (ufd == -1) { 26862306a36Sopenharmony_ci ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 26962306a36Sopenharmony_ci if (!ctx) 27062306a36Sopenharmony_ci return -ENOMEM; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci ctx->sigmask = *mask; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* 27562306a36Sopenharmony_ci * When we call this, the initialization must be complete, since 27662306a36Sopenharmony_ci * anon_inode_getfd() will install the fd. 27762306a36Sopenharmony_ci */ 27862306a36Sopenharmony_ci ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, 27962306a36Sopenharmony_ci O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK))); 28062306a36Sopenharmony_ci if (ufd < 0) 28162306a36Sopenharmony_ci kfree(ctx); 28262306a36Sopenharmony_ci } else { 28362306a36Sopenharmony_ci struct fd f = fdget(ufd); 28462306a36Sopenharmony_ci if (!f.file) 28562306a36Sopenharmony_ci return -EBADF; 28662306a36Sopenharmony_ci ctx = f.file->private_data; 28762306a36Sopenharmony_ci if (f.file->f_op != &signalfd_fops) { 28862306a36Sopenharmony_ci fdput(f); 28962306a36Sopenharmony_ci return -EINVAL; 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci spin_lock_irq(¤t->sighand->siglock); 29262306a36Sopenharmony_ci ctx->sigmask = *mask; 29362306a36Sopenharmony_ci spin_unlock_irq(¤t->sighand->siglock); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci wake_up(¤t->sighand->signalfd_wqh); 29662306a36Sopenharmony_ci fdput(f); 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci return ufd; 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ciSYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, 30362306a36Sopenharmony_ci size_t, sizemask, int, flags) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci sigset_t mask; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (sizemask != sizeof(sigset_t)) 30862306a36Sopenharmony_ci return -EINVAL; 30962306a36Sopenharmony_ci if (copy_from_user(&mask, user_mask, sizeof(mask))) 31062306a36Sopenharmony_ci return -EFAULT; 31162306a36Sopenharmony_ci return do_signalfd4(ufd, &mask, flags); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ciSYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask, 31562306a36Sopenharmony_ci size_t, sizemask) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci sigset_t mask; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci if (sizemask != sizeof(sigset_t)) 32062306a36Sopenharmony_ci return -EINVAL; 32162306a36Sopenharmony_ci if (copy_from_user(&mask, user_mask, sizeof(mask))) 32262306a36Sopenharmony_ci return -EFAULT; 32362306a36Sopenharmony_ci return do_signalfd4(ufd, &mask, 0); 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 32762306a36Sopenharmony_cistatic long do_compat_signalfd4(int ufd, 32862306a36Sopenharmony_ci const compat_sigset_t __user *user_mask, 32962306a36Sopenharmony_ci compat_size_t sigsetsize, int flags) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci sigset_t mask; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (sigsetsize != sizeof(compat_sigset_t)) 33462306a36Sopenharmony_ci return -EINVAL; 33562306a36Sopenharmony_ci if (get_compat_sigset(&mask, user_mask)) 33662306a36Sopenharmony_ci return -EFAULT; 33762306a36Sopenharmony_ci return do_signalfd4(ufd, &mask, flags); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd, 34162306a36Sopenharmony_ci const compat_sigset_t __user *, user_mask, 34262306a36Sopenharmony_ci compat_size_t, sigsetsize, 34362306a36Sopenharmony_ci int, flags) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci return do_compat_signalfd4(ufd, user_mask, sigsetsize, flags); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ciCOMPAT_SYSCALL_DEFINE3(signalfd, int, ufd, 34962306a36Sopenharmony_ci const compat_sigset_t __user *, user_mask, 35062306a36Sopenharmony_ci compat_size_t, sigsetsize) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0); 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci#endif 355