|WARNING| crypto/ipsec_mb: fix out-of-place operation handling

dpdklab at iol.unh.edu dpdklab at iol.unh.edu
Thu Jul 16 17:17:32 CEST 2026


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

_AI Code Review_

=== Patch Review: series.patch (via Claude) ===
Review date: 2026-07-16

# DPDK Patch Review

## Summary

This patch fixes buffer handling in out-of-place crypto operations in the ipsec_mb PMD. It removes a potentially dangerous memcpy in scatter-gather cases and adds missing buffer copies for non-scatter-gather out-of-place operations.

## Errors

### 1. Potential buffer overflow in NULL cipher out-of-place copy

**Location:** Lines 1843-1847

```c
memcpy(rte_pktmbuf_mtod(m_dst, uint8_t *),
    rte_pktmbuf_mtod(m_src, uint8_t *),
    job->msg_len_to_cipher_in_bytes +
    job->cipher_start_src_offset_in_bytes);
```

**Issue:** This copies `msg_len + offset` bytes starting from the beginning of `m_dst`, but should copy `msg_len` bytes starting at `offset` in the destination. The current code may:
1. Overflow the destination buffer if `offset + msg_len` exceeds the mbuf data size
2. Write to the wrong destination offset (always starts at byte 0 instead of at `offset`)

**Fix:**
```c
memcpy(rte_pktmbuf_mtod(m_dst, uint8_t *) +
    job->cipher_start_src_offset_in_bytes,
    rte_pktmbuf_mtod(m_src, uint8_t *) +
    job->cipher_start_src_offset_in_bytes,
    job->msg_len_to_cipher_in_bytes);
```

This matches the pattern from the removed code at line 1827-1829 (which correctly added the offset to both src and dst pointers).

### 2. Incorrect copy length for bit-granular ciphers

**Location:** Lines 1848-1851

```c
memcpy(rte_pktmbuf_mtod(m_dst, uint8_t *),
    rte_pktmbuf_mtod(m_src, uint8_t *),
    job->cipher_start_src_offset_in_bits >> 3);
```

**Issue:** For `SNOW3G_UEA2_BITLEN` and `KASUMI_UEA1_BITLEN`, this only copies the data **before** the cipher region (the offset converted to bytes). The cipher output itself is not copied. This is likely incorrect -- either:
- The cipher operation happens in-place in the src buffer and the entire buffer needs copying, or  
- Only the pre-cipher region should be copied and the cipher fills in its region directly in dst

The commit message states "missing buffer copy for out-of-place non-scatter-gather sessions" but this code does not copy the cipher output.

**Required clarification:** What is the correct behavior for these bit-granular ciphers in out-of-place mode? If the operation modifies `m_src` in-place and the result needs copying to `m_dst`, then the full buffer length should be copied, not just the offset.

**Suggested fix (assuming full buffer copy needed):**
```c
uint32_t total_len = (job->msg_len_to_cipher_in_bits +
    job->cipher_start_src_offset_in_bits + 7) >> 3;
memcpy(rte_pktmbuf_mtod(m_dst, uint8_t *),
    rte_pktmbuf_mtod(m_src, uint8_t *),
    total_len);
```

### 3. Wrong copy length for non-NULL cipher

**Location:** Lines 1852-1855

```c
memcpy(rte_pktmbuf_mtod(m_dst, uint8_t *),
    rte_pktmbuf_mtod(m_src, uint8_t *),
    job->cipher_start_src_offset_in_bytes);
```

**Issue:** Same as #2 -- this only copies the pre-cipher data, not the cipher output itself. For an out-of-place operation, the destination needs the entire buffer including the cipher result.

**Suggested fix:**
```c
uint32_t total_len = job->cipher_start_src_offset_in_bytes +
    job->msg_len_to_cipher_in_bytes;
memcpy(rte_pktmbuf_mtod(m_dst, uint8_t *),
    rte_pktmbuf_mtod(m_src, uint8_t *),
    total_len);
```

Or copy in two parts (pre-cipher region + cipher region) if the cipher backend writes directly to `m_dst` for the cipher portion.

---

## Warnings

### 1. Missing bounds check on mbuf data room

**Location:** All three memcpy calls (lines 1843, 1849, 1853)

**Issue:** None of the new memcpy operations verify that the source and destination mbufs have sufficient `data_len` or `buf_len` for the copy. If `msg_len_to_cipher_in_bytes + cipher_start_src_offset_in_bytes` exceeds the mbuf data room, this will write past the end of the buffer.

**Suggested addition:** Before the memcpy, add:
```c
uint32_t copy_len = /* calculated length */;
if (unlikely(copy_len > rte_pktmbuf_data_len(m_src) ||
             copy_len > rte_pktmbuf_tailroom(m_dst))) {
    return -EINVAL;
}
```

### 2. Inconsistent copy semantics between removed and added code

**Removed code (line 1827-1829):**
- Used `job->dst` and `job->src` (which are `uint8_t *` pointers already adjusted)
- Added offset to both pointers
- Copied `msg_len` bytes

**Added code (lines 1843-1847):**
- Uses `rte_pktmbuf_mtod()` to get base pointers
- Does NOT add offset to destination
- Copies `msg_len + offset` bytes

This inconsistency suggests the new code does not replicate the old behavior correctly. The removed code was specific to the NULL cipher scatter-gather case and may have had `job->dst` pre-adjusted. The new code appears in a different execution path (non-scatter-gather) and needs different handling.

---

## Info

### 1. Consider extracting common copy logic

The three new memcpy blocks (lines 1843-1855) all follow a similar pattern with different length calculations. Consider extracting this into a helper function:

```c
static inline int
copy_oop_buffer(struct rte_mbuf *m_dst, struct rte_mbuf *m_src,
                uint32_t offset, uint32_t length)
{
    if (unlikely(offset + length > rte_pktmbuf_data_len(m_src)))
        return -EINVAL;
    if (unlikely(offset + length > rte_pktmbuf_tailroom(m_dst)))
        return -EINVAL;
    
    memcpy(rte_pktmbuf_mtod(m_dst, uint8_t *) + offset,
           rte_pktmbuf_mtod(m_src, uint8_t *) + offset,
           length);
    return 0;
}
```

### 2. Commit message could be more specific

The commit message states "unnecessary memcpy() may dereference an invalid destination buffer" but doesn't explain why the destination might be invalid in the scatter-gather case. Adding detail about when `job->dst` is invalid would help reviewers understand the fix.

---

## Questions for Patch Author

1. **For NULL cipher out-of-place non-SGL:** Should the destination offset be added to the memcpy destination pointer (matching the removed code's behavior)?

2. **For bit-granular ciphers:** Does the cipher operation write directly to `m_dst`, or does it modify `m_src` in-place? The current code only copies the pre-cipher region, not the cipher output.

3. **For non-NULL non-bit-granular ciphers:** Same question -- does the result need to be copied from `m_src` after the operation, or does the cipher write to `m_dst` directly?

4. **Testing:** Have these code paths been tested with varying `cipher_start_src_offset_in_bytes` values to verify the destination is written at the correct offset?


More information about the test-report mailing list