On Sat, Jun 08, 2019 at 11:56:04AM -0400, Alan Stern wrote: > On Sat, 8 Jun 2019, Paul E. McKenney wrote: > > > On Thu, Jun 06, 2019 at 10:19:43AM -0400, Alan Stern wrote: > > > On Thu, 6 Jun 2019, Andrea Parri wrote: > > > > > > > This seems a sensible change to me: looking forward to seeing a patch, > > > > on top of -rcu/dev, for further review and testing! > > > > > > > > We could also add (to LKMM) the barrier() for rcu_read_{lock,unlock}() > > > > discussed in this thread (maybe once the RCU code and the informal doc > > > > will have settled in such direction). > > > > > > Yes. Also for SRCU. That point had not escaped me. > > > > And it does seem pretty settled. There are quite a few examples where > > there are normal accesses at either end of the RCU read-side critical > > sections, for example, the one in the requirements diffs below. > > > > For SRCU, srcu_read_lock() and srcu_read_unlock() have implied compiler > > barriers since 2006. ;-) > > > > Thanx, Paul > > > > ------------------------------------------------------------------------ > > > > diff --git a/Documentation/RCU/Design/Requirements/Requirements.html > > b/Documentation/RCU/Design/Requirements/Requirements.html > > index 5a9238a2883c..080b39cc1dbb 100644 > > --- a/Documentation/RCU/Design/Requirements/Requirements.html > > +++ b/Documentation/RCU/Design/Requirements/Requirements.html > > @@ -2129,6 +2129,8 @@ Some of the relevant points of interest are as > > follows: > > <li> <a href="#Hotplug CPU">Hotplug CPU</a>. > > <li> <a href="#Scheduler and RCU">Scheduler and RCU</a>. > > <li> <a href="#Tracing and RCU">Tracing and RCU</a>. > > +<li> <a href="#Accesses to User Mamory and RCU"> > ------------------------------------^ > > +Accesses to User Mamory and RCU</a>. > ---------------------^ > > <li> <a href="#Energy Efficiency">Energy Efficiency</a>. > > <li> <a href="#Scheduling-Clock Interrupts and RCU"> > > Scheduling-Clock Interrupts and RCU</a>. > > @@ -2521,6 +2523,75 @@ cannot be used. > > The tracing folks both located the requirement and provided the > > needed fix, so this surprise requirement was relatively painless. > > > > +<h3><a name="Accesses to User Mamory and RCU"> > ----------------------------------^ > > +Accesses to User Mamory and RCU</a></h3> > ---------------------^ > > Are these issues especially notable for female programmers? :-)
*Red face* Some days it just doesn't pay to get up in the morning... Well, those issues certainly seem a bit inconsiderate to non-mammalian programmers. :-/ How about the updated version shown below? Thanx, Paul ------------------------------------------------------------------------ diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html index 5a9238a2883c..f04c467e55c5 100644 --- a/Documentation/RCU/Design/Requirements/Requirements.html +++ b/Documentation/RCU/Design/Requirements/Requirements.html @@ -2129,6 +2129,8 @@ Some of the relevant points of interest are as follows: <li> <a href="#Hotplug CPU">Hotplug CPU</a>. <li> <a href="#Scheduler and RCU">Scheduler and RCU</a>. <li> <a href="#Tracing and RCU">Tracing and RCU</a>. +<li> <a href="#Accesses to User Memory and RCU"> +Accesses to User Memory and RCU</a>. <li> <a href="#Energy Efficiency">Energy Efficiency</a>. <li> <a href="#Scheduling-Clock Interrupts and RCU"> Scheduling-Clock Interrupts and RCU</a>. @@ -2521,6 +2523,75 @@ cannot be used. The tracing folks both located the requirement and provided the needed fix, so this surprise requirement was relatively painless. +<h3><a name="Accesses to User Memory and RCU"> +Accesses to User Memory and RCU</a></h3> + +<p> +The kernel needs to access user-space memory, for example, to access +data referenced by system-call parameters. +The <tt>get_user()</tt> macro does this job. + +<p> +However, user-space memory might well be paged out, which means +that <tt>get_user()</tt> might well page-fault and thus block while +waiting for the resulting I/O to complete. +It would be a very bad thing for the compiler to reorder +a <tt>get_user()</tt> invocation into an RCU read-side critical +section. +For example, suppose that the source code looked like this: + +<blockquote> +<pre> + 1 rcu_read_lock(); + 2 p = rcu_dereference(gp); + 3 v = p->value; + 4 rcu_read_unlock(); + 5 get_user(user_v, user_p); + 6 do_something_with(v, user_v); +</pre> +</blockquote> + +<p> +The compiler must not be permitted to transform this source code into +the following: + +<blockquote> +<pre> + 1 rcu_read_lock(); + 2 p = rcu_dereference(gp); + 3 get_user(user_v, user_p); // BUG: POSSIBLE PAGE FAULT!!! + 4 v = p->value; + 5 rcu_read_unlock(); + 6 do_something_with(v, user_v); +</pre> +</blockquote> + +<p> +If the compiler did make this transformation in a +<tt>CONFIG_PREEMPT=n</tt> kernel build, and if <tt>get_user()</tt> did +page fault, the result would be a quiescent state in the middle +of an RCU read-side critical section. +This misplaced quiescent state could result in line 4 being +a use-after-free access, which could be bad for your kernel's +actuarial statistics. +Similar examples can be constructed with the call to <tt>get_user()</tt> +preceding the <tt>rcu_read_lock()</tt>. + +<p> +Unfortunately, <tt>get_user()</tt> doesn't have any particular +ordering properties, and in some architectures the underlying <tt>asm</tt> +isn't even marked <tt>volatile</tt>. +And even if it was marked <tt>volatile</tt>, the above access to +<tt>p->value</tt> is not volatile, so the compiler would not have any +reason to keep those two accesses in order. + +<p> +Therefore, the Linux-kernel definitions of <tt>rcu_read_lock()</tt> +and <tt>rcu_read_unlock()</tt> must act as compiler barriers, +at least for outermost instances of <tt>rcu_read_lock()</tt> and +<tt>rcu_read_unlock()</tt> within a nested set of RCU read-side critical +sections. + <h3><a name="Energy Efficiency">Energy Efficiency</a></h3> <p>