From: Drew Fustini <fustini@kernel.org>
To: sashiko-reviews@lists.linux.dev
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH RFC v6 13/18] riscv_cbqri: resctrl: Add MB_MIN bandwidth allocation via Rbwb
Date: Mon, 1 Jun 2026 22:00:49 -0700 [thread overview]
Message-ID: <ah5jgXEHzQUEREV0@gen8> (raw)
In-Reply-To: <20260601205717.7FDA51F00893@smtp.kernel.org>
On Mon, Jun 01, 2026 at 08:57:17PM +0000, sashiko-bot@kernel.org wrote:
> > diff --git a/drivers/resctrl/cbqri_resctrl.c b/drivers/resctrl/cbqri_resctrl.c
> > index f379058b0114b..1d312004b07d9 100644
> > --- a/drivers/resctrl/cbqri_resctrl.c
> > +++ b/drivers/resctrl/cbqri_resctrl.c
> > @@ -363,6 +363,9 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
> > case RDT_RESOURCE_L2:
> > case RDT_RESOURCE_L3:
> > return cbqri_apply_cache_config_dom(dom, r, closid, t, cfg_val);
> > + case RDT_RESOURCE_MB_MIN:
> > + /* sum(Rbwb) <= MRBWB validation runs inside cbqri_apply_rbwb(). */
> > + return cbqri_apply_rbwb(dom->hw_ctrl, closid, cfg_val, true);
>
> [Severity: High]
> Does this code leak memory bandwidth capacity when a resctrl group is removed?
>
> When a resctrl group is removed via rmdir, the CLOSID is freed by the core,
> but no architecture hook is invoked to reset the hardware or software cache.
> This means ctrl->rbwb_cache[closid] permanently retains the deleted group's
> bandwidth allocation.
>
> Later, when cbqri_apply_rbwb() is called to modify bandwidth for any active
> group, it sums across all ctrl->rcid_count CLOSIDs, including the unallocated
> ones. The stranded bandwidth from deleted groups is included in the sum,
> causing new allocations to be rejected with -EINVAL.
>
> Can an attacker with mkdir permissions repeatedly create groups, assign high
> bandwidth, and remove them, to permanently starve the default group and
> active processes?
Only root can create directories in /sys/fs/resctrl so I do not think
this is a practical concern.
> > @@ -422,9 +433,22 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
> > return val;
> > }
> >
> > +/*
> > + * RCID 0 carries the remaining MRBWB after every other RCID is seeded with
> > + * the minimum Rbwb of 1. cbqri_probe_bc() rejects a bandwidth controller
> > + * with mrbwb < rcid_count, so this subtraction cannot underflow.
> > + */
> > +static u64 cbqri_rcid0_rbwb(struct cbqri_controller *ctrl)
> > +{
> > + if (WARN_ON_ONCE(ctrl->bc.mrbwb < ctrl->rcid_count))
> > + return 1;
> > + return ctrl->bc.mrbwb - (ctrl->rcid_count - 1);
> > +}
>
> [Severity: High]
> Does this calculation cause unconditional initialization failure on systems
> where MRBWB exceeds U16_MAX?
>
> The maximum reserved bandwidth blocks (mrbwb) is a 32-bit field in hardware
> capabilities, but cbqri_apply_rbwb() enforces a strict hardware limitation
> of 16 bits per RCID (rejecting values > U16_MAX).
>
> If the global mrbwb exceeds 65535, this function returns a value exceeding
> U16_MAX, causing cbqri_apply_rbwb() to reject it with -EINVAL. This in turn
> causes domain initialization to fail, preventing CPUs from coming online
> with resctrl.
This is not a real issue. MRBWB can not exceeds U16_MAX.
> > @@ -439,15 +463,41 @@ void resctrl_arch_reset_all_ctrls(struct rdt_resource *r)
> > return;
> >
> > list_for_each_entry(d, &r->ctrl_domains, hdr.list) {
> > - for (i = 0; i < hw_res->ctrl->rcid_count; i++) {
> > - for (t = 0; t < CDP_NUM_TYPES; t++) {
> > + dom = container_of(d, struct cbqri_resctrl_dom,
> > + resctrl_ctrl_dom);
> > +
> > + switch (r->rid) {
> > + case RDT_RESOURCE_MB_MIN:
> > + /*
> > + * CBQRI section 4.5: Rbwb >= 1, sum(Rbwb) <= MRBWB.
> > + * Walk N-1..1 first so RCID 0 lands last with the
> > + * remaining budget.
> > + */
> > + for (i = 0; i < hw_res->ctrl->rcid_count; i++) {
> > + u32 rcid = (i + 1) % hw_res->ctrl->rcid_count;
> > + u64 rbwb = (rcid == 0) ?
> > + cbqri_rcid0_rbwb(dom->hw_ctrl) : 1;
> > int rerr;
> >
> > - rerr = resctrl_arch_update_one(r, d, i, t, default_ctrl);
> > + rerr = cbqri_apply_rbwb(dom->hw_ctrl, rcid, rbwb, false);
> > if (rerr)
> > - pr_err_ratelimited("rid=%d reset RCID %u type %u failed (%d)\n",
> > - r->rid, i, t, rerr);
> > + pr_err_ratelimited("RBWB reset RCID %u failed (%d)\n",
> > + rcid, rerr);
>
> [Severity: High]
> Does this error handling violate the hardware bandwidth sum invariant?
>
> If cbqri_apply_rbwb() fails for any RCID (such as an MMIO error), it logs
> the error but continues the loop, leaving that RCID at its previous
> (potentially large) bandwidth.
>
> When it later blindly writes MRBWB - (N-1) to RCID 0 with check_sum = false,
> the total sum of all RCIDs in the hardware will exceed the hardware's MRBWB
> capacity. Could this violate the CBQRI invariant and potentially lock up the
> controller?
This is not a problem. The reset uses check_sum = false because the
intermediate sums during the walk legitimately exceed MRBWB, but the
hardware enforces sum(Rbwb) <= MRBWB itself.
> > + case RDT_RESOURCE_MB_MIN:
> > + res->name = "MB_MIN";
> > + res->schema_fmt = RESCTRL_SCHEMA_RANGE;
> > + /*
> > + * resctrl requires a cache scope for MBA-style domains.
> > + * Use L3 as a proxy until the resctrl supports non-cache
> > + * scopes for bandwidth resources.
> > + */
> > + res->ctrl_scope = RESCTRL_L3_CACHE;
> > + /* Rbwb is an integer block count, not a percentage. No MBA delay_linear. */
> > + res->membw.throttle_mode = THREAD_THROTTLE_UNDEFINED;
> > + res->membw.min_bw = 1;
> > + res->membw.max_bw = ctrl->bc.mrbwb;
>
> Does setting max_bw to ctrl->bc.mrbwb expose an unclamped 32-bit maximum
> bandwidth to userspace?
>
> If ctrl->bc.mrbwb exceeds U16_MAX, exposing this value to userspace allows
> requests that bypass core validation but will ultimately fail at the hardware
> layer in cbqri_apply_rbwb().
I will address this issue in the next revision.
> > + res->membw.bw_gran = 1;
> > + /*
> > + * CBQRI section 4.5 caps sum(Rbwb) <= MRBWB. Default new
> > + * groups to min_bw so mkdir cannot overflow that sum.
> > + */
> > + res->membw.default_to_min = true;
> > + res->alloc_capable = ctrl->alloc_capable;
> > + INIT_LIST_HEAD(&res->ctrl_domains);
> > + INIT_LIST_HEAD(&res->mon_domains);
>
> [Severity: High]
> Does enabling MB_MIN cause massive memory allocation failures due to an
> unbounded max_rmid?
>
> In cbqri_resctrl_accumulate_caps(), exposed_mon_capable is set to true if
> any hardware controller has mon_capable == true, which now includes the
> bandwidth controller backing MB_MIN.
>
> However, max_rmid is conditionally bounded only by the L3 capacity
> controller. If the system has a monitor-capable bandwidth controller but no
> monitor-capable L3 capacity controller, max_rmid remains U32_MAX.
>
> Later, resctrl_init() invokes rmid_init(), which attempts to allocate
> structures for U32_MAX RMIDs. This will fail with -ENOMEM and completely
> abort resctrl initialization.
I'll address this in the next rev.
>
> > @@ -893,14 +1054,24 @@ static int cbqri_attach_cpu_to_all_ctrls(unsigned int cpu)
> > lockdep_assert_held(&cbqri_domain_list_lock);
> >
> > list_for_each_entry(ctrl, &cbqri_controllers, list) {
> > - if (ctrl->type != CBQRI_CONTROLLER_TYPE_CAPACITY)
> > - continue;
> > - if (!cpumask_test_cpu(cpu, &ctrl->cache.cpu_mask))
> > - continue;
> > - if (!ctrl->alloc_capable)
> > + switch (ctrl->type) {
> > + case CBQRI_CONTROLLER_TYPE_CAPACITY:
> > + if (!cpumask_test_cpu(cpu, &ctrl->cache.cpu_mask))
> > + continue;
> > + if (!ctrl->alloc_capable)
> > + continue;
> > + err = cbqri_attach_cpu_to_cap_ctrl(ctrl, cpu);
> > + break;
> > + case CBQRI_CONTROLLER_TYPE_BANDWIDTH:
> > + if (!cpumask_test_cpu(cpu, &ctrl->mem.cpu_mask))
> > + continue;
> > + if (!ctrl->alloc_capable)
> > + continue;
> > + err = cbqri_attach_cpu_to_bw_ctrl(ctrl, cpu);
> > + break;
> > + default:
> > continue;
> > -
> > - err = cbqri_attach_cpu_to_cap_ctrl(ctrl, cpu);
> > + }
> > if (err) {
> > cbqri_detach_cpu_from_all_ctrls(cpu);
>
> [Severity: High]
> This is a pre-existing issue, but does cbqri_detach_cpu_from_l3_mon() have a
> use-after-free bug due to an unsafe cancel_delayed_work()?
>
> If cbqri_detach_cpu_from_all_ctrls() eventually calls into
> cbqri_detach_cpu_from_l3_mon():
>
> drivers/resctrl/cbqri_resctrl.c:cbqri_detach_cpu_from_l3_mon() {
> ...
> cancel_delayed_work(&mon_dom->cqm_limbo);
> ...
> kfree(mon_dom);
> ...
> }
>
> The CPU offline callback runs under cpus_write_lock(). If the worker has
> already dequeued from the workqueue but is preempted right before acquiring
> cpus_read_lock(), cancel_delayed_work() returns false and does not wait.
>
> The callback then proceeds to kfree(mon_dom). When the hotplug callback
> finishes and releases the write lock, the worker acquires the read lock and
> dereferences the freed mon_dom pointer, resulting in a use-after-free.
I don't believe this a problem.
Drew
next prev parent reply other threads:[~2026-06-02 5:00 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-01 20:35 [PATCH RFC v6 00/18] riscv: add Ssqosid and CBQRI resctrl support Drew Fustini
2026-06-01 20:35 ` [PATCH RFC v6 01/18] dt-bindings: riscv: Add Ssqosid extension description Drew Fustini
2026-06-01 20:35 ` [PATCH RFC v6 02/18] riscv: detect the Ssqosid extension Drew Fustini
2026-06-01 20:35 ` [PATCH RFC v6 03/18] riscv: add support for srmcfg CSR from " Drew Fustini
[not found] ` <20260601204931.3A9481F00893@smtp.kernel.org>
2026-06-02 0:58 ` Drew Fustini
2026-06-01 20:35 ` [PATCH RFC v6 04/18] fs/resctrl: Add resctrl_is_membw() helper Drew Fustini
2026-06-01 20:35 ` [PATCH RFC v6 05/18] fs/resctrl: Add RDT_RESOURCE_MB_MIN and RDT_RESOURCE_MB_WGHT Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 06/18] fs/resctrl: Let bandwidth resources default to min_bw at reset Drew Fustini
[not found] ` <20260601205517.7AAAC1F00893@smtp.kernel.org>
2026-06-02 1:11 ` Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 07/18] riscv_cbqri: Add capacity controller probe and allocation device ops Drew Fustini
[not found] ` <20260601204809.187341F00898@smtp.kernel.org>
2026-06-02 2:17 ` Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 08/18] riscv_cbqri: Add capacity controller monitoring " Drew Fustini
[not found] ` <20260601205149.A07E31F00893@smtp.kernel.org>
2026-06-02 2:20 ` Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 09/18] riscv_cbqri: Add bandwidth controller probe and allocation " Drew Fustini
[not found] ` <20260601204931.F08EA1F00898@smtp.kernel.org>
2026-06-02 4:27 ` Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 10/18] riscv_cbqri: Add bandwidth controller monitoring " Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 11/18] riscv_cbqri: resctrl: Add cache allocation via capacity block mask Drew Fustini
[not found] ` <20260601205608.D86481F00893@smtp.kernel.org>
2026-06-02 4:31 ` Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 12/18] riscv_cbqri: resctrl: Add L3 cache occupancy monitoring Drew Fustini
[not found] ` <20260601205837.C1AC91F00893@smtp.kernel.org>
2026-06-02 4:47 ` Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 13/18] riscv_cbqri: resctrl: Add MB_MIN bandwidth allocation via Rbwb Drew Fustini
[not found] ` <20260601205717.7FDA51F00893@smtp.kernel.org>
2026-06-02 5:00 ` Drew Fustini [this message]
2026-06-01 20:36 ` [PATCH RFC v6 14/18] riscv_cbqri: resctrl: Add MB_WGHT bandwidth allocation via Mweight Drew Fustini
[not found] ` <20260601205734.76D021F00893@smtp.kernel.org>
2026-06-02 17:35 ` Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 15/18] riscv_cbqri: resctrl: Add mbm_total_bytes bandwidth monitoring Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 16/18] ACPI: RISC-V: Parse RISC-V Quality of Service Controller (RQSC) table Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 17/18] ACPI: RISC-V: Add support for RISC-V Quality of Service Controller (RQSC) Drew Fustini
2026-06-01 20:36 ` [PATCH RFC v6 18/18] riscv: enable resctrl filesystem for Ssqosid Drew Fustini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ah5jgXEHzQUEREV0@gen8 \
--to=fustini@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome