public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Neil Horman <nhorman@tuxdriver.com>
Cc: akpm@linux-foundation.org, andi@firstfloor.org,
	jirislaby@gmail.com, linux-kernel@vger.kernel.org,
	gregkh@suse.de, kay.sievers@suse.de
Subject: Re: [PATCH] Fix up a few missed minor rcu errors in uevent_helper
Date: Tue, 16 Feb 2010 10:11:01 -0800	[thread overview]
Message-ID: <20100216181101.GD6797@linux.vnet.ibm.com> (raw)
In-Reply-To: <20100216155243.GA6155@hmsreliant.think-freely.org>

On Tue, Feb 16, 2010 at 10:52:43AM -0500, Neil Horman wrote:
> Fix up a few remaining nits in uevent_helper
> 
> Fixes the remaining missed lock points in uevent_helper, as reported by Paul
> McKenney in his review.  Specifically adds a spin lock to guard the write side
> of usevent_helper from concurrent writes, and fixes two remaining missed read
> side points that failed to use rcu_read_lock properly.  Also fixe up a minor
> string parsing issue in uvent_helper_set (was terminating the string on the
> wrong buffer).
> 
> I've done minimal testing on this (as the things this fixes were reported by
> code audit, not any actual oops or other failure).  I did run this for a few
> hours though, with several processes reading/writing different values to
> /sys/kernel/uevent_helper, while issued a few module loads that required issuing
> udev events (which, when overlapping with a proper write to /sys/kernel/uevent),
> triggered a fork in the appropriate binary.  Nothing has fallen over in that
> time, so I'm satisfied with this.  Applies as an incremental on top of the
> latest -mm
> Neil

>From and RCU perspective:

Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>

> Reported-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> Tested-by: Neil Horman <nhorman@tuxdriver.com>
> 
> 
>  kernel/ksysfs.c      |   17 ++++++++++++-----
>  lib/kobject_uevent.c |    3 ++-
>  2 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
> index 66d1e5b..401d1f0 100644
> --- a/kernel/ksysfs.c
> +++ b/kernel/ksysfs.c
> @@ -16,6 +16,7 @@
>  #include <linux/kexec.h>
>  #include <linux/profile.h>
>  #include <linux/sched.h>
> +#include <linux/spinlock.h>
> 
>  #define KERNEL_ATTR_RO(_name) \
>  static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
> @@ -37,13 +38,18 @@ KERNEL_ATTR_RO(uevent_seqnum);
>  static ssize_t uevent_helper_show(struct kobject *kobj,
>  				  struct kobj_attribute *attr, char *buf)
>  {
> -	return sprintf(buf, "%s\n", rcu_dereference(uevent_helper));
> +	ssize_t count;
> +	rcu_read_lock();
> +	count = sprintf(buf, "%s\n", rcu_dereference(uevent_helper));
> +	rcu_read_unlock();
> +	return count;
>  }
> 
>  struct uevent_helper_rcu {
>  	char *oldptr;
>  	struct rcu_head rcu;
>  };
> +static DEFINE_SPINLOCK(uevent_helper_lock);
> 
>  static void free_old_uevent_ptr(struct rcu_head *list)
>  {
> @@ -68,15 +74,16 @@ static ssize_t uevent_helper_store(struct kobject *kobj,
>  	kbuf = kstrndup(buf, UEVENT_HELPER_PATH_LEN, GFP_KERNEL);
>  	if (!kbuf)
>  		return -ENOMEM;
> -	uevent_helper[count] = '\0';
> -	if (count && uevent_helper[count-1] == '\n')
> -		uevent_helper[count-1] = '\0';
> +	kbuf[count] = '\0';
> +	if (count && kbuf[count-1] == '\n')
> +		kbuf[count-1] = '\0';
>  	old = kmalloc(sizeof(struct uevent_helper_rcu), GFP_KERNEL);
>  	if (!old)
>  		goto out_free;
> -
> +	spin_lock(&uevent_helper_lock);
>  	old->oldptr = rcu_dereference(uevent_helper);
>  	rcu_assign_pointer(uevent_helper, kbuf);
> +	spin_unlock(&uevent_helper_lock);
>  	call_rcu(&old->rcu, free_old_uevent_ptr);
> 
>  	return count;
> diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
> index 211f846..a7520d0 100644
> --- a/lib/kobject_uevent.c
> +++ b/lib/kobject_uevent.c
> @@ -273,10 +273,11 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
>  #endif
> 
>  	/* call uevent_helper, usually only enabled during early boot */
> +	rcu_read_lock();
>  	helper = rcu_dereference(uevent_helper);
>  	if (helper[0])
>  		retval = uevent_call_helper(subsystem, env);
> -
> +	rcu_read_unlock();
>  exit:
>  	kfree(devpath);
>  	kfree(env);

      reply	other threads:[~2010-02-16 18:11 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-16 15:52 [PATCH] Fix up a few missed minor rcu errors in uevent_helper Neil Horman
2010-02-16 18:11 ` Paul E. McKenney [this message]

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=20100216181101.GD6797@linux.vnet.ibm.com \
    --to=paulmck@linux.vnet.ibm.com \
    --cc=akpm@linux-foundation.org \
    --cc=andi@firstfloor.org \
    --cc=gregkh@suse.de \
    --cc=jirislaby@gmail.com \
    --cc=kay.sievers@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nhorman@tuxdriver.com \
    /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