Skip to content

Commit fc16126

Browse files
rchatrebp3tk0v
authored andcommitted
x86,fs/resctrl: Prevent out-of-bounds access while offlining CPU when SNC enabled
The architecture updates the cpu_mask in a domain's header to track which online CPUs are associated with the domain. When this mask becomes empty the architecture initiates offline of the domain that includes calling on resctrl fs to offline the domain. If it is a monitoring domain in which LLC occupancy is tracked resctrl fs forces the limbo handler to clear all busy RMID state associated with the domain. The limbo handler always reads the current event value associated with a busy RMID irrespective of it being checked as part of regular "is it still busy" check or whether it will be forced released anyway. When reading an RMID on a system with SNC enabled the "logical RMID" is converted to the "physical RMID" and this conversion requires the NUMA node ID of the resctrl monitoring domain that is in turn determined by querying the NUMA node ID of any CPU belonging to the monitoring domain. When the monitoring domain is going offline its cpu_mask is empty causing the NUMA node ID query via cpu_to_node() to be done with "nr_cpu_ids" as argument resulting in an out-of-bounds access. Refactor the limbo handler to skip reading the RMID when the RMID will just be forced to no longer be dirty in the domain anyway. Add a safety check to the architecture's RMID reader to protect against this scenario. Fixes: e13db55 ("x86/resctrl: Introduce snc_nodes_per_l3_cache") Closes: https://sashiko.dev/#/patchset/cover.1780456704.git.reinette.chatre%40intel.com?part=9 Reported-by: Sashiko <sashiko-bot@kernel.org> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Cc: <stable@kernel.org> Link: https://patch.msgid.link/16137433df42f85013b2f7a53626795cbd6637b9.1781029125.git.reinette.chatre@intel.com
1 parent dc59e4f commit fc16126

2 files changed

Lines changed: 27 additions & 17 deletions

File tree

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr,
259259
if (!domain_header_is_valid(hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3))
260260
return -EINVAL;
261261

262+
if (cpumask_empty(&hdr->cpu_mask)) {
263+
pr_warn_once("Domain %d has no CPUs\n", hdr->id);
264+
return -EINVAL;
265+
}
266+
262267
d = container_of(hdr, struct rdt_l3_mon_domain, hdr);
263268
hw_dom = resctrl_to_arch_mon_dom(d);
264269
cpu = cpumask_any(&hdr->cpu_mask);

fs/resctrl/monitor.c

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,10 @@ void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
135135
struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
136136
u32 idx_limit = resctrl_arch_system_num_rmid_idx();
137137
struct rmid_entry *entry;
138+
bool rmid_dirty = true;
138139
u32 idx, cur_idx = 1;
139140
void *arch_mon_ctx;
140141
void *arch_priv;
141-
bool rmid_dirty;
142142
u64 val = 0;
143143

144144
arch_priv = mon_event_all[QOS_L3_OCCUP_EVENT_ID].arch_priv;
@@ -161,22 +161,27 @@ void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
161161
break;
162162

163163
entry = __rmid_entry(idx);
164-
if (resctrl_arch_rmid_read(r, &d->hdr, entry->closid, entry->rmid,
165-
QOS_L3_OCCUP_EVENT_ID, arch_priv, &val,
166-
arch_mon_ctx)) {
167-
rmid_dirty = true;
168-
} else {
169-
rmid_dirty = (val >= resctrl_rmid_realloc_threshold);
170-
171-
/*
172-
* x86's CLOSID and RMID are independent numbers, so the entry's
173-
* CLOSID is an empty CLOSID (X86_RESCTRL_EMPTY_CLOSID). On Arm the
174-
* RMID (PMG) extends the CLOSID (PARTID) space with bits that aren't
175-
* used to select the configuration. It is thus necessary to track both
176-
* CLOSID and RMID because there may be dependencies between them
177-
* on some architectures.
178-
*/
179-
trace_mon_llc_occupancy_limbo(entry->closid, entry->rmid, d->hdr.id, val);
164+
if (!force_free) {
165+
if (resctrl_arch_rmid_read(r, &d->hdr, entry->closid,
166+
entry->rmid, QOS_L3_OCCUP_EVENT_ID,
167+
arch_priv, &val, arch_mon_ctx)) {
168+
rmid_dirty = true;
169+
} else {
170+
rmid_dirty = (val >= resctrl_rmid_realloc_threshold);
171+
172+
/*
173+
* x86's CLOSID and RMID are independent numbers,
174+
* so the entry's CLOSID is an empty CLOSID
175+
* (X86_RESCTRL_EMPTY_CLOSID). On Arm the RMID
176+
* (PMG) extends the CLOSID (PARTID) space with
177+
* bits that aren't used to select the configuration.
178+
* It is thus necessary to track both CLOSID and
179+
* RMID because there may be dependencies between
180+
* them on some architectures.
181+
*/
182+
trace_mon_llc_occupancy_limbo(entry->closid, entry->rmid,
183+
d->hdr.id, val);
184+
}
180185
}
181186

182187
if (force_free || !rmid_dirty) {

0 commit comments

Comments
 (0)