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
This commit is contained in:
Brian Feldman 1999-08-04 18:53:50 +00:00
parent 42fd81e3c9
commit e32c66c539
9 changed files with 102 additions and 42 deletions

View File

@ -30,7 +30,7 @@
* skeleton produced from /usr/share/examples/drivers/make_pseudo_driver.sh * skeleton produced from /usr/share/examples/drivers/make_pseudo_driver.sh
* in 3.0-980524-SNAP then hacked a bit (but probably not enough :-). * 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 */ #include "streams.h" /* generated file.. defines NSTREAMS */
@ -251,11 +251,11 @@ streamsopen(dev_t dev, int oflags, int devtype, struct proc *p)
return error; return error;
} }
fp->f_flag = FREAD|FWRITE;
fp->f_type = DTYPE_SOCKET;
fp->f_ops = &svr4_netops;
fp->f_data = (caddr_t)so; fp->f_data = (caddr_t)so;
fp->f_flag = FREAD|FWRITE;
fp->f_ops = &svr4_netops;
fp->f_type = DTYPE_SOCKET;
(void)svr4_stream_get(fp); (void)svr4_stream_get(fp);
p->p_dupfd = fd; p->p_dupfd = fd;
return ENXIO; return ENXIO;
@ -334,13 +334,13 @@ svr4_stream_get(fp)
return so->so_emuldata; return so->so_emuldata;
/* Allocate a new one. */ /* Allocate a new one. */
fp->f_ops = &svr4_netops;
st = malloc(sizeof(struct svr4_strm), M_TEMP, M_WAITOK); st = malloc(sizeof(struct svr4_strm), M_TEMP, M_WAITOK);
st->s_family = so->so_proto->pr_domain->dom_family; st->s_family = so->so_proto->pr_domain->dom_family;
st->s_cmd = ~0; st->s_cmd = ~0;
st->s_afd = -1; st->s_afd = -1;
st->s_eventmask = 0; st->s_eventmask = 0;
so->so_emuldata = st; so->so_emuldata = st;
fp->f_ops = &svr4_netops;
return st; return st;
} }

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 * @(#)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" #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 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. * Descriptor management.
*/ */
@ -836,16 +843,17 @@ falloc(p, resultfp, resultfd)
nfiles++; nfiles++;
MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK); MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
bzero(fp, sizeof(struct file)); 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])) { if ((fq = p->p_fd->fd_ofiles[0])) {
LIST_INSERT_AFTER(fq, fp, f_list); LIST_INSERT_AFTER(fq, fp, f_list);
} else { } else {
LIST_INSERT_HEAD(&filehead, fp, f_list); LIST_INSERT_HEAD(&filehead, fp, f_list);
} }
p->p_fd->fd_ofiles[i] = fp; 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) if (resultfp)
*resultfp = fp; *resultfp = fp;
if (resultfd) if (resultfd)
@ -1078,7 +1086,7 @@ closef(fp, p)
vp = (struct vnode *)fp->f_data; vp = (struct vnode *)fp->f_data;
(void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); (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); error = (*fp->f_ops->fo_close)(fp, p);
else else
error = 0; 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, SYSINIT(fildescdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,
fildesc_drvinit,NULL) fildesc_drvinit,NULL)

View File

