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]

Reply via email to