fix: reject non-zero status in OP_REQ_DEVLIST/IMPORT requests
Replace debug_assert!(status == 0) with proper error returns. Per the USB/IP protocol spec, the status field in these requests is "unused, shall be set to 0" — a non-zero value indicates a non-compliant client and should be rejected at the parsing boundary. Also document fuzzer crash triage guidelines in CLAUDE.md. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d97381396a
commit
e5339e9df6
2 changed files with 18 additions and 2 deletions
|
|
@ -34,6 +34,14 @@ nix run .#fuzz-clean-usbip -- fuzz_urb_hid # Prune fixed artifacts
|
|||
|
||||
Crash artifacts: `lib/fuzz/artifacts/<target>/`. Response validation is in `lib/src/fuzz_helpers.rs`.
|
||||
|
||||
### Fixing fuzzer crashes
|
||||
|
||||
1. **Priority**: Protect the host process and host kernel from untrusted client gaining code execution or privilege escalation. DoS is not a concern — the client would only be DoSing its own service.
|
||||
2. **Check reachability**: Determine whether the crashing state can be reached by a normal, well-behaved client (check the Linux kernel USB/IP source at `../linux/drivers/usb/usbip/` and `../linux/tools/usb/usbip/`). If not reachable by a well-behaved client, return an error rather than continuing to process garbage.
|
||||
3. **No `unsafe`** in parsing or sanitization paths.
|
||||
4. **Validate at the boundary**: Check constraints immediately after deserialization, not deep in business logic.
|
||||
5. **Update fuzz assertions**: Tighten the invariant assertions in `lib/src/fuzz_helpers.rs` whenever you add or change a constraint — the fuzzer can only find violations it can check.
|
||||
|
||||
## Key architecture
|
||||
|
||||
- `handle_urb_loop()` — main URB dispatch loop, generic over async transport
|
||||
|
|
|
|||
|
|
@ -182,13 +182,21 @@ impl UsbIpCommand {
|
|||
match command {
|
||||
OP_REQ_DEVLIST => {
|
||||
let status = socket.read_u32().await?;
|
||||
debug_assert!(status == 0);
|
||||
if status != 0 {
|
||||
return Err(std::io::Error::other(format!(
|
||||
"OP_REQ_DEVLIST: non-zero status {status:#010X}, expected 0"
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(UsbIpCommand::OpReqDevlist { status })
|
||||
}
|
||||
OP_REQ_IMPORT => {
|
||||
let status = socket.read_u32().await?;
|
||||
debug_assert!(status == 0);
|
||||
if status != 0 {
|
||||
return Err(std::io::Error::other(format!(
|
||||
"OP_REQ_IMPORT: non-zero status {status:#010X}, expected 0"
|
||||
)));
|
||||
}
|
||||
let mut busid = [0; 32];
|
||||
socket.read_exact(&mut busid).await?;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue