Message ID | 20240323-abtauchen-klauen-c2953810082d@brauner (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/2] block: handle BLK_OPEN_RESTRICT_WRITES correctly | expand |
On Sat 23-03-24 17:11:20, Christian Brauner wrote: > 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 that may have a bug. ^^^^^^^^ is :) Also AFAICT this can happen only the the reopen is O_RDONLY which would be probably good to mention here. > 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. > > If that's right then 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. > > Fixes: ed5cc702d311 ("block: Add config option to not allow writing to mounted devices") > Signed-off-by: Christian Brauner <brauner@kernel.org> Otherwise looks good so feel free to add: Reviewed-by: Jan Kara <jack@suse.cz> Honza > --- > block/bdev.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/block/bdev.c b/block/bdev.c > index f819f3086905..42f84692404c 100644 > --- a/block/bdev.c > +++ b/block/bdev.c > @@ -776,17 +776,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) > -- > 2.43.0 >
diff --git a/block/bdev.c b/block/bdev.c index f819f3086905..42f84692404c 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -776,17 +776,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)
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 that may have 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. If that's right then 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. Fixes: ed5cc702d311 ("block: Add config option to not allow writing to mounted devices") Signed-off-by: Christian Brauner <brauner@kernel.org> --- block/bdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)