Both writing a mounted device and writing part0 while mounting a partition will provide a prompt message.
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.
Li Lingfeng (3): block: Add config to show info about opening a mounted device for write block: detect confilt of write and mount between partitions and part0 block: show info of confilt of write and mount between partitions and part0
block/Kconfig | 9 ++++ block/bdev.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 122 insertions(+), 7 deletions(-)
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 | 9 ++++++ block/bdev.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 5 deletions(-)
diff --git a/block/Kconfig b/block/Kconfig index 03b53a50939f..0c8d126ed1a5 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -239,6 +239,15 @@ config BLK_INLINE_ENCRYPTION_FALLBACK by falling back to the kernel crypto API when inline encryption hardware is not present.
+config BLK_DEV_WRITE_MOUNTED_QUIET + bool "Keep quiet when detecting conflict of opening block device" + default y + depends on BLK_DEV_WRITE_MOUNTED + help + While writing to mounted block devices is allowed, disabling 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 dd39c26c44ad..0596afe840c9 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -33,6 +33,9 @@ /* Should we allow writing to mounted block devices? */ static bool bdev_allow_write_mounted = IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED);
+/* Should we keep quiet when opening mounted block devices for write? */ +static bool bdev_write_mounted_quiet = IS_ENABLED(CONFIG_BLK_DEV_WRITE_MOUNTED_QUIET); + struct bdev_inode { struct block_device bdev; struct inode vfs_inode; @@ -733,6 +736,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) { return bdev->bd_writers == -1; @@ -748,10 +772,25 @@ static void bdev_unblock_writes(struct block_device *bdev) bdev->bd_writers = 0; }
+static void bdev_dump_info(struct block_device *bdev, blk_mode_t mode) +{ + if (bdev_write_mounted_quiet) + return; + + if (mode & BLK_OPEN_WRITE && bdev_writes_blocked(bdev)) + blkdev_dump_conflict_opener(bdev, "Open a writes blocked device(has" + " been mounted) for write"); + else if (mode & BLK_OPEN_RESTRICT_WRITES && bdev->bd_writers > 0) + blkdev_dump_conflict_opener(bdev, "Open a write opened device for" + " restrict write(for mount)"); +} + static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) { - if (bdev_allow_write_mounted) + if (bdev_allow_write_mounted) { + bdev_dump_info(bdev, mode); return true; + } /* Writes blocked? */ if (mode & BLK_OPEN_WRITE && bdev_writes_blocked(bdev)) return false; @@ -762,25 +801,36 @@ static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode)
static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode) { - if (bdev_allow_write_mounted) + /* + * 1) BLK_DEV_WRITE_MOUNTED == Y + * Whether to claim depends on the setting of + * BLK_DEV_WRITE_MOUNTED_QUIET, and it has no effect + * on opening block device. + * 2) BLK_DEV_WRITE_MOUNTED == N + * BLK_DEV_WRITE_MOUNTED_QUIET is not set, and claiming + * will be done. + */ + if (bdev_write_mounted_quiet) return;
/* Claim exclusive or shared write access. */ if (mode & BLK_OPEN_RESTRICT_WRITES) bdev_block_writes(bdev); - else if (mode & BLK_OPEN_WRITE) + else if (mode & BLK_OPEN_WRITE && bdev->bd_writers > -1) + /* Ensure that write open does not touch blocking state */ bdev->bd_writers++; }
static void bdev_yield_write_access(struct block_device *bdev, blk_mode_t mode) { - if (bdev_allow_write_mounted) + if (bdev_write_mounted_quiet) return;
/* Yield exclusive or shared write access. */ if (mode & BLK_OPEN_RESTRICT_WRITES) bdev_unblock_writes(bdev); - else if (mode & BLK_OPEN_WRITE) + else if (mode & BLK_OPEN_WRITE && bdev->bd_writers > 0) + /* Don't subtract bd_writers if mount/umount has been done */ bdev->bd_writers--; }
@@ -1138,6 +1188,22 @@ static int __init setup_bdev_allow_write_mounted(char *str) if (kstrtobool(str, &bdev_allow_write_mounted)) pr_warn("Invalid option string for bdev_allow_write_mounted:" " '%s'\n", str); + else if (!bdev_allow_write_mounted) + bdev_write_mounted_quiet = 0; return 1; } __setup("bdev_allow_write_mounted=", setup_bdev_allow_write_mounted); + +static int __init setup_bdev_write_mounted_quiet(char *str) +{ + if (!bdev_allow_write_mounted) { + pr_warn("Can't set bdev_write_mounted_quiet_quiet since" + " bdev_allow_write_mounted is false\n"); + return 1; + } + if (kstrtobool(str, &bdev_write_mounted_quiet)) + pr_warn("Invalid option string for bdev_write_mounted_quiet:" + " '%s'\n", str); + return 1; +} +__setup("bdev_write_mounted_quiet=", setup_bdev_write_mounted_quiet);
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/bdev.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/block/bdev.c b/block/bdev.c index 0596afe840c9..ed9898343de1 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -759,7 +759,7 @@ static void blkdev_dump_conflict_opener(struct block_device *bdev, char *msg)
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) @@ -772,6 +772,27 @@ static void bdev_unblock_writes(struct block_device *bdev) bdev->bd_writers = 0; }
+static void bdev_partition_block_part0_writes(struct block_device *bdev) +{ + if (bdev_whole(bdev)->bd_writers > 0) + /* + * Mounting the partition for the first time blocks part0 + * writes while part0 is write opened. + */ + bdev_whole(bdev)->bd_writers = -1; + else + bdev_whole(bdev)->bd_writers--; +} + +static void bdev_partition_unblock_part0_writes(struct block_device *bdev) +{ + /* + * Make sure that umount does not cause bd_writers to be positive. + */ + if (bdev_whole(bdev)->bd_writers < 0) + bdev_whole(bdev)->bd_writers++; +} + static void bdev_dump_info(struct block_device *bdev, blk_mode_t mode) { if (bdev_write_mounted_quiet) @@ -794,7 +815,8 @@ 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->bd_writers > 0 || bdev_whole(bdev)->bd_writers > 0)) return false; return true; } @@ -819,6 +841,11 @@ static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode) else if (mode & BLK_OPEN_WRITE && bdev->bd_writers > -1) /* Ensure that write open does not touch blocking state */ bdev->bd_writers++; + + /* For partition, mounting partition block part0 writes */ + if (bdev_is_partition(bdev) && + mode & BLK_OPEN_RESTRICT_WRITES) + bdev_partition_block_part0_writes(bdev); }
static void bdev_yield_write_access(struct block_device *bdev, blk_mode_t mode) @@ -832,6 +859,11 @@ static void bdev_yield_write_access(struct block_device *bdev, blk_mode_t mode) else if (mode & BLK_OPEN_WRITE && bdev->bd_writers > 0) /* Don't subtract bd_writers if mount/umount has been done */ bdev->bd_writers--; + + /* For partition, unblock part0 writes */ + if (bdev_is_partition(bdev) && + mode & BLK_OPEN_RESTRICT_WRITES) + bdev_partition_unblock_part0_writes(bdev); }
/**
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8S3GW CVE: NA
---------------------------
Now that we can detect confilt of write and mount between partitions and part0, just show information about it.
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- block/bdev.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/block/bdev.c b/block/bdev.c index ed9898343de1..26324f7c61a6 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -795,15 +795,23 @@ static void bdev_partition_unblock_part0_writes(struct block_device *bdev)
static void bdev_dump_info(struct block_device *bdev, blk_mode_t mode) { + char msg[100]; if (bdev_write_mounted_quiet) return;
if (mode & BLK_OPEN_WRITE && bdev_writes_blocked(bdev)) - blkdev_dump_conflict_opener(bdev, "Open a writes blocked device(has" + blkdev_dump_conflict_opener(bdev, "Open a writes blocked device" + "(partition or itself has" " been mounted) for write"); - else if (mode & BLK_OPEN_RESTRICT_WRITES && bdev->bd_writers > 0) - blkdev_dump_conflict_opener(bdev, "Open a write opened device for" - " restrict write(for mount)"); + else if (mode & BLK_OPEN_RESTRICT_WRITES && + (bdev->bd_writers > 0 || bdev_whole(bdev)->bd_writers > 0)) { + snprintf(msg, sizeof(msg), + "Open a device %s%s for restrict write(for mount)", + (bdev->bd_writers > 0) ? "(which has been write opened)" : "", + (bdev_is_partition(bdev) && + bdev_whole(bdev)->bd_writers > 0) ? "(part0 has been write opend)" : ""); + blkdev_dump_conflict_opener(bdev, msg); + } }
static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode)
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/3762 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/M...
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/3762 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/M...