Skip to content

Commit 71cb46a

Browse files
joelagnelpaulmckrcu
authored andcommitted
Restore docs "rcu: Restore barrier() to rcu_read_lock() and rcu_read_unlock()"
This restores docs back in ReST format. Signed-off-by: Joel Fernandes (Google) <[email protected]> [ paulmck: Added Joel's SoB per Stephen Rothwell feedback. ] [ paulmck: Joel approved via private email. ] Signed-off-by: Paul E. McKenney <[email protected]>
1 parent d7424e2 commit 71cb46a

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

Documentation/RCU/Design/Requirements/Requirements.rst

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,6 +1691,7 @@ follows:
16911691
#. `Hotplug CPU`_
16921692
#. `Scheduler and RCU`_
16931693
#. `Tracing and RCU`_
1694+
#. `Accesses to User Memory and RCU`_
16941695
#. `Energy Efficiency`_
16951696
#. `Scheduling-Clock Interrupts and RCU`_
16961697
#. `Memory Efficiency`_
@@ -2004,6 +2005,59 @@ where RCU readers execute in environments in which tracing cannot be
20042005
used. The tracing folks both located the requirement and provided the
20052006
needed fix, so this surprise requirement was relatively painless.
20062007

2008+
Accesses to User Memory and RCU
2009+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2010+
2011+
The kernel needs to access user-space memory, for example, to access data
2012+
referenced by system-call parameters. The ``get_user()`` macro does this job.
2013+
2014+
However, user-space memory might well be paged out, which means that
2015+
``get_user()`` might well page-fault and thus block while waiting for the
2016+
resulting I/O to complete. It would be a very bad thing for the compiler to
2017+
reorder a ``get_user()`` invocation into an RCU read-side critical section.
2018+
2019+
For example, suppose that the source code looked like this:
2020+
2021+
::
2022+
2023+
1 rcu_read_lock();
2024+
2 p = rcu_dereference(gp);
2025+
3 v = p->value;
2026+
4 rcu_read_unlock();
2027+
5 get_user(user_v, user_p);
2028+
6 do_something_with(v, user_v);
2029+
2030+
The compiler must not be permitted to transform this source code into
2031+
the following:
2032+
2033+
::
2034+
2035+
1 rcu_read_lock();
2036+
2 p = rcu_dereference(gp);
2037+
3 get_user(user_v, user_p); // BUG: POSSIBLE PAGE FAULT!!!
2038+
4 v = p->value;
2039+
5 rcu_read_unlock();
2040+
6 do_something_with(v, user_v);
2041+
2042+
If the compiler did make this transformation in a ``CONFIG_PREEMPT=n`` kernel
2043+
build, and if ``get_user()`` did page fault, the result would be a quiescent
2044+
state in the middle of an RCU read-side critical section. This misplaced
2045+
quiescent state could result in line 4 being a use-after-free access,
2046+
which could be bad for your kernel's actuarial statistics. Similar examples
2047+
can be constructed with the call to ``get_user()`` preceding the
2048+
``rcu_read_lock()``.
2049+
2050+
Unfortunately, ``get_user()`` doesn't have any particular ordering properties,
2051+
and in some architectures the underlying ``asm`` isn't even marked
2052+
``volatile``. And even if it was marked ``volatile``, the above access to
2053+
``p->value`` is not volatile, so the compiler would not have any reason to keep
2054+
those two accesses in order.
2055+
2056+
Therefore, the Linux-kernel definitions of ``rcu_read_lock()`` and
2057+
``rcu_read_unlock()`` must act as compiler barriers, at least for outermost
2058+
instances of ``rcu_read_lock()`` and ``rcu_read_unlock()`` within a nested set
2059+
of RCU read-side critical sections.
2060+
20072061
Energy Efficiency
20082062
~~~~~~~~~~~~~~~~~
20092063

0 commit comments

Comments
 (0)