v1->v2: 1) Replace BLK_DEV_DUMPINFO with BLK_DEV_WRITE_MOUNTED_QUIET, which is logically opposite; 2) Make BLK_DEV_WRITE_MOUNTED_QUIET dependent on BLK_DEV_WRITE_MOUNTED, and decide whether to set bd_writers by BLK_DEV_WRITE_MOUNTED_QUIET; 3) Move bdev_dump_info() into bdev_may_open(); 4) Add the cmdline interface to control whether to show info; 5) Pass the state of "writes blocked" to part0 when mounting a partition. v2->v3: Add restriction for modifying bd_writers. v3->v4: 1) Count bd_writers regardless of whether bdev_allow_write_mounted is set; 2) Expand the meaning of bdev_allow_write_mounted; 3) Add config option to detect writing to part0 while partitions mounted; 4) Add bd_mounters to record the number of times that part0 or partition is mounted; 5) Show info about opening a lower device for write while upper-layers mounted. v4->v5: Move introduction of bd_mounters to patch1. v5->v6: Delete redundant conflict judgment. v6->v7: 1) Replace BLK_DEV_WRITE_MOUNTED_QUIET with BLK_DEV_WRITE_MOUNTED_DUMP; 2) Remove restriction for setting bdev_allow_write_mounted by cmdline. v7->v8: 1) Add detection of mounting part0 while partitions write opened; 2) Add detection of writing partitions while part0 mounted; 3) Add config in openeuler_defconfig.
Li Lingfeng (6): block: Count writers and mounters regardless of whether bdev_allow_write_mounted is set block: Expand the meaning of bdev_allow_write_mounted block: Add config option to detect writing to part0 while partitions mounted block: Add config option to show info about opening a mounted device for write block: Show info about opening a lower device for write while upper-layers mounted add config about writing mounted devices in openeuler_defconfig
arch/arm64/configs/openeuler_defconfig | 3 + arch/x86/configs/openeuler_defconfig | 3 + block/Kconfig | 17 ++++ block/bdev.c | 122 +++++++++++++++++++++---- include/linux/blk_types.h | 1 + 5 files changed, 129 insertions(+), 17 deletions(-)
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8S3GW CVE: NA
---------------------------
Introduce bd_mounters to record the num of mount. The count of bd_writers and bd_mounters can have other uses and they doesn't block writes when bdev_allow_write_mounted is not set, so remove the restriction for counting them.
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- block/bdev.c | 19 +++++++++---------- include/linux/blk_types.h | 1 + 2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/block/bdev.c b/block/bdev.c index dd39c26c44ad..715428eb6621 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -735,17 +735,22 @@ 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_mounters; }
static void bdev_block_writes(struct block_device *bdev) { - bdev->bd_writers = -1; + bdev->bd_mounters++; }
static void bdev_unblock_writes(struct block_device *bdev) { - bdev->bd_writers = 0; + bdev->bd_mounters--; +} + +static bool bdev_mount_blocked(struct block_device *bdev) +{ + return bdev->bd_writers > 0; }
static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) @@ -755,16 +760,13 @@ static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) /* Writes blocked? */ if (mode & BLK_OPEN_WRITE && bdev_writes_blocked(bdev)) return false; - if (mode & BLK_OPEN_RESTRICT_WRITES && bdev->bd_writers > 0) + if (mode & BLK_OPEN_RESTRICT_WRITES && bdev_mount_blocked(bdev)) return false; return true; }
static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode) { - if (bdev_allow_write_mounted) - return; - /* Claim exclusive or shared write access. */ if (mode & BLK_OPEN_RESTRICT_WRITES) bdev_block_writes(bdev); @@ -774,9 +776,6 @@ static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode)
static void bdev_yield_write_access(struct block_device *bdev, blk_mode_t mode) { - if (bdev_allow_write_mounted) - return; - /* Yield exclusive or shared write access. */ if (mode & BLK_OPEN_RESTRICT_WRITES) bdev_unblock_writes(bdev); diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 262ae789726b..0e1e429d3f74 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -70,6 +70,7 @@ struct block_device { bool bd_make_it_fail; #endif int bd_writers; + int bd_mounters; /* * keep this out-of-line as it's both big and not needed in the fast * path
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8S3GW CVE: NA
---------------------------
For bdev_allow_write_mounted, there will be more subdivided scenarios and different bits of it will be used to indicate different scenarios, so expand it now.
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- block/bdev.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/block/bdev.c b/block/bdev.c index 715428eb6621..8998c93a0814 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -31,7 +31,10 @@ #include "blk.h"
/* Should we allow writing to mounted block devices? */ -static bool bdev_allow_write_mounted = IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED); +#define BLKDEV_ALLOW_WRITE_MOUNTED 0 + +static u8 bdev_allow_write_mounted = + IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED) << BLKDEV_ALLOW_WRITE_MOUNTED;
struct bdev_inode { struct block_device bdev; @@ -755,7 +758,7 @@ static bool bdev_mount_blocked(struct block_device *bdev)
static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) { - if (bdev_allow_write_mounted) + if (bdev_allow_write_mounted & (1 << BLKDEV_ALLOW_WRITE_MOUNTED)) return true; /* Writes blocked? */ if (mode & BLK_OPEN_WRITE && bdev_writes_blocked(bdev)) @@ -1134,7 +1137,7 @@ void bdev_statx_dioalign(struct inode *inode, struct kstat *stat)
static int __init setup_bdev_allow_write_mounted(char *str) { - if (kstrtobool(str, &bdev_allow_write_mounted)) + if (kstrtou8(str, 0, &bdev_allow_write_mounted)) pr_warn("Invalid option string for bdev_allow_write_mounted:" " '%s'\n", str); return 1;
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: Li Lingfeng lilingfeng3@huawei.com --- block/Kconfig | 10 ++++++++++ block/bdev.c | 40 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/block/Kconfig b/block/Kconfig index 03b53a50939f..05fdd81a708f 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -239,6 +239,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(_QUIET), enabling this + to detect the scenario above. + source "block/partitions/Kconfig"
config BLK_MQ_PCI diff --git a/block/bdev.c b/block/bdev.c index 8998c93a0814..ad4388c75b81 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -32,9 +32,13 @@
/* 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 +#define PARTITION_WRITE_BIT 16
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; @@ -738,24 +742,54 @@ void blkdev_put_no_open(struct block_device *bdev)
static bool bdev_writes_blocked(struct block_device *bdev) { + if (bdev_allow_write_mounted & (1 << BLKDEV_DETECT_WRITING_PART0)) + return !!bdev->bd_mounters || + !!(bdev_whole(bdev)->bd_mounters & + ((1 << PARTITION_WRITE_BIT) -1)); return !!bdev->bd_mounters; }
static void bdev_block_writes(struct block_device *bdev) { bdev->bd_mounters++; + if (bdev_is_partition(bdev) && + bdev_allow_write_mounted & (1 << BLKDEV_DETECT_WRITING_PART0)) + bdev_whole(bdev)->bd_mounters += 1 << PARTITION_WRITE_BIT;; }
static void bdev_unblock_writes(struct block_device *bdev) { bdev->bd_mounters--; + if (bdev_is_partition(bdev) && + bdev_allow_write_mounted & (1 << BLKDEV_DETECT_WRITING_PART0)) + bdev_whole(bdev)->bd_mounters -= 1 << PARTITION_WRITE_BIT;; }
static bool bdev_mount_blocked(struct block_device *bdev) { + if (bdev_allow_write_mounted & (1 << BLKDEV_DETECT_WRITING_PART0)) + return bdev->bd_writers > 0 || + (bdev_whole(bdev)->bd_writers & + ((1 << PARTITION_WRITE_BIT) -1)) > 0; return bdev->bd_writers > 0; }
+static void bdev_block_mount(struct block_device *bdev) +{ + bdev->bd_writers++; + if (bdev_is_partition(bdev) && + bdev_allow_write_mounted & (1 << BLKDEV_DETECT_WRITING_PART0)) + bdev_whole(bdev)->bd_writers += 1 << PARTITION_WRITE_BIT; +} + +static void bdev_unblock_mount(struct block_device *bdev) +{ + bdev->bd_writers--; + if (bdev_is_partition(bdev) && + bdev_allow_write_mounted & (1 << BLKDEV_DETECT_WRITING_PART0)) + bdev_whole(bdev)->bd_writers -= 1 << PARTITION_WRITE_BIT; +} + static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) { if (bdev_allow_write_mounted & (1 << BLKDEV_ALLOW_WRITE_MOUNTED)) @@ -774,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) @@ -783,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); }
/**
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8S3GW CVE: NA
---------------------------
When writing to a mounted block device is allowed, we need to identify which processes may write to the block device to prevent the file system from being damaged in silence.
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- block/Kconfig | 7 +++++++ block/bdev.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/block/Kconfig b/block/Kconfig index 05fdd81a708f..214c1caeab4c 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -249,6 +249,13 @@ config BLK_DEV_DETECT_WRITING_PART0 As a supplement to BLK_DEV_WRITE_MOUNTED(_QUIET), enabling this to detect the scenario above.
+config BLK_DEV_WRITE_MOUNTED_DUMP + bool "Dump info when detecting conflict of opening block device" + default n + help + Enabling this to dump info when opening mounted block devices + for write or trying to mount write opened block devices. + source "block/partitions/Kconfig"
config BLK_MQ_PCI diff --git a/block/bdev.c b/block/bdev.c index ad4388c75b81..42bcde62967e 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -30,15 +30,21 @@ #include "../fs/internal.h" #include "blk.h"
+#define OPEN_EXCLUSIVE "VFS: Open an exclusive opened block device for write" +#define OPEN_FOR_EXCLUSIVE "VFS: Open a write opened block device exclusively" + /* 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 +/* Should we dump info when opening mounted block devices for write? */ +#define BLKDEV_WRITE_MOUNTED_DUMP 2 #define PARTITION_WRITE_BIT 16
static u8 bdev_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; + IS_ENABLED(CONFIG_BLK_DEV_DETECT_WRITING_PART0) << BLKDEV_DETECT_WRITING_PART0 || + IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED_DUMP) << BLKDEV_WRITE_MOUNTED_DUMP;
struct bdev_inode { struct block_device bdev; @@ -740,6 +746,27 @@ void blkdev_put_no_open(struct block_device *bdev) put_device(&bdev->bd_device); }
+static void blkdev_dump_conflict_opener(struct block_device *bdev, char *msg) +{ + char name[BDEVNAME_SIZE]; + struct task_struct *p = NULL; + char comm_buf[TASK_COMM_LEN]; + pid_t p_pid; + + rcu_read_lock(); + p = rcu_dereference(current->real_parent); + task_lock(p); + strncpy(comm_buf, p->comm, TASK_COMM_LEN); + p_pid = p->pid; + task_unlock(p); + rcu_read_unlock(); + + snprintf(name, sizeof(name), "%pg", bdev); + pr_info_ratelimited("%s [%s]. current [%d %s]. parent [%d %s]\n", + msg, name, + current->pid, current->comm, p_pid, comm_buf); +} + static bool bdev_writes_blocked(struct block_device *bdev) { if (bdev_allow_write_mounted & (1 << BLKDEV_DETECT_WRITING_PART0)) @@ -790,15 +817,29 @@ static void bdev_unblock_mount(struct block_device *bdev) bdev_whole(bdev)->bd_writers -= 1 << PARTITION_WRITE_BIT; }
-static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) +bool bdev_may_conflict_open(struct block_device *bdev, char *msg) { + if (bdev_allow_write_mounted & (1 << BLKDEV_WRITE_MOUNTED_DUMP)) + blkdev_dump_conflict_opener(bdev, msg); + if (bdev_allow_write_mounted & (1 << BLKDEV_ALLOW_WRITE_MOUNTED)) return true; + + return false; +} + +static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) +{ + if (bdev_allow_write_mounted & (1 << BLKDEV_ALLOW_WRITE_MOUNTED) && + !(bdev_allow_write_mounted & (1 << BLKDEV_WRITE_MOUNTED_DUMP))) + return true; + /* Writes blocked? */ if (mode & BLK_OPEN_WRITE && bdev_writes_blocked(bdev)) - return false; + return bdev_may_conflict_open(bdev, OPEN_EXCLUSIVE); if (mode & BLK_OPEN_RESTRICT_WRITES && bdev_mount_blocked(bdev)) - return false; + return bdev_may_conflict_open(bdev, OPEN_FOR_EXCLUSIVE); + return true; }
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8S3GW CVE: NA
---------------------------
Filesystem on logic devices may be corrupted when writing to a block device which is used to create logic devices, so show info to indicate this risk behavior.
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- block/bdev.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/block/bdev.c b/block/bdev.c index 42bcde62967e..b2b69cd82d66 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -776,6 +776,14 @@ static bool bdev_writes_blocked(struct block_device *bdev) return !!bdev->bd_mounters; }
+static bool bdev_lower_device_writes_blocked(struct block_device *bdev) +{ + if (bdev_allow_write_mounted & (1 << BLKDEV_DETECT_WRITING_PART0)) + return !!bdev->bd_holder; + else + return !!bdev->bd_holder && bdev->bd_holder != bd_may_claim; +} + static void bdev_block_writes(struct block_device *bdev) { bdev->bd_mounters++; @@ -839,6 +847,9 @@ static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) return bdev_may_conflict_open(bdev, OPEN_EXCLUSIVE); if (mode & BLK_OPEN_RESTRICT_WRITES && bdev_mount_blocked(bdev)) return bdev_may_conflict_open(bdev, OPEN_FOR_EXCLUSIVE); + if ((bdev_allow_write_mounted & (1 << BLKDEV_WRITE_MOUNTED_DUMP)) && + mode & BLK_OPEN_WRITE && bdev_lower_device_writes_blocked(bdev)) + blkdev_dump_conflict_opener(bdev, OPEN_EXCLUSIVE);
return true; }
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8S3GW CVE: NA
---------------------------
OpenEuler need detect conflict of opening block device, so enable it as default.
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- arch/arm64/configs/openeuler_defconfig | 3 +++ arch/x86/configs/openeuler_defconfig | 3 +++ 2 files changed, 6 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 6c6cf96e30f5..56ea1998899b 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -892,6 +892,9 @@ CONFIG_BLK_DEBUG_FS=y CONFIG_BLK_DEBUG_FS_ZONED=y # CONFIG_BLK_SED_OPAL is not set # CONFIG_BLK_INLINE_ENCRYPTION is not set +CONFIG_BLK_DEV_WRITE_MOUNTED=y +CONFIG_BLK_DEV_DETECT_WRITING_PART0=y +CONFIG_BLK_DEV_WRITE_MOUNTED_DUMP=y
# # Partition Types diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index 74c1329b6616..af576b81b15f 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -957,6 +957,9 @@ CONFIG_BLK_DEBUG_FS=y CONFIG_BLK_DEBUG_FS_ZONED=y # CONFIG_BLK_SED_OPAL is not set # CONFIG_BLK_INLINE_ENCRYPTION is not set +CONFIG_BLK_DEV_WRITE_MOUNTED=y +CONFIG_BLK_DEV_DETECT_WRITING_PART0=y +CONFIG_BLK_DEV_WRITE_MOUNTED_DUMP=y
# # Partition Types
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/3927 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/C...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/3927 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/C...