From: Ye Bin yebin10@huawei.com
mainline inclusion from mainline-v6.1-rc2 commit 60a9bb9048f9e95029df10a9bc346f6b066c593c category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5Z7DK CVE: NA
--------------------------------
Introduce 'blk_trace_{start,stop}' helper. No functional changed.
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20221019033602.752383-2-yebin@huaweicloud.com Signed-off-by: Jens Axboe axboe@kernel.dk
conflicts: kernel/trace/blktrace.c
Signed-off-by: Ye Bin yebin@huaweicloud.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- kernel/trace/blktrace.c | 74 ++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 38 deletions(-)
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index b1aa8c74442c..9cc04b09c42f 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -334,6 +334,37 @@ static void put_probe_ref(void) mutex_unlock(&blk_probe_mutex); }
+static int blk_trace_start(struct blk_trace *bt) +{ + if (bt->trace_state != Blktrace_setup && + bt->trace_state != Blktrace_stopped) + return -EINVAL; + + blktrace_seq++; + smp_mb(); + bt->trace_state = Blktrace_running; + spin_lock_irq(&running_trace_lock); + list_add(&bt->running_list, &running_trace_list); + spin_unlock_irq(&running_trace_lock); + trace_note_time(bt); + + return 0; +} + +static int blk_trace_stop(struct blk_trace *bt) +{ + if (bt->trace_state != Blktrace_running) + return -EINVAL; + + bt->trace_state = Blktrace_stopped; + spin_lock_irq(&running_trace_lock); + list_del_init(&bt->running_list); + spin_unlock_irq(&running_trace_lock); + relay_flush(bt->rchan); + + return 0; +} + static void blk_trace_cleanup(struct blk_trace *bt) { synchronize_rcu(); @@ -652,7 +683,6 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name,
static int __blk_trace_startstop(struct request_queue *q, int start) { - int ret; struct blk_trace *bt;
bt = rcu_dereference_protected(q->blk_trace, @@ -660,36 +690,10 @@ static int __blk_trace_startstop(struct request_queue *q, int start) if (bt == NULL) return -EINVAL;
- /* - * For starting a trace, we can transition from a setup or stopped - * trace. For stopping a trace, the state must be running - */ - ret = -EINVAL; - if (start) { - if (bt->trace_state == Blktrace_setup || - bt->trace_state == Blktrace_stopped) { - blktrace_seq++; - smp_mb(); - bt->trace_state = Blktrace_running; - spin_lock_irq(&running_trace_lock); - list_add(&bt->running_list, &running_trace_list); - spin_unlock_irq(&running_trace_lock); - - trace_note_time(bt); - ret = 0; - } - } else { - if (bt->trace_state == Blktrace_running) { - bt->trace_state = Blktrace_stopped; - spin_lock_irq(&running_trace_lock); - list_del_init(&bt->running_list); - spin_unlock_irq(&running_trace_lock); - relay_flush(bt->rchan); - ret = 0; - } - } - - return ret; + if (start) + return blk_trace_start(bt); + else + return blk_trace_stop(bt); }
int blk_trace_startstop(struct request_queue *q, int start) @@ -1657,13 +1661,7 @@ static int blk_trace_remove_queue(struct request_queue *q) if (bt == NULL) return -EINVAL;
- if (bt->trace_state == Blktrace_running) { - bt->trace_state = Blktrace_stopped; - spin_lock_irq(&running_trace_lock); - list_del_init(&bt->running_list); - spin_unlock_irq(&running_trace_lock); - relay_flush(bt->rchan); - } + blk_trace_stop(bt);
put_probe_ref(); synchronize_rcu();
From: Ye Bin yebin10@huawei.com
mainline inclusion from mainline-v6.1-rc2 commit dcd1a59c62dc49da75539213611156d6db50ab5d category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5Z7DK CVE: NA
--------------------------------
When test as follows: step1: ioctl(sda, BLKTRACESETUP, &arg) step2: ioctl(sda, BLKTRACESTART, NULL) step3: ioctl(sda, BLKTRACETEARDOWN, NULL) step4: ioctl(sda, BLKTRACESETUP, &arg) Got issue as follows: debugfs: File 'dropped' in directory 'sda' already present! debugfs: File 'msg' in directory 'sda' already present! debugfs: File 'trace0' in directory 'sda' already present!
And also find syzkaller report issue like "KASAN: use-after-free Read in relay_switch_subbuf" "https://syzkaller.appspot.com/bug?id=13849f0d9b1b818b087341691be6cc3ac6a6bfb..."
If remove block trace without stop(BLKTRACESTOP) block trace, '__blk_trace_remove' will just set 'q->blk_trace' with NULL. However, debugfs file isn't removed, so will report file already present when call BLKTRACESETUP. static int __blk_trace_remove(struct request_queue *q) { struct blk_trace *bt;
bt = rcu_replace_pointer(q->blk_trace, NULL, lockdep_is_held(&q->debugfs_mutex)); if (!bt) return -EINVAL;
if (bt->trace_state != Blktrace_running) blk_trace_cleanup(q, bt);
return 0; }
If do test as follows: step1: ioctl(sda, BLKTRACESETUP, &arg) step2: ioctl(sda, BLKTRACESTART, NULL) step3: ioctl(sda, BLKTRACETEARDOWN, NULL) step4: remove sda
There will remove debugfs directory which will remove recursively all file under directory.
blk_release_queue debugfs_remove_recursive(q->debugfs_dir)
So all files which created in 'do_blk_trace_setup' are removed, and 'dentry->d_inode' is NULL. But 'q->blk_trace' is still in 'running_trace_lock', 'trace_note_tsk' will traverse 'running_trace_lock' all nodes.
trace_note_tsk trace_note relay_reserve relay_switch_subbuf d_inode(buf->dentry)->i_size
To solve above issues, reference commit '5afedf670caf', call 'blk_trace_cleanup' unconditionally in '__blk_trace_remove' and first stop block trace in 'blk_trace_cleanup'.
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20221019033602.752383-3-yebin@huaweicloud.com Signed-off-by: Jens Axboe axboe@kernel.dk
conflicts: kernel/trace/blktrace.c
Signed-off-by: Ye Bin yebin@huaweicloud.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- kernel/trace/blktrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 9cc04b09c42f..4992ca523842 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -367,6 +367,7 @@ static int blk_trace_stop(struct blk_trace *bt)
static void blk_trace_cleanup(struct blk_trace *bt) { + blk_trace_stop(bt); synchronize_rcu(); blk_trace_free(bt); put_probe_ref(); @@ -380,8 +381,7 @@ static int __blk_trace_remove(struct request_queue *q) if (!bt) return -EINVAL;
- if (bt->trace_state != Blktrace_running) - blk_trace_cleanup(bt); + blk_trace_cleanup(bt);
return 0; }
From: Ye Bin yebin10@huawei.com
mainline inclusion from mainline-v6.1-rc2 commit 2db96217e7e515071726ca4ec791742c4202a1b2 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5Z7DK CVE: NA
--------------------------------
As previous commit, 'blk_trace_cleanup' will stop block trace if block trace's state is 'Blktrace_running'. So remove unnessary stop block trace in 'blk_trace_shutdown'.
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Christoph Hellwig hch@lst.de Link: https://lore.kernel.org/r/20221019033602.752383-4-yebin@huaweicloud.com Signed-off-by: Jens Axboe axboe@kernel.dk
conflicts: kernel/trace/blktrace.c
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- kernel/trace/blktrace.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 4992ca523842..671f464f92ae 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -770,10 +770,8 @@ void blk_trace_shutdown(struct request_queue *q) { mutex_lock(&q->blk_trace_mutex); if (rcu_dereference_protected(q->blk_trace, - lockdep_is_held(&q->blk_trace_mutex))) { - __blk_trace_startstop(q, 0); + lockdep_is_held(&q->blk_trace_mutex))) __blk_trace_remove(q); - }
mutex_unlock(&q->blk_trace_mutex); }