@ -16,7 +16,7 @@
* 4. Modifications may be freely made to this file if the above conditions * 4. Modifications may be freely made to this file if the above conditions
* are met. * 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; p->p_retval[0] = fd;
rf->f_flag = FREAD | FWRITE; rf->f_flag = FREAD | FWRITE;
rf->f_type = DTYPE_PIPE; rf->f_type = DTYPE_PIPE;
rf->f_ops = &pipeops;
rf->f_data = (caddr_t)rpipe; rf->f_data = (caddr_t)rpipe;
rf->f_ops = &pipeops;
error = falloc(p, &wf, &fd); error = falloc(p, &wf, &fd);
if (error) if (error)
goto free3; goto free3;
wf->f_flag = FREAD | FWRITE; wf->f_flag = FREAD | FWRITE;
wf->f_type = DTYPE_PIPE; wf->f_type = DTYPE_PIPE;
wf->f_ops = &pipeops;
wf->f_data = (caddr_t)wpipe; wf->f_data = (caddr_t)wpipe;
wf->f_ops = &pipeops;
p->p_retval[1] = fd; p->p_retval[1] = fd;
rpipe->pipe_peer = wpipe; rpipe->pipe_peer = wpipe;
@ -192,8 +192,8 @@ pipe(p, uap)
return (0); return (0);
free3: free3:
ffree(rf);
fdp->fd_ofiles[p->p_retval[0]] = 0; fdp->fd_ofiles[p->p_retval[0]] = 0;
ffree(rf);
free2: free2:
(void)pipeclose(wpipe); (void)pipeclose(wpipe);
(void)pipeclose(rpipe); (void)pipeclose(rpipe);
@ -1039,9 +1039,10 @@ pipe_close(fp, p)
{ {
struct pipe *cpipe = (struct pipe *)fp->f_data; struct pipe *cpipe = (struct pipe *)fp->f_data;
fp->f_ops = &badfileops;
fp->f_data = NULL;
funsetown(cpipe->pipe_sigio); funsetown(cpipe->pipe_sigio);
pipeclose(cpipe); pipeclose(cpipe);
fp->f_data = NULL;
return 0; return 0;
} }

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)sys_socket.c 8.1 (Berkeley) 6/10/93 * @(#)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 <sys/param.h> #include <sys/param.h>
@ -171,6 +171,7 @@ soo_close(fp, p)
{ {
int error = 0; int error = 0;
fp->f_ops = &badfileops;
if (fp->f_data) if (fp->f_data)
error = soclose((struct socket *)fp->f_data); error = soclose((struct socket *)fp->f_data);
fp->f_data = 0; fp->f_data = 0;

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 * @(#)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" #include "opt_compat.h"
@ -118,15 +118,15 @@ socket(p, uap)
error = falloc(p, &fp, &fd); error = falloc(p, &fp, &fd);
if (error) if (error)
return (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); error = socreate(uap->domain, &so, uap->type, uap->protocol, p);
if (error) { if (error) {
fdp->fd_ofiles[fd] = 0; fdp->fd_ofiles[fd] = 0;
ffree(fp); ffree(fp);
} else { } else {
fp->f_data = (caddr_t)so; 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; p->p_retval[0] = fd;
} }
return (error); return (error);
@ -263,10 +263,10 @@ accept1(p, uap, compat)
if (head->so_sigio != NULL) if (head->so_sigio != NULL)
fsetown(fgetown(head->so_sigio), &so->so_sigio); 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_flag = fflag;
fp->f_ops = &socketops; fp->f_ops = &socketops;
fp->f_data = (caddr_t)so; fp->f_type = DTYPE_SOCKET;
sa = 0; sa = 0;
(void) soaccept(so, &sa); (void) soaccept(so, &sa);
if (sa == 0) { if (sa == 0) {
@ -392,16 +392,10 @@ socketpair(p, uap)
if (error) if (error)
goto free2; goto free2;
sv[0] = fd; sv[0] = fd;
fp1->f_flag = FREAD|FWRITE;
fp1->f_type = DTYPE_SOCKET;
fp1->f_ops = &socketops;
fp1->f_data = (caddr_t)so1; fp1->f_data = (caddr_t)so1;
error = falloc(p, &fp2, &fd); error = falloc(p, &fp2, &fd);
if (error) if (error)
goto free3; goto free3;
fp2->f_flag = FREAD|FWRITE;
fp2->f_type = DTYPE_SOCKET;
fp2->f_ops = &socketops;
fp2->f_data = (caddr_t)so2; fp2->f_data = (caddr_t)so2;
sv[1] = fd; sv[1] = fd;
error = soconnect2(so1, so2); error = soconnect2(so1, so2);
@ -415,14 +409,17 @@ socketpair(p, uap)
if (error) if (error)
goto free4; 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)); error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
return (error); return (error);
free4: free4:
ffree(fp2);
fdp->fd_ofiles[sv[1]] = 0; fdp->fd_ofiles[sv[1]] = 0;
ffree(fp2);
free3: free3:
ffree(fp1);
fdp->fd_ofiles[sv[0]] = 0; fdp->fd_ofiles[sv[0]] = 0;
ffree(fp1);
free2: free2:
(void)soclose(so2); (void)soclose(so2);
free1: free1:

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 * @(#)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 */ /* For 4.3 integer FS ID compatibility */
@ -995,10 +995,10 @@ open(p, uap)
p->p_dupfd = 0; p->p_dupfd = 0;
vp = nd.ni_vp; vp = nd.ni_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_data = (caddr_t)vp;
fp->f_flag = flags & FMASK;
fp->f_ops = &vnops;
fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
if (flags & (O_EXLOCK | O_SHLOCK)) { if (flags & (O_EXLOCK | O_SHLOCK)) {
lf.l_whence = SEEK_SET; lf.l_whence = SEEK_SET;
lf.l_start = 0; lf.l_start = 0;

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 * @(#)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 */ /* For 4.3 integer FS ID compatibility */
@ -995,10 +995,10 @@ open(p, uap)
p->p_dupfd = 0; p->p_dupfd = 0;
vp = nd.ni_vp; vp = nd.ni_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_data = (caddr_t)vp;
fp->f_flag = flags & FMASK;
fp->f_ops = &vnops;
fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
if (flags & (O_EXLOCK | O_SHLOCK)) { if (flags & (O_EXLOCK | O_SHLOCK)) {
lf.l_whence = SEEK_SET; lf.l_whence = SEEK_SET;
lf.l_start = 0; lf.l_start = 0;

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94 * @(#)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 <sys/param.h> #include <sys/param.h>
@ -48,6 +48,7 @@
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/namei.h> #include <sys/namei.h>
#include <sys/vnode.h> #include <sys/vnode.h>
#include <sys/buf.h>
#include <sys/filio.h> #include <sys/filio.h>
#include <sys/ttycom.h> #include <sys/ttycom.h>
@ -563,6 +564,7 @@ vn_closefile(fp, p)
struct proc *p; struct proc *p;
{ {
fp->f_ops = &badfileops;
return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
fp->f_cred, p)); fp->f_cred, p));
} }

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)file.h 8.3 (Berkeley) 1/9/95 * @(#)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_ #ifndef _SYS_FILE_H_
@ -93,6 +93,7 @@ MALLOC_DECLARE(M_FILE);
LIST_HEAD(filelist, file); LIST_HEAD(filelist, file);
extern struct filelist filehead; /* head of list of open files */ extern struct filelist filehead; /* head of list of open files */
extern struct fileops vnops; extern struct fileops vnops;
extern struct fileops badfileops;
extern int maxfiles; /* kernel limit on number of open files */ extern int maxfiles; /* kernel limit on number of open files */
extern int maxfilesperproc; /* per process 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 */ extern int nfiles; /* actual number of open files */