All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] racy use of ->d_name
@ 2016-12-14 19:35 Mike Marshall
  2016-12-14 21:08 ` Al Viro
  0 siblings, 1 reply; 2+ messages in thread
From: Mike Marshall @ 2016-12-14 19:35 UTC (permalink / raw)
  To: linux-fsdevel, Mike Marshall

In a recent thread I read on fs-devel, Al Viro said:

AV> the use of ->d_name *is* racy, and while it might be
AV> tolerable for occasional debugging, for anything in heavier use it's
AV> asking for trouble.

Naturally <g> we use d_name in Orangefs some, so I looked at
some other code for inspiration on how to protect its usage.

I'm guessing this example is how I should protect simple usages
like this:

diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c
index 5355efb..05321f4 100644
--- a/fs/orangefs/dcache.c
+++ b/fs/orangefs/dcache.c
@@ -30,9 +30,11 @@ static int orangefs_revalidate_lookup(struct dentry *dentry)

        new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
        new_op->upcall.req.lookup.parent_refn = parent->refn;
+       spin_lock(&dentry->d_lock);
        strncpy(new_op->upcall.req.lookup.d_name,
                dentry->d_name.name,
                ORANGEFS_NAME_MAX);
+       spin_unlock(&dentry->d_lock);

        gossip_debug(GOSSIP_DCACHE_DEBUG,
                     "%s:%s:%d interrupt flag [%d]\n",


It seems that in debug statements, icky looking things like
file->f_path.dentry->d_name.name get replaced with "file" and "%pD".

I have a place where I use file->f_path.dentry->d_name.name in a
strcmp, and the way I "fixed" it seems verbose and hackerly... what
should I do instead?

diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c
index b5dbc9c..bb1e8a8 100644
--- a/fs/orangefs/orangefs-debugfs.c
+++ b/fs/orangefs/orangefs-debugfs.c
@@ -432,6 +432,8 @@ static ssize_t orangefs_debug_write(struct file *file,
        int rc = -EFAULT;
        size_t silly = 0;
        char *debug_string;
+       char *debug_file_name;
+       int debug_file_buf_len = strlen(ORANGEFS_KMOD_DEBUG_FILE) + 10;
        struct orangefs_kernel_op_s *new_op = NULL;
        struct client_debug_mask c_mask = { NULL, 0, 0 };

@@ -452,6 +454,11 @@ static ssize_t orangefs_debug_write(struct file *file,
        if (!buf)
                goto out;

+       debug_file_name =
+               kzalloc(debug_file_buf_len, GFP_KERNEL);
+       if (!debug_file_name)
+               goto out;
+
        if (copy_from_user(buf, ubuf, count - 1)) {
                gossip_debug(GOSSIP_DEBUGFS_DEBUG,
                             "%s: copy_from_user failed!\n",
@@ -468,8 +475,20 @@ static ssize_t orangefs_debug_write(struct file *file,
         * A service operation is required to set a new client-side
         * debug mask.
         */
-       if (!strcmp(file->f_path.dentry->d_name.name,
-                   ORANGEFS_KMOD_DEBUG_FILE)) {
+
+       /*
+        * We need to look and see whether they're setting the keyword
+        * string in the kernel debug file, or the client debug file.
+        * Fetching the filename out of "file" with "%pD" is better
+        * than fetching it out of file->f_path.dentry->d_name.name.
+        *
+        * debug_file_buf_len is longer than it needs to be in case
+        * some weirdo or malicious file that matches "the right thing
+        * and then some" gets passed into here somehow.
+        */
+       snprintf(debug_file_name, debug_file_buf_len, "%pD", file);
+
+       if (!strcmp(debug_file_name, ORANGEFS_KMOD_DEBUG_FILE)) {
                debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0);
                debug_mask_to_string(&orangefs_gossip_debug_mask, 0);
                debug_string = kernel_debug_string;
@@ -536,6 +555,7 @@ static ssize_t orangefs_debug_write(struct file *file,
                     "orangefs_debug_write: rc: %d\n",
                     rc);
        kfree(buf);
+       kfree(debug_file_name);
        return rc;
 }

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [RFC] racy use of ->d_name
  2016-12-14 19:35 [RFC] racy use of ->d_name Mike Marshall
@ 2016-12-14 21:08 ` Al Viro
  0 siblings, 0 replies; 2+ messages in thread
From: Al Viro @ 2016-12-14 21:08 UTC (permalink / raw)
  To: Mike Marshall; +Cc: linux-fsdevel

On Wed, Dec 14, 2016 at 02:35:39PM -0500, Mike Marshall wrote:

> I'm guessing this example is how I should protect simple usages
> like this:
> 
> diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c
> index 5355efb..05321f4 100644
> --- a/fs/orangefs/dcache.c
> +++ b/fs/orangefs/dcache.c
> @@ -30,9 +30,11 @@ static int orangefs_revalidate_lookup(struct dentry *dentry)
> 
>         new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW;
>         new_op->upcall.req.lookup.parent_refn = parent->refn;
> +       spin_lock(&dentry->d_lock);
>         strncpy(new_op->upcall.req.lookup.d_name,
>                 dentry->d_name.name,
>                 ORANGEFS_NAME_MAX);
> +       spin_unlock(&dentry->d_lock);
> 
>         gossip_debug(GOSSIP_DCACHE_DEBUG,
>                      "%s:%s:%d interrupt flag [%d]\n",

That one is potentially nastier - ->d_revalidate() *can* race with
rename().  Next cycle we'll hopefully get to the point where this
kind of "we need to force lookup" will be handled outside of ->d_revalidate();
the main problem with doing so right now is that we would lose anything
mounted on that thing or anywhere under it and we will always get a new
dentry for non-directories.  AFAICS, your instance is safe with that ->d_lock,
but I would really prefer to have that done from ->lookup() rather than
duplicate between lookup and d_revalidate like now.  I have some bits and
pieces in that direction, but it was way too late in this cycle to be
4.10 material.

> It seems that in debug statements, icky looking things like
> file->f_path.dentry->d_name.name get replaced with "file" and "%pD".
> 
> I have a place where I use file->f_path.dentry->d_name.name in a
> strcmp, and the way I "fixed" it seems verbose and hackerly... what
> should I do instead?

debugfs has no rename, so there it's actually stable.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2016-12-14 21:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-14 19:35 [RFC] racy use of ->d_name Mike Marshall
2016-12-14 21:08 ` Al Viro

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.