Commit bf779220 authored by Li Lingfeng's avatar Li Lingfeng
Browse files

block: Add config option to detect writing to part0 while partitions mounted

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8S3GW


CVE: NA

---------------------------

When a partition of a block device is mounted, opening the entire block
device for write operations may also damage the file system. Identify this
situation.

Signed-off-by: default avatarLi Lingfeng <lilingfeng3@huawei.com>
parent 108aa35d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -249,6 +249,16 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
	  by falling back to the kernel crypto API when inline
	  encryption hardware is not present.

config BLK_DEV_DETECT_WRITING_PART0
	bool "Detect writing to part0 when partitions mounted"
	default n
	help
	  When partitions of a block device are mounted, writing to part0's
	  buffer cache is likely going to cause filesystem corruption on
	  each partition.
	  As a supplement to BLK_DEV_WRITE_MOUNTED, enabling this
	  to detect the scenario above.

source "block/partitions/Kconfig"

config BLK_MQ_PCI
+38 −5
Original line number Diff line number Diff line
@@ -33,9 +33,12 @@
#define bdev_write_mounted_opt(opt) (bdev_allow_write_mounted & (1 << BLKDEV_##opt))
/* Should we allow writing to mounted block devices? */
#define BLKDEV_ALLOW_WRITE_MOUNTED	0
/* Should we detect writing to part0 when partitions mounted  */
#define BLKDEV_DETECT_WRITING_PART0	1

static u8 bdev_allow_write_mounted =
	IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED) << BLKDEV_ALLOW_WRITE_MOUNTED;
	IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED) << BLKDEV_ALLOW_WRITE_MOUNTED |
	IS_ENABLED(CONFIG_BLK_DEV_DETECT_WRITING_PART0) << BLKDEV_DETECT_WRITING_PART0;

struct bdev_inode {
	struct block_device bdev;
@@ -739,22 +742,52 @@ void blkdev_put_no_open(struct block_device *bdev)

static bool bdev_writes_blocked(struct block_device *bdev)
{
	return bdev->bd_mounted;
	if (bdev->bd_mounted)
		return true;
	if (bdev_opt(DETECT_WRITING_PART0))
		return bdev_is_partition(bdev) ? bdev_whole(bdev)->bd_mounted :
						 bdev->bd_disk->mount_partitions;

	return false;
}

static void bdev_block_writes(struct block_device *bdev)
{
	bdev->bd_mounted = true;
	if (bdev_is_partition(bdev))
		bdev->bd_disk->mount_partitions++;
}

static void bdev_unblock_writes(struct block_device *bdev)
{
	bdev->bd_mounted = false;
	if (bdev_is_partition(bdev))
		bdev->bd_disk->mount_partitions--;
}

static bool bdev_mount_blocked(struct block_device *bdev)
{
	return bdev->bd_writers > 0;
	if (bdev->bd_writers)
		return true;
	if (bdev_opt(DETECT_WRITING_PART0))
		return bdev_is_partition(bdev) ? bdev_whole(bdev)->bd_writers :
						 bdev->bd_disk->write_open_partitions;

	return false;
}

static void bdev_block_mount(struct block_device *bdev)
{
	bdev->bd_writers++;
	if (bdev_is_partition(bdev))
		bdev->bd_disk->write_open_partitions++;
}

static void bdev_unblock_mount(struct block_device *bdev)
{
	bdev->bd_writers--;
	if (bdev_is_partition(bdev))
		bdev->bd_disk->write_open_partitions--;
}

static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode)
@@ -775,7 +808,7 @@ static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode)
	if (mode & BLK_OPEN_RESTRICT_WRITES)
		bdev_block_writes(bdev);
	else if (mode & BLK_OPEN_WRITE)
		bdev->bd_writers++;
		bdev_block_mount(bdev);
}

static void bdev_yield_write_access(struct block_device *bdev, blk_mode_t mode)
@@ -784,7 +817,7 @@ static void bdev_yield_write_access(struct block_device *bdev, blk_mode_t mode)
	if (mode & BLK_OPEN_RESTRICT_WRITES)
		bdev_unblock_writes(bdev);
	else if (mode & BLK_OPEN_WRITE)
		bdev->bd_writers--;
		bdev_unblock_mount(bdev);
}

/**
+2 −0
Original line number Diff line number Diff line
@@ -162,6 +162,8 @@ struct gendisk {

	struct mutex open_mutex;	/* open/close mutex */
	unsigned open_partitions;	/* number of open partitions */
	unsigned write_open_partitions;	/* number of write open partitions */
	unsigned mount_partitions;	/* number of mount partitions */

	struct backing_dev_info	*bdi;
	struct kobject queue_kobj;	/* the queue/ directory */