Skip to content

Commit 45c2e30

Browse files
James Morsebp3tk0v
authored andcommitted
x86/resctrl: Fix rdtgroup_mkdir()'s unlocked use of kernfs_node::name
Since 741c10b ("kernfs: Use RCU to access kernfs_node::name.") a helper rdt_kn_name() that checks that rdtgroup_mutex is held has been used for all accesses to the kernfs node name. rdtgroup_mkdir() uses the name to determine if a valid monitor group is being created by checking the parent name is "mon_groups". This is done without holding rdtgroup_mutex, and now triggers the following warning: | WARNING: suspicious RCU usage | 6.15.0-rc1 #4465 Tainted: G E | ----------------------------- | arch/x86/kernel/cpu/resctrl/internal.h:408 suspicious rcu_dereference_check() usage! [...] | Call Trace: | <TASK> | dump_stack_lvl | lockdep_rcu_suspicious.cold | is_mon_groups | rdtgroup_mkdir | kernfs_iop_mkdir | vfs_mkdir | do_mkdirat | __x64_sys_mkdir | do_syscall_64 | entry_SYSCALL_64_after_hwframe Creating a control or monitor group calls mkdir_rdt_prepare(), which uses rdtgroup_kn_lock_live() to take the rdtgroup_mutex. To avoid taking and dropping the lock, move the check for the monitor group name and position into mkdir_rdt_prepare() so that it occurs under rdtgroup_mutex. Hoist is_mon_groups() earlier in the file. [ bp: Massage. ] Fixes: 741c10b ("kernfs: Use RCU to access kernfs_node::name.") Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com> Acked-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20250407124637.2433230-1-james.morse@arm.com
1 parent f2f29da commit 45c2e30

File tree

1 file changed

+27
-21
lines changed

1 file changed

+27
-21
lines changed

arch/x86/kernel/cpu/resctrl/rdtgroup.c

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3553,6 +3553,22 @@ static void mkdir_rdt_prepare_rmid_free(struct rdtgroup *rgrp)
35533553
free_rmid(rgrp->closid, rgrp->mon.rmid);
35543554
}
35553555

3556+
/*
3557+
* We allow creating mon groups only with in a directory called "mon_groups"
3558+
* which is present in every ctrl_mon group. Check if this is a valid
3559+
* "mon_groups" directory.
3560+
*
3561+
* 1. The directory should be named "mon_groups".
3562+
* 2. The mon group itself should "not" be named "mon_groups".
3563+
* This makes sure "mon_groups" directory always has a ctrl_mon group
3564+
* as parent.
3565+
*/
3566+
static bool is_mon_groups(struct kernfs_node *kn, const char *name)
3567+
{
3568+
return (!strcmp(rdt_kn_name(kn), "mon_groups") &&
3569+
strcmp(name, "mon_groups"));
3570+
}
3571+
35563572
static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
35573573
const char *name, umode_t mode,
35583574
enum rdt_group_type rtype, struct rdtgroup **r)
@@ -3568,6 +3584,15 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
35683584
goto out_unlock;
35693585
}
35703586

3587+
/*
3588+
* Check that the parent directory for a monitor group is a "mon_groups"
3589+
* directory.
3590+
*/
3591+
if (rtype == RDTMON_GROUP && !is_mon_groups(parent_kn, name)) {
3592+
ret = -EPERM;
3593+
goto out_unlock;
3594+
}
3595+
35713596
if (rtype == RDTMON_GROUP &&
35723597
(prdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
35733598
prdtgrp->mode == RDT_MODE_PSEUDO_LOCKED)) {
@@ -3751,22 +3776,6 @@ static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn,
37513776
return ret;
37523777
}
37533778

3754-
/*
3755-
* We allow creating mon groups only with in a directory called "mon_groups"
3756-
* which is present in every ctrl_mon group. Check if this is a valid
3757-
* "mon_groups" directory.
3758-
*
3759-
* 1. The directory should be named "mon_groups".
3760-
* 2. The mon group itself should "not" be named "mon_groups".
3761-
* This makes sure "mon_groups" directory always has a ctrl_mon group
3762-
* as parent.
3763-
*/
3764-
static bool is_mon_groups(struct kernfs_node *kn, const char *name)
3765-
{
3766-
return (!strcmp(rdt_kn_name(kn), "mon_groups") &&
3767-
strcmp(name, "mon_groups"));
3768-
}
3769-
37703779
static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
37713780
umode_t mode)
37723781
{
@@ -3782,11 +3791,8 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
37823791
if (resctrl_arch_alloc_capable() && parent_kn == rdtgroup_default.kn)
37833792
return rdtgroup_mkdir_ctrl_mon(parent_kn, name, mode);
37843793

3785-
/*
3786-
* If RDT monitoring is supported and the parent directory is a valid
3787-
* "mon_groups" directory, add a monitoring subdirectory.
3788-
*/
3789-
if (resctrl_arch_mon_capable() && is_mon_groups(parent_kn, name))
3794+
/* Else, attempt to add a monitoring subdirectory. */
3795+
if (resctrl_arch_mon_capable())
37903796
return rdtgroup_mkdir_mon(parent_kn, name, mode);
37913797

37923798
return -EPERM;

0 commit comments

Comments
 (0)