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