Zepp-Hanzj commented on PR #19000:
URL: https://github.com/apache/nuttx/pull/19000#issuecomment-4589302265
## Verification Report
Tested on the simulator target with `CONFIG_SIM_NETUSRSOCK` enabled (which
compiles `sim_usrsock.c` and activates the `usrsock_ioctl_handler` code path).
### Build Configuration
```
Board: sim:nsh
Enabled configs:
CONFIG_SIM_NETUSRSOCK=y
CONFIG_NET_USRSOCK_CUSTOM=y
CONFIG_NET=y
CONFIG_NET_USRSOCK=y
CONFIG_NET_USRSOCK_TCP=y
CONFIG_NET_USRSOCK_UDP=y
Toolchain: GCC 9.2.1 (arm-none-eabi)
```
### Test Method
Added a direct unit test function `usrsock_ioctl_handler_test()` in
`sim_usrsock.c` that calls the handler with crafted inputs to exercise all
three boundary checks. The test was invoked from `sim_bringup()` during boot.
### Test Code
```c
int 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 Results
```
=== usrsock_ioctl_handler boundary tests ===
PASS: len < sizeof(*req) => -EINVAL
PASS: arglen > len - sizeof(*req) => -EINVAL (OOB read)
PASS: arglen > bufsize - sizeof(*ack) => -EINVAL (OOB write)
PASS: valid request (arglen=0) => -22 (boundary checks passed)
=== Results: 4 passed, 0 failed ===
```
### Test Coverage
| Test | Condition | Expected | Result |
|------|-----------|----------|--------|
| 1 | `len=1 < sizeof(req)` | `-EINVAL` | ✅ PASS |
| 2 | `arglen=8192 > len - sizeof(req)` (OOB read) | `-EINVAL` | ✅ PASS |
| 3 | `arglen=UINT16_MAX > bufsize - sizeof(ack)` (OOB write) | `-EINVAL` |
✅ PASS |
| 4 | `arglen=0`, valid request | Pass boundary checks | ✅ PASS |
### Notes
- **Test 3 (OOB write)**: `arglen` is `uint16_t` (max 65535) while
`SIM_USRSOCK_BUFSIZE` is 400KB (409600). The check `copylen >
SIM_USRSOCK_BUFSIZE - sizeof(*ack)` is **defense-in-depth** — it guards against
future buffer size reductions and is consistent with the pattern used in other
handlers (e.g., `recvfrom`).
- **Test 4**: With `usockid=0` (invalid socket), `host_usrsock_ioctl()`
returns `-22` (`-EINVAL`). The key point is that the boundary checks did
**not** reject the request — the error comes from downstream, confirming the
validation logic is correct.
### Final Clean Build
After removing the test code, a clean rebuild with `make distclean` +
`configure` + `make` produces zero warnings, confirming no regression.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]