summaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-12-01 04:02:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-12-01 04:02:08 +0000
commitfd095d09f2d475dc2e8599b1b8bae1cd65e91685 (patch)
tree217f87a997699505e0dd752931409b9f10fffe65 /fs/fcntl.c
parentc02e0599c4233f97071928f8118841954bacdadf (diff)
Merge with 2.1.56 as first part of merging back my code.
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c86
1 files changed, 31 insertions, 55 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 57eef2530..ce00e439f 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -83,7 +83,7 @@ static int setfl(struct file * filp, unsigned long arg)
/* 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 @@ static int setfl(struct file * filp, unsigned long arg)
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 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
* 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 @@ out:
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;
}
}