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]

Reply via email to