linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: Lars Ellenberg <lars.ellenberg@linbit.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: Re: [RFC] [PATCH] fix infinite loop; increase robustness of debugfs_remove_recursive
Date: Tue, 27 Nov 2012 22:16:28 -0500	[thread overview]
Message-ID: <1354072588.6276.101.camel@gandalf.local.home> (raw)
In-Reply-To: <20121123171547.GB23670@soda.linbit>

On Fri, 2012-11-23 at 18:15 +0100, Lars Ellenberg wrote:
> When toying around with debugfs, intentionally trying to break things,
> I managed to get it into a reproducible endless loop when cleaning up.
> 
> debugfs_remove_recursive() completely ignores that entries found
> on ->d_subdirs may already be d_delete()d, but not yet d_kill()ed.
> 
> In this case, the first two entries found have both been such dentries
> (d_iname = ".", btw), while later in the list there was still a real,
> not yet deleted entry.
> 
> That way, the "goto next_sibling;" did not catch this case,
> the "break the infinit loop if we fail to remove something"
> did not catch it either.
> 
> 
> Disclaimer: I'm not a dentries and inodes guy...

I'm not a dentries or inodes guy either, so I wont comment on the actual
merits of this patch.

> 
> Still, I think the "is this child a non-empty subdir" check
> was just wrong. This is my fix:
> -	if (list_empty(&child->d_subdirs)) 
> +	if (!simple_emty(child))

"simple_empty"

> 
> Also, always trying to __debugfs_remove() the first entry found from
> parent->d_subdirs.next is wrong, we need to skip over any already
> deleted children. I introduced the debugfs_find_next_positive_child()
> helper for this.
> 
> If I understand it correctly, if we do it this way, it can never fail.
> That is, as long as we can be sure that no new dentries will be created
> while we are in debugfs_remove_recursive().
> So the 
> 		if (debugfs_positive(child)) {
>  			/*
>  			 * Avoid infinite loop if we fail to remove
>  			 * one dentry.
> is probably dead code now?
> 
> 
> As an additional fix, to prevent an access after free and resulting Oops,
> I serialize dereferencing of attr->get/set and attr->data with d_delete(),
> using the file->f_dentry->d_parent->d_inode->i_mutex.
> 
> If this file->f_dentry meanwhile has been deleted, simple_attr_read()
> and simple_attr_write() now returns -ESTALE. (Any other error code preferences?)
> 
> 
> With this patch, I was able to
> cd /sys/debugfs/test-module/some/dir
> exec 7< some-file
> rmmod test-module
> cat <&7

I saw this and thought "hmm, I wonder if the trace_events have issues,
as they create debugfs directories and files via modules too". I went
and tried to reproduce but couldn't get passed the rmmod, as the module
count gets incremented for any open files that the module creates. I
take it that you didn't add that feature to your test module.

> 
> without any infinite loops, hangs, oopses or other problems,
> and as expected get an ESTALE for the cat.
> 
> Without the patch, I'll get either an infinite loop and rmmod never
> terminates, or cat oopses.
> 
> 
> If you think this is correct, please comment on the FIXME
> below, and help me write a nice commit message.
> 
> If you think this is still wrong or even makes things worse,
> please help me with a proper fix ;-)
> 
> 
> Patch is against upstream as of yesterday,
> but looks like it still applies way back into 2009, 2.6.3x,
> so if it is correct, it may even qualify for the stable branches?
> 

Now, is there any current user of debugfs that is susceptible for this
bug? I'm not saying that these issues shouldn't be fixed. But I'm also
concerned about exploits and other things that just a root user may
accidentally cause harm. If there's current problem then maybe this
isn't needed for stable. But should probably be fixed for the future.

-- Steve

  reply	other threads:[~2012-11-28  3:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-23 17:15 [RFC] [PATCH] fix infinite loop; increase robustness of debugfs_remove_recursive Lars Ellenberg
2012-11-28  3:16 ` Steven Rostedt [this message]
2012-11-28  9:37   ` [RFC] [PATCH] fix infinite loop; increase robustness of debugfs_remove_recursive [attached test module] Lars Ellenberg
2012-11-28 10:05     ` Lars Ellenberg
2012-11-28 14:03     ` Steven Rostedt

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=1354072588.6276.101.camel@gandalf.local.home \
    --to=rostedt@goodmis.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=lars.ellenberg@linbit.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /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;
as well as URLs for NNTP newsgroup(s).