linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/6] bdi: fix use-after-free for bdi device
@ 2020-03-25 12:38 Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 1/6] bdi: use bdi_dev_name() to get device name Yufen Yu
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Yufen Yu @ 2020-03-25 12:38 UTC (permalink / raw)
  To: axboe, linux-block; +Cc: tj, jack, bvanassche, tytso, gregkh, hch

Hi, all 

We have reported a use-after-free crash for bdi device in __blkg_prfill_rwstat().
The bug is caused by printing device kobj->name while the device and kobj->name
has been freed by bdi_unregister().

In fact, commit 68f23b8906 "memcg: fix a crash in wb_workfn when a device disappears"
has tried to address the issue, but the code is till somewhat racy after that commit.

In this patchset, we try to protect bdi->dev with spinlock and copy device name
into caller buffer, avoiding use-after-free. 

V4:
  * Fix coding error in bdi_get_dev_name()
  * Write one patch for each broken caller

V3:
  https://www.spinics.net/lists/linux-block/msg51111.html 
  Use spinlock to protect bdi->dev and copy device name into caller buffer

V2:
  https://www.spinics.net/lists/linux-fsdevel/msg163206.html
  Try to protect device lifetime with RCU.

V1:
  https://www.spinics.net/lists/linux-block/msg49693.html
  Add a new spinlock and copy kobj->name into caller buffer.
  Or using synchronize_rcu() to wait until reader complete.

Yufen Yu (6):
  bdi: use bdi_dev_name() to get device name
  bdi: protect bdi->dev with spinlock
  bfq: fix potential kernel crash when print error info
  memcg: fix crash in wb_workfn when bdi unregister
  blk-wbt: replace bdi_dev_name() with bdi_get_dev_name()
  blkcg: fix use-after-free for bdi->dev

 block/bfq-iosched.c              |  6 +++--
 block/blk-cgroup-rwstat.c        |  6 +++--
 block/blk-cgroup.c               | 19 +++++-----------
 block/blk-iocost.c               | 14 +++++++-----
 block/blk-iolatency.c            |  5 +++--
 block/blk-throttle.c             |  6 +++--
 fs/ceph/debugfs.c                |  2 +-
 fs/fs-writeback.c                |  4 +++-
 include/linux/backing-dev-defs.h |  1 +
 include/linux/backing-dev.h      | 26 ++++++++++++++++++++++
 include/linux/blk-cgroup.h       |  1 -
 include/trace/events/wbt.h       |  8 +++----
 include/trace/events/writeback.h | 38 ++++++++++++++------------------
 mm/backing-dev.c                 |  9 ++++++--
 14 files changed, 88 insertions(+), 57 deletions(-)

-- 
2.17.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v4 1/6] bdi: use bdi_dev_name() to get device name
  2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
@ 2020-03-25 12:38 ` Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 2/6] bdi: protect bdi->dev with spinlock Yufen Yu
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Yufen Yu @ 2020-03-25 12:38 UTC (permalink / raw)
  To: axboe, linux-block; +Cc: tj, jack, bvanassche, tytso, gregkh, hch

Use the common interface bdi_dev_name() to get device name.

Signed-off-by: Yufen Yu <yuyufen@huawei.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 block/bfq-iosched.c        | 5 +++--
 block/blk-cgroup.c         | 2 +-
 fs/ceph/debugfs.c          | 2 +-
 include/trace/events/wbt.h | 8 ++++----
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 8c436abfaf14..94261b7d7181 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -4978,8 +4978,9 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic)
 	ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
 	switch (ioprio_class) {
 	default:
-		dev_err(bfqq->bfqd->queue->backing_dev_info->dev,
-			"bfq: bad prio class %d\n", ioprio_class);
+		pr_err("bdi %s: bfq: bad prio class %d\n",
+				bdi_dev_name(bfqq->bfqd->queue->backing_dev_info),
+				ioprio_class);
 		/* fall through */
 	case IOPRIO_CLASS_NONE:
 		/*
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index a229b94d5390..be92405c6547 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -496,7 +496,7 @@ const char *blkg_dev_name(struct blkcg_gq *blkg)
 {
 	/* some drivers (floppy) instantiate a queue w/o disk registered */
 	if (blkg->q->backing_dev_info->dev)
-		return dev_name(blkg->q->backing_dev_info->dev);
+		return bdi_dev_name(blkg->q->backing_dev_info);
 	return NULL;
 }
 
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index fb7cabd98e7b..1f8f3b631adb 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -271,7 +271,7 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 				    &congestion_kb_fops);
 
 	snprintf(name, sizeof(name), "../../bdi/%s",
-		 dev_name(fsc->sb->s_bdi->dev));
+		 bdi_dev_name(fsc->sb->s_bdi));
 	fsc->debugfs_bdi =
 		debugfs_create_symlink("bdi",
 				       fsc->client->debugfs_dir,
diff --git a/include/trace/events/wbt.h b/include/trace/events/wbt.h
index 37342a13c9cb..9996420d7ec4 100644
--- a/include/trace/events/wbt.h
+++ b/include/trace/events/wbt.h
@@ -33,7 +33,7 @@ TRACE_EVENT(wbt_stat,
 	),
 
 	TP_fast_assign(
-		strlcpy(__entry->name, dev_name(bdi->dev),
+		strlcpy(__entry->name, bdi_dev_name(bdi),
 			ARRAY_SIZE(__entry->name));
 		__entry->rmean		= stat[0].mean;
 		__entry->rmin		= stat[0].min;
@@ -68,7 +68,7 @@ TRACE_EVENT(wbt_lat,
 	),
 
 	TP_fast_assign(
-		strlcpy(__entry->name, dev_name(bdi->dev),
+		strlcpy(__entry->name, bdi_dev_name(bdi),
 			ARRAY_SIZE(__entry->name));
 		__entry->lat = div_u64(lat, 1000);
 	),
@@ -105,7 +105,7 @@ TRACE_EVENT(wbt_step,
 	),
 
 	TP_fast_assign(
-		strlcpy(__entry->name, dev_name(bdi->dev),
+		strlcpy(__entry->name, bdi_dev_name(bdi),
 			ARRAY_SIZE(__entry->name));
 		__entry->msg	= msg;
 		__entry->step	= step;
@@ -141,7 +141,7 @@ TRACE_EVENT(wbt_timer,
 	),
 
 	TP_fast_assign(
-		strlcpy(__entry->name, dev_name(bdi->dev),
+		strlcpy(__entry->name, bdi_dev_name(bdi),
 			ARRAY_SIZE(__entry->name));
 		__entry->status		= status;
 		__entry->step		= step;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 2/6] bdi: protect bdi->dev with spinlock
  2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 1/6] bdi: use bdi_dev_name() to get device name Yufen Yu
@ 2020-03-25 12:38 ` Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 3/6] bfq: fix potential kernel crash when print error info Yufen Yu
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Yufen Yu @ 2020-03-25 12:38 UTC (permalink / raw)
  To: axboe, linux-block; +Cc: tj, jack, bvanassche, tytso, gregkh, hch

