NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/46990: tmpfs_gro_genealogy() panic - rename/rmdir race condition not handled



>Number:         46990
>Category:       kern
>Synopsis:       tmpfs_gro_genealogy() panic - rename/rmdir race condition not 
>handled
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Sep 20 14:50:00 +0000 2012
>Originator:     Dr. Wolfgang Stukenbrock
>Release:        NetBSD-current (Head)
>Organization:
Dr. Nagler & Company GmbH
>Environment:
        
        
System: NetBSD test-s0 4.0 NetBSD 4.0 (NSW-WS) #0: Tue Aug 17 17:28:09 CEST 
2010 wgstuken@test-s0:/usr/src/sys/arch/amd64/compile/NSW-WS amd64
Architecture: x86_64
Machine: amd64
>Description:
        There is a race condition between rename() and rmdir(9 operations that 
may lead to a NULL pointer
        reference in the kernel in tmpfs.
        The rename() call determine all relevant vnode's but than gives up all 
lock's on them.
        At this point, the directory to that the the object should be moved may 
get deleted.
        If this happens, tmpfs_gro_genealogy() will lock the directory-vnode 
again, but that is no longer
        valid. The functions simply gets the no longer valid pointer to the 
parent-tmpfs-node structure and
        will try to lock the tn_vlock mutex in it - segfault in kernel ...
>How-To-Repeat:
        I run a dirconc version that uses seperate seed information in each 
worker on tmpfs on a system with
        12 CPU's found by NetBSD to validate my backport of tmpfs to 5.1_STABLE.
        It crashes from time to time with a reference to address 0x10.
        The code rm sys_rmdir() has not relay changed from 5.1_STABLE to 
current.
        I use the complete tmpfs-code from Head, so the problem exists there 
too.
>Fix:
        The comment in tmpfs_rename.c tmpfs_gro_genealogy() that dnode may not 
be NULL is simply
        not true. Need to check if dnode is NULL and return an error (e.g. 
ENOENT) instead.

--- potential patch:

-       KASSERT(dnode != NULL);
+       if (dnode == NULL) {
+               vput(vp);
+               *intermediate_node_ret = NULL;
+               return ENOENT;


        and correct the comment above ...
+       }

>Unformatted:
        
        


Home | Main Index | Thread Index | Old Index