Donny9 opened a new pull request, #17731:
URL: https://github.com/apache/nuttx/pull/17731
## Summary
This PR contains four bug fixes and improvements to the NuttX file system
layer, specifically focusing on file descriptor management and event handling:
### 1. Fix fd allocation exceeding OPEN_MAX (fs/inode/fs_files.c)
The OPEN_MAX boundary check in `fdlist_extend()` was incorrectly using
`orig_rows` instead of `(orig_rows + 1)` when validating whether the new
allocation would exceed limits. This allowed file descriptor allocation to
succeed even when it would exceed OPEN_MAX, potentially causing memory
corruption or exceeding system resource limits.
**Example:** With OPEN_MAX=256 and CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=32,
when orig_rows=8 (already at 256 fds), the old code would check `32 * 8 > 256`
(false, allows extension to 288), while the fixed code correctly checks `32 * 9
> 256` (true, blocks extension).
### 2. Fix fd tag loss during parent-to-child inheritance
(fs/inode/fs_files.c)
When child processes inherited file descriptors from parent via
`fdlist_copy()`, the fd tags (`fd_tag_fdsan` and `fd_tag_fdcheck`) were not
being preserved. This caused assertion failures when child processes closed
inherited fds, as the fdcheck/fdsan subsystems expected matching tags.
The fix adds a `copy` parameter to `fdlist_install()` to distinguish between
new fd allocation (initialize fresh tags) and fd inheritance (preserve parent
tags). This is critical for any application using fork/clone with inherited
file descriptors when CONFIG_FDSAN or CONFIG_FDCHECK are enabled.
### 3. Add DEBUGASSERT for full file descriptor list (fs/inode/fs_files.c)
Added a debug assertion when file descriptors exceed the maximum limit,
helping developers identify fd leaks early during development. When a task
exhausts its fd limit, it will actively crash (in debug builds) providing a
clear indication of the problem, rather than failing silently or with obscure
errors.
### 4. Fix busy loop in eventfd/timerfd (fs/vfs/fs_eventfd.c,
fs/vfs/fs_timerfd.c)
Updated semaphore handling to properly advance to the next waiting task,
preventing busy loops in event and timer file descriptor operations. Without
this fix, certain polling scenarios could cause the system to spin
unnecessarily.
## Impact
**Users:**
- Applications using fork/clone with CONFIG_FDSAN or CONFIG_FDCHECK will no
longer crash when closing inherited file descriptors
- Systems can no longer exceed OPEN_MAX limit, preventing potential memory
corruption
- Debug builds will clearly identify file descriptor leaks instead of
obscure failures
- Event and timer fd operations will be more efficient without busy loops
**Build Process:**
- No build process changes
- All changes are runtime behavior fixes
**Hardware:**
- No hardware-specific changes
- Fixes apply to all architectures
**Documentation:**
- No documentation changes required
**Security:**
- Prevents potential buffer overflow/memory corruption from exceeding
OPEN_MAX
- Improves system stability and resource management
**Compatibility:**
- All changes are backward compatible
- Fixes broken functionality without changing APIs
- May expose existing bugs in applications that were exceeding OPEN_MAX
undetected
## Testing
### Test 1: OPEN_MAX Boundary Check
**Test Procedure:**
```c
// Test program that attempts to open more than OPEN_MAX files
int fds[300];
int count = 0;
for (int i = 0; i < 300; i++) {
fds[i] = open("/dev/null", O_RDONLY);
if (fds[i] < 0) {
printf("Failed at count %d, errno=%d\n", count, errno);
break;
}
count++;
}
```
Before Fix:
Could allocate up to 288 fds (exceeded OPEN_MAX=256 by 32)
Potential memory corruption
After Fix:
Correctly stops at or before OPEN_MAX (253-256 depending on stdio fds)
Returns -EMFILE when limit reached
No memory corruption
### Test 2: Fork with Inherited FDs
Test Procedure:
```c
// Parent opens files
int fd1 = open("/tmp/test.txt", O_RDWR);
int fd2 = socket(AF_INET, SOCK_STREAM, 0);
// Fork child process
pid_t pid = fork();
if (pid == 0) {
// Child closes inherited fds
close(fd1);
close(fd2);
exit(0);
}
```
After Fix:
Child successfully closes inherited fds
fd_tag_fdsan and fd_tag_fdcheck properly preserved
No crashes, all tests pass
Test Log:
Ran complete test suite with uv_run_tests_main including:
run_helper_tcp4_echo_server
Multiple fork/close cycles
File descriptor inheritance scenarios
All tests PASSED without assertions
### OSTest Verification:
Ran full OSTest suite with all patches applied:
```c
nsh> ostest
...
```
All tests PASSED
--
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]