We have reported a kernel crash in __blkg_prfill_rwstat() for
use-after-free the bdi->dev. It tries to get the device name by
'bdi->dev', while the device and kobj->name has been freed by
bdi_unregister().

In fact, similar bug have been reported in wb_workfn when
bdi_unregister(). To fix it, commit 68f23b89067f ("memcg: fix a
crash in wb_workfn when a device disappears") has created bdi_dev_name()
to handle bdi->dev beening NULL. But, bdi->dev can be freed after
bdi_dev_name() return successly, which can cause use-after-free for
dev or kobj->name.

In this patch, we try to protect the 'bdi->dev' with spinlock to
avoid the race. A new helper function bdi_get_dev_name() is defined.
Then, the caller can get device name with this helper safely.

This patch is prepare for following patch to fix use-after-free bug.

Signed-off-by: Yufen Yu <yuyufen@huawei.com>
---
 include/linux/backing-dev-defs.h |  1 +
 include/linux/backing-dev.h      | 28 ++++++++++++++++++++++++++++
 mm/backing-dev.c                 |  9 +++++++--
 3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index 4fc87dee005a..c98dac4a7953 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -227,6 +227,7 @@ struct backing_dev_info {
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debug_dir;
 #endif
+	spinlock_t lock;		/* protects dev */
 };
 
 enum {
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index f88197c1ffc2..010d80956442 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -19,6 +19,8 @@
 #include <linux/backing-dev-defs.h>
 #include <linux/slab.h>
 
+#define BDI_DEV_NAME_LEN	32
+
 static inline struct backing_dev_info *bdi_get(struct backing_dev_info *bdi)
 {
 	kref_get(&bdi->refcnt);
@@ -514,4 +516,30 @@ static inline const char *bdi_dev_name(struct backing_dev_info *bdi)
 	return dev_name(bdi->dev);
 }
 
+/**
+ * bdi_get_dev_name - copy bdi device name into buffer
+ * @bdi: target bdi
+ * @dname: Where to copy the device name to
+ * @len: size of destination buffer
+ */
+static inline char *bdi_get_dev_name(struct backing_dev_info *bdi,
+			char *dname, int len)
+{
+	if (!bdi)
+		goto unknown;
+
+	spin_lock_irq(&bdi->lock);
+	if (!bdi->dev) {
+		spin_unlock_irq(&bdi->lock);
+		goto unknown;
+	}
+
+	strlcpy(dname, dev_name(bdi->dev), len);
+	spin_unlock_irq(&bdi->lock);
+	return dname;
+
+unknown:
+	strlcpy(dname, bdi_unknown_name, len);
+	return NULL;
+}
 #endif	/* _LINUX_BACKING_DEV_H */
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 62f05f605fb5..aa9ba7dcc2d9 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -859,6 +859,7 @@ static int bdi_init(struct backing_dev_info *bdi)
 	INIT_LIST_HEAD(&bdi->bdi_list);
 	INIT_LIST_HEAD(&bdi->wb_list);
 	init_waitqueue_head(&bdi->wb_waitq);
+	spin_lock_init(&bdi->lock);
 
 	ret = cgwb_bdi_init(bdi);
 
@@ -1007,15 +1008,19 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi)
 
 void bdi_unregister(struct backing_dev_info *bdi)
 {
+	struct device *dev = bdi->dev;
+
 	/* make sure nobody finds us on the bdi_list anymore */
 	bdi_remove_from_list(bdi);
 	wb_shutdown(&bdi->wb);
 	cgwb_bdi_unregister(bdi);
 
-	if (bdi->dev) {
+	if (dev) {
 		bdi_debug_unregister(bdi);
-		device_unregister(bdi->dev);
+		spin_lock_irq(&bdi->lock);
 		bdi->dev = NULL;
+		spin_unlock_irq(&bdi->lock);
+		device_unregister(dev);
 	}
 
 	if (bdi->owner) {
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 3/6] bfq: fix potential kernel crash when print error info
  2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 1/6] bdi: use bdi_dev_name() to get device name Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 2/6] bdi: protect bdi->dev with spinlock Yufen Yu
@ 2020-03-25 12:38 ` Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 4/6] memcg: fix crash in wb_workfn when bdi unregister Yufen Yu
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Yufen Yu @ 2020-03-25 12:38 UTC (permalink / raw)
  To: axboe, linux-block; +Cc: tj, jack, bvanassche, tytso, gregkh, hch

Replace bdi_dev_name() with bdi_get_dev_name(). Then, we can fix
potential use-after-free or NULL pointer reference for bdi->dev
when bdi unregister.

Signed-off-by: Yufen Yu <yuyufen@huawei.com>
---
 block/bfq-iosched.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 94261b7d7181..a8a67a95006e 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -4971,6 +4971,7 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic)
 	struct task_struct *tsk = current;
 	int ioprio_class;
 	struct bfq_data *bfqd = bfqq->bfqd;
+	char dname[BDI_DEV_NAME_LEN];
 
 	if (!bfqd)
 		return;
@@ -4978,9 +4979,9 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic)
 	ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
 	switch (ioprio_class) {
 	default:
-		pr_err("bdi %s: bfq: bad prio class %d\n",
-				bdi_dev_name(bfqq->bfqd->queue->backing_dev_info),
-				ioprio_class);
+		bdi_get_dev_name(bfqq->bfqd->queue->backing_dev_info, dname,
+				BDI_DEV_NAME_LEN);
+		pr_err("bdi %s: bfq: bad prio class %d\n", dname, ioprio_class);
 		/* fall through */
 	case IOPRIO_CLASS_NONE:
 		/*
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 4/6] memcg: fix crash in wb_workfn when bdi unregister
  2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
                   ` (2 preceding siblings ...)
  2020-03-25 12:38 ` [PATCH v4 3/6] bfq: fix potential kernel crash when print error info Yufen Yu
@ 2020-03-25 12:38 ` Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 5/6] blk-wbt: replace bdi_dev_name() with bdi_get_dev_name() Yufen Yu
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Yufen Yu @ 2020-03-25 12:38 UTC (permalink / raw)
  To: axboe, linux-block; +Cc: tj, jack, bvanassche, tytso, gregkh, hch

