mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Sasha Levin <sasha.levin@oracle.com>
To: Nicolai Stange <nicstange@gmail.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>,
	"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	Jonathan Corbet <corbet@lwn.net>, Jan Kara <jack@suse.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Julia Lawall <Julia.Lawall@lip6.fr>,
	Gilles Muller <Gilles.Muller@lip6.fr>,
	Nicolas Palix <nicolas.palix@imag.fr>,
	Michal Marek <mmarek@suse.com>,
	linux-kernel@vger.kernel.org, cocci@systeme.lip6.fr
Subject: Re: [PATCH v6 2/8] debugfs: prevent access to removed files' private data
Date: Wed, 18 May 2016 10:48:40 -0400	[thread overview]
Message-ID: <573C80C8.6090307@oracle.com> (raw)
In-Reply-To: <1458652280-19785-3-git-send-email-nicstange@gmail.com>

On 03/22/2016 09:11 AM, Nicolai Stange wrote:
> Upon return of debugfs_remove()/debugfs_remove_recursive(), it might
> still be attempted to access associated private file data through
> previously opened struct file objects. If that data has been freed by
> the caller of debugfs_remove*() in the meanwhile, the reading/writing
> process would either encounter a fault or, if the memory address in
> question has been reassigned again, unrelated data structures could get
> overwritten.
> 
> However, since debugfs files are seldomly removed, usually from module
> exit handlers only, the impact is very low.
> 
> Currently, there are ~1000 call sites of debugfs_create_file() spread
> throughout the whole tree and touching all of those struct file_operations
> in order to make them file removal aware by means of checking the result of
> debugfs_use_file_start() from within their methods is unfeasible.
> 
> Instead, wrap the struct file_operations by a lifetime managing proxy at
> file open:
> - In debugfs_create_file(), the original fops handed in has got stashed
>   away in ->d_fsdata already.
> - In debugfs_create_file(), install a proxy file_operations factory,
>   debugfs_full_proxy_file_operations, at ->i_fop.
> 
> This proxy factory has got an ->open() method only. It carries out some
> lifetime checks and if successful, dynamically allocates and sets up a new
> struct file_operations proxy at ->f_op. Afterwards, it forwards to the
> ->open() of the original struct file_operations in ->d_fsdata, if any.
> 
> The dynamically set up proxy at ->f_op has got a lifetime managing wrapper
> set for each of the methods defined in the original struct file_operations
> in ->d_fsdata.
> 
> Its ->release()er frees the proxy again and forwards to the original
> ->release(), if any.
> 
> In order not to mislead the VFS layer, it is strictly necessary to leave
> those fields blank in the proxy that have been NULL in the original
> struct file_operations also, i.e. aren't supported. This is why there is a
> need for dynamically allocated proxies. The choice made not to allocate a
> proxy instance for every dentry at file creation, but for every
> struct file object instantiated thereof is justified by the expected usage
> pattern of debugfs, namely that in general very few files get opened more
> than once at a time.
> 
> The wrapper methods set in the struct file_operations implement lifetime
> managing by means of the SRCU protection facilities already in place for
> debugfs:
> They set up a SRCU read side critical section and check whether the dentry
> is still alive by means of debugfs_use_file_start(). If so, they forward
> the call to the original struct file_operation stored in ->d_fsdata, still
> under the protection of the SRCU read side critical section.
> This SRCU read side critical section prevents any pending debugfs_remove()
> and friends to return to their callers. Since a file's private data must
> only be freed after the return of debugfs_remove(), the ongoing proxied
> call is guarded against any file removal race.
> 
> If, on the other hand, the initial call to debugfs_use_file_start() detects
> that the dentry is dead, the wrapper simply returns -EIO and does not
> forward the call. Note that the ->poll() wrapper is special in that its
> signature does not allow for the return of arbitrary -EXXX values and thus,
> POLLHUP is returned here.
> 
> In order not to pollute debugfs with wrapper definitions that aren't ever
> needed, I chose not to define a wrapper for every struct file_operations
> method possible. Instead, a wrapper is defined only for the subset of
> methods which are actually set by any debugfs users.
> Currently, these are:
> 
>   ->llseek()
>   ->read()
>   ->write()
>   ->unlocked_ioctl()
>   ->poll()
> 
> The ->release() wrapper is special in that it does not protect the original
> ->release() in any way from dead files in order not to leak resources.
> Thus, any ->release() handed to debugfs must implement file lifetime
> management manually, if needed.
> For only 33 out of a total of 434 releasers handed in to debugfs, it could
> not be verified immediately whether they access data structures that might
> have been freed upon a debugfs_remove() return in the meanwhile.
> 
> Export debugfs_use_file_start() and debugfs_use_file_finish() in order to
> allow any ->release() to manually implement file lifetime management.
> 
> For a set of common cases of struct file_operations implemented by the
> debugfs_core itself, future patches will incorporate file lifetime
> management directly within those in order to allow for their unproxied
> operation. Rename the original, non-proxying "debugfs_create_file()" to
> "debugfs_create_file_unsafe()" and keep it for future internal use by
> debugfs itself. Factor out code common to both into the new
> __debugfs_create_file().
> 
> Signed-off-by: Nicolai Stange <nicstange@gmail.com>

