[4.2.y-ckt stable] Patch "writeback, cgroup: fix premature wb_put() in locked_inode_to_wb_and_lock_list()" has been added to the 4.2.y-ckt tree

Kamal Mostafa kamal at canonical.com
Wed Mar 30 23:53:17 UTC 2016


This is a note to let you know that I have just added a patch titled

    writeback, cgroup: fix premature wb_put() in locked_inode_to_wb_and_lock_list()

to the linux-4.2.y-queue branch of the 4.2.y-ckt extended stable tree 
which can be found at:

    http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-4.2.y-queue

This patch is scheduled to be released in version 4.2.8-ckt7.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 4.2.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

---8<------------------------------------------------------------

>From a9d48062c7c2227a113d3a2ee9b88115a6593f51 Mon Sep 17 00:00:00 2001
From: Tejun Heo <tj at kernel.org>
Date: Fri, 18 Mar 2016 13:50:03 -0400
Subject: writeback, cgroup: fix premature wb_put() in
 locked_inode_to_wb_and_lock_list()

commit 614a4e3773148a31f58dc174bbf578ceb63510c2 upstream.

locked_inode_to_wb_and_lock_list() wb_get()'s the wb associated with
the target inode, unlocks inode, locks the wb's list_lock and verifies
that the inode is still associated with the wb.  To prevent the wb
going away between dropping inode lock and acquiring list_lock, the wb
is pinned while inode lock is held.  The wb reference is put right
after acquiring list_lock citing that the wb won't be dereferenced
anymore.

This isn't true.  If the inode is still associated with the wb, the
inode has reference and it's safe to return the wb; however, if inode
has been switched, the wb still needs to be unlocked which is a
dereference and can lead to use-after-free if it it races with wb
destruction.

Fix it by putting the reference after releasing list_lock.

Signed-off-by: Tejun Heo <tj at kernel.org>
Fixes: 87e1d789bf55 ("writeback: implement [locked_]inode_to_wb_and_lock_list()")
Tested-by: Tahsin Erdogan <tahsin at google.com>
Signed-off-by: Jens Axboe <axboe at fb.com>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
 fs/fs-writeback.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 5fa588e..5760ea9 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -283,13 +283,15 @@ locked_inode_to_wb_and_lock_list(struct inode *inode)
 		wb_get(wb);
 		spin_unlock(&inode->i_lock);
 		spin_lock(&wb->list_lock);
-		wb_put(wb);		/* not gonna deref it anymore */

 		/* i_wb may have changed inbetween, can't use inode_to_wb() */
-		if (likely(wb == inode->i_wb))
-			return wb;	/* @inode already has ref */
+		if (likely(wb == inode->i_wb)) {
+			wb_put(wb);	/* @inode already has ref */
+			return wb;
+		}

 		spin_unlock(&wb->list_lock);
+		wb_put(wb);
 		cpu_relax();
 		spin_lock(&inode->i_lock);
 	}
--
2.7.4





More information about the kernel-team mailing list