Skip to content

Commit

Permalink
block: count BLK_OPEN_RESTRICT_WRITES openers
Browse files Browse the repository at this point in the history
[ Upstream commit 3ff56e2 ]

The original changes in v6.8 do allow for a block device to be reopened
with BLK_OPEN_RESTRICT_WRITES provided the same holder is used as per
bdev_may_open(). I think this has a bug.

The first opener @F1 of that block device will set bdev->bd_writers to
-1. The second opener @F2 using the same holder will pass the check in
bdev_may_open() that bdev->bd_writers must not be greater than zero.

The first opener @F1 now closes the block device and in bdev_release()
will end up calling bdev_yield_write_access() which calls
bdev_writes_blocked() and sets bdev->bd_writers to 0 again.

Now @F2 holds a file to that block device which was opened with
exclusive write access but bdev->bd_writers has been reset to 0.

So now @f3 comes along and succeeds in opening the block device with
BLK_OPEN_WRITE betraying @F2's request to have exclusive write access.

This isn't a practical issue yet because afaict there's no codepath
inside the kernel that reopenes the same block device with
BLK_OPEN_RESTRICT_WRITES but it will be if there is.

Fix this by counting the number of BLK_OPEN_RESTRICT_WRITES openers. So
we only allow writes again once all BLK_OPEN_RESTRICT_WRITES openers are
done.

Link: https://lore.kernel.org/r/20240323-abtauchen-klauen-c2953810082d@brauner
Fixes: ed5cc70 ("block: Add config option to not allow writing to mounted devices")
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
brauner authored and gregkh committed Apr 10, 2024
1 parent 041fd51 commit 9b8612e
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions block/bdev.c
Expand Up @@ -738,17 +738,17 @@ void blkdev_put_no_open(struct block_device *bdev)

static bool bdev_writes_blocked(struct block_device *bdev)
{
return bdev->bd_writers == -1;
return bdev->bd_writers < 0;
}

static void bdev_block_writes(struct block_device *bdev)
{
bdev->bd_writers = -1;
bdev->bd_writers--;
}

static void bdev_unblock_writes(struct block_device *bdev)
{
bdev->bd_writers = 0;
bdev->bd_writers++;
}

static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode)
Expand Down

0 comments on commit 9b8612e

Please sign in to comment.