Hey,

I'm seeing a hang on boot which was bisected (twice) to this commit. I don't
see any lockup messages, but everything just seems to stop.


Thanks,
Sasha

  reply	other threads:[~2016-05-18 14:49 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-22 13:11 [PATCH v6 0/8] fix debugfs file removal races Nicolai Stange
2016-03-22 13:11 ` [PATCH v6 1/8] debugfs: prevent access to possibly dead file_operations at file open Nicolai Stange
2016-03-22 13:11 ` [PATCH v6 2/8] debugfs: prevent access to removed files' private data Nicolai Stange
2016-05-18 14:48   ` Sasha Levin [this message]
2016-05-18 15:01     ` Nicolai Stange
2016-05-18 15:18       ` Sasha Levin
2016-05-18 16:05         ` Greg Kroah-Hartman
2016-05-20 16:57           ` Sasha Levin
2016-05-21 17:57             ` Nicolai Stange
2016-05-22 13:28               ` Nicolai Stange
2016-05-18 16:32         ` Nicolai Stange
2016-05-20 16:55           ` Sasha Levin
2016-03-22 13:11 ` [PATCH v6 3/8] debugfs: add support for self-protecting attribute file fops Nicolai Stange
2016-03-22 13:11 ` [PATCH v6 4/8] debugfs, coccinelle: check for obsolete DEFINE_SIMPLE_ATTRIBUTE() usage Nicolai Stange
2016-03-22 13:18   ` Julia Lawall
2016-03-22 13:11 ` [PATCH v6 5/8] debugfs: unproxify integer attribute files Nicolai Stange
2016-03-22 13:11 ` [PATCH v6 6/8] debugfs: unproxify files created through debugfs_create_bool() Nicolai Stange
2016-03-22 13:11 ` [PATCH v6 7/8] debugfs: unproxify files created through debugfs_create_blob() Nicolai Stange
2016-03-22 13:11 ` [PATCH v6 8/8] debugfs: unproxify files created through debugfs_create_u32_array() Nicolai Stange
2017-03-19 16:30 [PATCH v6 2/8] debugfs: prevent access to removed files' private data Arkady

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=573C80C8.6090307@oracle.com \
    --to=sasha.levin@oracle.com \
    --cc=Gilles.Muller@lip6.fr \
    --cc=Julia.Lawall@lip6.fr \
    --cc=akpm@linux-foundation.org \
    --cc=cocci@systeme.lip6.fr \
    --cc=corbet@lwn.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=jack@suse.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@rasmusvillemoes.dk \
    --cc=mmarek@suse.com \
    --cc=nicolas.palix@imag.fr \
    --cc=nicstange@gmail.com \
    --cc=paulmck@linux.vnet.ibm.com \
    --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

Powered by JetHome