Fix #100: harden RPMsg buffer validation#145
Conversation
Code Review by Qodo
Context used✅ Tickets:
🎫 Review Linux RPMsg library design 1. pru_virtqueue_memory_barrier() no-op non-GNU
|
PR Summary by QodoHarden RPMsg buffer and virtqueue descriptor validation WalkthroughsDescription• Validate RPMsg send/receive descriptor and payload sizes before memcpy operations. • Tighten virtqueue head bounds checks and publish used-ring entries before idx increments. • Update RPMsg echo examples to pass receive buffer capacity via len each iteration. Diagramgraph TD
A["RPMsg API"] --> B{"Validate sizes"} --> C["Virtqueue get_avail"] --> D["Copy payload"] --> E["Virtqueue add_used"] --> F["Kick host"]
subgraph "Callers"
G["RPMsg examples"]
end
G --> A
High-Level AssessmentThe following are alternative approaches to this PR: 1. Break API: separate in-capacity and out-length params
2. Use platform-wide memory barrier abstraction
Recommendation: Current approach is a good non-breaking fix for #100: it adds concrete size/capacity checks and closes a subtle used-ring publication ordering hazard with minimal surface-area change. Consider a follow-up that modernizes the receive API to separate buffer capacity from returned payload length, and (if needed for non-GNU builds) centralizes the virtqueue memory barrier behind a portable abstraction. File ChangesBug fix (2)
Documentation (3)
ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan |
| static inline void pru_virtqueue_memory_barrier(void) | ||
| { | ||
| #ifdef __GNUC__ | ||
| __asm__ __volatile__ ("" : : : "memory"); | ||
| #endif | ||
| } |
There was a problem hiding this comment.
1. pru_virtqueue_memory_barrier() no-op non-gnu 📎 Requirement gap ☼ Reliability
pru_virtqueue_add_used_buf() now relies on pru_virtqueue_memory_barrier() to preserve used-ring publish ordering, but that barrier is compiled out when __GNUC__ is not defined (e.g., TI clpru builds). As a result, the host may observe used->idx updated before the corresponding used->ring[] entry is visible, creating a synchronization race and failing the required ordering guarantee.
Agent Prompt
## Issue description
`pru_virtqueue_add_used_buf()` depends on `pru_virtqueue_memory_barrier()` to ensure the `used->ring[...]` entry (including `used_elem->id/len`) is visible before incrementing `used->idx`, but `pru_virtqueue_memory_barrier()` is a no-op when `__GNUC__` is not defined (e.g., TI clpru). This removes the intended publish-ordering guarantee and can allow the host to observe `used->idx` update before the corresponding ring entry is visible.
## Issue Context
This repository supports non-GNU toolchains (the code already has `#ifdef __GNUC__` vs `#else` paths), and the rpmsg library is built with `clpru` via `source/rpmsg/makefile`. Because `used` and `used_elem` are not `volatile`, a missing barrier on non-GNU compilers provides no compile-time ordering guarantee and can permit reordering/caching of stores, violating the compliance requirement for a barrier before `used->idx` is incremented.
## Fix Focus Areas
- source/rpmsg/pru_virtqueue.c[59-64]
- source/rpmsg/pru_virtqueue.c[115-140]
- source/rpmsg/pru_virtqueue.c[135-140]
- source/rpmsg/makefile[20-56]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
pru_virtqueue_memory_barrier() was a no-op for non-GNU toolchains
(e.g. TI clpru), leaving used-ring publish ordering unenforced before
used->idx is incremented in pru_virtqueue_add_used_buf(). Add an empty
__asm(" ") for the clpru path, which the TI compiler treats as a
volatile optimization barrier it will not reorder memory accesses
across. Sufficient on the in-order PRU core (no hardware store
reordering). Verified compiles with clpru 2.3.3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Addressed the memory-barrier ordering gap (736218c).
|
Summary
used->idxlenbefore each receive callFixes #100.
Verification
git show --check --stat ea33ad99source/rpmsg/pru_rpmsg.candsource/rpmsg/pru_virtqueue.cwith a temporarypru/io.hstub; only expected 64-bit host pointer-size warnings from existing PRU address castsNotes
pru_rpmsg_receive()uint16_t *src/uint16_t *dstAPI to avoid an ABI/API break. The issue's width question remains a possible follow-up if maintainers want a breaking API update.