diff options
author | green <green@FreeBSD.org> | 1999-08-04 18:53:50 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 1999-08-04 18:53:50 +0000 |
commit | c03366a55d4ace981b016ae999ae67675c486cdd (patch) | |
tree | 12cd9e195ff9e1b516242767963c6e156b837539 /sys/kern/kern_descrip.c | |
parent | 0ab4dad80912358b49a3cee9e433dbd909334d19 (diff) | |
download | FreeBSD-src-c03366a55d4ace981b016ae999ae67675c486cdd.zip FreeBSD-src-c03366a55d4ace981b016ae999ae67675c486cdd.tar.gz |
Fix fd race conditions (during shared fd table usage.) Badfileops is
now used in f_ops in place of NULL, and modifications to the files
are more carefully ordered. f_ops should also be set to &badfileops
upon "close" of a file.
This does not fix other problems mentioned in this PR than the first
one.
PR: 11629
Reviewed by: peter
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 70 |
1 files changed, 64 insertions, 6 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 7b6ebe0..c90ce11 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 - * $Id: kern_descrip.c,v 1.63 1999/05/31 11:27:30 phk Exp $ + * $Id: kern_descrip.c,v 1.64 1999/06/07 20:37:27 msmith Exp $ */ #include "opt_compat.h" @@ -101,6 +101,13 @@ static struct cdevsw fildesc_cdevsw = { }; static int finishdup __P((struct filedesc *fdp, int old, int new, register_t *retval)); +static int badfo_readwrite __P((struct file *fp, struct uio *uio, + struct ucred *cred, int flags)); +static int badfo_ioctl __P((struct file *fp, u_long com, caddr_t data, + struct proc *p)); +static int badfo_poll __P((struct file *fp, int events, + struct ucred *cred, struct proc *p)); +static int badfo_close __P((struct file *fp, struct proc *p)); /* * Descriptor management. */ @@ -836,16 +843,17 @@ falloc(p, resultfp, resultfd) nfiles++; MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK); bzero(fp, sizeof(struct file)); + fp->f_count = 1; + fp->f_cred = p->p_ucred; + fp->f_ops = &badfileops; + fp->f_seqcount = 1; + crhold(fp->f_cred); if ((fq = p->p_fd->fd_ofiles[0])) { LIST_INSERT_AFTER(fq, fp, f_list); } else { LIST_INSERT_HEAD(&filehead, fp, f_list); } p->p_fd->fd_ofiles[i] = fp; - fp->f_count = 1; - fp->f_cred = p->p_ucred; - fp->f_seqcount = 1; - crhold(fp->f_cred); if (resultfp) *resultfp = fp; if (resultfd) @@ -1078,7 +1086,7 @@ closef(fp, p) vp = (struct vnode *)fp->f_data; (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); } - if (fp->f_ops) + if (fp->f_ops != &badfileops) error = (*fp->f_ops->fo_close)(fp, p); else error = 0; @@ -1323,6 +1331,56 @@ static void fildesc_drvinit(void *unused) } } +struct fileops badfileops = { + badfo_readwrite, + badfo_readwrite, + badfo_ioctl, + badfo_poll, + badfo_close +}; + +static int +badfo_readwrite(fp, uio, cred, flags) + struct file *fp; + struct uio *uio; + struct ucred *cred; + int flags; +{ + + return (EBADF); +} + +static int +badfo_ioctl(fp, com, data, p) + struct file *fp; + u_long com; + caddr_t data; + struct proc *p; +{ + + return (EBADF); +} + +static int +badfo_poll(fp, events, cred, p) + struct file *fp; + int events; + struct ucred *cred; + struct proc *p; +{ + + return (0); +} + +static int +badfo_close(fp, p) + struct file *fp; + struct proc *p; +{ + + return (EBADF); +} + SYSINIT(fildescdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, fildesc_drvinit,NULL) |