patch-2.1.56 linux/fs/fcntl.c

Next file: linux/fs/inode.c
Previous file: linux/fs/fat/mmap.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.55/linux/fs/fcntl.c linux/fs/fcntl.c
@@ -83,7 +83,7 @@
 	/* Did FASYNC state change? */
 	if ((arg ^ filp->f_flags) & FASYNC) {
 		if (filp->f_op->fasync)
-			filp->f_op->fasync(inode, filp, (arg & FASYNC) != 0);
+			filp->f_op->fasync(filp, (arg & FASYNC) != 0);
 	}
 
 	/* required for strict SunOS emulation */
@@ -98,8 +98,6 @@
 asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {	
 	struct file * filp;
-	struct task_struct *p;
-	int task_found = 0;
 	long err = -EBADF;
 
 	lock_kernel();
@@ -142,57 +140,13 @@
 			 * current syscall conventions, the only way
 			 * to fix this will be in libc.
 			 */
-			err = filp->f_owner;
+			err = filp->f_owner.pid;
 			break;
 		case F_SETOWN:
-			/*
-			 *	Add the security checks - AC. Without
-			 *	this there is a massive Linux security
-			 *	hole here - consider what happens if
-			 *	you do something like
-			 * 
-			 *		fcntl(0,F_SETOWN,some_root_process);
-			 *		getchar();
-			 * 
-			 *	and input a line!
-			 * 
-			 * BTW: Don't try this for fun. Several Unix
-			 *	systems I tried this on fall for the
-			 *	trick!
-			 * 
-			 * I had to fix this botch job as Linux
-			 *	kill_fasync asserts priv making it a
-			 *	free all user process killer!
-			 *
-			 * Changed to make the security checks more
-			 * liberal.  -- TYT
-			 */
-			if (current->pgrp == -arg || current->pid == arg)
-				goto fasync_ok;
-			
-			read_lock(&tasklist_lock);
-			for_each_task(p) {
-				if ((p->pid == arg) || (p->pid == -arg) || 
-				    (p->pgrp == -arg)) {
-					task_found++;
-					err = -EPERM;
-					if ((p->session != current->session) &&
-					    (p->uid != current->uid) &&
-					    (p->euid != current->euid) &&
-					    !suser()) {
-						read_unlock(&tasklist_lock);
-						goto out;
-					}
-					break;
-				}
-			}
-			read_unlock(&tasklist_lock);
-			err = -EINVAL;
-			if ((task_found == 0) && !suser())
-				break;
-		fasync_ok:
 			err = 0;
-			filp->f_owner = arg;
+			filp->f_owner.pid = arg;
+			filp->f_owner.uid = current->uid;
+			filp->f_owner.euid = current->euid;
 			if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
 				err = sock_fcntl (filp, F_SETOWN, arg);
 			break;
@@ -209,18 +163,40 @@
 	return err;
 }
 
+static void send_sigio(int pid, uid_t uid, uid_t euid)
+{
+	struct task_struct * p;
+
+	read_lock(&tasklist_lock);
+	for_each_task(p) {
+		int match = p->pid;
+		if (pid < 0)
+			match = -p->pgrp;
+		if (pid != match)
+			continue;
+		if (!euid &&
+		    (euid ^ p->suid) && (euid ^ p->uid) &&
+		    (uid ^ p->suid) && (uid ^ p->uid))
+			continue;
+		p->signal |= 1 << (SIGIO-1);
+		if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
+			wake_up_process(p);
+	}
+	read_unlock(&tasklist_lock);
+}
+
 void kill_fasync(struct fasync_struct *fa, int sig)
 {
 	while (fa) {
+		struct fown_struct * fown;
 		if (fa->magic != FASYNC_MAGIC) {
 			printk("kill_fasync: bad magic number in "
 			       "fasync_struct!\n");
 			return;
 		}
-		if (fa->fa_file->f_owner > 0)
-			kill_proc(fa->fa_file->f_owner, sig, 1);
-		else
-			kill_pg(-fa->fa_file->f_owner, sig, 1);
+		fown = &fa->fa_file->f_owner;
+		if (fown->pid)
+			send_sigio(fown->pid, fown->uid, fown->euid);
 		fa = fa->fa_next;
 	}
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov