[Devel] [PATCH RHEL7 COMMIT] dcache: fix dentry leak when shrink races with kill
Vladimir Davydov
vdavydov at virtuozzo.com
Thu Jul 7 07:33:14 PDT 2016
The commit is pushed to "branch-rh7-3.10.0-327.18.2.vz7.14.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.18.2.vz7.14.23
------>
commit 88b8ca0fe3055767d9b92495b3e28f587b923d04
Author: Vladimir Davydov <vdavydov at virtuozzo.com>
Date: Thu Jul 7 18:33:13 2016 +0400
dcache: fix dentry leak when shrink races with kill
dentry_kill() does not free a dentry in case it is on a shrink list -
see __dentry_kill() -> d_free(). Instead it just marks it
DCACHE_MAY_FREE, which will make the shrinker free it when it's done
with it. This is required to avoid use after free in
shrink_dentry_list(). This logic was back-ported by commit e33cae748d1a
("ms/dcache: dentry_kill(): don't try to remove from shrink list").
When back-porting this commit I occasionally missed a hunk for
shrink_dentry_list(). The hunk makes shrink_dentry_list() more carefully
check dentry->d_lock_ref.count, i.e. instead of merely checking if it's
0 or not, it makes it check if it's strictly greater than 0. W/o this
check a dentry might leak if shrink races with kill, because before
trying to free a dentry, dentry_kill() first calls
lockref_mark_dead(&dentry->d_lockref), which sets d_lockref.count to
-128, so that shrink_dentry_list() will silently skip the dentry instead
of freeing it.
This patch resurrects the missing hunk.
https://jira.sw.ru/browse/PSBM-49321
Fixes: e33cae748d1a ("ms/dcache: dentry_kill(): don't try to remove from shrink list")
Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
---
fs/dcache.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index 09ed486c9f1d..6433814a02d2 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -874,7 +874,7 @@ static void shrink_dentry_list(struct list_head *list)
* We found an inuse dentry which was not removed from
* the LRU because of laziness during lookup. Do not free it.
*/
- if (dentry->d_lockref.count) {
+ if ((int)dentry->d_lockref.count > 0) {
spin_unlock(&dentry->d_lock);
if (parent)
spin_unlock(&parent->d_lock);
More information about the Devel
mailing list