]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
idpf: bound interrupt-vector register fill to the allocated array
authorMichael Bommarito <michael.bommarito@gmail.com>
Wed, 17 Jun 2026 21:57:54 +0000 (17:57 -0400)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Tue, 28 Jul 2026 18:23:01 +0000 (11:23 -0700)
idpf_get_reg_intr_vecs() fills the caller-allocated reg_vals[] array from
the VIRTCHNL2_OP_ALLOC_VECTORS reply in adapter->req_vec_chunks, bounding
its inner loop only by the per-chunk num_vectors. The array is sized
separately: idpf_intr_reg_init() allocates
kzalloc_objs(struct idpf_vec_regs, total_vecs) from
caps.num_allocated_vectors and only checks the returned count after the
fill. The sum of per-chunk num_vectors is never reconciled against
total_vecs, so a reply with a small num_allocated_vectors but chunks
summing higher writes past the end of reg_vals[].

Impact: a control plane (a PF or hypervisor device model) that returns a
VIRTCHNL2_OP_ALLOC_VECTORS reply whose per-chunk num_vectors sum exceeds
num_allocated_vectors writes struct idpf_vec_regs entries past the end of
the reg_vals kmalloc allocation (KASAN slab-out-of-bounds write).

Bound the fill loop to the array capacity passed in by the callers,
mirroring the sibling idpf_vport_get_q_reg(). The existing
num_regs < num_vecs check then rejects an undersized reply without the
out-of-bounds write happening first.

Fixes: d4d558718266 ("idpf: initialize interrupts and enable vport")
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Tested-by: Samuel Salin <Samuel.salin@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/idpf/idpf_dev.c
drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
drivers/net/ethernet/intel/idpf/idpf_virtchnl.h

index 1a0c71c95ef124cbebb8b346830521d88862b675..4079a787657f15cee7fd830a9c0338003e43cee2 100644 (file)
@@ -87,7 +87,7 @@ static int idpf_intr_reg_init(struct idpf_vport *vport,
        if (!reg_vals)
                return -ENOMEM;
 
-       num_regs = idpf_get_reg_intr_vecs(adapter, reg_vals);
+       num_regs = idpf_get_reg_intr_vecs(adapter, reg_vals, total_vecs);
        if (num_regs < num_vecs) {
                err = -EINVAL;
                goto free_reg_vals;
index a07d7e808ca9b6e65d73c10f741779c1114fd29f..6726084f6cfa0bd2527d2d48f20fc53f5513923e 100644 (file)
@@ -86,7 +86,7 @@ static int idpf_vf_intr_reg_init(struct idpf_vport *vport,
        if (!reg_vals)
                return -ENOMEM;
 
-       num_regs = idpf_get_reg_intr_vecs(adapter, reg_vals);
+       num_regs = idpf_get_reg_intr_vecs(adapter, reg_vals, total_vecs);
        if (num_regs < num_vecs) {
                err = -EINVAL;
                goto free_reg_vals;
index dc5ad784f456f029f59411aa9610632215cb319f..8bd6cca64c9bff76240e64fa1931ce632298884a 100644 (file)
@@ -1318,11 +1318,12 @@ idpf_vport_init_queue_reg_chunks(struct idpf_vport_config *vport_config,
  * idpf_get_reg_intr_vecs - Get vector queue register offset
  * @adapter: adapter structure to get the vector chunks
  * @reg_vals: Register offsets to store in
+ * @num_vecs: number of entries the @reg_vals array can hold
  *
  * Return: number of registers that got populated
  */
 int idpf_get_reg_intr_vecs(struct idpf_adapter *adapter,
-                          struct idpf_vec_regs *reg_vals)
+                          struct idpf_vec_regs *reg_vals, int num_vecs)
 {
        struct virtchnl2_vector_chunks *chunks;
        struct idpf_vec_regs reg_val;
@@ -1346,7 +1347,7 @@ int idpf_get_reg_intr_vecs(struct idpf_adapter *adapter,
                dynctl_reg_spacing = le32_to_cpu(chunk->dynctl_reg_spacing);
                itrn_reg_spacing = le32_to_cpu(chunk->itrn_reg_spacing);
 
-               for (i = 0; i < num_vec; i++) {
+               for (i = 0; i < num_vec && num_regs < num_vecs; i++) {
                        reg_vals[num_regs].dyn_ctl_reg = reg_val.dyn_ctl_reg;
                        reg_vals[num_regs].itrn_reg = reg_val.itrn_reg;
                        reg_vals[num_regs].itrn_index_spacing =
index 6876e3ed9d1be0dcc8232390c36f45a7e2324d88..9b1c9c86f6eac84ffc68e1cee5797956e2bb78f7 100644 (file)
@@ -104,7 +104,7 @@ int idpf_vc_core_init(struct idpf_adapter *adapter);
 void idpf_vc_core_deinit(struct idpf_adapter *adapter);
 
 int idpf_get_reg_intr_vecs(struct idpf_adapter *adapter,
-                          struct idpf_vec_regs *reg_vals);
+                          struct idpf_vec_regs *reg_vals, int num_vecs);
 int idpf_queue_reg_init(struct idpf_vport *vport,
                        struct idpf_q_vec_rsrc *rsrc,
                        struct idpf_queue_id_reg_info *chunks);