From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Oleg Nesterov <oleg@redhat.com>,
Steven Rostedt <rostedt@goodmis.org>
Subject: [ 13/17] debugfs: debugfs_remove_recursive() must not rely on list_empty(d_subdirs)
Date: Mon, 12 Aug 2013 23:35:59 -0700 [thread overview]
Message-ID: <20130813063502.789393673@linuxfoundation.org> (raw)
In-Reply-To: <20130813063501.728847844@linuxfoundation.org>
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Nesterov <oleg@redhat.com>
commit 776164c1faac4966ab14418bb0922e1820da1d19 upstream.
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.com
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/debugfs/inode.c | 69 ++++++++++++++++-------------------------------------
1 file changed, 22 insertions(+), 47 deletions(-)
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -527,8 +527,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove);
*/
void debugfs_remove_recursive(struct dentry *dentry)
{
- struct dentry *child;
- struct dentry *parent;
+ struct dentry *child, *next, *parent;
if (!dentry)
return;
@@ -538,61 +537,37 @@ void debugfs_remove_recursive(struct den
return;
parent = dentry;
+ down:
mutex_lock(&parent->d_inode->i_mutex);
+ list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) {
+ if (!debugfs_positive(child))
+ continue;
- while (1) {
- /*
- * When all dentries under "parent" has been removed,
- * walk up the tree until we reach our starting point.
- */
- if (list_empty(&parent->d_subdirs)) {
- mutex_unlock(&parent->d_inode->i_mutex);
- if (parent == dentry)
- break;
- parent = parent->d_parent;
- mutex_lock(&parent->d_inode->i_mutex);
- }
- child = list_entry(parent->d_subdirs.next, struct dentry,
- d_u.d_child);
- next_sibling:
-
- /*
- * If "child" isn't empty, walk down the tree and
- * remove all its descendants first.
- */
+ /* perhaps simple_empty(child) makes more sense */
if (!list_empty(&child->d_subdirs)) {
mutex_unlock(&parent->d_inode->i_mutex);
parent = child;
- mutex_lock(&parent->d_inode->i_mutex);
- continue;
+ goto down;
}
- __debugfs_remove(child, parent);
- if (parent->d_subdirs.next == &child->d_u.d_child) {
- /*
- * Try the next sibling.
- */
- if (child->d_u.d_child.next != &parent->d_subdirs) {
- child = list_entry(child->d_u.d_child.next,
- struct dentry,
- d_u.d_child);
- goto next_sibling;
- }
-
- /*
- * Avoid infinite loop if we fail to remove
- * one dentry.
- */
- mutex_unlock(&parent->d_inode->i_mutex);
- break;
- }
- simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+ up:
+ if (!__debugfs_remove(child, parent))
+ simple_release_fs(&debugfs_mount, &debugfs_mount_count);
}
- parent = dentry->d_parent;
+ mutex_unlock(&parent->d_inode->i_mutex);
+ child = parent;
+ parent = parent->d_parent;
mutex_lock(&parent->d_inode->i_mutex);
- __debugfs_remove(dentry, parent);
+
+ if (child != dentry) {
+ next = list_entry(child->d_u.d_child.next, struct dentry,
+ d_u.d_child);
+ goto up;
+ }
+
+ if (!__debugfs_remove(child, parent))
+ simple_release_fs(&debugfs_mount, &debugfs_mount_count);
mutex_unlock(&parent->d_inode->i_mutex);
- simple_release_fs(&debugfs_mount, &debugfs_mount_count);
}
EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
next prev parent reply other threads:[~2013-08-13 6:39 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-13 6:35 [ 00/17] 3.4.58-stable review Greg Kroah-Hartman
2013-08-13 6:35 ` [ 01/17] SCSI: Dont attempt to send extended INQUIRY command if skip_vpd_pages is set Greg Kroah-Hartman
2013-08-13 6:35 ` [ 02/17] SCSI: megaraid_sas: megaraid_sas driver init fails in kdump kernel Greg Kroah-Hartman
2013-08-13 6:35 ` [ 03/17] ext4: make sure group number is bumped after a inode allocation race Greg Kroah-Hartman
2013-08-13 6:35 ` [ 04/17] hwmon: (adt7470) Fix incorrect return code check Greg Kroah-Hartman
2013-08-13 6:35 ` [ 05/17] virtio: console: fix race with port unplug and open/close Greg Kroah-Hartman
2013-08-13 6:35 ` [ 06/17] virtio: console: fix race in port_fops_open() and port unplug Greg Kroah-Hartman
2013-08-13 6:35 ` [ 07/17] virtio: console: clean up port data immediately at time of unplug Greg Kroah-Hartman
2013-08-13 6:35 ` [ 08/17] virtio: console: fix raising SIGIO after port unplug Greg Kroah-Hartman
2013-08-13 6:35 ` [ 09/17] virtio: console: return -ENODEV on all read operations after unplug Greg Kroah-Hartman
2013-08-13 6:35 ` [ 10/17] ext4: fix mount/remount error messages for incompatible mount options Greg Kroah-Hartman
2013-08-13 6:35 ` [ 11/17] cifs: extend the buffer length enought for sprintf() using Greg Kroah-Hartman
2013-08-13 6:35 ` [ 12/17] usb: core: dont try to reset_device() a port that got just disconnected Greg Kroah-Hartman
2013-08-13 6:35 ` Greg Kroah-Hartman [this message]
2013-08-13 6:36 ` [ 14/17] tracing: Fix fields of struct trace_iterator that are zeroed by mistake Greg Kroah-Hartman
2013-08-13 6:36 ` [ 15/17] SCSI: nsp32: use mdelay instead of large udelay constants Greg Kroah-Hartman
2013-08-13 6:36 ` [ 16/17] vfs: d_obtain_alias() needs to use "/" as default name Greg Kroah-Hartman
2013-08-13 6:36 ` [ 17/17] perf tools: Add anonymous huge page recognition Greg Kroah-Hartman
2013-08-13 11:49 ` [ 00/17] 3.4.58-stable review Guenter Roeck
2013-08-13 17:58 ` Greg Kroah-Hartman
2013-08-13 20:19 ` Guenter Roeck
2013-08-13 20:49 ` Geert Uytterhoeven
2013-08-13 22:36 ` Guenter Roeck
2013-08-14 8:26 ` Geert Uytterhoeven
2013-08-14 10:14 ` Guenter Roeck
2013-08-15 6:36 ` Greg Kroah-Hartman
2013-08-15 7:08 ` Guenter Roeck
2013-08-15 8:40 ` Guenter Roeck
2013-08-16 0:54 ` Greg Kroah-Hartman
2013-08-15 9:07 ` Guenter Roeck
2013-08-16 0:58 ` Greg Kroah-Hartman
2013-08-16 1:07 ` Guenter Roeck
2013-08-15 14:45 ` Guenter Roeck
2013-08-16 1:22 ` Greg Kroah-Hartman
2013-08-16 1:28 ` Guenter Roeck
2013-08-16 1:38 ` Greg Kroah-Hartman
2013-08-15 15:12 ` Guenter Roeck
2013-08-16 1:18 ` Greg Kroah-Hartman
2013-08-15 6:35 ` Greg Kroah-Hartman
2013-08-15 16:54 ` Luis Henriques
2013-08-15 6:34 ` Greg Kroah-Hartman
2013-08-15 6:31 ` Greg Kroah-Hartman
2013-08-15 7:43 ` Guenter Roeck
2013-08-15 7:55 ` Geert Uytterhoeven
2013-08-15 8:05 ` Guenter Roeck
2013-08-16 4:53 ` Guenter Roeck
2013-08-16 5:10 ` Greg Kroah-Hartman
2013-08-16 8:26 ` Guenter Roeck
2013-08-16 12:41 ` Greg Kroah-Hartman
2013-08-16 20:27 ` Guenter Roeck
2013-08-16 21:55 ` Geert Uytterhoeven
2013-08-16 22:39 ` Guenter Roeck
2013-08-16 23:08 ` Greg Kroah-Hartman
2013-08-16 0:53 ` Greg Kroah-Hartman
2013-08-13 20:33 ` Guenter Roeck
2013-08-13 17:19 ` Shuah Khan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130813063502.789393673@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=oleg@redhat.com \
--cc=rostedt@goodmis.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox