• Oleg Nesterov's avatar
    debugfs: debugfs_remove_recursive() must not rely on list_empty(d_subdirs) · 776164c1
    Oleg Nesterov authored
    debugfs_remove_recursive() is wrong,
    
    1. it wrongly assumes that !list_empty(d_subdirs) means that this
       dir should be removed.
    
       This is not that bad by itself, but:
    
    2. if d_subdirs does not becomes empty after __debugfs_remove()
       it gives up and silently fails, it doesn't even try to remove
       other entries.
    
       However ->d_subdirs can be non-empty because it still has the
       already deleted !debugfs_positive() entries.
    
    3. simple_release_fs() is called even if __debugfs_remove() fails.
    
    Suppose we have
    
    	dir1/
    		dir2/
    			file2
    		file1
    
    and someone opens dir1/dir2/file2.
    
    Now, debugfs_remove_recursive(dir1/dir2) succeeds, and dir1/dir2 goes
    away.
    
    But debugfs_remove_recursive(dir1) silently fails and doesn't remove
    this directory. Because it tries to delete (the already deleted)
    dir1/dir2/file2 again and then fails due to "Avoid infinite loop"
    logic.
    
    Test-case:
    
    	#!/bin/sh
    
    	cd /sys/kernel/debug/tracing
    	echo 'p:probe/sigprocmask sigprocmask' >> kprobe_events
    	sleep 1000 < events/probe/sigprocmask/id &
    	echo -n >| kprobe_events
    
    	[ -d events/probe ] && echo "ERR!! failed to rm probe"
    
    And after that it is not possible to create another probe entry.
    
    With this patch debugfs_remove_recursive() skips !debugfs_positive()
    files although this is not strictly needed. The most important change
    is that it does not try to make ->d_subdirs empty, it simply scans
    the whole list(s) recursively and removes as much as possible.
    
    Link: http://lkml.kernel.org/r/20130726151256.GC19472@redhat.comAcked-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: 's avatarOleg Nesterov <oleg@redhat.com>
    Signed-off-by: 's avatarSteven Rostedt <rostedt@goodmis.org>
    776164c1
Name
Last commit
Last update
..
Makefile Loading commit data...
file.c Loading commit data...
inode.c Loading commit data...