diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-01 04:02:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-01 04:02:08 +0000 |
commit | fd095d09f2d475dc2e8599b1b8bae1cd65e91685 (patch) | |
tree | 217f87a997699505e0dd752931409b9f10fffe65 /fs/fcntl.c | |
parent | c02e0599c4233f97071928f8118841954bacdadf (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.c | 86 |
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; } } |