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 | 48 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 8 deletions(-)
diff --git a/block/Kconfig b/block/Kconfig index 45044f1d2942..11fad1ab8fd6 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, 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 bc3ed0014f55..050a5cc5d4c2 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -30,15 +30,20 @@ #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" #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 +/* Should we dump info when opening mounted block devices for write? */ +#define BLKDEV_WRITE_MOUNTED_DUMP 2
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,11 +745,34 @@ 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; + + if (!bdev_write_mounted_opt(WRITE_MOUNTED_DUMP)) + return; + 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->bd_mounted) return true; - if (bdev_opt(DETECT_WRITING_PART0)) + if (bdev_write_mounted_opt(DETECT_WRITING_PART0)) return bdev_is_partition(bdev) ? bdev_whole(bdev)->bd_mounted : bdev->bd_disk->mount_partitions;
@@ -769,7 +797,7 @@ static bool bdev_mount_blocked(struct block_device *bdev) { if (bdev->bd_writers) return true; - if (bdev_opt(DETECT_WRITING_PART0)) + if (bdev_write_mounted_opt(DETECT_WRITING_PART0)) return bdev_is_partition(bdev) ? bdev_whole(bdev)->bd_writers : bdev->bd_disk->write_open_partitions;
@@ -792,14 +820,18 @@ static void bdev_unblock_mount(struct block_device *bdev)
static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) { - if (bdev_write_mounted_opt(ALLOW_WRITE_MOUNTED)) + if (bdev_write_mounted_opt(ALLOW_WRITE_MOUNTED) && + !bdev_write_mounted_opt(WRITE_MOUNTED_DUMP)) return true; /* Writes blocked? */ if (mode & BLK_OPEN_WRITE && bdev_writes_blocked(bdev)) - return false; - if (mode & BLK_OPEN_RESTRICT_WRITES && bdev_mount_blocked(bdev)) - return false; - return true; + blkdev_dump_conflict_opener(bdev, OPEN_EXCLUSIVE); + else if (mode & BLK_OPEN_RESTRICT_WRITES && bdev_mount_blocked(bdev)) + blkdev_dump_conflict_opener(bdev, OPEN_FOR_EXCLUSIVE); + else + return true; + + return bdev_write_mounted_opt(ALLOW_WRITE_MOUNTED); }
static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode)