11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/fs/fcntl.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds #include <linux/syscalls.h> 81da177e4SLinus Torvalds #include <linux/init.h> 91da177e4SLinus Torvalds #include <linux/mm.h> 101da177e4SLinus Torvalds #include <linux/fs.h> 111da177e4SLinus Torvalds #include <linux/file.h> 129f3acc31SAl Viro #include <linux/fdtable.h> 1316f7e0feSRandy Dunlap #include <linux/capability.h> 141da177e4SLinus Torvalds #include <linux/dnotify.h> 151da177e4SLinus Torvalds #include <linux/slab.h> 161da177e4SLinus Torvalds #include <linux/module.h> 171da177e4SLinus Torvalds #include <linux/security.h> 181da177e4SLinus Torvalds #include <linux/ptrace.h> 197ed20e1aSJesper Juhl #include <linux/signal.h> 20ab2af1f5SDipankar Sarma #include <linux/rcupdate.h> 21b488893aSPavel Emelyanov #include <linux/pid_namespace.h> 22218d11a8SJonathan Corbet #include <linux/smp_lock.h> 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds #include <asm/poll.h> 251da177e4SLinus Torvalds #include <asm/siginfo.h> 261da177e4SLinus Torvalds #include <asm/uaccess.h> 271da177e4SLinus Torvalds 28fc9b52cdSHarvey Harrison void set_close_on_exec(unsigned int fd, int flag) 291da177e4SLinus Torvalds { 301da177e4SLinus Torvalds struct files_struct *files = current->files; 31badf1662SDipankar Sarma struct fdtable *fdt; 321da177e4SLinus Torvalds spin_lock(&files->file_lock); 33badf1662SDipankar Sarma fdt = files_fdtable(files); 341da177e4SLinus Torvalds if (flag) 35badf1662SDipankar Sarma FD_SET(fd, fdt->close_on_exec); 361da177e4SLinus Torvalds else 37badf1662SDipankar Sarma FD_CLR(fd, fdt->close_on_exec); 381da177e4SLinus Torvalds spin_unlock(&files->file_lock); 391da177e4SLinus Torvalds } 401da177e4SLinus Torvalds 41858119e1SArjan van de Ven static int get_close_on_exec(unsigned int fd) 421da177e4SLinus Torvalds { 431da177e4SLinus Torvalds struct files_struct *files = current->files; 44badf1662SDipankar Sarma struct fdtable *fdt; 451da177e4SLinus Torvalds int res; 46b835996fSDipankar Sarma rcu_read_lock(); 47badf1662SDipankar Sarma fdt = files_fdtable(files); 48badf1662SDipankar Sarma res = FD_ISSET(fd, fdt->close_on_exec); 49b835996fSDipankar Sarma rcu_read_unlock(); 501da177e4SLinus Torvalds return res; 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 53a26eab24SHeiko Carstens SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds int err = -EBADF; 561da177e4SLinus Torvalds struct file * file, *tofree; 571da177e4SLinus Torvalds struct files_struct * files = current->files; 58badf1662SDipankar Sarma struct fdtable *fdt; 591da177e4SLinus Torvalds 60336dd1f7SUlrich Drepper if ((flags & ~O_CLOEXEC) != 0) 61336dd1f7SUlrich Drepper return -EINVAL; 62336dd1f7SUlrich Drepper 636c5d0512SAl Viro if (unlikely(oldfd == newfd)) 646c5d0512SAl Viro return -EINVAL; 656c5d0512SAl Viro 661da177e4SLinus Torvalds spin_lock(&files->file_lock); 671da177e4SLinus Torvalds err = expand_files(files, newfd); 681b7e190bSAl Viro file = fcheck(oldfd); 691b7e190bSAl Viro if (unlikely(!file)) 701b7e190bSAl Viro goto Ebadf; 714e1e018eSAl Viro if (unlikely(err < 0)) { 724e1e018eSAl Viro if (err == -EMFILE) 731b7e190bSAl Viro goto Ebadf; 741b7e190bSAl Viro goto out_unlock; 754e1e018eSAl Viro } 761b7e190bSAl Viro /* 771b7e190bSAl Viro * We need to detect attempts to do dup2() over allocated but still 781b7e190bSAl Viro * not finished descriptor. NB: OpenBSD avoids that at the price of 791b7e190bSAl Viro * extra work in their equivalent of fget() - they insert struct 801b7e190bSAl Viro * file immediately after grabbing descriptor, mark it larval if 811b7e190bSAl Viro * more work (e.g. actual opening) is needed and make sure that 821b7e190bSAl Viro * fget() treats larval files as absent. Potentially interesting, 831b7e190bSAl Viro * but while extra work in fget() is trivial, locking implications 841b7e190bSAl Viro * and amount of surgery on open()-related paths in VFS are not. 851b7e190bSAl Viro * FreeBSD fails with -EBADF in the same situation, NetBSD "solution" 861b7e190bSAl Viro * deadlocks in rather amusing ways, AFAICS. All of that is out of 871b7e190bSAl Viro * scope of POSIX or SUS, since neither considers shared descriptor 881b7e190bSAl Viro * tables and this condition does not arise without those. 891b7e190bSAl Viro */ 901da177e4SLinus Torvalds err = -EBUSY; 91badf1662SDipankar Sarma fdt = files_fdtable(files); 92badf1662SDipankar Sarma tofree = fdt->fd[newfd]; 93badf1662SDipankar Sarma if (!tofree && FD_ISSET(newfd, fdt->open_fds)) 941b7e190bSAl Viro goto out_unlock; 951b7e190bSAl Viro get_file(file); 96ab2af1f5SDipankar Sarma rcu_assign_pointer(fdt->fd[newfd], file); 97badf1662SDipankar Sarma FD_SET(newfd, fdt->open_fds); 98336dd1f7SUlrich Drepper if (flags & O_CLOEXEC) 99336dd1f7SUlrich Drepper FD_SET(newfd, fdt->close_on_exec); 100336dd1f7SUlrich Drepper else 101badf1662SDipankar Sarma FD_CLR(newfd, fdt->close_on_exec); 1021da177e4SLinus Torvalds spin_unlock(&files->file_lock); 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds if (tofree) 1051da177e4SLinus Torvalds filp_close(tofree, files); 1061b7e190bSAl Viro 1071b7e190bSAl Viro return newfd; 1081b7e190bSAl Viro 1091b7e190bSAl Viro Ebadf: 1101b7e190bSAl Viro err = -EBADF; 1111da177e4SLinus Torvalds out_unlock: 1121da177e4SLinus Torvalds spin_unlock(&files->file_lock); 1131b7e190bSAl Viro return err; 1141da177e4SLinus Torvalds } 1151da177e4SLinus Torvalds 116a26eab24SHeiko Carstens SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd) 117336dd1f7SUlrich Drepper { 1186c5d0512SAl Viro if (unlikely(newfd == oldfd)) { /* corner case */ 1196c5d0512SAl Viro struct files_struct *files = current->files; 1206c5d0512SAl Viro rcu_read_lock(); 1216c5d0512SAl Viro if (!fcheck_files(files, oldfd)) 1226c5d0512SAl Viro oldfd = -EBADF; 1236c5d0512SAl Viro rcu_read_unlock(); 1246c5d0512SAl Viro return oldfd; 1256c5d0512SAl Viro } 126336dd1f7SUlrich Drepper return sys_dup3(oldfd, newfd, 0); 127336dd1f7SUlrich Drepper } 128336dd1f7SUlrich Drepper 129a26eab24SHeiko Carstens SYSCALL_DEFINE1(dup, unsigned int, fildes) 1301da177e4SLinus Torvalds { 1311da177e4SLinus Torvalds int ret = -EBADF; 1321da177e4SLinus Torvalds struct file *file = fget(fildes); 1331da177e4SLinus Torvalds 1341027abe8SAl Viro if (file) { 1351027abe8SAl Viro ret = get_unused_fd(); 1361027abe8SAl Viro if (ret >= 0) 1371027abe8SAl Viro fd_install(ret, file); 1381027abe8SAl Viro else 1391027abe8SAl Viro fput(file); 1401027abe8SAl Viro } 1411da177e4SLinus Torvalds return ret; 1421da177e4SLinus Torvalds } 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME) 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds static int setfl(int fd, struct file * filp, unsigned long arg) 1471da177e4SLinus Torvalds { 1480f7fc9e4SJosef "Jeff" Sipek struct inode * inode = filp->f_path.dentry->d_inode; 1491da177e4SLinus Torvalds int error = 0; 1501da177e4SLinus Torvalds 1517d95c8f2Sdean gaudet /* 1527d95c8f2Sdean gaudet * O_APPEND cannot be cleared if the file is marked as append-only 1537d95c8f2Sdean gaudet * and the file is open for write. 1547d95c8f2Sdean gaudet */ 1557d95c8f2Sdean gaudet if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode)) 1561da177e4SLinus Torvalds return -EPERM; 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds /* O_NOATIME can only be set by the owner or superuser */ 1591da177e4SLinus Torvalds if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME)) 1603bd858abSSatyam Sharma if (!is_owner_or_cap(inode)) 1611da177e4SLinus Torvalds return -EPERM; 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds /* required for strict SunOS emulation */ 1641da177e4SLinus Torvalds if (O_NONBLOCK != O_NDELAY) 1651da177e4SLinus Torvalds if (arg & O_NDELAY) 1661da177e4SLinus Torvalds arg |= O_NONBLOCK; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds if (arg & O_DIRECT) { 1691da177e4SLinus Torvalds if (!filp->f_mapping || !filp->f_mapping->a_ops || 1701da177e4SLinus Torvalds !filp->f_mapping->a_ops->direct_IO) 1711da177e4SLinus Torvalds return -EINVAL; 1721da177e4SLinus Torvalds } 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds if (filp->f_op && filp->f_op->check_flags) 1751da177e4SLinus Torvalds error = filp->f_op->check_flags(arg); 1761da177e4SLinus Torvalds if (error) 1771da177e4SLinus Torvalds return error; 1781da177e4SLinus Torvalds 179218d11a8SJonathan Corbet /* 180218d11a8SJonathan Corbet * We still need a lock here for now to keep multiple FASYNC calls 181218d11a8SJonathan Corbet * from racing with each other. 182218d11a8SJonathan Corbet */ 183218d11a8SJonathan Corbet lock_kernel(); 1841da177e4SLinus Torvalds if ((arg ^ filp->f_flags) & FASYNC) { 1851da177e4SLinus Torvalds if (filp->f_op && filp->f_op->fasync) { 1861da177e4SLinus Torvalds error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); 1871da177e4SLinus Torvalds if (error < 0) 1881da177e4SLinus Torvalds goto out; 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds 192*db1dd4d3SJonathan Corbet spin_lock(&filp->f_lock); 1931da177e4SLinus Torvalds filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); 194*db1dd4d3SJonathan Corbet spin_unlock(&filp->f_lock); 1951da177e4SLinus Torvalds out: 196218d11a8SJonathan Corbet unlock_kernel(); 1971da177e4SLinus Torvalds return error; 1981da177e4SLinus Torvalds } 1991da177e4SLinus Torvalds 200609d7fa9SEric W. Biederman static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, 2011da177e4SLinus Torvalds uid_t uid, uid_t euid, int force) 2021da177e4SLinus Torvalds { 2031da177e4SLinus Torvalds write_lock_irq(&filp->f_owner.lock); 2041da177e4SLinus Torvalds if (force || !filp->f_owner.pid) { 205609d7fa9SEric W. Biederman put_pid(filp->f_owner.pid); 206609d7fa9SEric W. Biederman filp->f_owner.pid = get_pid(pid); 207609d7fa9SEric W. Biederman filp->f_owner.pid_type = type; 2081da177e4SLinus Torvalds filp->f_owner.uid = uid; 2091da177e4SLinus Torvalds filp->f_owner.euid = euid; 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds write_unlock_irq(&filp->f_owner.lock); 2121da177e4SLinus Torvalds } 2131da177e4SLinus Torvalds 214609d7fa9SEric W. Biederman int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, 215609d7fa9SEric W. Biederman int force) 2161da177e4SLinus Torvalds { 21786a264abSDavid Howells const struct cred *cred = current_cred(); 2181da177e4SLinus Torvalds int err; 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds err = security_file_set_fowner(filp); 2211da177e4SLinus Torvalds if (err) 2221da177e4SLinus Torvalds return err; 2231da177e4SLinus Torvalds 22486a264abSDavid Howells f_modown(filp, pid, type, cred->uid, cred->euid, force); 2251da177e4SLinus Torvalds return 0; 2261da177e4SLinus Torvalds } 227609d7fa9SEric W. Biederman EXPORT_SYMBOL(__f_setown); 2281da177e4SLinus Torvalds 229609d7fa9SEric W. Biederman int f_setown(struct file *filp, unsigned long arg, int force) 230609d7fa9SEric W. Biederman { 231609d7fa9SEric W. Biederman enum pid_type type; 232609d7fa9SEric W. Biederman struct pid *pid; 233609d7fa9SEric W. Biederman int who = arg; 234609d7fa9SEric W. Biederman int result; 235609d7fa9SEric W. Biederman type = PIDTYPE_PID; 236609d7fa9SEric W. Biederman if (who < 0) { 237609d7fa9SEric W. Biederman type = PIDTYPE_PGID; 238609d7fa9SEric W. Biederman who = -who; 239609d7fa9SEric W. Biederman } 240609d7fa9SEric W. Biederman rcu_read_lock(); 241b488893aSPavel Emelyanov pid = find_vpid(who); 242609d7fa9SEric W. Biederman result = __f_setown(filp, pid, type, force); 243609d7fa9SEric W. Biederman rcu_read_unlock(); 244609d7fa9SEric W. Biederman return result; 245609d7fa9SEric W. Biederman } 2461da177e4SLinus Torvalds EXPORT_SYMBOL(f_setown); 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds void f_delown(struct file *filp) 2491da177e4SLinus Torvalds { 250609d7fa9SEric W. Biederman f_modown(filp, NULL, PIDTYPE_PID, 0, 0, 1); 251609d7fa9SEric W. Biederman } 252609d7fa9SEric W. Biederman 253609d7fa9SEric W. Biederman pid_t f_getown(struct file *filp) 254609d7fa9SEric W. Biederman { 255609d7fa9SEric W. Biederman pid_t pid; 25643fa1adbSEric W. Biederman read_lock(&filp->f_owner.lock); 2576c5f3e7bSPavel Emelyanov pid = pid_vnr(filp->f_owner.pid); 258609d7fa9SEric W. Biederman if (filp->f_owner.pid_type == PIDTYPE_PGID) 259609d7fa9SEric W. Biederman pid = -pid; 26043fa1adbSEric W. Biederman read_unlock(&filp->f_owner.lock); 261609d7fa9SEric W. Biederman return pid; 2621da177e4SLinus Torvalds } 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, 2651da177e4SLinus Torvalds struct file *filp) 2661da177e4SLinus Torvalds { 2671da177e4SLinus Torvalds long err = -EINVAL; 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds switch (cmd) { 2701da177e4SLinus Torvalds case F_DUPFD: 27122d2b35bSUlrich Drepper case F_DUPFD_CLOEXEC: 2724e1e018eSAl Viro if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 2734e1e018eSAl Viro break; 2741027abe8SAl Viro err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0); 2751027abe8SAl Viro if (err >= 0) { 2761da177e4SLinus Torvalds get_file(filp); 2771027abe8SAl Viro fd_install(err, filp); 2781027abe8SAl Viro } 2791da177e4SLinus Torvalds break; 2801da177e4SLinus Torvalds case F_GETFD: 2811da177e4SLinus Torvalds err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; 2821da177e4SLinus Torvalds break; 2831da177e4SLinus Torvalds case F_SETFD: 2841da177e4SLinus Torvalds err = 0; 2851da177e4SLinus Torvalds set_close_on_exec(fd, arg & FD_CLOEXEC); 2861da177e4SLinus Torvalds break; 2871da177e4SLinus Torvalds case F_GETFL: 2881da177e4SLinus Torvalds err = filp->f_flags; 2891da177e4SLinus Torvalds break; 2901da177e4SLinus Torvalds case F_SETFL: 2911da177e4SLinus Torvalds err = setfl(fd, filp, arg); 2921da177e4SLinus Torvalds break; 2931da177e4SLinus Torvalds case F_GETLK: 2941da177e4SLinus Torvalds err = fcntl_getlk(filp, (struct flock __user *) arg); 2951da177e4SLinus Torvalds break; 2961da177e4SLinus Torvalds case F_SETLK: 2971da177e4SLinus Torvalds case F_SETLKW: 298c293621bSPeter Staubach err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg); 2991da177e4SLinus Torvalds break; 3001da177e4SLinus Torvalds case F_GETOWN: 3011da177e4SLinus Torvalds /* 3021da177e4SLinus Torvalds * XXX If f_owner is a process group, the 3031da177e4SLinus Torvalds * negative return value will get converted 3041da177e4SLinus Torvalds * into an error. Oops. If we keep the 3051da177e4SLinus Torvalds * current syscall conventions, the only way 3061da177e4SLinus Torvalds * to fix this will be in libc. 3071da177e4SLinus Torvalds */ 308609d7fa9SEric W. Biederman err = f_getown(filp); 3091da177e4SLinus Torvalds force_successful_syscall_return(); 3101da177e4SLinus Torvalds break; 3111da177e4SLinus Torvalds case F_SETOWN: 3121da177e4SLinus Torvalds err = f_setown(filp, arg, 1); 3131da177e4SLinus Torvalds break; 3141da177e4SLinus Torvalds case F_GETSIG: 3151da177e4SLinus Torvalds err = filp->f_owner.signum; 3161da177e4SLinus Torvalds break; 3171da177e4SLinus Torvalds case F_SETSIG: 3181da177e4SLinus Torvalds /* arg == 0 restores default behaviour. */ 3197ed20e1aSJesper Juhl if (!valid_signal(arg)) { 3201da177e4SLinus Torvalds break; 3211da177e4SLinus Torvalds } 3221da177e4SLinus Torvalds err = 0; 3231da177e4SLinus Torvalds filp->f_owner.signum = arg; 3241da177e4SLinus Torvalds break; 3251da177e4SLinus Torvalds case F_GETLEASE: 3261da177e4SLinus Torvalds err = fcntl_getlease(filp); 3271da177e4SLinus Torvalds break; 3281da177e4SLinus Torvalds case F_SETLEASE: 3291da177e4SLinus Torvalds err = fcntl_setlease(fd, filp, arg); 3301da177e4SLinus Torvalds break; 3311da177e4SLinus Torvalds case F_NOTIFY: 3321da177e4SLinus Torvalds err = fcntl_dirnotify(fd, filp, arg); 3331da177e4SLinus Torvalds break; 3341da177e4SLinus Torvalds default: 3351da177e4SLinus Torvalds break; 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds return err; 3381da177e4SLinus Torvalds } 3391da177e4SLinus Torvalds 340a26eab24SHeiko Carstens SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) 3411da177e4SLinus Torvalds { 3421da177e4SLinus Torvalds struct file *filp; 3431da177e4SLinus Torvalds long err = -EBADF; 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds filp = fget(fd); 3461da177e4SLinus Torvalds if (!filp) 3471da177e4SLinus Torvalds goto out; 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds err = security_file_fcntl(filp, cmd, arg); 3501da177e4SLinus Torvalds if (err) { 3511da177e4SLinus Torvalds fput(filp); 3521da177e4SLinus Torvalds return err; 3531da177e4SLinus Torvalds } 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds err = do_fcntl(fd, cmd, arg, filp); 3561da177e4SLinus Torvalds 3571da177e4SLinus Torvalds fput(filp); 3581da177e4SLinus Torvalds out: 3591da177e4SLinus Torvalds return err; 3601da177e4SLinus Torvalds } 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds #if BITS_PER_LONG == 32 363a26eab24SHeiko Carstens SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, 364a26eab24SHeiko Carstens unsigned long, arg) 3651da177e4SLinus Torvalds { 3661da177e4SLinus Torvalds struct file * filp; 3671da177e4SLinus Torvalds long err; 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds err = -EBADF; 3701da177e4SLinus Torvalds filp = fget(fd); 3711da177e4SLinus Torvalds if (!filp) 3721da177e4SLinus Torvalds goto out; 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds err = security_file_fcntl(filp, cmd, arg); 3751da177e4SLinus Torvalds if (err) { 3761da177e4SLinus Torvalds fput(filp); 3771da177e4SLinus Torvalds return err; 3781da177e4SLinus Torvalds } 3791da177e4SLinus Torvalds err = -EBADF; 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds switch (cmd) { 3821da177e4SLinus Torvalds case F_GETLK64: 3831da177e4SLinus Torvalds err = fcntl_getlk64(filp, (struct flock64 __user *) arg); 3841da177e4SLinus Torvalds break; 3851da177e4SLinus Torvalds case F_SETLK64: 3861da177e4SLinus Torvalds case F_SETLKW64: 387c293621bSPeter Staubach err = fcntl_setlk64(fd, filp, cmd, 388c293621bSPeter Staubach (struct flock64 __user *) arg); 3891da177e4SLinus Torvalds break; 3901da177e4SLinus Torvalds default: 3911da177e4SLinus Torvalds err = do_fcntl(fd, cmd, arg, filp); 3921da177e4SLinus Torvalds break; 3931da177e4SLinus Torvalds } 3941da177e4SLinus Torvalds fput(filp); 3951da177e4SLinus Torvalds out: 3961da177e4SLinus Torvalds return err; 3971da177e4SLinus Torvalds } 3981da177e4SLinus Torvalds #endif 3991da177e4SLinus Torvalds 4001da177e4SLinus Torvalds /* Table to convert sigio signal codes into poll band bitmaps */ 4011da177e4SLinus Torvalds 402fa3536ccSEric Dumazet static const long band_table[NSIGPOLL] = { 4031da177e4SLinus Torvalds POLLIN | POLLRDNORM, /* POLL_IN */ 4041da177e4SLinus Torvalds POLLOUT | POLLWRNORM | POLLWRBAND, /* POLL_OUT */ 4051da177e4SLinus Torvalds POLLIN | POLLRDNORM | POLLMSG, /* POLL_MSG */ 4061da177e4SLinus Torvalds POLLERR, /* POLL_ERR */ 4071da177e4SLinus Torvalds POLLPRI | POLLRDBAND, /* POLL_PRI */ 4081da177e4SLinus Torvalds POLLHUP | POLLERR /* POLL_HUP */ 4091da177e4SLinus Torvalds }; 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds static inline int sigio_perm(struct task_struct *p, 4121da177e4SLinus Torvalds struct fown_struct *fown, int sig) 4131da177e4SLinus Torvalds { 414c69e8d9cSDavid Howells const struct cred *cred; 415c69e8d9cSDavid Howells int ret; 416c69e8d9cSDavid Howells 417c69e8d9cSDavid Howells rcu_read_lock(); 418c69e8d9cSDavid Howells cred = __task_cred(p); 419c69e8d9cSDavid Howells ret = ((fown->euid == 0 || 420c69e8d9cSDavid Howells fown->euid == cred->suid || fown->euid == cred->uid || 421c69e8d9cSDavid Howells fown->uid == cred->suid || fown->uid == cred->uid) && 4221da177e4SLinus Torvalds !security_file_send_sigiotask(p, fown, sig)); 423c69e8d9cSDavid Howells rcu_read_unlock(); 424c69e8d9cSDavid Howells return ret; 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds static void send_sigio_to_task(struct task_struct *p, 4281da177e4SLinus Torvalds struct fown_struct *fown, 4291da177e4SLinus Torvalds int fd, 4301da177e4SLinus Torvalds int reason) 4311da177e4SLinus Torvalds { 4321da177e4SLinus Torvalds if (!sigio_perm(p, fown, fown->signum)) 4331da177e4SLinus Torvalds return; 4341da177e4SLinus Torvalds 4351da177e4SLinus Torvalds switch (fown->signum) { 4361da177e4SLinus Torvalds siginfo_t si; 4371da177e4SLinus Torvalds default: 4381da177e4SLinus Torvalds /* Queue a rt signal with the appropriate fd as its 4391da177e4SLinus Torvalds value. We use SI_SIGIO as the source, not 4401da177e4SLinus Torvalds SI_KERNEL, since kernel signals always get 4411da177e4SLinus Torvalds delivered even if we can't queue. Failure to 4421da177e4SLinus Torvalds queue in this case _should_ be reported; we fall 4431da177e4SLinus Torvalds back to SIGIO in that case. --sct */ 4441da177e4SLinus Torvalds si.si_signo = fown->signum; 4451da177e4SLinus Torvalds si.si_errno = 0; 4461da177e4SLinus Torvalds si.si_code = reason; 4471da177e4SLinus Torvalds /* Make sure we are called with one of the POLL_* 4481da177e4SLinus Torvalds reasons, otherwise we could leak kernel stack into 4491da177e4SLinus Torvalds userspace. */ 450f6298aabSEric Sesterhenn BUG_ON((reason & __SI_MASK) != __SI_POLL); 4511da177e4SLinus Torvalds if (reason - POLL_IN >= NSIGPOLL) 4521da177e4SLinus Torvalds si.si_band = ~0L; 4531da177e4SLinus Torvalds else 4541da177e4SLinus Torvalds si.si_band = band_table[reason - POLL_IN]; 4551da177e4SLinus Torvalds si.si_fd = fd; 456850d6fbeSOleg Nesterov if (!group_send_sig_info(fown->signum, &si, p)) 4571da177e4SLinus Torvalds break; 4581da177e4SLinus Torvalds /* fall-through: fall back on the old plain SIGIO signal */ 4591da177e4SLinus Torvalds case 0: 460850d6fbeSOleg Nesterov group_send_sig_info(SIGIO, SEND_SIG_PRIV, p); 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds } 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds void send_sigio(struct fown_struct *fown, int fd, int band) 4651da177e4SLinus Torvalds { 4661da177e4SLinus Torvalds struct task_struct *p; 467609d7fa9SEric W. Biederman enum pid_type type; 468609d7fa9SEric W. Biederman struct pid *pid; 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds read_lock(&fown->lock); 471609d7fa9SEric W. Biederman type = fown->pid_type; 4721da177e4SLinus Torvalds pid = fown->pid; 4731da177e4SLinus Torvalds if (!pid) 4741da177e4SLinus Torvalds goto out_unlock_fown; 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds read_lock(&tasklist_lock); 477609d7fa9SEric W. Biederman do_each_pid_task(pid, type, p) { 4781da177e4SLinus Torvalds send_sigio_to_task(p, fown, fd, band); 479609d7fa9SEric W. Biederman } while_each_pid_task(pid, type, p); 4801da177e4SLinus Torvalds read_unlock(&tasklist_lock); 4811da177e4SLinus Torvalds out_unlock_fown: 4821da177e4SLinus Torvalds read_unlock(&fown->lock); 4831da177e4SLinus Torvalds } 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds static void send_sigurg_to_task(struct task_struct *p, 4861da177e4SLinus Torvalds struct fown_struct *fown) 4871da177e4SLinus Torvalds { 4881da177e4SLinus Torvalds if (sigio_perm(p, fown, SIGURG)) 489850d6fbeSOleg Nesterov group_send_sig_info(SIGURG, SEND_SIG_PRIV, p); 4901da177e4SLinus Torvalds } 4911da177e4SLinus Torvalds 4921da177e4SLinus Torvalds int send_sigurg(struct fown_struct *fown) 4931da177e4SLinus Torvalds { 4941da177e4SLinus Torvalds struct task_struct *p; 495609d7fa9SEric W. Biederman enum pid_type type; 496609d7fa9SEric W. Biederman struct pid *pid; 497609d7fa9SEric W. Biederman int ret = 0; 4981da177e4SLinus Torvalds 4991da177e4SLinus Torvalds read_lock(&fown->lock); 500609d7fa9SEric W. Biederman type = fown->pid_type; 5011da177e4SLinus Torvalds pid = fown->pid; 5021da177e4SLinus Torvalds if (!pid) 5031da177e4SLinus Torvalds goto out_unlock_fown; 5041da177e4SLinus Torvalds 5051da177e4SLinus Torvalds ret = 1; 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds read_lock(&tasklist_lock); 508609d7fa9SEric W. Biederman do_each_pid_task(pid, type, p) { 5091da177e4SLinus Torvalds send_sigurg_to_task(p, fown); 510609d7fa9SEric W. Biederman } while_each_pid_task(pid, type, p); 5111da177e4SLinus Torvalds read_unlock(&tasklist_lock); 5121da177e4SLinus Torvalds out_unlock_fown: 5131da177e4SLinus Torvalds read_unlock(&fown->lock); 5141da177e4SLinus Torvalds return ret; 5151da177e4SLinus Torvalds } 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds static DEFINE_RWLOCK(fasync_lock); 518e18b890bSChristoph Lameter static struct kmem_cache *fasync_cache __read_mostly; 5191da177e4SLinus Torvalds 5201da177e4SLinus Torvalds /* 5211da177e4SLinus Torvalds * fasync_helper() is used by some character device drivers (mainly mice) 5221da177e4SLinus Torvalds * to set up the fasync queue. It returns negative on error, 0 if it did 5231da177e4SLinus Torvalds * no changes and positive if it added/deleted the entry. 5241da177e4SLinus Torvalds */ 5251da177e4SLinus Torvalds int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) 5261da177e4SLinus Torvalds { 5271da177e4SLinus Torvalds struct fasync_struct *fa, **fp; 5281da177e4SLinus Torvalds struct fasync_struct *new = NULL; 5291da177e4SLinus Torvalds int result = 0; 5301da177e4SLinus Torvalds 5311da177e4SLinus Torvalds if (on) { 532e94b1766SChristoph Lameter new = kmem_cache_alloc(fasync_cache, GFP_KERNEL); 5331da177e4SLinus Torvalds if (!new) 5341da177e4SLinus Torvalds return -ENOMEM; 5351da177e4SLinus Torvalds } 5361da177e4SLinus Torvalds write_lock_irq(&fasync_lock); 5371da177e4SLinus Torvalds for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { 5381da177e4SLinus Torvalds if (fa->fa_file == filp) { 5391da177e4SLinus Torvalds if(on) { 5401da177e4SLinus Torvalds fa->fa_fd = fd; 5411da177e4SLinus Torvalds kmem_cache_free(fasync_cache, new); 5421da177e4SLinus Torvalds } else { 5431da177e4SLinus Torvalds *fp = fa->fa_next; 5441da177e4SLinus Torvalds kmem_cache_free(fasync_cache, fa); 5451da177e4SLinus Torvalds result = 1; 5461da177e4SLinus Torvalds } 5471da177e4SLinus Torvalds goto out; 5481da177e4SLinus Torvalds } 5491da177e4SLinus Torvalds } 5501da177e4SLinus Torvalds 5511da177e4SLinus Torvalds if (on) { 5521da177e4SLinus Torvalds new->magic = FASYNC_MAGIC; 5531da177e4SLinus Torvalds new->fa_file = filp; 5541da177e4SLinus Torvalds new->fa_fd = fd; 5551da177e4SLinus Torvalds new->fa_next = *fapp; 5561da177e4SLinus Torvalds *fapp = new; 5571da177e4SLinus Torvalds result = 1; 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds out: 5601da177e4SLinus Torvalds write_unlock_irq(&fasync_lock); 5611da177e4SLinus Torvalds return result; 5621da177e4SLinus Torvalds } 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds EXPORT_SYMBOL(fasync_helper); 5651da177e4SLinus Torvalds 5661da177e4SLinus Torvalds void __kill_fasync(struct fasync_struct *fa, int sig, int band) 5671da177e4SLinus Torvalds { 5681da177e4SLinus Torvalds while (fa) { 5691da177e4SLinus Torvalds struct fown_struct * fown; 5701da177e4SLinus Torvalds if (fa->magic != FASYNC_MAGIC) { 5711da177e4SLinus Torvalds printk(KERN_ERR "kill_fasync: bad magic number in " 5721da177e4SLinus Torvalds "fasync_struct!\n"); 5731da177e4SLinus Torvalds return; 5741da177e4SLinus Torvalds } 5751da177e4SLinus Torvalds fown = &fa->fa_file->f_owner; 5761da177e4SLinus Torvalds /* Don't send SIGURG to processes which have not set a 5771da177e4SLinus Torvalds queued signum: SIGURG has its own default signalling 5781da177e4SLinus Torvalds mechanism. */ 5791da177e4SLinus Torvalds if (!(sig == SIGURG && fown->signum == 0)) 5801da177e4SLinus Torvalds send_sigio(fown, fa->fa_fd, band); 5811da177e4SLinus Torvalds fa = fa->fa_next; 5821da177e4SLinus Torvalds } 5831da177e4SLinus Torvalds } 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds EXPORT_SYMBOL(__kill_fasync); 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds void kill_fasync(struct fasync_struct **fp, int sig, int band) 5881da177e4SLinus Torvalds { 5891da177e4SLinus Torvalds /* First a quick test without locking: usually 5901da177e4SLinus Torvalds * the list is empty. 5911da177e4SLinus Torvalds */ 5921da177e4SLinus Torvalds if (*fp) { 5931da177e4SLinus Torvalds read_lock(&fasync_lock); 5941da177e4SLinus Torvalds /* reread *fp after obtaining the lock */ 5951da177e4SLinus Torvalds __kill_fasync(*fp, sig, band); 5961da177e4SLinus Torvalds read_unlock(&fasync_lock); 5971da177e4SLinus Torvalds } 5981da177e4SLinus Torvalds } 5991da177e4SLinus Torvalds EXPORT_SYMBOL(kill_fasync); 6001da177e4SLinus Torvalds 6011da177e4SLinus Torvalds static int __init fasync_init(void) 6021da177e4SLinus Torvalds { 6031da177e4SLinus Torvalds fasync_cache = kmem_cache_create("fasync_cache", 60420c2df83SPaul Mundt sizeof(struct fasync_struct), 0, SLAB_PANIC, NULL); 6051da177e4SLinus Torvalds return 0; 6061da177e4SLinus Torvalds } 6071da177e4SLinus Torvalds 6081da177e4SLinus Torvalds module_init(fasync_init) 609