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:
parent
97b1d5e817
commit
ee44937dc2
@ -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)
|
||||
|
@ -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;
|
||||
nrele++;
|
||||
}
|
||||
FILEDESC_UNLOCK(fdp);
|
||||
PROC_UNLOCK(p);
|
||||
while (nrele--)
|
||||
vrele(olddp);
|
||||
} else
|
||||
FILEDESC_UNLOCK(fdp);
|
||||
}
|
||||
sx_sunlock(&allproc_lock);
|
||||
if (rootvnode == olddp) {
|
||||
|
@ -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;
|
||||
nrele++;
|
||||
}
|
||||
FILEDESC_UNLOCK(fdp);
|
||||
PROC_UNLOCK(p);
|
||||
while (nrele--)
|
||||
vrele(olddp);
|
||||
} else
|
||||
FILEDESC_UNLOCK(fdp);
|
||||
}
|
||||
sx_sunlock(&allproc_lock);
|
||||
if (rootvnode == olddp) {
|
||||
|
Loading…
Reference in New Issue
Block a user