Close a race when vfs_syscalls.c:checkdirs() runs.

To do this protect the filedesc pointer in the proc with PROC_LOCK
in both checkdirs() and kern_descrip.c:fdfree().
This commit is contained in:
alfred 2002-03-19 04:30:04 +00:00
parent 97b1d5e817
commit ee44937dc2
3 changed files with 31 additions and 15 deletions

View File

@ -1321,10 +1321,11 @@ void
fdfree(td)
struct thread *td;
{
register struct filedesc *fdp = td->td_proc->p_fd;
register struct filedesc *fdp;
struct file **fpp;
register int i;
fdp = td->td_proc->p_fd;
/* Certain daemons might not have file descriptors. */
if (fdp == NULL)
return;
@ -1344,6 +1345,11 @@ fdfree(td)
if (*fpp)
(void) closef(*fpp, td);
}
PROC_LOCK(td->td_proc);
td->td_proc->p_fd = NULL;
PROC_UNLOCK(td->td_proc);
if (fdp->fd_nfiles > NDFILE)
FREE(fdp->fd_ofiles, M_FILEDESC);
if (fdp->fd_cdir)

View File

@ -446,29 +446,34 @@ checkdirs(olddp, newdp)
{
struct filedesc *fdp;
struct proc *p;
int nrele;
if (olddp->v_usecount == 1)
return;
sx_slock(&allproc_lock);
LIST_FOREACH(p, &allproc, p_list) {
PROC_LOCK(p);
fdp = p->p_fd;
if (fdp == NULL)
if (fdp == NULL) {
PROC_UNLOCK(p);
continue;
}
nrele = 0;
FILEDESC_LOCK(fdp);
if (fdp->fd_cdir == olddp) {
VREF(newdp);
fdp->fd_cdir = newdp;
FILEDESC_UNLOCK(fdp);
vrele(olddp);
FILEDESC_LOCK(fdp);
nrele++;
}
if (fdp->fd_rdir == olddp) {
VREF(newdp);
fdp->fd_rdir = newdp;
FILEDESC_UNLOCK(fdp);
nrele++;
}
FILEDESC_UNLOCK(fdp);
PROC_UNLOCK(p);
while (nrele--)
vrele(olddp);
} else
FILEDESC_UNLOCK(fdp);
}
sx_sunlock(&allproc_lock);
if (rootvnode == olddp) {

View File

@ -446,29 +446,34 @@ checkdirs(olddp, newdp)
{
struct filedesc *fdp;
struct proc *p;
int nrele;
if (olddp->v_usecount == 1)
return;
sx_slock(&allproc_lock);
LIST_FOREACH(p, &allproc, p_list) {
PROC_LOCK(p);
fdp = p->p_fd;
if (fdp == NULL)
if (fdp == NULL) {
PROC_UNLOCK(p);
continue;
}
nrele = 0;
FILEDESC_LOCK(fdp);
if (fdp->fd_cdir == olddp) {
VREF(newdp);
fdp->fd_cdir = newdp;
FILEDESC_UNLOCK(fdp);
vrele(olddp);
FILEDESC_LOCK(fdp);
nrele++;
}
if (fdp->fd_rdir == olddp) {
VREF(newdp);
fdp->fd_rdir = newdp;
FILEDESC_UNLOCK(fdp);
nrele++;
}
FILEDESC_UNLOCK(fdp);
PROC_UNLOCK(p);
while (nrele--)
vrele(olddp);
} else
FILEDESC_UNLOCK(fdp);
}
sx_sunlock(&allproc_lock);
if (rootvnode == olddp) {