Commit 68f23b89067f ("memcg: fix a crash in wb_workfn when a device
disappears") try to handle bdi->dev beening NULL by adding bdi_dev_name().
But, bdi->dev can be freed and set as 'NULL' after bdi_dev_name()
think the value is valid. Then it can cause use-after-free for dev
or kobj->name.

After protecting the bdi->dev with lock, the race can be fixed thoroughly.
Here, we just need to replace bdi_dev_name() with bdi_get_dev_name().

Fixes: 68f23b89067f ("memcg: fix a crash in wb_workfn when a device disappears")
Signed-off-by: Yufen Yu <yuyufen@huawei.com>
---
 fs/fs-writeback.c                |  4 +++-
 include/trace/events/writeback.h | 38 ++++++++++++++------------------
 2 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 76ac9c7d32ec..8d36c256560c 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -2062,8 +2062,10 @@ void wb_workfn(struct work_struct *work)
 	struct bdi_writeback *wb = container_of(to_delayed_work(work),
 						struct bdi_writeback, dwork);
 	long pages_written;
+	char dname[BDI_DEV_NAME_LEN];
 
-	set_worker_desc("flush-%s", bdi_dev_name(wb->bdi));
+	set_worker_desc("flush-%s",
+			bdi_get_dev_name(wb->bdi, dname, BDI_DEV_NAME_LEN));
 	current->flags |= PF_SWAPWRITE;
 
 	if (likely(!current_is_workqueue_rescuer() ||
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index d94def25e4dc..4767a5ab5e36 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -66,9 +66,8 @@ DECLARE_EVENT_CLASS(writeback_page_template,
 	),
 
 	TP_fast_assign(
-		strscpy_pad(__entry->name,
-			    bdi_dev_name(mapping ? inode_to_bdi(mapping->host) :
-					 NULL), 32);
+		bdi_get_dev_name(mapping ? inode_to_bdi(mapping->host) : NULL,
+				__entry->name, 32);
 		__entry->ino = mapping ? mapping->host->i_ino : 0;
 		__entry->index = page->index;
 	),
@@ -111,7 +110,7 @@ DECLARE_EVENT_CLASS(writeback_dirty_inode_template,
 		struct backing_dev_info *bdi = inode_to_bdi(inode);
 
 		/* may be called for files on pseudo FSes w/ unregistered bdi */
-		strscpy_pad(__entry->name, bdi_dev_name(bdi), 32);
+		bdi_get_dev_name(bdi, __entry->name, 32);
 		__entry->ino		= inode->i_ino;
 		__entry->state		= inode->i_state;
 		__entry->flags		= flags;
@@ -192,7 +191,7 @@ TRACE_EVENT(inode_foreign_history,
 	),
 
 	TP_fast_assign(
-		strncpy(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32);
+		bdi_get_dev_name(inode_to_bdi(inode), __entry->name, 32);
 		__entry->ino		= inode->i_ino;
 		__entry->cgroup_ino	= __trace_wbc_assign_cgroup(wbc);
 		__entry->history	= history;
@@ -221,7 +220,7 @@ TRACE_EVENT(inode_switch_wbs,
 	),
 
 	TP_fast_assign(
-		strncpy(__entry->name,	bdi_dev_name(old_wb->bdi), 32);
+		bdi_get_dev_name(old_wb->bdi, __entry->name, 32);
 		__entry->ino		= inode->i_ino;
 		__entry->old_cgroup_ino	= __trace_wb_assign_cgroup(old_wb);
 		__entry->new_cgroup_ino	= __trace_wb_assign_cgroup(new_wb);
@@ -254,7 +253,7 @@ TRACE_EVENT(track_foreign_dirty,
 		struct address_space *mapping = page_mapping(page);
 		struct inode *inode = mapping ? mapping->host : NULL;
 
-		strncpy(__entry->name,	bdi_dev_name(wb->bdi), 32);
+		bdi_get_dev_name(wb->bdi, __entry->name, 32);
 		__entry->bdi_id		= wb->bdi->id;
 		__entry->ino		= inode ? inode->i_ino : 0;
 		__entry->memcg_id	= wb->memcg_css->id;
@@ -287,7 +286,7 @@ TRACE_EVENT(flush_foreign,
 	),
 
 	TP_fast_assign(
-		strncpy(__entry->name,	bdi_dev_name(wb->bdi), 32);
+		bdi_get_dev_name(wb->bdi, __entry->name, 32);
 		__entry->cgroup_ino	= __trace_wb_assign_cgroup(wb);
 		__entry->frn_bdi_id	= frn_bdi_id;
 		__entry->frn_memcg_id	= frn_memcg_id;
@@ -316,8 +315,7 @@ DECLARE_EVENT_CLASS(writeback_write_inode_template,
 	),
 
 	TP_fast_assign(
-		strscpy_pad(__entry->name,
-			    bdi_dev_name(inode_to_bdi(inode)), 32);
+		bdi_get_dev_name(inode_to_bdi(inode), __entry->name, 32);
 		__entry->ino		= inode->i_ino;
 		__entry->sync_mode	= wbc->sync_mode;
 		__entry->cgroup_ino	= __trace_wbc_assign_cgroup(wbc);
@@ -360,7 +358,7 @@ DECLARE_EVENT_CLASS(writeback_work_class,
 		__field(ino_t, cgroup_ino)
 	),
 	TP_fast_assign(
-		strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32);
+		bdi_get_dev_name(wb->bdi, __entry->name, 32);
 		__entry->nr_pages = work->nr_pages;
 		__entry->sb_dev = work->sb ? work->sb->s_dev : 0;
 		__entry->sync_mode = work->sync_mode;
@@ -413,7 +411,7 @@ DECLARE_EVENT_CLASS(writeback_class,
 		__field(ino_t, cgroup_ino)
 	),
 	TP_fast_assign(
-		strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32);
+		bdi_get_dev_name(wb->bdi, __entry->name, 32);
 		__entry->cgroup_ino = __trace_wb_assign_cgroup(wb);
 	),
 	TP_printk("bdi %s: cgroup_ino=%lu",
@@ -435,7 +433,7 @@ TRACE_EVENT(writeback_bdi_register,
 		__array(char, name, 32)
 	),
 	TP_fast_assign(
-		strscpy_pad(__entry->name, bdi_dev_name(bdi), 32);
+		bdi_get_dev_name(bdi, __entry->name, 32);
 	),
 	TP_printk("bdi %s",
 		__entry->name
@@ -460,7 +458,7 @@ DECLARE_EVENT_CLASS(wbc_class,
 	),
 
 	TP_fast_assign(
-		strscpy_pad(__entry->name, bdi_dev_name(bdi), 32);
+		bdi_get_dev_name(bdi, __entry->name, 32);
 		__entry->nr_to_write	= wbc->nr_to_write;
 		__entry->pages_skipped	= wbc->pages_skipped;
 		__entry->sync_mode	= wbc->sync_mode;
@@ -511,7 +509,7 @@ TRACE_EVENT(writeback_queue_io,
 	),
 	TP_fast_assign(
 		unsigned long *older_than_this = work->older_than_this;
-		strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32);
+		bdi_get_dev_name(wb->bdi, __entry->name, 32);
 		__entry->older	= older_than_this ?  *older_than_this : 0;
 		__entry->age	= older_than_this ?
 				  (jiffies - *older_than_this) * 1000 / HZ : -1;
@@ -597,7 +595,7 @@ TRACE_EVENT(bdi_dirty_ratelimit,
 	),
 
 	TP_fast_assign(
-		strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32);
+		bdi_get_dev_name(wb->bdi, __entry->bdi, 32);
 		__entry->write_bw	= KBps(wb->write_bandwidth);
 		__entry->avg_write_bw	= KBps(wb->avg_write_bandwidth);
 		__entry->dirty_rate	= KBps(dirty_rate);
@@ -662,7 +660,7 @@ TRACE_EVENT(balance_dirty_pages,
 
 	TP_fast_assign(
 		unsigned long freerun = (thresh + bg_thresh) / 2;
-		strscpy_pad(__entry->bdi, bdi_dev_name(wb->bdi), 32);
+		bdi_get_dev_name(wb->bdi, __entry->bdi, 32);
 
 		__entry->limit		= global_wb_domain.dirty_limit;
 		__entry->setpoint	= (global_wb_domain.dirty_limit +
@@ -722,8 +720,7 @@ TRACE_EVENT(writeback_sb_inodes_requeue,
 	),
 
 	TP_fast_assign(
-		strscpy_pad(__entry->name,
-			    bdi_dev_name(inode_to_bdi(inode)), 32);
+		bdi_get_dev_name(inode_to_bdi(inode), __entry->name, 32);
 		__entry->ino		= inode->i_ino;
 		__entry->state		= inode->i_state;
 		__entry->dirtied_when	= inode->dirtied_when;
@@ -796,8 +793,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template,
 	),
 
 	TP_fast_assign(
-		strscpy_pad(__entry->name,
-			    bdi_dev_name(inode_to_bdi(inode)), 32);
+		bdi_get_dev_name(inode_to_bdi(inode), __entry->name, 32);
 		__entry->ino		= inode->i_ino;
 		__entry->state		= inode->i_state;
 		__entry->dirtied_when	= inode->dirtied_when;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 5/6] blk-wbt: replace bdi_dev_name() with bdi_get_dev_name()
  2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
                   ` (3 preceding siblings ...)
  2020-03-25 12:38 ` [PATCH v4 4/6] memcg: fix crash in wb_workfn when bdi unregister Yufen Yu
@ 2020-03-25 12:38 ` Yufen Yu
  2020-03-25 12:38 ` [PATCH v4 6/6] blkcg: fix use-after-free for bdi->dev Yufen Yu
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Yufen Yu @ 2020-03-25 12:38 UTC (permalink / raw)
  To: axboe, linux-block; +Cc: tj, jack, bvanassche, tytso, gregkh, hch

wb_timer_fn() can be called after bdi unregister. So, we get bdi
device name by bdi_get_dev_name() to avoid use-after-free or null
pointer deference for bdi->dev.

Signed-off-by: Yufen Yu <yuyufen@huawei.com>
---
 include/trace/events/wbt.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/trace/events/wbt.h b/include/trace/events/wbt.h
index 9996420d7ec4..3fbf15565962 100644
--- a/include/trace/events/wbt.h
+++ b/include/trace/events/wbt.h
@@ -33,7 +33,7 @@ TRACE_EVENT(wbt_stat,
 	),
 
 	TP_fast_assign(
-		strlcpy(__entry->name, bdi_dev_name(bdi),
+		bdi_get_dev_name(bdi, __entry->name,
 			ARRAY_SIZE(__entry->name));
 		__entry->rmean		= stat[0].mean;
 		__entry->rmin		= stat[0].min;
@@ -68,7 +68,7 @@ TRACE_EVENT(wbt_lat,
 	),
 
 	TP_fast_assign(
-		strlcpy(__entry->name, bdi_dev_name(bdi),
+		bdi_get_dev_name(bdi, __entry->name,
 			ARRAY_SIZE(__entry->name));
 		__entry->lat = div_u64(lat, 1000);
 	),
@@ -105,7 +105,7 @@ TRACE_EVENT(wbt_step,
 	),
 
 	TP_fast_assign(
-		strlcpy(__entry->name, bdi_dev_name(bdi),
+		bdi_get_dev_name(bdi, __entry->name,
 			ARRAY_SIZE(__entry->name));
 		__entry->msg	= msg;
 		__entry->step	= step;
@@ -141,7 +141,7 @@ TRACE_EVENT(wbt_timer,
 	),
 
 	TP_fast_assign(
-		strlcpy(__entry->name, bdi_dev_name(bdi),
+		bdi_get_dev_name(bdi, __entry->name,
 			ARRAY_SIZE(__entry->name));
 		__entry->status		= status;
 		__entry->step		= step;
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 6/6] blkcg: fix use-after-free for bdi->dev
  2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
                   ` (4 preceding siblings ...)
  2020-03-25 12:38 ` [PATCH v4 5/6] blk-wbt: replace bdi_dev_name() with bdi_get_dev_name() Yufen Yu
@ 2020-03-25 12:38 ` Yufen Yu
  2020-04-09 13:28 ` [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
  2020-04-14 15:52 ` Christoph Hellwig
  7 siblings, 0 replies; 12+ messages in thread
From: Yufen Yu @ 2020-03-25 12:38 UTC (permalink / raw)
  To: axboe, linux-block; +Cc: tj, jack, bvanassche, tytso, gregkh, hch

__blkg_prfill_rwstat() tries to get the device name by 'bdi->dev',
while the device and kobj->name has been freed by bdi_unregister().
Then, blkg_dev_name() will return an invalid name pointer, resulting
in crash on string(). The race as following:

CPU1                          CPU2
blkg_print_stat_bytes
                              __scsi_remove_device
                              del_gendisk
                                bdi_unregister

                                put_device(bdi->dev)
                                  kfree(bdi->dev)
__blkg_prfill_rwstat
  blkg_dev_name
    //use the freed bdi->dev
    dev_name(blkg->q->backing_dev_info->dev)
                                bdi->dev = NULL

After protecing "bdi->dev" with lock, we just need to use
bdi_get_dev_name() to get device name. Then, the race can be fixed.

Signed-off-by: Yufen Yu <yuyufen@huawei.com>
---
 block/blk-cgroup-rwstat.c  |  6 ++++--
 block/blk-cgroup.c         | 19 ++++++-------------
 block/blk-iocost.c         | 14 ++++++++------
 block/blk-iolatency.c      |  5 +++--
 block/blk-throttle.c       |  6 ++++--
 include/linux/blk-cgroup.h |  1 -
 6 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/block/blk-cgroup-rwstat.c b/block/blk-cgroup-rwstat.c
index 85d5790ac49b..2dc260802228 100644
--- a/block/blk-cgroup-rwstat.c
+++ b/block/blk-cgroup-rwstat.c
@@ -4,6 +4,7 @@
  * Do not use in new code.
  */
 #include "blk-cgroup-rwstat.h"
+#include <linux/backing-dev.h>
 
 int blkg_rwstat_init(struct blkg_rwstat *rwstat, gfp_t gfp)
 {
@@ -49,11 +50,12 @@ u64 __blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,
 		[BLKG_RWSTAT_ASYNC]	= "Async",
 		[BLKG_RWSTAT_DISCARD]	= "Discard",
 	};
-	const char *dname = blkg_dev_name(pd->blkg);
+	char dname[BDI_DEV_NAME_LEN];
 	u64 v;
 	int i;
 
-	if (!dname)
+	if (!bdi_get_dev_name(pd->blkg->q->backing_dev_info, dname,
+				BDI_DEV_NAME_LEN))
 		return 0;
 
 	for (i = 0; i < BLKG_RWSTAT_NR; i++)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index be92405c6547..a072ca6141ca 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -492,14 +492,6 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css,
 	return 0;
 }
 
-const char *blkg_dev_name(struct blkcg_gq *blkg)
-{
-	/* some drivers (floppy) instantiate a queue w/o disk registered */
-	if (blkg->q->backing_dev_info->dev)
-		return bdi_dev_name(blkg->q->backing_dev_info);
-	return NULL;
-}
-
 /**
  * blkcg_print_blkgs - helper for printing per-blkg data
  * @sf: seq_file to print to
@@ -551,9 +543,10 @@ EXPORT_SYMBOL_GPL(blkcg_print_blkgs);
  */
 u64 __blkg_prfill_u64(struct seq_file *sf, struct blkg_policy_data *pd, u64 v)
 {
-	const char *dname = blkg_dev_name(pd->blkg);
+	char dname[BDI_DEV_NAME_LEN];
 
-	if (!dname)
+	if (!bdi_get_dev_name(pd->blkg->q->backing_dev_info, dname,
+				BDI_DEV_NAME_LEN))
 		return 0;
 
 	seq_printf(sf, "%s %llu\n", dname, (unsigned long long)v);
@@ -749,7 +742,7 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
 
 	hlist_for_each_entry_rcu(blkg, &blkcg->blkg_list, blkcg_node) {
 		struct blkg_iostat_set *bis = &blkg->iostat;
-		const char *dname;
+		char dname[BDI_DEV_NAME_LEN];
 		char *buf;
 		u64 rbytes, wbytes, rios, wios, dbytes, dios;
 		size_t size = seq_get_buf(sf, &buf), off = 0;
@@ -762,8 +755,8 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
 		if (!blkg->online)
 			goto skip;
 
-		dname = blkg_dev_name(blkg);
-		if (!dname)
+		if (!bdi_get_dev_name(blkg->q->backing_dev_info, dname,
+					BDI_DEV_NAME_LEN))
 			goto skip;
 
 		/*
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 9a599cc28c29..2ae69d475d60 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -2047,10 +2047,11 @@ static void ioc_pd_free(struct blkg_policy_data *pd)
 static u64 ioc_weight_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
 			     int off)
 {
-	const char *dname = blkg_dev_name(pd->blkg);
+	char dname[BDI_DEV_NAME_LEN];
 	struct ioc_gq *iocg = pd_to_iocg(pd);
 
-	if (dname && iocg->cfg_weight)
+	if (bdi_get_dev_name(pd->blkg, dname, BDI_DEV_NAME_LEN) &&
+			iocg->cfg_weight)
 		seq_printf(sf, "%s %u\n", dname, iocg->cfg_weight);
 	return 0;
 }
@@ -2133,10 +2134,11 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
 static u64 ioc_qos_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
 			  int off)
 {
-	const char *dname = blkg_dev_name(pd->blkg);
+	char dname[BDI_DEV_NAME_LEN];
 	struct ioc *ioc = pd_to_iocg(pd)->ioc;
 
-	if (!dname)
+	if (!bdi_get_dev_name(pd->blkg->q->backing_dev_info, dname,
+				BDI_DEV_NAME_LEN))
 		return 0;
 
 	seq_printf(sf, "%s enable=%d ctrl=%s rpct=%u.%02u rlat=%u wpct=%u.%02u wlat=%u min=%u.%02u max=%u.%02u\n",
@@ -2304,11 +2306,11 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 static u64 ioc_cost_model_prfill(struct seq_file *sf,
 				 struct blkg_policy_data *pd, int off)
 {
-	const char *dname = blkg_dev_name(pd->blkg);
+	char dname[BDI_DEV_NAME_LEN];
 	struct ioc *ioc = pd_to_iocg(pd)->ioc;
 	u64 *u = ioc->params.i_lcoefs;
 
-	if (!dname)
+	if (!bdi_get_dev_name(pd->blkg, dname, BDI_DEV_NAME_LEN))
 		return 0;
 
 	seq_printf(sf, "%s ctrl=%s model=linear "
diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c
index c128d50cb410..2ab49167aea1 100644
--- a/block/blk-iolatency.c
+++ b/block/blk-iolatency.c
@@ -868,9 +868,10 @@ static u64 iolatency_prfill_limit(struct seq_file *sf,
 				  struct blkg_policy_data *pd, int off)
 {
 	struct iolatency_grp *iolat = pd_to_lat(pd);
-	const char *dname = blkg_dev_name(pd->blkg);
+	char dname[BDI_DEV_NAME_LEN];
 
-	if (!dname || !iolat->min_lat_nsec)
+	if (!bdi_get_dev_name(pd->blkg, dname, BDI_DEV_NAME_LEN)
+			|| !iolat->min_lat_nsec)
 		return 0;
 	seq_printf(sf, "%s target=%llu\n",
 		   dname, div_u64(iolat->min_lat_nsec, NSEC_PER_USEC));
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 98233c9c65a8..f77dc93d4e83 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -13,6 +13,7 @@
 #include <linux/blk-cgroup.h>
 #include "blk.h"
 #include "blk-cgroup-rwstat.h"
+#include <linux/backing-dev.h>
 
 /* Max dispatch from a group in 1 round */
 static int throtl_grp_quantum = 8;
@@ -1560,14 +1561,15 @@ static u64 tg_prfill_limit(struct seq_file *sf, struct blkg_policy_data *pd,
 			 int off)
 {
 	struct throtl_grp *tg = pd_to_tg(pd);
-	const char *dname = blkg_dev_name(pd->blkg);
+	char dname[BDI_DEV_NAME_LEN];
 	char bufs[4][21] = { "max", "max", "max", "max" };
 	u64 bps_dft;
 	unsigned int iops_dft;
 	char idle_time[26] = "";
 	char latency_time[26] = "";
 
-	if (!dname)
+	if (!bdi_get_dev_name(pd->blkg->q->backing_dev_info, dname,
+				BDI_DEV_NAME_LEN))
 		return 0;
 
 	if (off == LIMIT_LOW) {
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index e4a6949fd171..384b3343d5f4 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -198,7 +198,6 @@ int blkcg_activate_policy(struct request_queue *q,
 void blkcg_deactivate_policy(struct request_queue *q,
 			     const struct blkcg_policy *pol);
 
-const char *blkg_dev_name(struct blkcg_gq *blkg);
 void blkcg_print_blkgs(struct seq_file *sf, struct blkcg *blkcg,
 		       u64 (*prfill)(struct seq_file *,
 				     struct blkg_policy_data *, int),
-- 
2.17.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 0/6] bdi: fix use-after-free for bdi device
  2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
                   ` (5 preceding siblings ...)
  2020-03-25 12:38 ` [PATCH v4 6/6] blkcg: fix use-after-free for bdi->dev Yufen Yu
@ 2020-04-09 13:28 ` Yufen Yu
  2020-04-14 14:44   ` Theodore Y. Ts'o
  2020-04-14 15:52 ` Christoph Hellwig
  7 siblings, 1 reply; 12+ messages in thread
From: Yufen Yu @ 2020-04-09 13:28 UTC (permalink / raw)
  To: axboe, linux-block; +Cc: tj, jack, bvanassche, tytso, gregkh, hch

ping

On 2020/3/25 20:38, Yufen Yu wrote:
> Hi, all
> 
> We have reported a use-after-free crash for bdi device in __blkg_prfill_rwstat().
> The bug is caused by printing device kobj->name while the device and kobj->name
> has been freed by bdi_unregister().
> 
> In fact, commit 68f23b8906 "memcg: fix a crash in wb_workfn when a device disappears"
> has tried to address the issue, but the code is till somewhat racy after that commit.
> 
> In this patchset, we try to protect bdi->dev with spinlock and copy device name
> into caller buffer, avoiding use-after-free.
> 
> V4:
>    * Fix coding error in bdi_get_dev_name()
>    * Write one patch for each broken caller
> 
> V3:
>    https://www.spinics.net/lists/linux-block/msg51111.html
>    Use spinlock to protect bdi->dev and copy device name into caller buffer
> 
> V2:
>    https://www.spinics.net/lists/linux-fsdevel/msg163206.html
>    Try to protect device lifetime with RCU.
> 
> V1:
>    https://www.spinics.net/lists/linux-block/msg49693.html
>    Add a new spinlock and copy kobj->name into caller buffer.
>    Or using synchronize_rcu() to wait until reader complete.
> 
> Yufen Yu (6):
>    bdi: use bdi_dev_name() to get device name
>    bdi: protect bdi->dev with spinlock
>    bfq: fix potential kernel crash when print error info
>    memcg: fix crash in wb_workfn when bdi unregister
>    blk-wbt: replace bdi_dev_name() with bdi_get_dev_name()
>    blkcg: fix use-after-free for bdi->dev
> 
>   block/bfq-iosched.c              |  6 +++--
>   block/blk-cgroup-rwstat.c        |  6 +++--
>   block/blk-cgroup.c               | 19 +++++-----------
>   block/blk-iocost.c               | 14 +++++++-----
>   block/blk-iolatency.c            |  5 +++--
>   block/blk-throttle.c             |  6 +++--
>   fs/ceph/debugfs.c                |  2 +-
>   fs/fs-writeback.c                |  4 +++-
>   include/linux/backing-dev-defs.h |  1 +
>   include/linux/backing-dev.h      | 26 ++++++++++++++++++++++
>   include/linux/blk-cgroup.h       |  1 -
>   include/trace/events/wbt.h       |  8 +++----
>   include/trace/events/writeback.h | 38 ++++++++++++++------------------
>   mm/backing-dev.c                 |  9 ++++++--
>   14 files changed, 88 insertions(+), 57 deletions(-)
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 0/6] bdi: fix use-after-free for bdi device
  2020-04-09 13:28 ` [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
@ 2020-04-14 14:44   ` Theodore Y. Ts'o
  0 siblings, 0 replies; 12+ messages in thread
From: Theodore Y. Ts'o @ 2020-04-14 14:44 UTC (permalink / raw)
  To: Yufen Yu; +Cc: axboe, linux-block, tj, jack, bvanassche, gregkh, hch

On Thu, Apr 09, 2020 at 09:28:07PM +0800, Yufen Yu wrote:
> ping

ping**2

Can this go in as a bugfix during this cycle?

    	       	    	   	  - Ted

> 
> On 2020/3/25 20:38, Yufen Yu wrote:
> > Hi, all
> > 
> > We have reported a use-after-free crash for bdi device in __blkg_prfill_rwstat().
> > The bug is caused by printing device kobj->name while the device and kobj->name
> > has been freed by bdi_unregister().
> > 
> > In fact, commit 68f23b8906 "memcg: fix a crash in wb_workfn when a device disappears"
> > has tried to address the issue, but the code is till somewhat racy after that commit.
> > 
> > In this patchset, we try to protect bdi->dev with spinlock and copy device name
> > into caller buffer, avoiding use-after-free.
> > 
> > V4:
> >    * Fix coding error in bdi_get_dev_name()
> >    * Write one patch for each broken caller
> > 
> > V3:
> >    https://www.spinics.net/lists/linux-block/msg51111.html
> >    Use spinlock to protect bdi->dev and copy device name into caller buffer
> > 
> > V2:
> >    https://www.spinics.net/lists/linux-fsdevel/msg163206.html
> >    Try to protect device lifetime with RCU.
> > 
> > V1:
> >    https://www.spinics.net/lists/linux-block/msg49693.html
> >    Add a new spinlock and copy kobj->name into caller buffer.
> >    Or using synchronize_rcu() to wait until reader complete.
> > 
> > Yufen Yu (6):
> >    bdi: use bdi_dev_name() to get device name
> >    bdi: protect bdi->dev with spinlock
> >    bfq: fix potential kernel crash when print error info
> >    memcg: fix crash in wb_workfn when bdi unregister
> >    blk-wbt: replace bdi_dev_name() with bdi_get_dev_name()
> >    blkcg: fix use-after-free for bdi->dev
> > 
> >   block/bfq-iosched.c              |  6 +++--
> >   block/blk-cgroup-rwstat.c        |  6 +++--
> >   block/blk-cgroup.c               | 19 +++++-----------
> >   block/blk-iocost.c               | 14 +++++++-----
> >   block/blk-iolatency.c            |  5 +++--
> >   block/blk-throttle.c             |  6 +++--
> >   fs/ceph/debugfs.c                |  2 +-
> >   fs/fs-writeback.c                |  4 +++-
> >   include/linux/backing-dev-defs.h |  1 +
> >   include/linux/backing-dev.h      | 26 ++++++++++++++++++++++
> >   include/linux/blk-cgroup.h       |  1 -
> >   include/trace/events/wbt.h       |  8 +++----
> >   include/trace/events/writeback.h | 38 ++++++++++++++------------------
> >   mm/backing-dev.c                 |  9 ++++++--
> >   14 files changed, 88 insertions(+), 57 deletions(-)
> > 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 0/6] bdi: fix use-after-free for bdi device
  2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
                   ` (6 preceding siblings ...)
  2020-04-09 13:28 ` [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
@ 2020-04-14 15:52 ` Christoph Hellwig
  2020-04-15  9:34   ` Jan Kara
  7 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2020-04-14 15:52 UTC (permalink / raw)
  To: Yufen Yu; +Cc: axboe, linux-block, tj, jack, bvanassche, tytso, gregkh, hch

Looking through this series the whoe approach of using a lock to clear
the ->dev pointer looks rather odd to me.  What is the reason for now
simply adding a separately allocated name field to struct
backing_dev_info that the name is copied to on allocation, and then
the ->dev field is not relevant for name printing and we don't need
to copy out the name in the potentionally more fast path callers that
want to print it?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 0/6] bdi: fix use-after-free for bdi device
  2020-04-14 15:52 ` Christoph Hellwig
@ 2020-04-15  9:34   ` Jan Kara
  2020-04-16  5:36     ` Christoph Hellwig
  0 siblings, 1 reply; 12+ messages in thread
From: Jan Kara @ 2020-04-15  9:34 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Yufen Yu, axboe, linux-block, tj, jack, bvanassche, tytso, gregkh

On Tue 14-04-20 08:52:28, Christoph Hellwig wrote:
> Looking through this series the whoe approach of using a lock to clear
> the ->dev pointer looks rather odd to me.  What is the reason for now
> simply adding a separately allocated name field to struct
> backing_dev_info that the name is copied to on allocation, and then
> the ->dev field is not relevant for name printing and we don't need
> to copy out the name in the potentionally more fast path callers that
> want to print it?

Yeah, that's what I was suggesting as well [1] - especially since we
already have bdi->name with a dubious value (but looking into it now, we
would need a separate dev_name field since bdi->name is visible in sysfs so
we cannot change that). But Yufen explained to me that this could result in
bogus name being reported when bdi gets re-registered. Not sure if that's
serious enough but it could happen...

								Honza

[1] https://lore.kernel.org/linux-block/20200219125505.GP16121@quack2.suse.cz

-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 0/6] bdi: fix use-after-free for bdi device
  2020-04-15  9:34   ` Jan Kara
@ 2020-04-16  5:36     ` Christoph Hellwig
  0 siblings, 0 replies; 12+ messages in thread
From: Christoph Hellwig @ 2020-04-16  5:36 UTC (permalink / raw)
  To: Jan Kara
  Cc: Christoph Hellwig, Yufen Yu, axboe, linux-block, tj, bvanassche,
	tytso, gregkh

On Wed, Apr 15, 2020 at 11:34:59AM +0200, Jan Kara wrote:
> Yeah, that's what I was suggesting as well [1] - especially since we
> already have bdi->name with a dubious value (but looking into it now, we
> would need a separate dev_name field since bdi->name is visible in sysfs so
> we cannot change that).

That is a little anoying, but not the end of the world.

> But Yufen explained to me that this could result in
> bogus name being reported when bdi gets re-registered. Not sure if that's
> serious enough but it could happen...

I don't think that is a problem at all.  If it is a problem we can just
replace the ->dev_name pointer with one that says "(unregistered)" at
unregister time, but to me that seems worse than just keeping the name
around.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-04-16  5:36 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-25 12:38 [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
2020-03-25 12:38 ` [PATCH v4 1/6] bdi: use bdi_dev_name() to get device name Yufen Yu
2020-03-25 12:38 ` [PATCH v4 2/6] bdi: protect bdi->dev with spinlock Yufen Yu
2020-03-25 12:38 ` [PATCH v4 3/6] bfq: fix potential kernel crash when print error info Yufen Yu
2020-03-25 12:38 ` [PATCH v4 4/6] memcg: fix crash in wb_workfn when bdi unregister Yufen Yu
2020-03-25 12:38 ` [PATCH v4 5/6] blk-wbt: replace bdi_dev_name() with bdi_get_dev_name() Yufen Yu
2020-03-25 12:38 ` [PATCH v4 6/6] blkcg: fix use-after-free for bdi->dev Yufen Yu
2020-04-09 13:28 ` [PATCH v4 0/6] bdi: fix use-after-free for bdi device Yufen Yu
2020-04-14 14:44   ` Theodore Y. Ts'o
2020-04-14 15:52 ` Christoph Hellwig
2020-04-15  9:34   ` Jan Kara
2020-04-16  5:36     ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).