arch/sim: Fix OOB read/write in usrsock_ioctl_handler#19000
Conversation
usrsock_ioctl_handler() copies req->arglen bytes from the request payload into the fixed-size usrsock->out buffer without validating that the payload fits either the received request or the destination buffer. This is the same class of vulnerability as the one already fixed in nrf91_modem_sock.c (commit a43fb69). Add three checks before the copy: - len >= sizeof(*req): ensure the full request header is present. - copylen <= len - sizeof(*req): payload must fit the received data. - copylen <= SIM_USRSOCK_BUFSIZE - sizeof(*ack): payload must fit the destination buffer. Signed-off-by: hanzj <hanzjian@zepp.com>
There was a problem hiding this comment.
Hello @Zepp-Hanzj, checkpatch, code review and pattern matching (while good) generally aren't sufficient testing. In this case, since the simulator doesn't require specific hardware, could you please perform a test to make sure this fixes the regression?
The code does look fine though.
Verification ReportTested on the simulator target with Build ConfigurationTest MethodAdded a direct unit test function Test Codeint usrsock_ioctl_handler_test(void)
{
struct usrsock_request_ioctl_s req;
int pass = 0;
int fail = 0;
int ret;
syslog(LOG_INFO, "=== usrsock_ioctl_handler boundary tests ===\n");
/* Test 1: len < sizeof(*req) should return -EINVAL */
memset(&req, 0, sizeof(req));
req.head.reqid = USRSOCK_REQUEST_IOCTL;
req.usockid = 0;
req.cmd = FIONBIO;
req.arglen = 0;
ret = usrsock_ioctl_handler(&g_usrsock, &req, 1); /* len=1 < sizeof(req) */
/* Test 2: arglen > len - sizeof(*req) => -EINVAL (OOB read prevention) */
memset(&req, 0, sizeof(req));
req.head.reqid = USRSOCK_REQUEST_IOCTL;
req.usockid = 0;
req.cmd = FIONBIO;
req.arglen = 8192;
ret = usrsock_ioctl_handler(&g_usrsock, &req, sizeof(req));
/* Test 3: arglen > SIM_USRSOCK_BUFSIZE - sizeof(*ack) => -EINVAL
* (OOB write prevention). Note: arglen is uint16_t (max 65535) and
* SIM_USRSOCK_BUFSIZE is 400KB, so this check is defense-in-depth.
*/
memset(&req, 0, sizeof(req));
req.head.reqid = USRSOCK_REQUEST_IOCTL;
req.usockid = 0;
req.cmd = FIONBIO;
req.arglen = UINT16_MAX;
ret = usrsock_ioctl_handler(&g_usrsock, &req, sizeof(req) + UINT16_MAX);
/* Test 4: valid request with arglen=0 should pass boundary checks */
memset(&req, 0, sizeof(req));
req.head.reqid = USRSOCK_REQUEST_IOCTL;
req.usockid = 0;
req.cmd = FIONBIO;
req.arglen = 0;
ret = usrsock_ioctl_handler(&g_usrsock, &req, sizeof(req));
}Test ResultsTest Coverage
Notes
Final Clean BuildAfter removing the test code, a clean rebuild with |
My apologies for the oversight. I've since updated the PR with runtime verification on the simulator — directly testing the usrsock_ioctl_handler with crafted inputs covering all three boundary checks. All 4 test cases pass. I'll make sure to include proper verification upfront in future PRs. Thanks for the review! |
Description
Fix out-of-bounds read and write in
usrsock_ioctl_handler()inarch/sim/src/sim/sim_usrsock.c, the same class of vulnerability already fixed innrf91_modem_sock.c(PR #18998).Problem
usrsock_ioctl_handler()copiesreq->arglenbytes from the request payload into the fixed-sizeusrsock->outbuffer (SIM_USRSOCK_BUFSIZE= 400KB) without validating that the payload fits either the received request or the destination buffer. A crafted ioctl request with an inflatedarglentriggers OOB read and OOB write.Solution
Add three validation checks before the
memcpy, identical to the fix applied tonrf91_modem_sock.c:len >= sizeof(*req): ensure the full request header is present.copylen <= len - sizeof(*req): payload must fit the received data.copylen <= SIM_USRSOCK_BUFSIZE - sizeof(*ack): payload must fit the destination buffer.Verification
✅ Checkpatch: All checks pass
✅ Consistency: Pattern matches the nrf91 fix (PR #18998) and the recvfrom handler buffer-size check
✅ Runtime testing: Direct boundary test on
sim:nshwithCONFIG_SIM_NETUSRSOCK— all 4 test cases pass:✅ Clean build: Zero warnings after removing test code, no regression
References
Signed-off-by
hanzj hanzjian@zepp.com