fix: close connection on devid mismatch, matching kernel behavior
The kernel's valid_request() in stub_rx.c tears down the TCP connection when devid doesn't match (SDEV_EVENT_ERROR_TCP). Previously we sent an error response and continued, which is non-standard. Now we break out of the loop to close the connection, matching the kernel. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d5ddb48eff
commit
76f5134e25
1 changed files with 9 additions and 32 deletions
|
|
@ -326,23 +326,14 @@ pub async fn handle_urb_loop<T: AsyncReadExt + AsyncWriteExt + Unpin + Send + 's
|
|||
let out = header.direction == 0;
|
||||
|
||||
// Validate devid matches the imported device. The Linux
|
||||
// kernel performs this same check in stub_rx.c:293.
|
||||
// kernel's valid_request() in stub_rx.c performs this same
|
||||
// check and tears down the connection on mismatch.
|
||||
if header.devid != expected_devid {
|
||||
warn!(
|
||||
"devid mismatch: got {:#x}, expected {:#x}",
|
||||
"devid mismatch: got {:#x}, expected {:#x} — closing connection",
|
||||
header.devid, expected_devid
|
||||
);
|
||||
header.command = USBIP_RET_SUBMIT.into();
|
||||
let res = UsbIpResponse::usbip_ret_submit_fail(&header);
|
||||
match res.to_bytes() {
|
||||
Ok(bytes) => {
|
||||
if response_tx.send(bytes).await.is_err() {
|
||||
break Err(std::io::Error::other("Response channel closed"));
|
||||
}
|
||||
}
|
||||
Err(e) => warn!("Failed to serialize response for devid mismatch: {e}"),
|
||||
}
|
||||
continue;
|
||||
break Err(std::io::Error::other("devid mismatch"));
|
||||
}
|
||||
|
||||
// Validate endpoint number (must be 0-15 per USB spec).
|
||||
|
|
@ -575,29 +566,15 @@ pub async fn handle_urb_loop<T: AsyncReadExt + AsyncWriteExt + Unpin + Send + 's
|
|||
} => {
|
||||
trace!("Got USBIP_CMD_UNLINK for seqnum={unlink_seqnum:10x?}");
|
||||
|
||||
// Validate devid matches the imported device.
|
||||
// On mismatch, respond with status 0 ("not found"), matching
|
||||
// the Linux kernel's stub_recv_cmd_unlink() which returns 0
|
||||
// when the target URB doesn't exist.
|
||||
// Validate devid matches the imported device. The Linux
|
||||
// kernel's valid_request() in stub_rx.c performs this same
|
||||
// check and tears down the connection on mismatch.
|
||||
if header.devid != expected_devid {
|
||||
warn!(
|
||||
"UNLINK devid mismatch: got {:#x}, expected {:#x}",
|
||||
"UNLINK devid mismatch: got {:#x}, expected {:#x} — closing connection",
|
||||
header.devid, expected_devid
|
||||
);
|
||||
header.command = USBIP_RET_UNLINK.into();
|
||||
let res = UsbIpResponse::UsbIpRetUnlink {
|
||||
header: header.clone(),
|
||||
status: 0,
|
||||
};
|
||||
match res.to_bytes() {
|
||||
Ok(bytes) => {
|
||||
if response_tx.send(bytes).await.is_err() {
|
||||
break Err(std::io::Error::other("Response channel closed"));
|
||||
}
|
||||
}
|
||||
Err(e) => warn!("Failed to serialize UNLINK devid mismatch response: {e}"),
|
||||
}
|
||||
continue;
|
||||
break Err(std::io::Error::other("devid mismatch"));
|
||||
}
|
||||
|
||||
header.command = USBIP_RET_UNLINK.into();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue