The patch titled Subject: writeback: protect race between bdi release and bdi_debug_stats_show has been added to the -mm mm-unstable branch. Its filename is writeback-protect-race-between-bdi-release-and-bdi_debug_stats_show.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/writeback-protect-race-between-bdi-release-and-bdi_debug_stats_show.patch This patch will later appear in the mm-unstable branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via the mm-everything branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there every 2-3 working days ------------------------------------------------------ From: Kemeng Shi <shikemeng@xxxxxxxxxxxxxxx> Subject: writeback: protect race between bdi release and bdi_debug_stats_show Date: Wed, 27 Mar 2024 23:57:46 +0800 There is a race between bdi release and bdi_debug_stats_show: /* get debug info */ /* bdi release */ bdi_debug_stats_show bdi = m->private; wb = &bdi->wb; bdi_unregister bdi_put release_bdi kfree(bdi) /* use after free */ spin_lock(&wb->list_lock); Search bdi on bdi_list under rcu lock in bdi_debug_stats_show to ensure the bdi is not freed to fix the issue. Link: https://lkml.kernel.org/r/20240327155751.3536-2-shikemeng@xxxxxxxxxxxxxxx Signed-off-by: Kemeng Shi <shikemeng@xxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/backing-dev.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) --- a/mm/backing-dev.c~writeback-protect-race-between-bdi-release-and-bdi_debug_stats_show +++ a/mm/backing-dev.c @@ -46,16 +46,44 @@ static void bdi_debug_init(void) bdi_debug_root = debugfs_create_dir("bdi", NULL); } -static int bdi_debug_stats_show(struct seq_file *m, void *v) +static struct backing_dev_info *lookup_bdi(struct seq_file *m) { + const struct file *file = m->file; struct backing_dev_info *bdi = m->private; - struct bdi_writeback *wb = &bdi->wb; + struct backing_dev_info *exist; + + list_for_each_entry_rcu(exist, &bdi_list, bdi_list) { + if (exist != bdi) + continue; + + if (exist->debug_dir == file->f_path.dentry->d_parent) + return bdi; + else + return NULL; + } + + return NULL; +} + + +static int bdi_debug_stats_show(struct seq_file *m, void *v) +{ + struct backing_dev_info *bdi; + struct bdi_writeback *wb; unsigned long background_thresh; unsigned long dirty_thresh; unsigned long wb_thresh; unsigned long nr_dirty, nr_io, nr_more_io, nr_dirty_time; struct inode *inode; + rcu_read_lock(); + bdi = lookup_bdi(m); + if (!bdi) { + rcu_read_unlock(); + return -EEXIST; + } + + wb = &bdi->wb; nr_dirty = nr_io = nr_more_io = nr_dirty_time = 0; spin_lock(&wb->list_lock); list_for_each_entry(inode, &wb->b_dirty, i_io_list) @@ -101,6 +129,7 @@ static int bdi_debug_stats_show(struct s nr_dirty_time, !list_empty(&bdi->bdi_list), bdi->wb.state); + rcu_read_unlock(); return 0; } DEFINE_SHOW_ATTRIBUTE(bdi_debug_stats); _ Patches currently in -mm which might be from shikemeng@xxxxxxxxxxxxxxx are writeback-protect-race-between-bdi-release-and-bdi_debug_stats_show.patch writeback-collect-stats-of-all-wb-of-bdi-in-bdi_debug_stats_show.patch writeback-support-retrieving-per-group-debug-writeback-stats-of-bdi.patch writeback-add-wb_monitorpy-script-to-monitor-writeback-info-on-bdi.patch writeback-rename-nr_reclaimable-to-nr_dirty-in-balance_dirty_pages.patch writeback-define-gdtc_init_no_wb-to-null.patch