From: sashiko-bot@kernel.org
To: "Ratheesh Kannoth" <rkannoth@marvell.com>,
intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org
Subject: Re: [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem
Date: Fri, 30 Oct 2026 04:54:05 +0000 [thread overview]
Message-ID: <sashiko-outbox-190401@kernel.org> (raw)
In-Reply-To: <20260508034912.4082520-8-rkannoth@marvell.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Global Data Corruption and Data Race via shared static array
- [High] Integer underflow and missing bounds checks in legacy firmware parsers
- [High] Fragile firmware ABI heavily coupled to internal kernel structure size
- [High] Filesystem profile loading truncates KPU programming, breaking default parsing rules
- [Medium] Missing endianness conversion for u16 fields
--
commit c9233fb2ae7b0ce301cfbbff2b1cd306d7c325ba
Author: Ratheesh Kannoth <rkannoth@marvell.com>
octeontx2-af: npc: Support for custom KPU profile from filesystem
This commit provides a mechanism to load a custom KPU (Key Parse Unit)
profile directly from the filesystem at module load time.
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> index cefc5d70f3e49..c8c0cb68535c7 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
> @@ -265,6 +265,19 @@ struct npc_kpu_profile_cam {
> u16 dp2_mask;
> } __packed;
>
> +struct npc_kpu_profile_cam2 {
> + u8 state;
> + u8 state_mask;
> + u16 dp0;
> + u16 dp0_mask;
> + u16 dp1;
> + u16 dp1_mask;
> + u16 dp2;
> + u16 dp2_mask;
Since the firmware image is little-endian, should these fields be defined as
__le16?
When they are accessed as host-order integers without le16_to_cpu() conversion,
will this lead to incorrect packet parsing rules and silent data corruption on
big-endian architectures?
[ ... ]
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
> index 5fa9e1c7ae9fa..a0f97e683145f 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
[ ... ]
> @@ -1788,26 +1872,168 @@ static void npc_prepare_default_kpu(struct rvu *rvu,
> npc_cn20k_update_action_entries_n_flags(rvu, profile);
> }
>
> -static int npc_apply_custom_kpu(struct rvu *rvu,
> - struct npc_kpu_profile_adapter *profile)
> +static int npc_alloc_kpu_cam2_n_action2(struct rvu *rvu, int kpu_num,
> + int num_entries)
> +{
> + struct npc_kpu_profile_adapter *adapter = &rvu->kpu;
> + struct npc_kpu_profile *kpu;
> +
> + kpu = &adapter->kpu[kpu_num];
> +
> + kpu->cam2 = devm_kcalloc(rvu->dev, num_entries,
> + sizeof(*kpu->cam2), GFP_KERNEL);
> + if (!kpu->cam2)
> + return -ENOMEM;
> +
> + kpu->action2 = devm_kcalloc(rvu->dev, num_entries,
> + sizeof(*kpu->action2), GFP_KERNEL);
Will this cause data corruption and a use-after-free across devices?
In npc_prepare_default_kpu(), the device's profile->kpu pointer is initialized
to point to the statically defined npc_kpu_profiles global array.
Here, we are assigning device-scoped devm_kcalloc memory directly into this
globally shared array. If multiple RVU devices probe concurrently, they might
data-race on this shared state. Additionally, upon device unbind, devres will
free the memory, leaving dangling pointers in the global array.
[ ... ]
> +static int npc_apply_custom_kpu_from_fw(struct rvu *rvu,
> + struct npc_kpu_profile_adapter *profile)
> {
> size_t hdr_sz = sizeof(struct npc_kpu_profile_fwdata), offset = 0;
> + const struct npc_kpu_profile_fwdata *fw;
> struct npc_kpu_profile_action *action;
> - struct npc_kpu_profile_fwdata *fw;
> struct npc_kpu_profile_cam *cam;
> struct npc_kpu_fwdata *fw_kpu;
> - int entries;
> - u16 kpu, entry;
> + int entries, entry, kpu;
>
> - if (is_cn20k(rvu->pdev))
> - return npc_cn20k_apply_custom_kpu(rvu, profile);
> + fw = rvu->kpu_fwdata;
> +
> + for (kpu = 0; kpu < fw->kpus; kpu++) {
> + if (rvu->kpu_fwdata_sz < hdr_sz + offset) {
> + dev_warn(rvu->dev,
> + "Profile size mismatch on KPU%i parsing\n",
> + kpu + 1);
> + return -EINVAL;
> + }
> +
> + fw_kpu = (struct npc_kpu_fwdata *)(fw->data + offset);
> + if (fw_kpu->entries > KPU_MAX_CST_ENT)
> + dev_warn(rvu->dev,
> + "Too many custom entries on KPU%d: %d > %d\n",
> + kpu, fw_kpu->entries, KPU_MAX_CST_ENT);
> + entries = min_t(int, fw_kpu->entries, KPU_MAX_CST_ENT);
> + cam = (struct npc_kpu_profile_cam *)fw_kpu->data;
> + offset += sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam);
Is there a missing bounds check here for negative values?
Since fw_kpu->entries is read as a signed int, a malicious firmware blob
providing a negative value (e.g., -1) could cause the offset calculation to
underflow the unsigned size_t offset.
This would wrap the offset backwards, allowing the boundary check
(rvu->kpu_fwdata_sz < hdr_sz + offset) to incorrectly pass in the next
iteration, resulting in an out-of-bounds access.
[ ... ]
> +static int npc_apply_custom_kpu_from_fs(struct rvu *rvu,
> + struct npc_kpu_profile_adapter *profile)
> +{
> + size_t hdr_sz = sizeof(struct npc_kpu_profile_fwdata), offset = 0;
> + const struct npc_kpu_profile_fwdata *fw;
> + struct npc_kpu_profile_action *action;
> + struct npc_kpu_profile_cam2 *cam2;
> + struct npc_kpu_fwdata *fw_kpu;
> + int entries, ret, entry, kpu;
>
> fw = rvu->kpu_fwdata;
>
> + /* Binary blob contains ikpu actions entries at start of data[0] */
> + profile->ikpu2 = devm_kcalloc(rvu->dev, 1,
> + sizeof(ikpu_action_entries),
> + GFP_KERNEL);
> + if (!profile->ikpu2)
> + return -ENOMEM;
> +
> + action = (struct npc_kpu_profile_action *)(fw->data + offset);
> +
> + if (rvu->kpu_fwdata_sz < hdr_sz + sizeof(ikpu_action_entries))
> + return -EINVAL;
> +
> + /* The firmware layout does dependent on the internal size of
> + * ikpu_action_entries.
> + */
> + memcpy((void *)profile->ikpu2, action, sizeof(ikpu_action_entries));
> + offset += sizeof(ikpu_action_entries);
Will this create a fragile firmware ABI coupled to the internal kernel
structure size?
Because ikpu_action_entries is a kernel-internal static array, its size
depends on the number of port kinds (NPC_MAX_PKIND) defined in the specific
kernel version compiling it.
If future kernel versions add elements to this array, the parser will expect a
larger initial block than the firmware file actually provides. This would
misalign all subsequent read offsets, causing the driver to interpret garbage
memory.
[ ... ]
> +static int npc_load_kpu_profile_from_fs(struct rvu *rvu)
> +{
> + struct npc_kpu_profile_adapter *profile = &rvu->kpu;
> + const char *kpu_profile = rvu->kpu_pfl_name;
> + const struct firmware *fw = NULL;
> + int ret, fw_kpus = 0;
> + char path[512] = "kpu/";
> +
> + if (strlen(kpu_profile) > sizeof(path) - strlen("kpu/") - 1) {
> + dev_err(rvu->dev, "kpu profile name is too big\n");
> + return -ENOSPC;
> + }
> +
> + strcat(path, kpu_profile);
> +
> + if (request_firmware_direct(&fw, path, rvu->dev))
> + return -ENOENT;
> +
> + dev_info(rvu->dev, "Loading KPU profile from filesystem: %s\n",
> + path);
> +
> + rvu->kpu_fwdata = fw->data;
> + rvu->kpu_fwdata_sz = fw->size;
> +
> + ret = npc_apply_custom_kpu(rvu, profile, true, &fw_kpus);
> + release_firmware(fw);
> + rvu->kpu_fwdata = NULL;
> +
> + if (ret) {
> + rvu->kpu_fwdata_sz = 0;
> + dev_err(rvu->dev,
> + "Loading KPU profile from filesystem failed\n");
> + return ret;
> + }
> +
> + rvu->kpu.kpus = fw_kpus;
> + profile->kpus = fw_kpus;
Does this truncate the hardware programming loop in npc_parser_profile_init()?
By explicitly updating profile->kpus to fw_kpus, the hardware programming loop
will only configure up to fw_kpus. Since all KPUs are disabled at the beginning
of npc_parser_profile_init(), the remaining hardware KPUs will be left
completely disabled, breaking network parsing for traffic reliant on default
KPU logic.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260508034912.4082520-1-rkannoth@marvell.com?part=7
next prev parent reply other threads:[~2026-10-30 4:54 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 1/9] octeontx2-af: npc: cn20k: debugfs enhancements Ratheesh Kannoth
2026-05-11 2:25 ` Ratheesh Kannoth
2026-10-30 4:54 ` sashiko-bot
2026-05-08 3:49 ` [PATCH v12 net-next 2/9] net/mlx5e: trim stack use in PCIe congestion threshold helper Ratheesh Kannoth
2026-05-08 9:02 ` David Laight
2026-10-30 4:54 ` sashiko-bot
2026-05-08 3:49 ` [PATCH v12 net-next 3/9] devlink: pass param values by pointer Ratheesh Kannoth
2026-05-11 13:39 ` Przemek Kitszel
2026-10-30 4:54 ` sashiko-bot
2026-05-08 3:49 ` [PATCH v12 net-next 4/9] devlink: Implement devlink param multi attribute nested data values Ratheesh Kannoth
2026-05-11 2:31 ` Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 5/9] octeontx2-af: npc: cn20k: add subbank search order control Ratheesh Kannoth
2026-05-11 2:32 ` Ratheesh Kannoth
2026-10-30 4:54 ` sashiko-bot
2026-05-08 3:49 ` [PATCH v12 net-next 6/9] octeontx2: cn20k: Coordinate default rules with NIX LF lifecycle Ratheesh Kannoth
2026-05-11 2:44 ` Ratheesh Kannoth
2026-10-30 4:54 ` sashiko-bot
2026-05-08 3:49 ` [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem Ratheesh Kannoth
2026-05-11 3:23 ` Ratheesh Kannoth
2026-05-11 3:27 ` Ratheesh Kannoth
2026-05-11 11:55 ` [Intel-wired-lan] " Loktionov, Aleksandr
2026-05-12 2:11 ` Ratheesh Kannoth
2026-10-30 4:54 ` sashiko-bot [this message]
2026-05-08 3:49 ` [PATCH v12 net-next 8/9] octeontx2: cn20k: Respect NPC MCAM X2/X4 profile in flows and DFT alloc Ratheesh Kannoth
2026-05-11 3:25 ` Ratheesh Kannoth
2026-10-30 4:54 ` sashiko-bot
2026-05-08 3:49 ` [PATCH v12 net-next 9/9] octeontx2-af: npc: cn20k: Allocate npc_priv and dstats dynamically Ratheesh Kannoth
2026-05-11 3:26 ` Ratheesh Kannoth
2026-10-30 4:54 ` sashiko-bot
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=sashiko-outbox-190401@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=intel-wired-lan@lists.osuosl.org \
--cc=linux-rdma@vger.kernel.org \
--cc=rkannoth@marvell.com \
--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