diff options
author | alfred <alfred@FreeBSD.org> | 2003-02-15 05:52:56 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 2003-02-15 05:52:56 +0000 |
commit | d9a7e5d6275ad9bb5fb49ed6879def1058777294 (patch) | |
tree | e6573e84f9435faccc517948a6e15ec04999d9b3 /sys/kern/kern_descrip.c | |
parent | 40ff51b25dfaa13508d632a1885e2773f419ff02 (diff) | |
download | FreeBSD-src-d9a7e5d6275ad9bb5fb49ed6879def1058777294.zip FreeBSD-src-d9a7e5d6275ad9bb5fb49ed6879def1058777294.tar.gz |
Fix LOR with PROC/filedesc. Introduce fdesc_mtx that will be used as a
barrier between free'ing filedesc structures. Basically if you want to
access another process's filedesc, you want to hold this mutex over the
entire operation.
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index fe52ec1..5e2ac9b 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1366,6 +1366,10 @@ retry: return (newfdp); } +/* A mutex to protect the association between a proc and filedesc. */ +struct mtx fdesc_mtx; +MTX_SYSINIT(fdesc, &fdesc_mtx, "fdesc", MTX_DEF); + /* * Release a filedesc structure. */ @@ -1382,6 +1386,10 @@ fdfree(td) if (fdp == NULL) return; + mtx_lock(&fdesc_mtx); + td->td_proc->p_fd = NULL; + mtx_unlock(&fdesc_mtx); + FILEDESC_LOCK(fdp); if (--fdp->fd_refcnt > 0) { FILEDESC_UNLOCK(fdp); @@ -1398,7 +1406,6 @@ fdfree(td) if (*fpp) (void) closef(*fpp, td); } - td->td_proc->p_fd = NULL; if (fdp->fd_nfiles > NDFILE) FREE(fdp->fd_ofiles, M_FILEDESC); if (fdp->fd_cdir) @@ -2105,7 +2112,9 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) xf.xf_pid = p->p_pid; xf.xf_uid = p->p_ucred->cr_uid; PROC_UNLOCK(p); + mtx_lock(&fdesc_mtx); if ((fdp = p->p_fd) == NULL) { + mtx_unlock(&fdesc_mtx); continue; } FILEDESC_LOCK(fdp); @@ -2125,6 +2134,7 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) break; } FILEDESC_UNLOCK(fdp); + mtx_unlock(&fdesc_mtx); if (error) break; } |