diskfs_startup_diskfs unlocks the root node after looking up the
virtual root in it, then lets go of it with diskfs_nput, which unlocks
it a second time.  Release only its reference.

With --virtual-root=., the lookup of "." gives back the root node
itself, already unlocked with the root: do not unlock it again either.

A default mutex does not check its owner, so the second unlock goes
unnoticed unless another thread holds the lock by then, which loses it.
With error-checking mutexes, an ext2fs started with --virtual-root=.
dies at that unlock.
---
 libdiskfs/init-startup.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libdiskfs/init-startup.c b/libdiskfs/init-startup.c
index d51cc2787..736cdb502 100644
--- a/libdiskfs/init-startup.c
+++ b/libdiskfs/init-startup.c
@@ -120,8 +120,10 @@ diskfs_startup_diskfs (mach_port_t fs_bootstrap, int flags)
         if _diskfs_chroot_directory is non-null.  */
       old = diskfs_root_node;
       diskfs_root_node = np;
-      pthread_mutex_unlock (&np->lock);
-      diskfs_nput (old);
+      /* A virtual root that is the root itself was unlocked with it.  */
+      if (np != old)
+       pthread_mutex_unlock (&np->lock);
+      diskfs_nrele (old);
     }
 
   if (fs_bootstrap != MACH_PORT_NULL)
-- 
2.56.0


Reply via email to