Skip to content

Commit

Permalink
x86/resctrl: Fix rdtgroup_mkdir()'s unlocked use of kernfs_node::name
Browse files Browse the repository at this point in the history
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
  • Loading branch information
James Morse authored and Borislav Petkov (AMD) committed Apr 9, 2025
1 parent f2f29da commit 45c2e30
Showing 1 changed file with 27 additions and 21 deletions.
48 changes: 27 additions & 21 deletions arch/x86/kernel/cpu/resctrl/rdtgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)) {
Expand Down Expand Up @@ -3751,22 +3776,6 @@ static int rdtgroup_mkdir_ctrl_mon(struct kernfs_node *parent_kn,
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)
{
Expand All @@ -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;
Expand Down

0 comments on commit 45c2e30

Please sign in to comment.