xref: /linux/fs/fcntl.c (revision db1dd4d376134eba0e08af523b61cc566a4ea1cd)
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