From c03366a55d4ace981b016ae999ae67675c486cdd Mon Sep 17 00:00:00 2001 From: green Date: Wed, 4 Aug 1999 18:53:50 +0000 Subject: 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 --- sys/dev/streams/streams.c | 8 +++--- sys/kern/kern_descrip.c | 70 +++++++++++++++++++++++++++++++++++++++++++---- sys/kern/sys_pipe.c | 11 ++++---- sys/kern/sys_socket.c | 3 +- sys/kern/uipc_syscalls.c | 25 ++++++++--------- sys/kern/vfs_extattr.c | 6 ++-- sys/kern/vfs_syscalls.c | 6 ++-- sys/kern/vfs_vnops.c | 4 ++- sys/sys/file.h | 3 +- 9 files changed, 98 insertions(+), 38 deletions(-) diff --git a/sys/dev/streams/streams.c b/sys/dev/streams/streams.c index cd5a6fa..07717d5 100644 --- a/sys/dev/streams/streams.c +++ b/sys/dev/streams/streams.c @@ -30,7 +30,7 @@ * skeleton produced from /usr/share/examples/drivers/make_pseudo_driver.sh * in 3.0-980524-SNAP then hacked a bit (but probably not enough :-). * - * $Id$ + * $Id: streams.c,v 1.8 1999/08/01 12:51:06 newton Exp $ */ #include "streams.h" /* generated file.. defines NSTREAMS */ @@ -251,11 +251,11 @@ streamsopen(dev_t dev, int oflags, int devtype, struct proc *p) return error; } + fp->f_data = (caddr_t)so; fp->f_flag = FREAD|FWRITE; - fp->f_type = DTYPE_SOCKET; fp->f_ops = &svr4_netops; + fp->f_type = DTYPE_SOCKET; - fp->f_data = (caddr_t)so; (void)svr4_stream_get(fp); p->p_dupfd = fd; return ENXIO; @@ -334,13 +334,13 @@ svr4_stream_get(fp) return so->so_emuldata; /* Allocate a new one. */ - fp->f_ops = &svr4_netops; st = malloc(sizeof(struct svr4_strm), M_TEMP, M_WAITOK); st->s_family = so->so_proto->pr_domain->dom_family; st->s_cmd = ~0; st->s_afd = -1; st->s_eventmask = 0; so->so_emuldata = st; + fp->f_ops = &svr4_netops; return st; } 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) diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index a7266eb..06b897f 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -16,7 +16,7 @@ * 4. Modifications may be freely made to this file if the above conditions * are met. * - * $Id: sys_pipe.c,v 1.51 1999/04/04 21:41:15 dt Exp $ + * $Id: sys_pipe.c,v 1.52 1999/06/05 03:53:57 alc Exp $ */ /* @@ -176,15 +176,15 @@ pipe(p, uap) p->p_retval[0] = fd; rf->f_flag = FREAD | FWRITE; rf->f_type = DTYPE_PIPE; - rf->f_ops = &pipeops; rf->f_data = (caddr_t)rpipe; + rf->f_ops = &pipeops; error = falloc(p, &wf, &fd); if (error) goto free3; wf->f_flag = FREAD | FWRITE; wf->f_type = DTYPE_PIPE; - wf->f_ops = &pipeops; wf->f_data = (caddr_t)wpipe; + wf->f_ops = &pipeops; p->p_retval[1] = fd; rpipe->pipe_peer = wpipe; @@ -192,8 +192,8 @@ pipe(p, uap) return (0); free3: - ffree(rf); fdp->fd_ofiles[p->p_retval[0]] = 0; + ffree(rf); free2: (void)pipeclose(wpipe); (void)pipeclose(rpipe); @@ -1039,9 +1039,10 @@ pipe_close(fp, p) { struct pipe *cpipe = (struct pipe *)fp->f_data; + fp->f_ops = &badfileops; + fp->f_data = NULL; funsetown(cpipe->pipe_sigio); pipeclose(cpipe); - fp->f_data = NULL; return 0; } diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index ad92d87..123ff93 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93 - * $Id: sys_socket.c,v 1.23 1999/02/01 21:16:29 newton Exp $ + * $Id: sys_socket.c,v 1.24 1999/04/04 21:41:16 dt Exp $ */ #include @@ -171,6 +171,7 @@ soo_close(fp, p) { int error = 0; + fp->f_ops = &badfileops; if (fp->f_data) error = soclose((struct socket *)fp->f_data); fp->f_data = 0; diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 6909958..5cf6100 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 - * $Id: uipc_syscalls.c,v 1.54 1999/01/25 16:53:53 fenner Exp $ + * $Id: uipc_syscalls.c,v 1.55 1999/01/27 21:49:57 dillon Exp $ */ #include "opt_compat.h" @@ -118,15 +118,15 @@ socket(p, uap) error = falloc(p, &fp, &fd); if (error) return (error); - fp->f_flag = FREAD|FWRITE; - fp->f_type = DTYPE_SOCKET; - fp->f_ops = &socketops; error = socreate(uap->domain, &so, uap->type, uap->protocol, p); if (error) { fdp->fd_ofiles[fd] = 0; ffree(fp); } else { fp->f_data = (caddr_t)so; + fp->f_flag = FREAD|FWRITE; + fp->f_ops = &socketops; + fp->f_type = DTYPE_SOCKET; p->p_retval[0] = fd; } return (error); @@ -263,10 +263,10 @@ accept1(p, uap, compat) if (head->so_sigio != NULL) fsetown(fgetown(head->so_sigio), &so->so_sigio); - fp->f_type = DTYPE_SOCKET; + fp->f_data = (caddr_t)so; fp->f_flag = fflag; fp->f_ops = &socketops; - fp->f_data = (caddr_t)so; + fp->f_type = DTYPE_SOCKET; sa = 0; (void) soaccept(so, &sa); if (sa == 0) { @@ -392,16 +392,10 @@ socketpair(p, uap) if (error) goto free2; sv[0] = fd; - fp1->f_flag = FREAD|FWRITE; - fp1->f_type = DTYPE_SOCKET; - fp1->f_ops = &socketops; fp1->f_data = (caddr_t)so1; error = falloc(p, &fp2, &fd); if (error) goto free3; - fp2->f_flag = FREAD|FWRITE; - fp2->f_type = DTYPE_SOCKET; - fp2->f_ops = &socketops; fp2->f_data = (caddr_t)so2; sv[1] = fd; error = soconnect2(so1, so2); @@ -415,14 +409,17 @@ socketpair(p, uap) if (error) goto free4; } + fp1->f_flag = fp2->f_flag = FREAD|FWRITE; + fp1->f_ops = fp2->f_ops = &socketops; + fp1->f_type = fp2->f_type = DTYPE_SOCKET; error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); return (error); free4: - ffree(fp2); fdp->fd_ofiles[sv[1]] = 0; + ffree(fp2); free3: - ffree(fp1); fdp->fd_ofiles[sv[0]] = 0; + ffree(fp1); free2: (void)soclose(so2); free1: diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 3617bfd..bedf79f 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 - * $Id: vfs_syscalls.c,v 1.127 1999/08/03 17:07:04 imp Exp $ + * $Id: vfs_syscalls.c,v 1.128 1999/08/04 04:52:18 imp Exp $ */ /* For 4.3 integer FS ID compatibility */ @@ -995,10 +995,10 @@ open(p, uap) p->p_dupfd = 0; vp = nd.ni_vp; + fp->f_data = (caddr_t)vp; fp->f_flag = flags & FMASK; - fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); fp->f_ops = &vnops; - fp->f_data = (caddr_t)vp; + fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); if (flags & (O_EXLOCK | O_SHLOCK)) { lf.l_whence = SEEK_SET; lf.l_start = 0; diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 3617bfd..bedf79f 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 - * $Id: vfs_syscalls.c,v 1.127 1999/08/03 17:07:04 imp Exp $ + * $Id: vfs_syscalls.c,v 1.128 1999/08/04 04:52:18 imp Exp $ */ /* For 4.3 integer FS ID compatibility */ @@ -995,10 +995,10 @@ open(p, uap) p->p_dupfd = 0; vp = nd.ni_vp; + fp->f_data = (caddr_t)vp; fp->f_flag = flags & FMASK; - fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); fp->f_ops = &vnops; - fp->f_data = (caddr_t)vp; + fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); if (flags & (O_EXLOCK | O_SHLOCK)) { lf.l_whence = SEEK_SET; lf.l_start = 0; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 04c5ef5..c6663de 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94 - * $Id: vfs_vnops.c,v 1.70 1999/07/08 06:05:56 mckusick Exp $ + * $Id: vfs_vnops.c,v 1.71 1999/07/26 06:25:18 alc Exp $ */ #include @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -563,6 +564,7 @@ vn_closefile(fp, p) struct proc *p; { + fp->f_ops = &badfileops; return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, fp->f_cred, p)); } diff --git a/sys/sys/file.h b/sys/sys/file.h index 005240f..ec425b4 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)file.h 8.3 (Berkeley) 1/9/95 - * $Id: file.h,v 1.16 1998/06/07 17:12:58 dfr Exp $ + * $Id: file.h,v 1.17 1999/04/04 21:41:25 dt Exp $ */ #ifndef _SYS_FILE_H_ @@ -93,6 +93,7 @@ MALLOC_DECLARE(M_FILE); LIST_HEAD(filelist, file); extern struct filelist filehead; /* head of list of open files */ extern struct fileops vnops; +extern struct fileops badfileops; extern int maxfiles; /* kernel limit on number of open files */ extern int maxfilesperproc; /* per process limit on number of open files */ extern int nfiles; /* actual number of open files */ -- cgit v1.1