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> 1735f3d14dSJens Axboe #include <linux/pipe_fs_i.h> 181da177e4SLinus Torvalds #include <linux/security.h> 191da177e4SLinus Torvalds #include <linux/ptrace.h> 207ed20e1aSJesper Juhl #include <linux/signal.h> 21ab2af1f5SDipankar Sarma #include <linux/rcupdate.h> 22b488893aSPavel Emelyanov #include <linux/pid_namespace.h> 231d151c33SCyrill Gorcunov #include <linux/user_namespace.h> 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #include <asm/poll.h> 261da177e4SLinus Torvalds #include <asm/siginfo.h> 271da177e4SLinus Torvalds #include <asm/uaccess.h> 281da177e4SLinus Torvalds 2976398425SJonathan Corbet #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds static int setfl(int fd, struct file * filp, unsigned long arg) 321da177e4SLinus Torvalds { 33496ad9aaSAl Viro struct inode * inode = file_inode(filp); 341da177e4SLinus Torvalds int error = 0; 351da177e4SLinus Torvalds 367d95c8f2Sdean gaudet /* 377d95c8f2Sdean gaudet * O_APPEND cannot be cleared if the file is marked as append-only 387d95c8f2Sdean gaudet * and the file is open for write. 397d95c8f2Sdean gaudet */ 407d95c8f2Sdean gaudet if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode)) 411da177e4SLinus Torvalds return -EPERM; 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds /* O_NOATIME can only be set by the owner or superuser */ 441da177e4SLinus Torvalds if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME)) 452e149670SSerge E. Hallyn if (!inode_owner_or_capable(inode)) 461da177e4SLinus Torvalds return -EPERM; 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds /* required for strict SunOS emulation */ 491da177e4SLinus Torvalds if (O_NONBLOCK != O_NDELAY) 501da177e4SLinus Torvalds if (arg & O_NDELAY) 511da177e4SLinus Torvalds arg |= O_NONBLOCK; 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds if (arg & O_DIRECT) { 541da177e4SLinus Torvalds if (!filp->f_mapping || !filp->f_mapping->a_ops || 551da177e4SLinus Torvalds !filp->f_mapping->a_ops->direct_IO) 561da177e4SLinus Torvalds return -EINVAL; 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 59*72c2d531SAl Viro if (filp->f_op->check_flags) 601da177e4SLinus Torvalds error = filp->f_op->check_flags(arg); 611da177e4SLinus Torvalds if (error) 621da177e4SLinus Torvalds return error; 631da177e4SLinus Torvalds 64218d11a8SJonathan Corbet /* 6576398425SJonathan Corbet * ->fasync() is responsible for setting the FASYNC bit. 66218d11a8SJonathan Corbet */ 67*72c2d531SAl Viro if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op->fasync) { 681da177e4SLinus Torvalds error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); 691da177e4SLinus Torvalds if (error < 0) 701da177e4SLinus Torvalds goto out; 7160aa4924SJonathan Corbet if (error > 0) 7260aa4924SJonathan Corbet error = 0; 731da177e4SLinus Torvalds } 74db1dd4d3SJonathan Corbet spin_lock(&filp->f_lock); 751da177e4SLinus Torvalds filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); 76db1dd4d3SJonathan Corbet spin_unlock(&filp->f_lock); 7776398425SJonathan Corbet 781da177e4SLinus Torvalds out: 791da177e4SLinus Torvalds return error; 801da177e4SLinus Torvalds } 811da177e4SLinus Torvalds 82609d7fa9SEric W. Biederman static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, 832f38d70fSOleg Nesterov int force) 841da177e4SLinus Torvalds { 8580e1e823SLinus Torvalds write_lock_irq(&filp->f_owner.lock); 861da177e4SLinus Torvalds if (force || !filp->f_owner.pid) { 87609d7fa9SEric W. Biederman put_pid(filp->f_owner.pid); 88609d7fa9SEric W. Biederman filp->f_owner.pid = get_pid(pid); 89609d7fa9SEric W. Biederman filp->f_owner.pid_type = type; 902f38d70fSOleg Nesterov 912f38d70fSOleg Nesterov if (pid) { 922f38d70fSOleg Nesterov const struct cred *cred = current_cred(); 932f38d70fSOleg Nesterov filp->f_owner.uid = cred->uid; 942f38d70fSOleg Nesterov filp->f_owner.euid = cred->euid; 952f38d70fSOleg Nesterov } 961da177e4SLinus Torvalds } 9780e1e823SLinus Torvalds write_unlock_irq(&filp->f_owner.lock); 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds 100609d7fa9SEric W. Biederman int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, 101609d7fa9SEric W. Biederman int force) 1021da177e4SLinus Torvalds { 1031da177e4SLinus Torvalds int err; 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds err = security_file_set_fowner(filp); 1061da177e4SLinus Torvalds if (err) 1071da177e4SLinus Torvalds return err; 1081da177e4SLinus Torvalds 1092f38d70fSOleg Nesterov f_modown(filp, pid, type, force); 1101da177e4SLinus Torvalds return 0; 1111da177e4SLinus Torvalds } 112609d7fa9SEric W. Biederman EXPORT_SYMBOL(__f_setown); 1131da177e4SLinus Torvalds 114609d7fa9SEric W. Biederman int f_setown(struct file *filp, unsigned long arg, int force) 115609d7fa9SEric W. Biederman { 116609d7fa9SEric W. Biederman enum pid_type type; 117609d7fa9SEric W. Biederman struct pid *pid; 118609d7fa9SEric W. Biederman int who = arg; 119609d7fa9SEric W. Biederman int result; 120609d7fa9SEric W. Biederman type = PIDTYPE_PID; 121609d7fa9SEric W. Biederman if (who < 0) { 122609d7fa9SEric W. Biederman type = PIDTYPE_PGID; 123609d7fa9SEric W. Biederman who = -who; 124609d7fa9SEric W. Biederman } 125609d7fa9SEric W. Biederman rcu_read_lock(); 126b488893aSPavel Emelyanov pid = find_vpid(who); 127609d7fa9SEric W. Biederman result = __f_setown(filp, pid, type, force); 128609d7fa9SEric W. Biederman rcu_read_unlock(); 129609d7fa9SEric W. Biederman return result; 130609d7fa9SEric W. Biederman } 1311da177e4SLinus Torvalds EXPORT_SYMBOL(f_setown); 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds void f_delown(struct file *filp) 1341da177e4SLinus Torvalds { 1352f38d70fSOleg Nesterov f_modown(filp, NULL, PIDTYPE_PID, 1); 136609d7fa9SEric W. Biederman } 137609d7fa9SEric W. Biederman 138609d7fa9SEric W. Biederman pid_t f_getown(struct file *filp) 139609d7fa9SEric W. Biederman { 140609d7fa9SEric W. Biederman pid_t pid; 14143fa1adbSEric W. Biederman read_lock(&filp->f_owner.lock); 1426c5f3e7bSPavel Emelyanov pid = pid_vnr(filp->f_owner.pid); 143609d7fa9SEric W. Biederman if (filp->f_owner.pid_type == PIDTYPE_PGID) 144609d7fa9SEric W. Biederman pid = -pid; 14543fa1adbSEric W. Biederman read_unlock(&filp->f_owner.lock); 146609d7fa9SEric W. Biederman return pid; 1471da177e4SLinus Torvalds } 1481da177e4SLinus Torvalds 149ba0a6c9fSPeter Zijlstra static int f_setown_ex(struct file *filp, unsigned long arg) 150ba0a6c9fSPeter Zijlstra { 15163784dd0SAl Viro struct f_owner_ex __user *owner_p = (void __user *)arg; 152ba0a6c9fSPeter Zijlstra struct f_owner_ex owner; 153ba0a6c9fSPeter Zijlstra struct pid *pid; 154ba0a6c9fSPeter Zijlstra int type; 155ba0a6c9fSPeter Zijlstra int ret; 156ba0a6c9fSPeter Zijlstra 157ba0a6c9fSPeter Zijlstra ret = copy_from_user(&owner, owner_p, sizeof(owner)); 158ba0a6c9fSPeter Zijlstra if (ret) 1595b54470dSDan Carpenter return -EFAULT; 160ba0a6c9fSPeter Zijlstra 161ba0a6c9fSPeter Zijlstra switch (owner.type) { 162ba0a6c9fSPeter Zijlstra case F_OWNER_TID: 163ba0a6c9fSPeter Zijlstra type = PIDTYPE_MAX; 164ba0a6c9fSPeter Zijlstra break; 165ba0a6c9fSPeter Zijlstra 166ba0a6c9fSPeter Zijlstra case F_OWNER_PID: 167ba0a6c9fSPeter Zijlstra type = PIDTYPE_PID; 168ba0a6c9fSPeter Zijlstra break; 169ba0a6c9fSPeter Zijlstra 170978b4053SPeter Zijlstra case F_OWNER_PGRP: 171ba0a6c9fSPeter Zijlstra type = PIDTYPE_PGID; 172ba0a6c9fSPeter Zijlstra break; 173ba0a6c9fSPeter Zijlstra 174ba0a6c9fSPeter Zijlstra default: 175ba0a6c9fSPeter Zijlstra return -EINVAL; 176ba0a6c9fSPeter Zijlstra } 177ba0a6c9fSPeter Zijlstra 178ba0a6c9fSPeter Zijlstra rcu_read_lock(); 179ba0a6c9fSPeter Zijlstra pid = find_vpid(owner.pid); 180ba0a6c9fSPeter Zijlstra if (owner.pid && !pid) 181ba0a6c9fSPeter Zijlstra ret = -ESRCH; 182ba0a6c9fSPeter Zijlstra else 183ba0a6c9fSPeter Zijlstra ret = __f_setown(filp, pid, type, 1); 184ba0a6c9fSPeter Zijlstra rcu_read_unlock(); 185ba0a6c9fSPeter Zijlstra 186ba0a6c9fSPeter Zijlstra return ret; 187ba0a6c9fSPeter Zijlstra } 188ba0a6c9fSPeter Zijlstra 189ba0a6c9fSPeter Zijlstra static int f_getown_ex(struct file *filp, unsigned long arg) 190ba0a6c9fSPeter Zijlstra { 19163784dd0SAl Viro struct f_owner_ex __user *owner_p = (void __user *)arg; 192ba0a6c9fSPeter Zijlstra struct f_owner_ex owner; 193ba0a6c9fSPeter Zijlstra int ret = 0; 194ba0a6c9fSPeter Zijlstra 195ba0a6c9fSPeter Zijlstra read_lock(&filp->f_owner.lock); 196ba0a6c9fSPeter Zijlstra owner.pid = pid_vnr(filp->f_owner.pid); 197ba0a6c9fSPeter Zijlstra switch (filp->f_owner.pid_type) { 198ba0a6c9fSPeter Zijlstra case PIDTYPE_MAX: 199ba0a6c9fSPeter Zijlstra owner.type = F_OWNER_TID; 200ba0a6c9fSPeter Zijlstra break; 201ba0a6c9fSPeter Zijlstra 202ba0a6c9fSPeter Zijlstra case PIDTYPE_PID: 203ba0a6c9fSPeter Zijlstra owner.type = F_OWNER_PID; 204ba0a6c9fSPeter Zijlstra break; 205ba0a6c9fSPeter Zijlstra 206ba0a6c9fSPeter Zijlstra case PIDTYPE_PGID: 207978b4053SPeter Zijlstra owner.type = F_OWNER_PGRP; 208ba0a6c9fSPeter Zijlstra break; 209ba0a6c9fSPeter Zijlstra 210ba0a6c9fSPeter Zijlstra default: 211ba0a6c9fSPeter Zijlstra WARN_ON(1); 212ba0a6c9fSPeter Zijlstra ret = -EINVAL; 213ba0a6c9fSPeter Zijlstra break; 214ba0a6c9fSPeter Zijlstra } 215ba0a6c9fSPeter Zijlstra read_unlock(&filp->f_owner.lock); 216ba0a6c9fSPeter Zijlstra 2175b54470dSDan Carpenter if (!ret) { 218ba0a6c9fSPeter Zijlstra ret = copy_to_user(owner_p, &owner, sizeof(owner)); 2195b54470dSDan Carpenter if (ret) 2205b54470dSDan Carpenter ret = -EFAULT; 2215b54470dSDan Carpenter } 222ba0a6c9fSPeter Zijlstra return ret; 223ba0a6c9fSPeter Zijlstra } 224ba0a6c9fSPeter Zijlstra 2251d151c33SCyrill Gorcunov #ifdef CONFIG_CHECKPOINT_RESTORE 2261d151c33SCyrill Gorcunov static int f_getowner_uids(struct file *filp, unsigned long arg) 2271d151c33SCyrill Gorcunov { 2281d151c33SCyrill Gorcunov struct user_namespace *user_ns = current_user_ns(); 22963784dd0SAl Viro uid_t __user *dst = (void __user *)arg; 2301d151c33SCyrill Gorcunov uid_t src[2]; 2311d151c33SCyrill Gorcunov int err; 2321d151c33SCyrill Gorcunov 2331d151c33SCyrill Gorcunov read_lock(&filp->f_owner.lock); 2341d151c33SCyrill Gorcunov src[0] = from_kuid(user_ns, filp->f_owner.uid); 2351d151c33SCyrill Gorcunov src[1] = from_kuid(user_ns, filp->f_owner.euid); 2361d151c33SCyrill Gorcunov read_unlock(&filp->f_owner.lock); 2371d151c33SCyrill Gorcunov 2381d151c33SCyrill Gorcunov err = put_user(src[0], &dst[0]); 2391d151c33SCyrill Gorcunov err |= put_user(src[1], &dst[1]); 2401d151c33SCyrill Gorcunov 2411d151c33SCyrill Gorcunov return err; 2421d151c33SCyrill Gorcunov } 2431d151c33SCyrill Gorcunov #else 2441d151c33SCyrill Gorcunov static int f_getowner_uids(struct file *filp, unsigned long arg) 2451d151c33SCyrill Gorcunov { 2461d151c33SCyrill Gorcunov return -EINVAL; 2471d151c33SCyrill Gorcunov } 2481d151c33SCyrill Gorcunov #endif 2491d151c33SCyrill Gorcunov 2501da177e4SLinus Torvalds static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, 2511da177e4SLinus Torvalds struct file *filp) 2521da177e4SLinus Torvalds { 2531da177e4SLinus Torvalds long err = -EINVAL; 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds switch (cmd) { 2561da177e4SLinus Torvalds case F_DUPFD: 257fe17f22dSAl Viro err = f_dupfd(arg, filp, 0); 2584e1e018eSAl Viro break; 259fe17f22dSAl Viro case F_DUPFD_CLOEXEC: 26012197718SAl Viro err = f_dupfd(arg, filp, O_CLOEXEC); 2611da177e4SLinus Torvalds break; 2621da177e4SLinus Torvalds case F_GETFD: 2631da177e4SLinus Torvalds err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; 2641da177e4SLinus Torvalds break; 2651da177e4SLinus Torvalds case F_SETFD: 2661da177e4SLinus Torvalds err = 0; 2671da177e4SLinus Torvalds set_close_on_exec(fd, arg & FD_CLOEXEC); 2681da177e4SLinus Torvalds break; 2691da177e4SLinus Torvalds case F_GETFL: 2701da177e4SLinus Torvalds err = filp->f_flags; 2711da177e4SLinus Torvalds break; 2721da177e4SLinus Torvalds case F_SETFL: 2731da177e4SLinus Torvalds err = setfl(fd, filp, arg); 2741da177e4SLinus Torvalds break; 2751da177e4SLinus Torvalds case F_GETLK: 2761da177e4SLinus Torvalds err = fcntl_getlk(filp, (struct flock __user *) arg); 2771da177e4SLinus Torvalds break; 2781da177e4SLinus Torvalds case F_SETLK: 2791da177e4SLinus Torvalds case F_SETLKW: 280c293621bSPeter Staubach err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg); 2811da177e4SLinus Torvalds break; 2821da177e4SLinus Torvalds case F_GETOWN: 2831da177e4SLinus Torvalds /* 2841da177e4SLinus Torvalds * XXX If f_owner is a process group, the 2851da177e4SLinus Torvalds * negative return value will get converted 2861da177e4SLinus Torvalds * into an error. Oops. If we keep the 2871da177e4SLinus Torvalds * current syscall conventions, the only way 2881da177e4SLinus Torvalds * to fix this will be in libc. 2891da177e4SLinus Torvalds */ 290609d7fa9SEric W. Biederman err = f_getown(filp); 2911da177e4SLinus Torvalds force_successful_syscall_return(); 2921da177e4SLinus Torvalds break; 2931da177e4SLinus Torvalds case F_SETOWN: 2941da177e4SLinus Torvalds err = f_setown(filp, arg, 1); 2951da177e4SLinus Torvalds break; 296ba0a6c9fSPeter Zijlstra case F_GETOWN_EX: 297ba0a6c9fSPeter Zijlstra err = f_getown_ex(filp, arg); 298ba0a6c9fSPeter Zijlstra break; 299ba0a6c9fSPeter Zijlstra case F_SETOWN_EX: 300ba0a6c9fSPeter Zijlstra err = f_setown_ex(filp, arg); 301ba0a6c9fSPeter Zijlstra break; 3021d151c33SCyrill Gorcunov case F_GETOWNER_UIDS: 3031d151c33SCyrill Gorcunov err = f_getowner_uids(filp, arg); 3041d151c33SCyrill Gorcunov break; 3051da177e4SLinus Torvalds case F_GETSIG: 3061da177e4SLinus Torvalds err = filp->f_owner.signum; 3071da177e4SLinus Torvalds break; 3081da177e4SLinus Torvalds case F_SETSIG: 3091da177e4SLinus Torvalds /* arg == 0 restores default behaviour. */ 3107ed20e1aSJesper Juhl if (!valid_signal(arg)) { 3111da177e4SLinus Torvalds break; 3121da177e4SLinus Torvalds } 3131da177e4SLinus Torvalds err = 0; 3141da177e4SLinus Torvalds filp->f_owner.signum = arg; 3151da177e4SLinus Torvalds break; 3161da177e4SLinus Torvalds case F_GETLEASE: 3171da177e4SLinus Torvalds err = fcntl_getlease(filp); 3181da177e4SLinus Torvalds break; 3191da177e4SLinus Torvalds case F_SETLEASE: 3201da177e4SLinus Torvalds err = fcntl_setlease(fd, filp, arg); 3211da177e4SLinus Torvalds break; 3221da177e4SLinus Torvalds case F_NOTIFY: 3231da177e4SLinus Torvalds err = fcntl_dirnotify(fd, filp, arg); 3241da177e4SLinus Torvalds break; 32535f3d14dSJens Axboe case F_SETPIPE_SZ: 32635f3d14dSJens Axboe case F_GETPIPE_SZ: 32735f3d14dSJens Axboe err = pipe_fcntl(filp, cmd, arg); 32835f3d14dSJens Axboe break; 3291da177e4SLinus Torvalds default: 3301da177e4SLinus Torvalds break; 3311da177e4SLinus Torvalds } 3321da177e4SLinus Torvalds return err; 3331da177e4SLinus Torvalds } 3341da177e4SLinus Torvalds 3351abf0c71SAl Viro static int check_fcntl_cmd(unsigned cmd) 3361abf0c71SAl Viro { 3371abf0c71SAl Viro switch (cmd) { 3381abf0c71SAl Viro case F_DUPFD: 3391abf0c71SAl Viro case F_DUPFD_CLOEXEC: 3401abf0c71SAl Viro case F_GETFD: 3411abf0c71SAl Viro case F_SETFD: 3421abf0c71SAl Viro case F_GETFL: 3431abf0c71SAl Viro return 1; 3441abf0c71SAl Viro } 3451abf0c71SAl Viro return 0; 3461abf0c71SAl Viro } 3471abf0c71SAl Viro 348a26eab24SHeiko Carstens SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) 3491da177e4SLinus Torvalds { 3502903ff01SAl Viro struct fd f = fdget_raw(fd); 3511da177e4SLinus Torvalds long err = -EBADF; 3521da177e4SLinus Torvalds 3532903ff01SAl Viro if (!f.file) 3541da177e4SLinus Torvalds goto out; 3551da177e4SLinus Torvalds 3562903ff01SAl Viro if (unlikely(f.file->f_mode & FMODE_PATH)) { 357545ec2c7SAl Viro if (!check_fcntl_cmd(cmd)) 358545ec2c7SAl Viro goto out1; 3591abf0c71SAl Viro } 3601abf0c71SAl Viro 3612903ff01SAl Viro err = security_file_fcntl(f.file, cmd, arg); 362545ec2c7SAl Viro if (!err) 3632903ff01SAl Viro err = do_fcntl(fd, cmd, arg, f.file); 3641da177e4SLinus Torvalds 365545ec2c7SAl Viro out1: 3662903ff01SAl Viro fdput(f); 3671da177e4SLinus Torvalds out: 3681da177e4SLinus Torvalds return err; 3691da177e4SLinus Torvalds } 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds #if BITS_PER_LONG == 32 372a26eab24SHeiko Carstens SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, 373a26eab24SHeiko Carstens unsigned long, arg) 3741da177e4SLinus Torvalds { 3752903ff01SAl Viro struct fd f = fdget_raw(fd); 376545ec2c7SAl Viro long err = -EBADF; 3771da177e4SLinus Torvalds 3782903ff01SAl Viro if (!f.file) 3791da177e4SLinus Torvalds goto out; 3801da177e4SLinus Torvalds 3812903ff01SAl Viro if (unlikely(f.file->f_mode & FMODE_PATH)) { 382545ec2c7SAl Viro if (!check_fcntl_cmd(cmd)) 383545ec2c7SAl Viro goto out1; 3841abf0c71SAl Viro } 3851abf0c71SAl Viro 3862903ff01SAl Viro err = security_file_fcntl(f.file, cmd, arg); 387545ec2c7SAl Viro if (err) 388545ec2c7SAl Viro goto out1; 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds switch (cmd) { 3911da177e4SLinus Torvalds case F_GETLK64: 3922903ff01SAl Viro err = fcntl_getlk64(f.file, (struct flock64 __user *) arg); 3931da177e4SLinus Torvalds break; 3941da177e4SLinus Torvalds case F_SETLK64: 3951da177e4SLinus Torvalds case F_SETLKW64: 3962903ff01SAl Viro err = fcntl_setlk64(fd, f.file, cmd, 397c293621bSPeter Staubach (struct flock64 __user *) arg); 3981da177e4SLinus Torvalds break; 3991da177e4SLinus Torvalds default: 4002903ff01SAl Viro err = do_fcntl(fd, cmd, arg, f.file); 4011da177e4SLinus Torvalds break; 4021da177e4SLinus Torvalds } 403545ec2c7SAl Viro out1: 4042903ff01SAl Viro fdput(f); 4051da177e4SLinus Torvalds out: 4061da177e4SLinus Torvalds return err; 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds #endif 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds /* Table to convert sigio signal codes into poll band bitmaps */ 4111da177e4SLinus Torvalds 412fa3536ccSEric Dumazet static const long band_table[NSIGPOLL] = { 4131da177e4SLinus Torvalds POLLIN | POLLRDNORM, /* POLL_IN */ 4141da177e4SLinus Torvalds POLLOUT | POLLWRNORM | POLLWRBAND, /* POLL_OUT */ 4151da177e4SLinus Torvalds POLLIN | POLLRDNORM | POLLMSG, /* POLL_MSG */ 4161da177e4SLinus Torvalds POLLERR, /* POLL_ERR */ 4171da177e4SLinus Torvalds POLLPRI | POLLRDBAND, /* POLL_PRI */ 4181da177e4SLinus Torvalds POLLHUP | POLLERR /* POLL_HUP */ 4191da177e4SLinus Torvalds }; 4201da177e4SLinus Torvalds 4211da177e4SLinus Torvalds static inline int sigio_perm(struct task_struct *p, 4221da177e4SLinus Torvalds struct fown_struct *fown, int sig) 4231da177e4SLinus Torvalds { 424c69e8d9cSDavid Howells const struct cred *cred; 425c69e8d9cSDavid Howells int ret; 426c69e8d9cSDavid Howells 427c69e8d9cSDavid Howells rcu_read_lock(); 428c69e8d9cSDavid Howells cred = __task_cred(p); 4298e96e3b7SEric W. Biederman ret = ((uid_eq(fown->euid, GLOBAL_ROOT_UID) || 4308e96e3b7SEric W. Biederman uid_eq(fown->euid, cred->suid) || uid_eq(fown->euid, cred->uid) || 4318e96e3b7SEric W. Biederman uid_eq(fown->uid, cred->suid) || uid_eq(fown->uid, cred->uid)) && 4321da177e4SLinus Torvalds !security_file_send_sigiotask(p, fown, sig)); 433c69e8d9cSDavid Howells rcu_read_unlock(); 434c69e8d9cSDavid Howells return ret; 4351da177e4SLinus Torvalds } 4361da177e4SLinus Torvalds 4371da177e4SLinus Torvalds static void send_sigio_to_task(struct task_struct *p, 4381da177e4SLinus Torvalds struct fown_struct *fown, 439ba0a6c9fSPeter Zijlstra int fd, int reason, int group) 4401da177e4SLinus Torvalds { 4418eeee4e2SOleg Nesterov /* 4428eeee4e2SOleg Nesterov * F_SETSIG can change ->signum lockless in parallel, make 4438eeee4e2SOleg Nesterov * sure we read it once and use the same value throughout. 4448eeee4e2SOleg Nesterov */ 4458eeee4e2SOleg Nesterov int signum = ACCESS_ONCE(fown->signum); 4468eeee4e2SOleg Nesterov 4478eeee4e2SOleg Nesterov if (!sigio_perm(p, fown, signum)) 4481da177e4SLinus Torvalds return; 4491da177e4SLinus Torvalds 4508eeee4e2SOleg Nesterov switch (signum) { 4511da177e4SLinus Torvalds siginfo_t si; 4521da177e4SLinus Torvalds default: 4531da177e4SLinus Torvalds /* Queue a rt signal with the appropriate fd as its 4541da177e4SLinus Torvalds value. We use SI_SIGIO as the source, not 4551da177e4SLinus Torvalds SI_KERNEL, since kernel signals always get 4561da177e4SLinus Torvalds delivered even if we can't queue. Failure to 4571da177e4SLinus Torvalds queue in this case _should_ be reported; we fall 4581da177e4SLinus Torvalds back to SIGIO in that case. --sct */ 4598eeee4e2SOleg Nesterov si.si_signo = signum; 4601da177e4SLinus Torvalds si.si_errno = 0; 4611da177e4SLinus Torvalds si.si_code = reason; 4621da177e4SLinus Torvalds /* Make sure we are called with one of the POLL_* 4631da177e4SLinus Torvalds reasons, otherwise we could leak kernel stack into 4641da177e4SLinus Torvalds userspace. */ 465f6298aabSEric Sesterhenn BUG_ON((reason & __SI_MASK) != __SI_POLL); 4661da177e4SLinus Torvalds if (reason - POLL_IN >= NSIGPOLL) 4671da177e4SLinus Torvalds si.si_band = ~0L; 4681da177e4SLinus Torvalds else 4691da177e4SLinus Torvalds si.si_band = band_table[reason - POLL_IN]; 4701da177e4SLinus Torvalds si.si_fd = fd; 471ba0a6c9fSPeter Zijlstra if (!do_send_sig_info(signum, &si, p, group)) 4721da177e4SLinus Torvalds break; 4731da177e4SLinus Torvalds /* fall-through: fall back on the old plain SIGIO signal */ 4741da177e4SLinus Torvalds case 0: 475ba0a6c9fSPeter Zijlstra do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, group); 4761da177e4SLinus Torvalds } 4771da177e4SLinus Torvalds } 4781da177e4SLinus Torvalds 4791da177e4SLinus Torvalds void send_sigio(struct fown_struct *fown, int fd, int band) 4801da177e4SLinus Torvalds { 4811da177e4SLinus Torvalds struct task_struct *p; 482609d7fa9SEric W. Biederman enum pid_type type; 483609d7fa9SEric W. Biederman struct pid *pid; 484ba0a6c9fSPeter Zijlstra int group = 1; 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds read_lock(&fown->lock); 487ba0a6c9fSPeter Zijlstra 488609d7fa9SEric W. Biederman type = fown->pid_type; 489ba0a6c9fSPeter Zijlstra if (type == PIDTYPE_MAX) { 490ba0a6c9fSPeter Zijlstra group = 0; 491ba0a6c9fSPeter Zijlstra type = PIDTYPE_PID; 492ba0a6c9fSPeter Zijlstra } 493ba0a6c9fSPeter Zijlstra 4941da177e4SLinus Torvalds pid = fown->pid; 4951da177e4SLinus Torvalds if (!pid) 4961da177e4SLinus Torvalds goto out_unlock_fown; 4971da177e4SLinus Torvalds 4981da177e4SLinus Torvalds read_lock(&tasklist_lock); 499609d7fa9SEric W. Biederman do_each_pid_task(pid, type, p) { 500ba0a6c9fSPeter Zijlstra send_sigio_to_task(p, fown, fd, band, group); 501609d7fa9SEric W. Biederman } while_each_pid_task(pid, type, p); 5021da177e4SLinus Torvalds read_unlock(&tasklist_lock); 5031da177e4SLinus Torvalds out_unlock_fown: 5041da177e4SLinus Torvalds read_unlock(&fown->lock); 5051da177e4SLinus Torvalds } 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds static void send_sigurg_to_task(struct task_struct *p, 508ba0a6c9fSPeter Zijlstra struct fown_struct *fown, int group) 5091da177e4SLinus Torvalds { 5101da177e4SLinus Torvalds if (sigio_perm(p, fown, SIGURG)) 511ba0a6c9fSPeter Zijlstra do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, group); 5121da177e4SLinus Torvalds } 5131da177e4SLinus Torvalds 5141da177e4SLinus Torvalds int send_sigurg(struct fown_struct *fown) 5151da177e4SLinus Torvalds { 5161da177e4SLinus Torvalds struct task_struct *p; 517609d7fa9SEric W. Biederman enum pid_type type; 518609d7fa9SEric W. Biederman struct pid *pid; 519ba0a6c9fSPeter Zijlstra int group = 1; 520609d7fa9SEric W. Biederman int ret = 0; 5211da177e4SLinus Torvalds 5221da177e4SLinus Torvalds read_lock(&fown->lock); 523ba0a6c9fSPeter Zijlstra 524609d7fa9SEric W. Biederman type = fown->pid_type; 525ba0a6c9fSPeter Zijlstra if (type == PIDTYPE_MAX) { 526ba0a6c9fSPeter Zijlstra group = 0; 527ba0a6c9fSPeter Zijlstra type = PIDTYPE_PID; 528ba0a6c9fSPeter Zijlstra } 529ba0a6c9fSPeter Zijlstra 5301da177e4SLinus Torvalds pid = fown->pid; 5311da177e4SLinus Torvalds if (!pid) 5321da177e4SLinus Torvalds goto out_unlock_fown; 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds ret = 1; 5351da177e4SLinus Torvalds 5361da177e4SLinus Torvalds read_lock(&tasklist_lock); 537609d7fa9SEric W. Biederman do_each_pid_task(pid, type, p) { 538ba0a6c9fSPeter Zijlstra send_sigurg_to_task(p, fown, group); 539609d7fa9SEric W. Biederman } while_each_pid_task(pid, type, p); 5401da177e4SLinus Torvalds read_unlock(&tasklist_lock); 5411da177e4SLinus Torvalds out_unlock_fown: 5421da177e4SLinus Torvalds read_unlock(&fown->lock); 5431da177e4SLinus Torvalds return ret; 5441da177e4SLinus Torvalds } 5451da177e4SLinus Torvalds 546989a2979SEric Dumazet static DEFINE_SPINLOCK(fasync_lock); 547e18b890bSChristoph Lameter static struct kmem_cache *fasync_cache __read_mostly; 5481da177e4SLinus Torvalds 549989a2979SEric Dumazet static void fasync_free_rcu(struct rcu_head *head) 550989a2979SEric Dumazet { 551989a2979SEric Dumazet kmem_cache_free(fasync_cache, 552989a2979SEric Dumazet container_of(head, struct fasync_struct, fa_rcu)); 553989a2979SEric Dumazet } 554989a2979SEric Dumazet 5551da177e4SLinus Torvalds /* 55653281b6dSLinus Torvalds * Remove a fasync entry. If successfully removed, return 55753281b6dSLinus Torvalds * positive and clear the FASYNC flag. If no entry exists, 55853281b6dSLinus Torvalds * do nothing and return 0. 55953281b6dSLinus Torvalds * 56053281b6dSLinus Torvalds * NOTE! It is very important that the FASYNC flag always 56153281b6dSLinus Torvalds * match the state "is the filp on a fasync list". 56253281b6dSLinus Torvalds * 5631da177e4SLinus Torvalds */ 564f7347ce4SLinus Torvalds int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp) 5651da177e4SLinus Torvalds { 5661da177e4SLinus Torvalds struct fasync_struct *fa, **fp; 5671da177e4SLinus Torvalds int result = 0; 5681da177e4SLinus Torvalds 5694a6a4499SJonathan Corbet spin_lock(&filp->f_lock); 570989a2979SEric Dumazet spin_lock(&fasync_lock); 5711da177e4SLinus Torvalds for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { 57253281b6dSLinus Torvalds if (fa->fa_file != filp) 57353281b6dSLinus Torvalds continue; 574989a2979SEric Dumazet 575989a2979SEric Dumazet spin_lock_irq(&fa->fa_lock); 576989a2979SEric Dumazet fa->fa_file = NULL; 577989a2979SEric Dumazet spin_unlock_irq(&fa->fa_lock); 578989a2979SEric Dumazet 5791da177e4SLinus Torvalds *fp = fa->fa_next; 580989a2979SEric Dumazet call_rcu(&fa->fa_rcu, fasync_free_rcu); 58153281b6dSLinus Torvalds filp->f_flags &= ~FASYNC; 5821da177e4SLinus Torvalds result = 1; 58353281b6dSLinus Torvalds break; 5841da177e4SLinus Torvalds } 585989a2979SEric Dumazet spin_unlock(&fasync_lock); 58653281b6dSLinus Torvalds spin_unlock(&filp->f_lock); 58753281b6dSLinus Torvalds return result; 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds 590f7347ce4SLinus Torvalds struct fasync_struct *fasync_alloc(void) 59153281b6dSLinus Torvalds { 592f7347ce4SLinus Torvalds return kmem_cache_alloc(fasync_cache, GFP_KERNEL); 593f7347ce4SLinus Torvalds } 59453281b6dSLinus Torvalds 595f7347ce4SLinus Torvalds /* 596f7347ce4SLinus Torvalds * NOTE! This can be used only for unused fasync entries: 597f7347ce4SLinus Torvalds * entries that actually got inserted on the fasync list 598f7347ce4SLinus Torvalds * need to be released by rcu - see fasync_remove_entry. 599f7347ce4SLinus Torvalds */ 600f7347ce4SLinus Torvalds void fasync_free(struct fasync_struct *new) 601f7347ce4SLinus Torvalds { 602f7347ce4SLinus Torvalds kmem_cache_free(fasync_cache, new); 603f7347ce4SLinus Torvalds } 604f7347ce4SLinus Torvalds 605f7347ce4SLinus Torvalds /* 606f7347ce4SLinus Torvalds * Insert a new entry into the fasync list. Return the pointer to the 607f7347ce4SLinus Torvalds * old one if we didn't use the new one. 60855f335a8SLinus Torvalds * 60955f335a8SLinus Torvalds * NOTE! It is very important that the FASYNC flag always 61055f335a8SLinus Torvalds * match the state "is the filp on a fasync list". 611f7347ce4SLinus Torvalds */ 612f7347ce4SLinus Torvalds struct fasync_struct *fasync_insert_entry(int fd, struct file *filp, struct fasync_struct **fapp, struct fasync_struct *new) 613f7347ce4SLinus Torvalds { 614f7347ce4SLinus Torvalds struct fasync_struct *fa, **fp; 61553281b6dSLinus Torvalds 61653281b6dSLinus Torvalds spin_lock(&filp->f_lock); 617989a2979SEric Dumazet spin_lock(&fasync_lock); 61853281b6dSLinus Torvalds for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { 61953281b6dSLinus Torvalds if (fa->fa_file != filp) 62053281b6dSLinus Torvalds continue; 621989a2979SEric Dumazet 622989a2979SEric Dumazet spin_lock_irq(&fa->fa_lock); 62353281b6dSLinus Torvalds fa->fa_fd = fd; 624989a2979SEric Dumazet spin_unlock_irq(&fa->fa_lock); 62553281b6dSLinus Torvalds goto out; 62653281b6dSLinus Torvalds } 62753281b6dSLinus Torvalds 628989a2979SEric Dumazet spin_lock_init(&new->fa_lock); 6291da177e4SLinus Torvalds new->magic = FASYNC_MAGIC; 6301da177e4SLinus Torvalds new->fa_file = filp; 6311da177e4SLinus Torvalds new->fa_fd = fd; 6321da177e4SLinus Torvalds new->fa_next = *fapp; 633989a2979SEric Dumazet rcu_assign_pointer(*fapp, new); 63476398425SJonathan Corbet filp->f_flags |= FASYNC; 63553281b6dSLinus Torvalds 63653281b6dSLinus Torvalds out: 637989a2979SEric Dumazet spin_unlock(&fasync_lock); 6384a6a4499SJonathan Corbet spin_unlock(&filp->f_lock); 639f7347ce4SLinus Torvalds return fa; 640f7347ce4SLinus Torvalds } 641f7347ce4SLinus Torvalds 642f7347ce4SLinus Torvalds /* 643f7347ce4SLinus Torvalds * Add a fasync entry. Return negative on error, positive if 644f7347ce4SLinus Torvalds * added, and zero if did nothing but change an existing one. 645f7347ce4SLinus Torvalds */ 646f7347ce4SLinus Torvalds static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp) 647f7347ce4SLinus Torvalds { 648f7347ce4SLinus Torvalds struct fasync_struct *new; 649f7347ce4SLinus Torvalds 650f7347ce4SLinus Torvalds new = fasync_alloc(); 651f7347ce4SLinus Torvalds if (!new) 652f7347ce4SLinus Torvalds return -ENOMEM; 653f7347ce4SLinus Torvalds 654f7347ce4SLinus Torvalds /* 655f7347ce4SLinus Torvalds * fasync_insert_entry() returns the old (update) entry if 656f7347ce4SLinus Torvalds * it existed. 657f7347ce4SLinus Torvalds * 658f7347ce4SLinus Torvalds * So free the (unused) new entry and return 0 to let the 659f7347ce4SLinus Torvalds * caller know that we didn't add any new fasync entries. 660f7347ce4SLinus Torvalds */ 661f7347ce4SLinus Torvalds if (fasync_insert_entry(fd, filp, fapp, new)) { 662f7347ce4SLinus Torvalds fasync_free(new); 663f7347ce4SLinus Torvalds return 0; 664f7347ce4SLinus Torvalds } 665f7347ce4SLinus Torvalds 666f7347ce4SLinus Torvalds return 1; 6671da177e4SLinus Torvalds } 6681da177e4SLinus Torvalds 66953281b6dSLinus Torvalds /* 67053281b6dSLinus Torvalds * fasync_helper() is used by almost all character device drivers 67153281b6dSLinus Torvalds * to set up the fasync queue, and for regular files by the file 67253281b6dSLinus Torvalds * lease code. It returns negative on error, 0 if it did no changes 67353281b6dSLinus Torvalds * and positive if it added/deleted the entry. 67453281b6dSLinus Torvalds */ 67553281b6dSLinus Torvalds int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) 67653281b6dSLinus Torvalds { 67753281b6dSLinus Torvalds if (!on) 67853281b6dSLinus Torvalds return fasync_remove_entry(filp, fapp); 67953281b6dSLinus Torvalds return fasync_add_entry(fd, filp, fapp); 68053281b6dSLinus Torvalds } 68153281b6dSLinus Torvalds 6821da177e4SLinus Torvalds EXPORT_SYMBOL(fasync_helper); 6831da177e4SLinus Torvalds 684989a2979SEric Dumazet /* 685989a2979SEric Dumazet * rcu_read_lock() is held 686989a2979SEric Dumazet */ 687989a2979SEric Dumazet static void kill_fasync_rcu(struct fasync_struct *fa, int sig, int band) 6881da177e4SLinus Torvalds { 6891da177e4SLinus Torvalds while (fa) { 6901da177e4SLinus Torvalds struct fown_struct *fown; 691f4985dc7SAndrew Morton unsigned long flags; 692f4985dc7SAndrew Morton 6931da177e4SLinus Torvalds if (fa->magic != FASYNC_MAGIC) { 6941da177e4SLinus Torvalds printk(KERN_ERR "kill_fasync: bad magic number in " 6951da177e4SLinus Torvalds "fasync_struct!\n"); 6961da177e4SLinus Torvalds return; 6971da177e4SLinus Torvalds } 698f4985dc7SAndrew Morton spin_lock_irqsave(&fa->fa_lock, flags); 699989a2979SEric Dumazet if (fa->fa_file) { 7001da177e4SLinus Torvalds fown = &fa->fa_file->f_owner; 7011da177e4SLinus Torvalds /* Don't send SIGURG to processes which have not set a 7021da177e4SLinus Torvalds queued signum: SIGURG has its own default signalling 7031da177e4SLinus Torvalds mechanism. */ 7041da177e4SLinus Torvalds if (!(sig == SIGURG && fown->signum == 0)) 7051da177e4SLinus Torvalds send_sigio(fown, fa->fa_fd, band); 706989a2979SEric Dumazet } 707f4985dc7SAndrew Morton spin_unlock_irqrestore(&fa->fa_lock, flags); 708989a2979SEric Dumazet fa = rcu_dereference(fa->fa_next); 7091da177e4SLinus Torvalds } 7101da177e4SLinus Torvalds } 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds void kill_fasync(struct fasync_struct **fp, int sig, int band) 7131da177e4SLinus Torvalds { 7141da177e4SLinus Torvalds /* First a quick test without locking: usually 7151da177e4SLinus Torvalds * the list is empty. 7161da177e4SLinus Torvalds */ 7171da177e4SLinus Torvalds if (*fp) { 718989a2979SEric Dumazet rcu_read_lock(); 719989a2979SEric Dumazet kill_fasync_rcu(rcu_dereference(*fp), sig, band); 720989a2979SEric Dumazet rcu_read_unlock(); 7211da177e4SLinus Torvalds } 7221da177e4SLinus Torvalds } 7231da177e4SLinus Torvalds EXPORT_SYMBOL(kill_fasync); 7241da177e4SLinus Torvalds 725454eedb8SWu Fengguang static int __init fcntl_init(void) 7261da177e4SLinus Torvalds { 7273ab04d5cSJames Bottomley /* 7283ab04d5cSJames Bottomley * Please add new bits here to ensure allocation uniqueness. 7293ab04d5cSJames Bottomley * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY 7303ab04d5cSJames Bottomley * is defined as O_NONBLOCK on some platforms and not on others. 7313ab04d5cSJames Bottomley */ 7323d62c45bSZheng Liu BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( 733454eedb8SWu Fengguang O_RDONLY | O_WRONLY | O_RDWR | 734454eedb8SWu Fengguang O_CREAT | O_EXCL | O_NOCTTY | 7353ab04d5cSJames Bottomley O_TRUNC | O_APPEND | /* O_NONBLOCK | */ 736454eedb8SWu Fengguang __O_SYNC | O_DSYNC | FASYNC | 737454eedb8SWu Fengguang O_DIRECT | O_LARGEFILE | O_DIRECTORY | 738454eedb8SWu Fengguang O_NOFOLLOW | O_NOATIME | O_CLOEXEC | 7393d62c45bSZheng Liu __FMODE_EXEC | O_PATH | __O_TMPFILE 740454eedb8SWu Fengguang )); 741454eedb8SWu Fengguang 7421da177e4SLinus Torvalds fasync_cache = kmem_cache_create("fasync_cache", 74320c2df83SPaul Mundt sizeof(struct fasync_struct), 0, SLAB_PANIC, NULL); 7441da177e4SLinus Torvalds return 0; 7451da177e4SLinus Torvalds } 7461da177e4SLinus Torvalds 747454eedb8SWu Fengguang module_init(fcntl_init) 748