LCOV - code coverage report
Current view: top level - fs - signalfd.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 94 161 58.4 %
Date: 2021-04-22 12:43:58 Functions: 9 17 52.9 %

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

Generated by: LCOV version 1.14