cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

signalfd.c (8916B)


      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
     36void signalfd_cleanup(struct sighand_struct *sighand)
     37{
     38	wake_up_pollfree(&sighand->signalfd_wqh);
     39}
     40
     41struct signalfd_ctx {
     42	sigset_t sigmask;
     43};
     44
     45static int signalfd_release(struct inode *inode, struct file *file)
     46{
     47	kfree(file->private_data);
     48	return 0;
     49}
     50
     51static __poll_t signalfd_poll(struct file *file, poll_table *wait)
     52{
     53	struct signalfd_ctx *ctx = file->private_data;
     54	__poll_t events = 0;
     55
     56	poll_wait(file, &current->sighand->signalfd_wqh, wait);
     57
     58	spin_lock_irq(&current->sighand->siglock);
     59	if (next_signal(&current->pending, &ctx->sigmask) ||
     60	    next_signal(&current->signal->shared_pending,
     61			&ctx->sigmask))
     62		events |= EPOLLIN;
     63	spin_unlock_irq(&current->sighand->siglock);
     64
     65	return events;
     66}
     67
     68/*
     69 * Copied from copy_siginfo_to_user() in kernel/signal.c
     70 */
     71static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
     72			     kernel_siginfo_t const *kinfo)
     73{
     74	struct signalfd_siginfo new;
     75
     76	BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
     77
     78	/*
     79	 * Unused members should be zero ...
     80	 */
     81	memset(&new, 0, sizeof(new));
     82
     83	/*
     84	 * If you change siginfo_t structure, please be sure
     85	 * this code is fixed accordingly.
     86	 */
     87	new.ssi_signo = kinfo->si_signo;
     88	new.ssi_errno = kinfo->si_errno;
     89	new.ssi_code  = kinfo->si_code;
     90	switch (siginfo_layout(kinfo->si_signo, kinfo->si_code)) {
     91	case SIL_KILL:
     92		new.ssi_pid = kinfo->si_pid;
     93		new.ssi_uid = kinfo->si_uid;
     94		break;
     95	case SIL_TIMER:
     96		new.ssi_tid = kinfo->si_tid;
     97		new.ssi_overrun = kinfo->si_overrun;
     98		new.ssi_ptr = (long) kinfo->si_ptr;
     99		new.ssi_int = kinfo->si_int;
    100		break;
    101	case SIL_POLL:
    102		new.ssi_band = kinfo->si_band;
    103		new.ssi_fd   = kinfo->si_fd;
    104		break;
    105	case SIL_FAULT_BNDERR:
    106	case SIL_FAULT_PKUERR:
    107	case SIL_FAULT_PERF_EVENT:
    108		/*
    109		 * Fall through to the SIL_FAULT case.  SIL_FAULT_BNDERR,
    110		 * SIL_FAULT_PKUERR, and SIL_FAULT_PERF_EVENT are only
    111		 * generated by faults that deliver them synchronously to
    112		 * userspace.  In case someone injects one of these signals
    113		 * and signalfd catches it treat it as SIL_FAULT.
    114		 */
    115	case SIL_FAULT:
    116		new.ssi_addr = (long) kinfo->si_addr;
    117		break;
    118	case SIL_FAULT_TRAPNO:
    119		new.ssi_addr = (long) kinfo->si_addr;
    120		new.ssi_trapno = kinfo->si_trapno;
    121		break;
    122	case SIL_FAULT_MCEERR:
    123		new.ssi_addr = (long) kinfo->si_addr;
    124		new.ssi_addr_lsb = (short) kinfo->si_addr_lsb;
    125		break;
    126	case SIL_CHLD:
    127		new.ssi_pid    = kinfo->si_pid;
    128		new.ssi_uid    = kinfo->si_uid;
    129		new.ssi_status = kinfo->si_status;
    130		new.ssi_utime  = kinfo->si_utime;
    131		new.ssi_stime  = kinfo->si_stime;
    132		break;
    133	case SIL_RT:
    134		/*
    135		 * This case catches also the signals queued by sigqueue().
    136		 */
    137		new.ssi_pid = kinfo->si_pid;
    138		new.ssi_uid = kinfo->si_uid;
    139		new.ssi_ptr = (long) kinfo->si_ptr;
    140		new.ssi_int = kinfo->si_int;
    141		break;
    142	case SIL_SYS:
    143		new.ssi_call_addr = (long) kinfo->si_call_addr;
    144		new.ssi_syscall   = kinfo->si_syscall;
    145		new.ssi_arch      = kinfo->si_arch;
    146		break;
    147	}
    148
    149	if (copy_to_user(uinfo, &new, sizeof(struct signalfd_siginfo)))
    150		return -EFAULT;
    151
    152	return sizeof(*uinfo);
    153}
    154
    155static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info,
    156				int nonblock)
    157{
    158	enum pid_type type;
    159	ssize_t ret;
    160	DECLARE_WAITQUEUE(wait, current);
    161
    162	spin_lock_irq(&current->sighand->siglock);
    163	ret = dequeue_signal(current, &ctx->sigmask, info, &type);
    164	switch (ret) {
    165	case 0:
    166		if (!nonblock)
    167			break;
    168		ret = -EAGAIN;
    169		fallthrough;
    170	default:
    171		spin_unlock_irq(&current->sighand->siglock);
    172		return ret;
    173	}
    174
    175	add_wait_queue(&current->sighand->signalfd_wqh, &wait);
    176	for (;;) {
    177		set_current_state(TASK_INTERRUPTIBLE);
    178		ret = dequeue_signal(current, &ctx->sigmask, info, &type);
    179		if (ret != 0)
    180			break;
    181		if (signal_pending(current)) {
    182			ret = -ERESTARTSYS;
    183			break;
    184		}
    185		spin_unlock_irq(&current->sighand->siglock);
    186		schedule();
    187		spin_lock_irq(&current->sighand->siglock);
    188	}
    189	spin_unlock_irq(&current->sighand->siglock);
    190
    191	remove_wait_queue(&current->sighand->signalfd_wqh, &wait);
    192	__set_current_state(TASK_RUNNING);
    193
    194	return ret;
    195}
    196
    197/*
    198 * Returns a multiple of the size of a "struct signalfd_siginfo", or a negative
    199 * error code. The "count" parameter must be at least the size of a
    200 * "struct signalfd_siginfo".
    201 */
    202static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
    203			     loff_t *ppos)
    204{
    205	struct signalfd_ctx *ctx = file->private_data;
    206	struct signalfd_siginfo __user *siginfo;
    207	int nonblock = file->f_flags & O_NONBLOCK;
    208	ssize_t ret, total = 0;
    209	kernel_siginfo_t info;
    210
    211	count /= sizeof(struct signalfd_siginfo);
    212	if (!count)
    213		return -EINVAL;
    214
    215	siginfo = (struct signalfd_siginfo __user *) buf;
    216	do {
    217		ret = signalfd_dequeue(ctx, &info, nonblock);
    218		if (unlikely(ret <= 0))
    219			break;
    220		ret = signalfd_copyinfo(siginfo, &info);
    221		if (ret < 0)
    222			break;
    223		siginfo++;
    224		total += ret;
    225		nonblock = 1;
    226	} while (--count);
    227
    228	return total ? total: ret;
    229}
    230
    231#ifdef CONFIG_PROC_FS
    232static void signalfd_show_fdinfo(struct seq_file *m, struct file *f)
    233{
    234	struct signalfd_ctx *ctx = f->private_data;
    235	sigset_t sigmask;
    236
    237	sigmask = ctx->sigmask;
    238	signotset(&sigmask);
    239	render_sigset_t(m, "sigmask:\t", &sigmask);
    240}
    241#endif
    242
    243static const struct file_operations signalfd_fops = {
    244#ifdef CONFIG_PROC_FS
    245	.show_fdinfo	= signalfd_show_fdinfo,
    246#endif
    247	.release	= signalfd_release,
    248	.poll		= signalfd_poll,
    249	.read		= signalfd_read,
    250	.llseek		= noop_llseek,
    251};
    252
    253static int do_signalfd4(int ufd, sigset_t *mask, int flags)
    254{
    255	struct signalfd_ctx *ctx;
    256
    257	/* Check the SFD_* constants for consistency.  */
    258	BUILD_BUG_ON(SFD_CLOEXEC != O_CLOEXEC);
    259	BUILD_BUG_ON(SFD_NONBLOCK != O_NONBLOCK);
    260
    261	if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
    262		return -EINVAL;
    263
    264	sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
    265	signotset(mask);
    266
    267	if (ufd == -1) {
    268		ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
    269		if (!ctx)
    270			return -ENOMEM;
    271
    272		ctx->sigmask = *mask;
    273
    274		/*
    275		 * When we call this, the initialization must be complete, since
    276		 * anon_inode_getfd() will install the fd.
    277		 */
    278		ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
    279				       O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK)));
    280		if (ufd < 0)
    281			kfree(ctx);
    282	} else {
    283		struct fd f = fdget(ufd);
    284		if (!f.file)
    285			return -EBADF;
    286		ctx = f.file->private_data;
    287		if (f.file->f_op != &signalfd_fops) {
    288			fdput(f);
    289			return -EINVAL;
    290		}
    291		spin_lock_irq(&current->sighand->siglock);
    292		ctx->sigmask = *mask;
    293		spin_unlock_irq(&current->sighand->siglock);
    294
    295		wake_up(&current->sighand->signalfd_wqh);
    296		fdput(f);
    297	}
    298
    299	return ufd;
    300}
    301
    302SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
    303		size_t, sizemask, int, flags)
    304{
    305	sigset_t mask;
    306
    307	if (sizemask != sizeof(sigset_t))
    308		return -EINVAL;
    309	if (copy_from_user(&mask, user_mask, sizeof(mask)))
    310		return -EFAULT;
    311	return do_signalfd4(ufd, &mask, flags);
    312}
    313
    314SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask,
    315		size_t, sizemask)
    316{
    317	sigset_t mask;
    318
    319	if (sizemask != sizeof(sigset_t))
    320		return -EINVAL;
    321	if (copy_from_user(&mask, user_mask, sizeof(mask)))
    322		return -EFAULT;
    323	return do_signalfd4(ufd, &mask, 0);
    324}
    325
    326#ifdef CONFIG_COMPAT
    327static long do_compat_signalfd4(int ufd,
    328			const compat_sigset_t __user *user_mask,
    329			compat_size_t sigsetsize, int flags)
    330{
    331	sigset_t mask;
    332
    333	if (sigsetsize != sizeof(compat_sigset_t))
    334		return -EINVAL;
    335	if (get_compat_sigset(&mask, user_mask))
    336		return -EFAULT;
    337	return do_signalfd4(ufd, &mask, flags);
    338}
    339
    340COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd,
    341		     const compat_sigset_t __user *, user_mask,
    342		     compat_size_t, sigsetsize,
    343		     int, flags)
    344{
    345	return do_compat_signalfd4(ufd, user_mask, sigsetsize, flags);
    346}
    347
    348COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd,
    349		     const compat_sigset_t __user *, user_mask,
    350		     compat_size_t, sigsetsize)
    351{
    352	return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0);
    353}
    354#endif