mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-12 09:58:36 +00:00
- Fix a leaked reference to a vnode via v_dd. We rely on cache_purge() and
cache_zap() to clear the v_dd pointers when a directory vnode is forcibly discarded. For this to work, all vnodes with v_dd pointers to a directory must also have name cache entries linked via v_cache_dst to that dvp otherwise we could not find them at cache_purge() time. The following code snipit could break this guarantee by unlinking a directory before fetching it's dotdot. The dotdot lookup would initialize the v_dd field of the unlinked directory which could never be cleared. To fix this we don't initialize v_dd for orphaned vnodes. printf("rmdir: %d\n", rmdir("../foo")); /* foo is cwd */ printf("chdir: %d\n", chdir("..")); printf("%s\n", getwd(NULL)); Sponsored by: Isilon Systems, Inc. Discovered by: kkenn Approved by: re (blanket vfs)
This commit is contained in:
parent
482b893365
commit
32b6dcd8a4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147450
@ -493,8 +493,18 @@ cache_enter(dvp, vp, cnp)
|
||||
if (cnp->cn_namelen == 1) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* For dotdot lookups only cache the v_dd pointer if the
|
||||
* directory has a link back to its parent via v_cache_dst.
|
||||
* Without this an unlinked directory would keep a soft
|
||||
* reference to its parent which could not be NULLd at
|
||||
* cache_purge() time.
|
||||
*/
|
||||
if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
|
||||
dvp->v_dd = vp;
|
||||
CACHE_LOCK();
|
||||
if (!TAILQ_EMPTY(&dvp->v_cache_dst))
|
||||
dvp->v_dd = vp;
|
||||
CACHE_UNLOCK();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user