lkml.org 
[lkml]   [2021]   [Jan]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[fs PATCH] fs: fix freeze count problem in freeze_bdev
    Hi,

    I wrote this patch to fix the freeze/thaw device problem before I saw
    the patch "fs: Fix freeze_bdev()/thaw_bdev() accounting of bd_fsfreeze_sb"
    from Satya Tangirala. That one, however, does not fix the bd_freeze_count
    problem and this patch does. Jens, Christoph, what do you think?
    This is a very recreatable problem via repeated runs of generic/085,
    at least on gfs2.

    Description:

    Before this patch, if you tried to freeze a device (function freeze_bdev)
    while it was being unmounted, it would get NULL back from get_active_super
    and correctly bypass the freeze calls. Unfortunately, it forgot to decrement
    its bd_fsfreeze_count. Subsequent calls to device thaw (thaw_bdev) would
    see the non-zero bd_fsfreeze_count and assume the bd_fsfreeze_sb value was
    still valid. That's not a safe assumption and resulted in use-after-free,
    which often caused fatal kernel errors like: "unable to handle page fault
    for address."

    This patch adds the necessary decrement of bd_fsfreeze_count for that
    error path. It also adds code to set the bd_fsfreeze_sb to NULL when the
    last reference is reached in thaw_bdev.

    Signed-off-by: Bob Peterson <rpeterso@redhat.com>
    ---
    fs/block_dev.c | 5 ++++-
    1 file changed, 4 insertions(+), 1 deletion(-)

    diff --git a/fs/block_dev.c b/fs/block_dev.c
    index 9e56ee1f2652..c6daf7d12546 100644
    --- a/fs/block_dev.c
    +++ b/fs/block_dev.c
    @@ -555,8 +555,10 @@ int freeze_bdev(struct block_device *bdev)
    goto done;

    sb = get_active_super(bdev);
    - if (!sb)
    + if (!sb) {
    + bdev->bd_fsfreeze_count--;
    goto sync;
    + }
    if (sb->s_op->freeze_super)
    error = sb->s_op->freeze_super(sb);
    else
    @@ -600,6 +602,7 @@ int thaw_bdev(struct block_device *bdev)
    if (!sb)
    goto out;

    + bdev->bd_fsfreeze_sb = NULL;
    if (sb->s_op->thaw_super)
    error = sb->s_op->thaw_super(sb);
    else
    \
     
     \ /
      Last update: 2021-01-07 19:23    [W:3.124 / U:0.068 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site