|WARNING| net/bnxt: fix out-of-bounds read in TCAM get

dpdklab at iol.unh.edu dpdklab at iol.unh.edu
Mon Oct 5 18:54:13 CEST 2026


Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/170566

_AI Code Review_

=== Patch Review: series.patch (via Claude) ===
Review date: 2026-10-05

# DPDK Patch Review

## Summary
This patch fixes a critical out-of-bounds read vulnerability in the TCAM get function. The fix adds proper bounds checking and error handling before data is copied from firmware responses.

---

## Errors

### 1. Missing error check in early return path
After `bnxt_hwrm_tf_message_direct()`, the code now returns immediately on `rc != 0` but does not log the error condition. This makes debugging harder when HWRM communication fails.

**Suggested fix:**
```c
if (rc) {
	PMD_DRV_LOG_LINE(ERR, "%s: HWRM TCAM get failed, rc:%d",
			 __func__, rc);
	return rc;
}
```

---

## Warnings

### 1. Inconsistent return value on buffer size check
The original code set `rc = -EINVAL` when the caller's buffer was too small but did not return immediately, allowing fallthrough to the memcpy operations (which is the bug being fixed). The patch now correctly returns immediately, but the earlier conditional combined `rc` check with buffer size checks using `||`, which could have masked the HWRM failure. While the patch separates these checks correctly, the original logic flaw should be acknowledged.

**No action required** - the patch fixes this correctly by separating the checks.

### 2. Potential integer overflow in bounds check (theoretical)
The bounds check casts `resp.key_size` and `resp.result_size` to `size_t` before multiplication:
```c
if ((size_t)rte_le_to_cpu_16(resp.key_size) * 2 +
    (size_t)rte_le_to_cpu_16(resp.result_size) > sizeof(resp.dev_data))
```

While `resp.key_size` is `uint16_t` (max 65535), the multiplication `key_size * 2` could theoretically overflow a 16-bit value before the cast to `size_t`. However, since the cast happens first (`(size_t)rte_le_to_cpu_16(resp.key_size)`), this is safe - the widening to `size_t` occurs before multiplication.

**No action required** - the cast order is correct.

### 3. `result_size` cast to `size_t` in bounds check but direct use in buffer size check
In the firmware bounds check, `result_size` is cast to `size_t`:
```c
(size_t)rte_le_to_cpu_16(resp.result_size) > sizeof(resp.dev_data)
```

But in the caller buffer check, it's compared directly:
```c
*remap_size < rte_le_to_cpu_16(resp.result_size)
```

This is safe because `*remap_size` has type `uint16_t *` (dereferenced to `uint16_t`), so both sides are 16-bit unsigned. However, consistency would suggest casting here too for clarity, or not casting in the bounds check since `sizeof(resp.dev_data)` fits in `uint16_t` range.

**Consider for clarity (optional):**
```c
if ((size_t)*key_size < (size_t)rte_le_to_cpu_16(resp.key_size) ||
    (size_t)*remap_size < (size_t)rte_le_to_cpu_16(resp.result_size))
```

---

## Informational

### 1. Commit message references removed code pattern
The commit message states "A missing return after a buffer size check allowed execution to fall through". While accurate, it could be clearer that the original code *conditionally* set `rc` but did not return, and the patch now returns immediately on *either* error condition. The fix is correct.

### 2. Error message wording
The error message "Caller buffer too small" could specify which buffer (key or remap) is insufficient. However, this is a minor improvement and not required.

**Optional enhancement:**
```c
PMD_DRV_LOG_LINE(ERR, "%s: Buffer too small (key:%u<%u or remap:%u<%u), rc:%d",
		 __func__, *key_size, rte_le_to_cpu_16(resp.key_size),
		 *remap_size, rte_le_to_cpu_16(resp.result_size), rc);
```

### 3. Byte order conversion placement
The patch correctly converts `resp.key_size` and `resp.result_size` from little-endian to host byte order before use in all bounds checks and assignments. The original code failed to do this, which could cause incorrect buffer size comparisons on big-endian systems. This is a **correctness fix** beyond just the out-of-bounds read.

---

## Positive Observations

1. **Correctly fixes use-after-check bug**: The patch prevents out-of-bounds read by returning before any `memcpy` operations when bounds checks fail.

2. **Adds firmware response validation**: The new check `(size_t)rte_le_to_cpu_16(resp.key_size) * 2 + (size_t)rte_le_to_cpu_16(resp.result_size) > sizeof(resp.dev_data)` prevents firmware from reporting sizes that exceed the response buffer, which would cause out-of-bounds reads even if the caller's buffers were large enough.

3. **Fixes byte-order bug**: Converting `resp.key_size` and `resp.result_size` to host byte order before use corrects a latent bug that would affect big-endian platforms.

4. **Proper use of `size_t` casts**: The cast to `size_t` in the bounds check against `sizeof()` is the recommended pattern to avoid sign/width comparison warnings.

5. **Correct propagation of converted sizes**: The converted sizes are stored in `*key_size` and `*remap_size` and used for `memcpy` lengths, ensuring consistency.

---

## Conclusion

This is a **high-quality security fix** that addresses a critical out-of-bounds read vulnerability. The only error is the missing error log on HWRM failure. The warnings and informational items are minor and do not affect correctness.

**Recommendation**: Fix the missing error log on HWRM failure (Error #1). The patch is otherwise ready to merge.


More information about the test-report mailing list