jasonbu opened a new pull request, #18200:
URL: https://github.com/apache/nuttx/pull/18200
## Summary
Fix race condition in inode creation where inode data is accessed before
initialization completes in SMP scenarios.
## Problem Description
When creating named semaphores, events, or symlinks, the original code flow
was:
```c
inode_lock();
ret = inode_reserve(fullpath, mode, &inode); // Step 1: Create inode
inode_unlock(); // Step 2: Release lock
// Step 3: Initialize inode fields (OUTSIDE the lock!)
inode->u.i_nsem = nsem;
nsem->ns_inode = inode;
INODE_SET_NAMEDSEM(inode);
atomic_fetch_add(&inode->i_crefs, 1);
nxsem_init(&nsem->ns_sem, 0, value);
```
Race Condition Scenario (SMP)
```
CPU0 CPU1
---- ----
inode_lock()
inode_reserve() -> inode created
inode_unlock()
inode_lock()
inode_find() -> finds the inode!
inode_unlock()
// CPU1 now uses inode with:
// - u.i_nsem = NULL (not set yet!)
// - i_crefs not incremented
// - semaphore not initialized
// -> UNDEFINED BEHAVIOR / CRASH
inode->u.i_nsem = nsem; // Too late!
INODE_SET_NAMEDSEM(inode);
```
In the SMP scenario above:
CPU0 creates the inode via inode_reserve() and immediately releases the lock
CPU1 re-enters with the same path, calls inode_find() and successfully
finds the inode (because it exists in the pseudo-filesystem)
CPU1 returns the inode to the caller, but the inode's critical fields
(u.i_nsem, u.i_link, u.i_nevent) are still NULL/uninitialized
CPU0 then initializes these fields, but CPU1 has already returned
an incomplete inode to its caller
The caller on CPU1 dereferences NULL pointers or accesses uninitialized
data, causing crashes or undefined behavior
Solution
Move all inode initialization operations inside the critical section:
This ensures that when inode_unlock() is called, the inode is fully
initialized and safe for concurrent access.
## Files Changed
fs/vfs/fs_symlink.c - Fix for symlink inode (u.i_link)
fs/semaphore/sem_open.c - Fix for named semaphore inode (u.i_nsem)
fs/event/event_open.c - Fix for named event inode (u.i_nevent)
## Impact
Without fix: Random crashes, NULL pointer dereferences, or data
corruption in SMP systems when multiple CPUs concurrently create/open
the same named semaphore, event, or symlink
With fix: Proper serialization ensures inode is fully initialized
before being visible to other CPUs
## Testing
CI-test, local sim ostest, qemu-armv7a-smp ostest.
Tested on SMP configuration with concurrent access patterns using
stress tests that create/open the same named objects from multiple cores.
--
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]