Skip to content

Commit

Permalink
writeback, cgroup: fix premature wb_put() in locked_inode_to_wb_and_l…
Browse files Browse the repository at this point in the history
…ock_list()

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@kernel.org>
Fixes: 87e1d78 ("writeback: implement [locked_]inode_to_wb_and_lock_list()")
Cc: stable@vger.kernel.org # v4.2+
Tested-by: Tahsin Erdogan <tahsin@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
  • Loading branch information
Tejun Heo authored and Jens Axboe committed Mar 20, 2016
1 parent 897bb0c commit 614a4e3
Showing 1 changed file with 5 additions and 3 deletions.
8 changes: 5 additions & 3 deletions fs/fs-writeback.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,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);
}
Expand Down

0 comments on commit 614a4e3

Please sign in to comment.