casaroli opened a new pull request, #21533: URL: https://github.com/apache/nuttx/pull/21533
## Summary In a kernel build, `sendto()` and `recvfrom()` keep the address in a `struct sockaddr_storage` on the kernel stack. `sendto()` copied `tolen` bytes to it, and `tolen` comes from the program, so a large `tolen` wrote over the kernel stack: `sendto()` with an address length of 4096 panics the kernel. `recvfrom()` copied `*fromlen` bytes from it back to the program, so a large `*fromlen` read past it, and a socket type that returns no address (TCP) gave the program the old bytes of the stack. This PR: - `sendto()`: returns `EINVAL` when `tolen` is larger than `struct sockaddr_storage`, as other systems do. - `recvfrom()`: clears the structure and uses its own copy of the length, at most the size of the structure. It copies back at most that length, also when the socket gives a longer length (usrsock gives the length before truncation), and writes the length only when `fromlen` is not NULL. ## Impact Kernel builds only (`CONFIG_BUILD_KERNEL`); flat and protected builds have no such copy and do not change. No architecture code. `sendto()` with an address longer than `struct sockaddr_storage` now fails with `EINVAL`; any other call behaves as before. No flat-build API change. No Documentation change: `Documentation/reference/user/11_network.rst` lists `EINVAL` for `sendto()` already. ## Testing Test program `dgramabs.c` (the socket cases), on a TCP connection over loopback and a local stream socket pair: `recvfrom()` with `*fromlen` = `sizeof(struct sockaddr_storage)` (`recvtcp`) and = 4096 (`recvtcplong`) must leave the buffer after the address zero and give a length of at most the size of the structure; `sendto()` with an address length of 4096 must fail with `EINVAL` (`tolong`, also as a separate program `kaddrlong.c`). The tests are not in apps; a regression guard would need an apps PR. | `qemu-armv8a:knsh` (kernel), HVF | master 43f7f34b995 | this branch | |---|---|---| | `recvtcp` | FAIL: 36 bytes that are not zero after the address | PASS | | `recvtcplong` | FAIL: length 4096, 248 bytes that are not zero after the address | PASS | | `recvlocal` | PASS | PASS | | `tolong` (`kaddrlong` on master) | kernel panic, `ELR_ELn: 0x7878787878787878` (the bytes of the address) | PASS (`EINVAL`) | | ostest | status 0 | status 0 | `qemu-armv8a:nsh` (flat), HVF, the tests as builtin applications: the same results on master and on this branch (no change expected), ostest status 0. In the flat build `recvtcplong` gives the length 4096 back unchanged (not in this PR), and `kaddrlong` on master reports `ENOENT`: a flat build has no such copy. The other `dgramabs` cases are local socket address cases, the same on master and this branch. Options: `NET`, `NET_LOCAL`, `NET_LOCAL_STREAM`, `NET_LOCAL_DGRAM`, `NET_TCP`, `NET_TCPBACKLOG`, `NET_IPv4`, `NET_LOOPBACK`, `NETDEV_LATEINIT`, `NET_SOCKOPTS`, `PIPES`. Builds with `EXTRAFLAGS="-Wno-cpp -Werror"` and the network options, each OK with no warning and `recvfrom.c` built: `qemu-armv8a:knsh`, `rv-virt:knsh64` (kernel), `qemu-armv8a:nsh` (flat), `mps2-an500:knsh` (protected). Compilers: aarch64 GCC 14.2, riscv-none-elf GCC 14.3, arm-none-eabi GCC 15.3. Not run: usrsock, and other architectures (the change has no architecture code). `tools/checkpatch.sh -c -u -m -g` passes. -- 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]
