Re: [PATCH v2 3/5] fs/resctrl: Fix use-after-free during unmount

From: Babu Moger

Date: Mon May 18 2026 - 16:55:16 EST


Hi Tony,


On 5/15/26 14:39, Tony Luck wrote:
Sashiko reported[1] this issue:

During unmount or failure teardown, resctrl_fs_teardown() calls
mon_put_kn_priv() (which frees all mon_data structures) followed
by rdtgroup_destroy_root() (which destroys kernfs nodes). However, the
RDT_DELETED flag is never set for rdtgroup_default.

If a concurrent reader (e.g., rdtgroup_mondata_show()) invokes
rdtgroup_kn_lock_live(), it drops kernfs active protection and blocks on
rdtgroup_mutex. resctrl_fs_teardown() (holding the mutex) proceeds to free
the private data and destroy the nodes without waiting for the reader.

When the mutex is released, the reader wakes up, observes that RDT_DELETED is
not set for the default group, and dereferences the already-freed of->kn->priv
pointer.

Set RDT_DELETED for the default group (if there are any tasks waiting).

It only mentions about the one fix. It is better to add a line about fixing "Avoid races from pending operations from a previous mount".


Fixes: 60cf5e101fd4 ("x86/intel_rdt: Add mkdir to resctrl file system")
Signed-off-by: Tony Luck <tony.luck@xxxxxxxxx>
Link: https://sashiko.dev/#/patchset/20260508182143.14592-1-tony.luck%40intel.com?part=2 [1]
---
fs/resctrl/rdtgroup.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 506b40dc9430..97d1a3648b9e 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -593,6 +593,13 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
*/
static void rdtgroup_remove(struct rdtgroup *rdtgrp)
{
+ /*
+ * Groups created with mkdir() have an extra hold, that doesn't
+ * apply to the default group. It is stacically allocated, so

stacically -> statically

Thanks
Babu

+ * does not need to be freed.
+ */
+ if (rdtgrp == &rdtgroup_default)
+ return;
kernfs_put(rdtgrp->kn);
kfree(rdtgrp);
}
@@ -2965,6 +2972,7 @@ static void resctrl_fs_teardown(void)
mon_put_kn_priv();
rdt_pseudo_lock_release();
rdtgroup_default.mode = RDT_MODE_SHAREABLE;
+ rdtgroup_default.flags = RDT_DELETED;
closid_exit();
schemata_list_destroy();
rdtgroup_destroy_root();
@@ -2990,6 +2998,12 @@ static int rdt_get_tree(struct fs_context *fc)
goto out;
}
+ /* Avoid races from pending operations from a previous mount */
+ if (atomic_read(&rdtgroup_default.waitcount) != 0) {
+ ret = -EBUSY;
+ goto out;
+ }
+
ret = setup_rmid_lru_list();
if (ret)
goto out;
@@ -4265,6 +4279,7 @@ static int rdtgroup_setup_root(struct rdt_fs_context *ctx)
ctx->kfc.root = rdt_root;
rdtgroup_default.kn = kernfs_root_to_node(rdt_root);
+ rdtgroup_default.flags = 0;
return 0;
}