mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 07:39:12 -04:00
idpf: bound interrupt-vector register fill to the allocated array
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: d4d5587182 ("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>
This commit is contained in:
committed by
Tony Nguyen
parent
e095f249e2
commit
9f7007ee98
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user