All of lore.kernel.org
 help / color / mirror / Atom feed
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: [ 52/60] debugfs: debugfs_remove_recursive() must not rely on list_empty(d_subdirs)
Date: Mon, 12 Aug 2013 23:34:19 -0700	[thread overview]
Message-ID: <20130813063338.520866227@linuxfoundation.org> (raw)
In-Reply-To: <20130813063331.950321483@linuxfoundation.org>

3.10-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
@@ -533,8 +533,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 (IS_ERR_OR_NULL(dentry))
 		return;
@@ -544,61 +543,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);
 



  parent reply	other threads:[~2013-08-13  6:33 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-13  6:33 [ 00/60] 3.10.7-stable review Greg Kroah-Hartman
2013-08-13  6:33 ` [ 01/60] SCSI: Dont attempt to send extended INQUIRY command if skip_vpd_pages is set Greg Kroah-Hartman
2013-08-13  6:33 ` [ 02/60] SCSI: megaraid_sas: megaraid_sas driver init fails in kdump kernel Greg Kroah-Hartman
2013-08-13  6:33 ` [ 03/60] virtio-scsi: Fix virtqueue affinity setup Greg Kroah-Hartman
2013-08-13  6:33 ` [ 04/60] powerpc: On POWERNV enable PPC_DENORMALISATION by default Greg Kroah-Hartman
2013-08-13  6:33 ` [ 05/60] powerpc: Fix hypervisor facility unavaliable vector number Greg Kroah-Hartman
2013-08-13  6:33 ` [ 06/60] powerpc: Rework setting up H/FSCR bit definitions Greg Kroah-Hartman
2013-08-13  6:33 ` [ 07/60] powerpc: Fix context switch DSCR on POWER8 Greg Kroah-Hartman
2013-08-13  6:33 ` [ 08/60] powerpc: Save the TAR register earlier Greg Kroah-Hartman
2013-08-13  6:33 ` [ 09/60] powerpc/tm: Fix context switching TAR, PPR and DSCR SPRs Greg Kroah-Hartman
2013-08-13  6:33 ` [ 10/60] ext4: destroy ext4_es_cachep on module unload Greg Kroah-Hartman
2013-08-13  6:33 ` [ 11/60] ext4: make sure group number is bumped after a inode allocation race Greg Kroah-Hartman
2013-08-13  6:33 ` [ 12/60] ext4: fix retry handling in ext4_ext_truncate() Greg Kroah-Hartman
2013-08-13  6:33 ` [ 13/60] regmap: cache: Make sure to sync the last register in a block Greg Kroah-Hartman
2013-08-13  6:33 ` [ 14/60] regmap: Add missing header for !CONFIG_REGMAP stubs Greg Kroah-Hartman
2013-08-13  6:33 ` [ 15/60] hwmon: (adt7470) Fix incorrect return code check Greg Kroah-Hartman
2013-08-13  6:33 ` [ 16/60] staging: zcache: fix "zcache=" kernel parameter Greg Kroah-Hartman
2013-08-13  6:33 ` [ 17/60] media: em28xx: fix assignment of the eeprom data Greg Kroah-Hartman
2013-08-13  6:33 ` [ 18/60] i2c: i2c-mxs: Use DMA mode even for small transfers Greg Kroah-Hartman
2013-08-13  6:33 ` [ 19/60] cpufreq: loongson2: fix regression related to clock management Greg Kroah-Hartman
2013-08-13  6:33 ` [ 20/60] cpufreq: rename ignore_nice as ignore_nice_load Greg Kroah-Hartman
2013-08-13  6:33 ` [ 21/60] ACPI / PM: Walk physical_node_list under physical_node_lock Greg Kroah-Hartman
2013-08-13  6:33 ` [ 22/60] tracing: Fix fields of struct trace_iterator that are zeroed by mistake Greg Kroah-Hartman
2013-08-13  6:33 ` [ 23/60] tracing: Make TRACE_ITER_STOP_ON_FREE stop the correct buffer Greg Kroah-Hartman
2013-08-13  6:33 ` [ 24/60] tracing: Use flag buffer_disabled for irqsoff tracer Greg Kroah-Hartman
2013-08-13  6:33 ` [ 25/60] tracing: Fix reset of time stamps during trace_clock changes Greg Kroah-Hartman
2013-08-13  6:33 ` [ 26/60] ALSA: usb-audio: do not trust too-big wMaxPacketSize values Greg Kroah-Hartman
2013-08-13  6:33 ` [ 27/60] ALSA: 6fire: fix DMA issues with URB transfer_buffer usage Greg Kroah-Hartman
2013-08-13  6:33 ` [ 28/60] Btrfs: release both paths before logging dir/changed extents Greg Kroah-Hartman
2013-08-13  6:33 ` [ 29/60] LOCKD: Dont call utsname()->nodename from nlmclnt_setlockargs Greg Kroah-Hartman
2013-08-13  6:33 ` [ 30/60] SUNRPC: Dont auto-disconnect from the local rpcbind socket Greg Kroah-Hartman
2013-08-13  6:33 ` [ 31/60] SUNRPC: If the rpcbind channel is disconnected, fail the call to unregister Greg Kroah-Hartman
2013-08-13  6:33 ` [ 32/60] virtio/console: Quit from splice_write if pipe->nrbufs is 0 Greg Kroah-Hartman
2013-08-13  6:34 ` [ 33/60] virtio/console: Add pipe_lock/unlock for splice_write Greg Kroah-Hartman
2013-08-13  6:34 ` [ 34/60] virtio: console: fix race with port unplug and open/close Greg Kroah-Hartman
2013-08-13  6:34 ` [ 35/60] virtio: console: fix race in port_fops_open() and port unplug Greg Kroah-Hartman
2013-08-13  6:34 ` [ 36/60] virtio: console: clean up port data immediately at time of unplug Greg Kroah-Hartman
2013-08-13  6:34 ` [ 37/60] virtio: console: fix raising SIGIO after port unplug Greg Kroah-Hartman
2013-08-13  6:34 ` [ 38/60] virtio: console: return -ENODEV on all read operations after unplug Greg Kroah-Hartman
2013-08-13  6:34 ` [ 39/60] drm/cirrus: Invalidate page tables when pinning a BO Greg Kroah-Hartman
2013-08-13  6:34 ` [ 40/60] drm/mgag200: " Greg Kroah-Hartman
2013-08-13  6:34 ` [ 41/60] drm/ast: invalidate " Greg Kroah-Hartman
2013-08-13  6:34 ` [ 42/60] drm: Dont pass negative delta to ktime_sub_ns() Greg Kroah-Hartman
2013-08-13  6:34 ` [ 43/60] drm/radeon: select audio dto based on encoder id for DCE3 Greg Kroah-Hartman
2013-08-13  6:34 ` [ 44/60] drm/radeon: stop sending invalid UVD destroy msg Greg Kroah-Hartman
2013-08-13  6:34 ` [ 45/60] ext4: allow the mount options nodelalloc and data=journal Greg Kroah-Hartman
2013-08-13  6:34 ` [ 46/60] ext4: fix mount/remount error messages for incompatible mount options Greg Kroah-Hartman
2013-08-13  6:34 ` [ 47/60] ext4: flush the extent status cache during EXT4_IOC_SWAP_BOOT Greg Kroah-Hartman
2013-08-13  6:34 ` [ 48/60] cifs: extend the buffer length enought for sprintf() using Greg Kroah-Hartman
2013-08-13  6:34 ` [ 49/60] cifs: dont instantiate new dentries in readdir for inodes that need to be revalidated immediately Greg Kroah-Hartman
2013-08-13  6:34 ` [ 50/60] zram: allow request end to coincide with disksize Greg Kroah-Hartman
2013-08-13  6:34 ` [ 51/60] usb: core: dont try to reset_device() a port that got just disconnected Greg Kroah-Hartman
2013-08-13  6:34 ` Greg Kroah-Hartman [this message]
2013-08-13  6:34 ` [ 53/60] reiserfs: fix deadlock in umount Greg Kroah-Hartman
2013-08-13  6:34 ` [ 54/60] drm/i915: initialize gt_lock early with other spin locks Greg Kroah-Hartman
2013-08-13  6:34 ` [ 55/60] drm/radeon: fix halting UVD Greg Kroah-Hartman
2013-08-13  6:34 ` [ 56/60] drm/radeon: only save UVD bo when we have open handles Greg Kroah-Hartman
2013-08-13  6:34 ` [ 57/60] drm/radeon: always program the MC on startup Greg Kroah-Hartman
2013-08-13  6:34 ` [ 58/60] SCSI: nsp32: use mdelay instead of large udelay constants Greg Kroah-Hartman
2013-08-13  6:34 ` [ 59/60] mtd: omap2: allow bulding as a module Greg Kroah-Hartman
2013-08-13  6:34 ` [ 60/60] MIPS: Expose missing pci_io{map,unmap} declarations Greg Kroah-Hartman
2013-08-13 11:57 ` [ 00/60] 3.10.7-stable review Guenter Roeck
2013-08-13 17:57   ` Greg Kroah-Hartman
2013-08-13 17:18 ` Shuah Khan
2013-08-13 17:57   ` Greg Kroah-Hartman

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=20130813063338.520866227@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.