casaroli opened a new pull request, #21490: URL: https://github.com/apache/nuttx/pull/21490
## Summary `poll_teardown()` looked up the file again by its descriptor. If another thread closes the descriptor during `poll()`, the lookup fails, so the driver is not told that the poll ended and the reference of the setup is not dropped. The file stays open, and the driver keeps a pointer to the `struct pollfd_s`, which is gone when `poll()` returns. The next event of that driver uses this pointer. In a kernel build this panics the kernel from an ordinary program: a pipe, one thread in `poll()` on the read end, and another thread that calls `close()` on it. Then the close of the write end posts an event through the old pointer: ``` arm64_el1_undef: Undefined instruction at 0x402edc10 dump_assert_info: Assertion failed panic: at file: common/arm64_fatal.c:696 ``` This PR keeps the file of the setup in `struct pollfd_s` and uses it in `poll_teardown()`. The file stays open until `poll()` ends, and then it closes. `epoll` already keeps the file this way. ## Impact All drivers and all build modes: `poll()` and `select()`. The poll method of a driver does not change. `struct pollfd_s` is kernel only; the user `struct pollfd` does not change. No ABI change. Not a breaking change. A descriptor that another thread closes during `poll()` now closes when `poll()` ends. Before, it never closed. Size, image text from master 6e1126a2362, float and numbered arguments off: Cortex-M0 `nucleo-f072rb:nsh` 0, Cortex-M3 `nucleo-f103rb:nsh` 0, `rv-virt:nsh` -10, `qemu-armv8a:nsh` -8. Data and bss do not change. RAM: `struct pollfd_s` grows by one pointer. `poll()` keeps 4 entries on its stack (+16 bytes on a 32-bit CPU, +32 on a 64-bit CPU), a Unix domain socket has 4 entries, and an `epoll` entry has one. This comes from the types and was not measured. Documentation: `Documentation/os/filesystem/index.rst` names the new field, in this commit. ## Testing Test: `poll_close_test` in ostest, apache/nuttx-apps PR to follow, as a draft that depends on this PR. Another thread closes the read end of a pipe during `poll()`. When `poll()` ends, the write end must report `POLLERR`, because no reader is left. | Config | master 6e1126a2362 | this PR | |---|---|---| | `qemu-armv8a:knsh` (kernel) | ERROR: no `POLLERR`, then kernel panic | PASS, ostest status 0 | | `qemu-armv8a:nsh` (flat) | ERROR: no `POLLERR`, ostest status 256 | PASS, ostest status 0 | | `rv-virt:knsh64` (kernel) | not run | PASS, ostest status 0 | | `mps2-an500:knsh` (protected) | not run | PASS, ostest status 0 | `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]
