diff options
author | kib <kib@FreeBSD.org> | 2007-02-07 10:30:49 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2007-02-07 10:30:49 +0000 |
commit | 0e5b15d726fe05f6c5c50c0dc9f7d5aed285d3c9 (patch) | |
tree | 8ea493a77b12f3dc48651402856803c2d9de34b1 /sys | |
parent | 2eb15b506b7d7b69a41d0fcdf2d7a806d723e4c7 (diff) | |
download | FreeBSD-src-0e5b15d726fe05f6c5c50c0dc9f7d5aed285d3c9.zip FreeBSD-src-0e5b15d726fe05f6c5c50c0dc9f7d5aed285d3c9.tar.gz |
Fix the race of dereferencing /proc/<pid>/file with execve(2) by caching
the value of p_textvp. This way, we always unlock the locked vnode.
While there, vhold() the vnode around the vn_lock().
Reported and tested by: Guy Helmer (ghelmer palisadesys com)
Approved by: des (procfs maintainer)
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/fs/procfs/procfs.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/fs/procfs/procfs.c b/sys/fs/procfs/procfs.c index 90d8975..d311a98 100644 --- a/sys/fs/procfs/procfs.c +++ b/sys/fs/procfs/procfs.c @@ -69,10 +69,18 @@ procfs_doprocfile(PFS_FILL_ARGS) { char *fullpath = "unknown"; char *freepath = NULL; - - vn_lock(p->p_textvp, LK_EXCLUSIVE | LK_RETRY, td); - vn_fullpath(td, p->p_textvp, &fullpath, &freepath); - VOP_UNLOCK(p->p_textvp, 0, td); + struct vnode *textvp; + int err; + + textvp = p->p_textvp; + VI_LOCK(textvp); + vholdl(textvp); + err = vn_lock(textvp, LK_EXCLUSIVE | LK_INTERLOCK, td); + vdrop(textvp); + if (err) + return (err); + vn_fullpath(td, textvp, &fullpath, &freepath); + VOP_UNLOCK(textvp, 0, td); sbuf_printf(sb, "%s", fullpath); if (freepath) free(freepath, M_TEMP); |