mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-13 01:39:06 +08:00
x86/resctrl: Fix rdtgroup_mkdir()'s unlocked use of kernfs_node::name
Since741c10b096("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:741c10b096("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
This commit is contained in:
committed by
Borislav Petkov (AMD)
parent
f2f29da9f0
commit
45c2e30bbd
@@ -3553,6 +3553,22 @@ static void mkdir_rdt_prepare_rmid_free(struct rdtgroup *rgrp)
|
||||
free_rmid(rgrp->closid, rgrp->mon.rmid);
|
||||
}
|
||||
|
||||
/*
|
||||
* We allow creating mon groups only with in a directory called "mon_groups"
|
||||
* which is present in every ctrl_mon group. Check if this is a valid
|
||||
* "mon_groups" directory.
|
||||
*
|
||||
* 1. The directory should be named "mon_groups".
|
||||
* 2. The mon group itself should "not" be named "mon_groups".
|
||||
* This makes sure "mon_groups" directory always has a ctrl_mon group
|
||||
* as parent.
|
||||
*/
|
||||
static bool is_mon_groups(struct kernfs_node *kn, const char *name)
|
||||
{
|
||||
return (!strcmp(rdt_kn_name(kn), "mon_groups") &&
|
||||
strcmp(name, "mon_groups"));
|
||||
}
|
||||
|
||||
static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
|
||||
const char *name, umode_t mode,
|
||||
enum rdt_group_type rtype, struct rdtgroup **r)
|
||||
@@ -3568,6 +3584,15 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the parent directory for a monitor group is a "mon_groups"
|
||||
* directory.
|
||||
*/
|
||||
if (rtype == RDTMON_GROUP && !is_mon_groups(parent_kn, name)) {
|
||||
ret = -EPERM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (rtype == RDTMON_GROUP &&
|
||||
(prdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
|
||||
prdtgrp->mode == RDT_MODE_PSEUDO_LOCKED)) {
|
||||
@@ -3751,22 +3776,6 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* We allow creating mon groups only with in a directory called "mon_groups"
|
||||
* which is present in every ctrl_mon group. Check if this is a valid
|
||||
* "mon_groups" directory.
|
||||
*
|
||||
* 1. The directory should be named "mon_groups".
|
||||
* 2. The mon group itself should "not" be named "mon_groups".
|
||||
* This makes sure "mon_groups" directory always has a ctrl_mon group
|
||||
* as parent.
|
||||
*/
|
||||
static bool is_mon_groups(struct kernfs_node *kn, const char *name)
|
||||
{
|
||||
return (!strcmp(rdt_kn_name(kn), "mon_groups") &&
|
||||
strcmp(name, "mon_groups"));
|
||||
}
|
||||
|
||||
static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
|
||||
umode_t mode)
|
||||
{
|
||||
@@ -3782,11 +3791,8 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
|
||||
if (resctrl_arch_alloc_capable() && parent_kn == rdtgroup_default.kn)
|
||||
return rdtgroup_mkdir_ctrl_mon(parent_kn, name, mode);
|
||||
|
||||
/*
|
||||
* If RDT monitoring is supported and the parent directory is a valid
|
||||
* "mon_groups" directory, add a monitoring subdirectory.
|
||||
*/
|
||||
if (resctrl_arch_mon_capable() && is_mon_groups(parent_kn, name))
|
||||
/* Else, attempt to add a monitoring subdirectory. */
|
||||
if (resctrl_arch_mon_capable())
|
||||
return rdtgroup_mkdir_mon(parent_kn, name, mode);
|
||||
|
||||
return -EPERM;
|
||||
|
||||
Reference in New Issue
Block a user