All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: "Ted Ts'o" <tytso@mit.edu>, Matt Mackall <mpm@selenic.com>,
	Greg Kroah-Hartman <greg@kroah.com>,
	linux-kernel@vger.kernel.org
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Subject: Re: [PATCH] char random: fix boot id uniqueness race
Date: Tue, 31 Jan 2012 11:25:05 -0500	[thread overview]
Message-ID: <20120131162505.GA8298@Krystal> (raw)
In-Reply-To: <20120131155955.GA24356@thunk.org>

* Ted Ts'o (tytso@mit.edu) wrote:
> On Sun, Jan 29, 2012 at 11:40:12PM -0500, Mathieu Desnoyers wrote:
> > Index: linux-2.6-lttng/drivers/char/random.c
> > ===================================================================
> > --- linux-2.6-lttng.orig/drivers/char/random.c
> > +++ linux-2.6-lttng/drivers/char/random.c
> > @@ -1231,6 +1231,8 @@ static int min_read_thresh = 8, min_writ
> >  static int max_read_thresh = INPUT_POOL_WORDS * 32;
> >  static int max_write_thresh = INPUT_POOL_WORDS * 32;
> >  static char sysctl_bootid[16];
> > +static int boot_id_generated;
> > +static DEFINE_MUTEX(boot_id_mutex);

Hi Ted,

> 
> My preference would be to put these statics in proc_do_uuid(), but
> that's arguably a nit.

No problem, can do.

> 
> > +	} else {
> > +		if (unlikely(!ACCESS_ONCE(boot_id_generated))) {
> > +			mutex_lock(&boot_id_mutex);
> > +			if (!boot_id_generated) {
> > +				generate_random_uuid(uuid);
> > +				/* Store uuid before boot_id_generated. */
> > +				smp_wmb();
> > +				boot_id_generated = 1;
> > +			}
> > +			mutex_unlock(&boot_id_mutex);
> > +		} else {
> > +			/* Load boot_id_generated before uuid */
> > +			smp_rmb();
> > +		}
> > +	}
> 
> I don't believe the smp_wmb() and smp_rmb() are necessary here; the
> mutex_lock() and mutex_unlock() should put the necessary memory
> barriers in place.

The need for memory barriers is a consequence of letting the fast-path
run without holding this mutex.

Here is the race dealt with by the smp_rmb()/smp_wmb(). I'm showing the
result of reversed write order here:

CPU A                             CPU B

Load boot_id_generated            
  (test -> false)
mutex_lock(&boot_id_mutex)
  (implied memory barrier
   with acquire semantic)
Load boot_id_generated again
  (test -> false)
boot_id_generated = 1
  (both the compiler and
   CPU are free to reorder
   the boot_id_generated
   store before uuid stores)
                                  Load boot_id_generated
                                    (test -> true)
                                  Load uuid content
                                    (races with generate_random_uuid:
                                     result either 0 or corrupted)
                                  Return corrupted uuid.
generate_random_uuid(uuid)
mutex_unlock(&boot_id_mutex)

I prefer not requiring the fast-path to take a mutex, because this
would transform a read-mostly operation into an operation that
requires cache-line exchanges (the mutex). However, if we want the
fast-path to be mutex-free, we need to enforce order with
memory barriers: smp_rmb on the read-side, smp_wmb on the
update-side. Failure to do so leads to the race shown above,
where a corrupted boot_id can be returned.

Please let me know if there are aspects of your question I can
address better,

Thanks,

Mathieu

> 
> Regards,
> 
> 						- Ted

-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com

      reply	other threads:[~2012-01-31 16:25 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-30  4:40 [PATCH] char random: fix boot id uniqueness race Mathieu Desnoyers
2012-01-31 15:59 ` Ted Ts'o
2012-01-31 16:25   ` Mathieu Desnoyers [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=20120131162505.GA8298@Krystal \
    --to=mathieu.desnoyers@efficios.com \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpm@selenic.com \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=tytso@mit.edu \
    /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.