@@ -2129,8 +2129,6 @@ <h2><a name="Linux Kernel Complications">Linux Kernel Complications</a></h2>
2129
2129
< li > < a href ="#Hotplug CPU "> Hotplug CPU</ a > .
2130
2130
< li > < a href ="#Scheduler and RCU "> Scheduler and RCU</ a > .
2131
2131
< li > < a href ="#Tracing and RCU "> Tracing and RCU</ a > .
2132
- < li > < a href ="#Accesses to User Memory and RCU ">
2133
- Accesses to User Memory and RCU</ a > .
2134
2132
< li > < a href ="#Energy Efficiency "> Energy Efficiency</ a > .
2135
2133
< li > < a href ="#Scheduling-Clock Interrupts and RCU ">
2136
2134
Scheduling-Clock Interrupts and RCU</ a > .
@@ -2523,75 +2521,6 @@ <h3><a name="Tracing and RCU">Tracing and RCU</a></h3>
2523
2521
The tracing folks both located the requirement and provided the
2524
2522
needed fix, so this surprise requirement was relatively painless.
2525
2523
2526
- < h3 > < a name ="Accesses to User Memory and RCU ">
2527
- Accesses to User Memory and RCU</ a > </ h3 >
2528
-
2529
- < p >
2530
- The kernel needs to access user-space memory, for example, to access
2531
- data referenced by system-call parameters.
2532
- The < tt > get_user()</ tt > macro does this job.
2533
-
2534
- < p >
2535
- However, user-space memory might well be paged out, which means
2536
- that < tt > get_user()</ tt > might well page-fault and thus block while
2537
- waiting for the resulting I/O to complete.
2538
- It would be a very bad thing for the compiler to reorder
2539
- a < tt > get_user()</ tt > invocation into an RCU read-side critical
2540
- section.
2541
- For example, suppose that the source code looked like this:
2542
-
2543
- < blockquote >
2544
- < pre >
2545
- 1 rcu_read_lock();
2546
- 2 p = rcu_dereference(gp);
2547
- 3 v = p->value;
2548
- 4 rcu_read_unlock();
2549
- 5 get_user(user_v, user_p);
2550
- 6 do_something_with(v, user_v);
2551
- </ pre >
2552
- </ blockquote >
2553
-
2554
- < p >
2555
- The compiler must not be permitted to transform this source code into
2556
- the following:
2557
-
2558
- < blockquote >
2559
- < pre >
2560
- 1 rcu_read_lock();
2561
- 2 p = rcu_dereference(gp);
2562
- 3 get_user(user_v, user_p); // BUG: POSSIBLE PAGE FAULT!!!
2563
- 4 v = p->value;
2564
- 5 rcu_read_unlock();
2565
- 6 do_something_with(v, user_v);
2566
- </ pre >
2567
- </ blockquote >
2568
-
2569
- < p >
2570
- If the compiler did make this transformation in a
2571
- < tt > CONFIG_PREEMPT=n</ tt > kernel build, and if < tt > get_user()</ tt > did
2572
- page fault, the result would be a quiescent state in the middle
2573
- of an RCU read-side critical section.
2574
- This misplaced quiescent state could result in line 4 being
2575
- a use-after-free access, which could be bad for your kernel's
2576
- actuarial statistics.
2577
- Similar examples can be constructed with the call to < tt > get_user()</ tt >
2578
- preceding the < tt > rcu_read_lock()</ tt > .
2579
-
2580
- < p >
2581
- Unfortunately, < tt > get_user()</ tt > doesn't have any particular
2582
- ordering properties, and in some architectures the underlying < tt > asm</ tt >
2583
- isn't even marked < tt > volatile</ tt > .
2584
- And even if it was marked < tt > volatile</ tt > , the above access to
2585
- < tt > p->value</ tt > is not volatile, so the compiler would not have any
2586
- reason to keep those two accesses in order.
2587
-
2588
- < p >
2589
- Therefore, the Linux-kernel definitions of < tt > rcu_read_lock()</ tt >
2590
- and < tt > rcu_read_unlock()</ tt > must act as compiler barriers,
2591
- at least for outermost instances of < tt > rcu_read_lock()</ tt > and
2592
- < tt > rcu_read_unlock()</ tt > within a nested set of RCU read-side critical
2593
- sections.
2594
-
2595
2524
< h3 > < a name ="Energy Efficiency "> Energy Efficiency</ a > </ h3 >
2596
2525
2597
2526
< p >
0 commit comments