This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 80bf4835e80 fs/vfs: hold the inode lock in read_pseudodir()
80bf4835e80 is described below

commit 80bf4835e800ec45b6a5df7404a5ee8cbe88c393
Author: dengwenqi <[email protected]>
AuthorDate: Wed Nov 11 16:17:56 2026 +0800

    fs/vfs: hold the inode lock in read_pseudodir()
    
    read_pseudodir() reads pdir->next and its name, operations and child
    pointers without the inode lock, and takes the lock only to advance to
    the next peer.  If another thread unregisters a driver in between, the
    peer can be unlinked and freed, and readdir() then dereferences freed
    memory.
    
    Take the inode lock at the start of read_pseudodir(), as
    seek_pseudodir() already does, and release it on both return paths.
    
    Signed-off-by: dengwenqi <[email protected]>
    Signed-off-by: jingfei <[email protected]>
---
 fs/vfs/fs_dir.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/fs/vfs/fs_dir.c b/fs/vfs/fs_dir.c
index 156abe15550..1e0d1753a00 100644
--- a/fs/vfs/fs_dir.c
+++ b/fs/vfs/fs_dir.c
@@ -299,9 +299,17 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir,
                           FAR struct dirent *entry)
 {
   FAR struct fs_pseudodir_s *pdir = (FAR struct fs_pseudodir_s *)dir;
-  FAR struct inode *next = pdir->next;
+  FAR struct inode *next;
   FAR struct inode *prev;
 
+  /* Hold the lock while the entry is used: a concurrent unregister may
+   * unlink and free it.
+   */
+
+  inode_lock();
+
+  next = pdir->next;
+
   /* Check if we are at the end of the list */
 
   if (next == NULL)
@@ -310,6 +318,7 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir,
        * readdir. Here we return -ENOENT to signal the end of the directory.
        */
 
+      inode_unlock();
       return -ENOENT;
     }
 
@@ -394,8 +403,6 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir,
 
   /* Now get the inode to visit next time that readdir() is called */
 
-  inode_lock();
-
   prev       = pdir->next;
   pdir->next = prev->i_peer; /* The next node to visit */
 

Reply via email to