|WARNING| [v5,10/10] net/iavf: fix IPsec flow metadata leaks
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Fri Oct 23 12:26:47 CEST 2026
Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/171886
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-10-23
# DPDK Patch Review
## PATCH 01/10: net/iavf: keep device stopped if start fails
### Errors
**Correctness bug - partial state on error path:**
Line 1116: `iavf_phc_sync_alarm_start(dev);` is called before setting `adapter->stopped = 0`, but the new `irq_error` path does not stop the phc_sync alarm before returning.
```c
iavf_phc_sync_alarm_start(dev);
adapter->stopped = 0;
/* ... */
irq_error:
/* cleanup irq resources */
/* Missing: iavf_phc_sync_alarm_stop(dev); */
error:
return -1;
```
If `iavf_start_queues()` fails after `iavf_phc_sync_alarm_start()`, the alarm remains running even though the device never entered the running state. This leaves stale timers active that may reference freed resources when they fire.
**Fix:** Add `iavf_phc_sync_alarm_stop(dev);` at the start of the `irq_error:` block, before the IRQ cleanup.
---
## PATCH 02/10: net/iavf: do not store ethdev pointer
### Info
**Pre-existing observation (not introduced by this patch):**
The `iavf_get_eth_dev()` helper assumes `adapter->dev_data` is non-NULL and dereferences it unconditionally. Most call sites occur after the adapter has been fully initialized, where `dev_data` is guaranteed valid. However, if future code calls this helper during early setup or after teardown, the NULL dereference would occur.
This is not a bug introduced by this patch--it is a property of the helper's current usage. Consider adding a NULL check if the helper is ever used outside fully-initialized contexts.
---
## PATCH 03/10: net/iavf: fix false success on flow validation
### Clean
No issues found. The fix correctly returns NULL on validation failure so that `iavf_flow_process_filter()` treats it as an error, and returns the engine pointer only when validation succeeds.
---
## PATCH 04/10: net/iavf: fix memory leaks around IRQ resources
### Errors
**Missing cleanup - queue-vector map not freed on early failure:**
Line 874: If `rte_intr_vec_list_alloc()` fails, the code jumps to `qv_map_alloc_err`, which calls `rte_intr_vec_list_free()` and `rte_intr_efd_disable()`. However, `vf->qv_map` was allocated earlier at line 867 and is not freed on this path.
```c
vf->qv_map = rte_zmalloc("qv_map", ...);
if (!vf->qv_map) {
/* ... */
return -1; /* leaks nothing, qv_map is NULL */
}
/* ... */
if (!rte_intr_vec_list_alloc(...)) {
/* ... */
goto qv_map_alloc_err; /* qv_map still allocated, not freed */
}
qv_map_alloc_err:
rte_intr_vec_list_free(intr_handle);
rte_intr_efd_disable(intr_handle);
/* Missing: rte_free(vf->qv_map); vf->qv_map = NULL; */
return -1;
```
**Fix:** Add cleanup of `vf->qv_map` to the `qv_map_alloc_err` label:
```c
qv_map_alloc_err:
rte_intr_vec_list_free(intr_handle);
rte_intr_efd_disable(intr_handle);
rte_free(vf->qv_map);
vf->qv_map = NULL;
return -1;
```
---
## PATCH 05/10: net/iavf: fix generic flow error-path leaks
### Clean
No issues found. The patch correctly adds unwinding of registered parsers on engine init failure and frees the items array when match-result allocation fails.
---
## PATCH 06/10: net/iavf: centralize memory management for flows
### Warnings
**Potential logic error - meta freed twice on create failure:**
Lines 2110-2118 in `iavf_parse_engine_create()`:
```c
if (engine->create(ad, flow, meta, error) == 0) {
if (flow->rule != meta)
rte_free(meta);
return engine;
}
if (flow->rule != NULL && flow->rule != meta)
rte_free(flow->rule);
rte_free(meta);
flow->rule = NULL;
meta = NULL;
```
If `engine->create()` fails and has set `flow->rule = meta`, then:
1. Line 2114 condition `flow->rule != meta` is false, so `flow->rule` is not freed.
2. Line 2115 frees `meta` unconditionally.
3. `flow->rule` now points to freed memory.
This depends on engine behavior. If an engine sets `flow->rule` to the `meta` pointer on a failed create, the above logic would be wrong. However, inspecting the engines in this patch:
- FDIR: sets `flow->rule = filter` only on success (line 368).
- FSUB: sets `flow->rule = filter` only on success (line 85).
- RSS: sets `flow->rule = rss_cfg` only on success (line 1602).
So in practice, `flow->rule` is only set on success, and the error path is safe. The double-check on line 2114 is defensive but not necessary given current engine implementations.
**Suggested improvement (optional):** Simplify to:
```c
if (engine->create(ad, flow, meta, error) == 0) {
if (flow->rule != meta)
rte_free(meta);
return engine;
}
/* On failure, flow->rule is NULL or stale; free both unconditionally */
rte_free(flow->rule);
rte_free(meta);
flow->rule = NULL;
```
This is more robust if a future engine mistakenly sets `flow->rule` on failure.
---
## PATCH 07/10: net/iavf: skip RSS teardown during PF-initiated reset
### Clean
No issues found. The patch correctly moves RSS teardown under the same `pf_reset_in_progress` check as flow flush, so no virtchnl commands are sent during PF-initiated reset.
---
## PATCH 08/10: net/iavf: remove redundant reset checks from RSS engine
### Clean
No issues found. The patch correctly removes checks that are no longer needed because:
- `iavf_hash_init()` sends no commands.
- `iavf_dev_close()` skips RSS teardown during PF-initiated reset.
- `iavf_execute_vf_cmd()` already refuses commands when `vf_reset` is set.
---
## PATCH 09/10: net/iavf: fix null engine for egress security flows
### Warnings
**Code duplication - engine init/uninit are identical:**
The egress engine's `iavf_ipsec_egress_flow_init()` and `iavf_ipsec_egress_flow_uninit()` duplicate the capability check and register/unregister calls from the ingress engine, differing only in the parser pointer.
```c
/* Ingress */
static int
iavf_ipsec_flow_init(struct iavf_adapter *ad) {
/* ... capability check ... */
return iavf_register_parser(&iavf_ipsec_flow_parser, ad);
}
/* Egress - identical except parser */
static int
iavf_ipsec_egress_flow_init(struct iavf_adapter *ad) {
/* ... same capability check ... */
return iavf_register_parser(&iavf_ipsec_egress_flow_parser, ad);
}
```
**Suggested improvement (optional):** A common helper taking the parser as a parameter would reduce duplication:
```c
static int
iavf_ipsec_flow_init_common(struct iavf_adapter *ad,
struct iavf_flow_parser *parser) {
struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
if (!vf->vf_res)
return -EINVAL;
if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_INLINE_IPSEC_CRYPTO))
return -ENOTSUP;
return iavf_register_parser(parser, ad);
}
static int iavf_ipsec_flow_init(struct iavf_adapter *ad) {
return iavf_ipsec_flow_init_common(ad, &iavf_ipsec_flow_parser);
}
static int iavf_ipsec_egress_flow_init(struct iavf_adapter *ad) {
return iavf_ipsec_flow_init_common(ad, &iavf_ipsec_egress_flow_parser);
}
```
This is a minor style improvement, not a correctness issue.
---
## PATCH 10/10: net/iavf: fix IPsec flow metadata leaks
### Errors
**Logic error - success path may return error:**
Lines 1968-1977:
```c
if (fi == NULL)
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"Invalid IPsec flow.");
if (meta != NULL)
*meta = fi;
else
rte_free(fi);
return 0;
```
If `iavf_ipsec_flow_item_parse()` returns NULL (line 1963), the code sets an error and returns non-zero (line 1968). However, `iavf_ipsec_flow_item_parse()` already logs errors internally and returns NULL on failure. The patch does not verify that an error was set by the callee before setting a new one, potentially overwriting a more specific error.
**More importantly:** If `item->meta` is NULL (line 1960), `fi` is never assigned (it remains NULL from line 1945). The code then hits line 1968 and returns an error claiming "Invalid IPsec flow", but this may be a valid case where the pattern-match item has no metadata. The original code returned `-1` unconditionally when `item->meta` was NULL; the patch changes this to an error even if the pattern matched.
**Suggested fix:** Initialize `ret = 0` after the `item` NULL check, and only set an error if `fi` is NULL when metadata is actually required:
```c
item = iavf_search_pattern_match_item(pattern, array, array_len, error);
if (item == NULL)
return -rte_errno;
ret = 0;
if (item->meta != NULL) {
const struct rte_security_session *session = parsed_actions.actions[0]->conf;
uint32_t type = (uint64_t)(item->meta);
fi = iavf_ipsec_flow_item_parse(ad, pattern, session, type);
if (fi == NULL)
ret = rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"Failed to parse IPsec flow.");
}
rte_free(item);
if (ret != 0)
return ret;
if (meta != NULL)
*meta = fi;
else
rte_free(fi);
return 0;
```
---
## Summary
### Errors
1. **PATCH 01/10:** Missing `iavf_phc_sync_alarm_stop()` on `irq_error` path--alarm remains running after start failure.
2. **PATCH 04/10:** `vf->qv_map` not freed when `rte_intr_vec_list_alloc()` fails--memory leak.
3. **PATCH 10/10:** Returns error when `item->meta` is NULL even if pattern matched--may reject valid flows.
### Warnings
1. **PATCH 06/10:** Defensive double-check on `flow->rule != meta` in error path is safe but could be simplified for clarity.
2. **PATCH 09/10:** Code duplication between ingress and egress engine init/uninit could be reduced with a common helper.
### Info
1. **PATCH 02/10:** `iavf_get_eth_dev()` assumes `adapter->dev_data` is non-NULL; safe in current usage but worth noting for future expansion.
---
Review-Result: ERROR
More information about the test-report
mailing list