Commit e79323bd87808fdfbc68ce6c5371bd224d9672ee

Authored by Mikulas Patocka
Committed by Linus Torvalds
1 parent c9eaa447e7

user namespace: fix incorrect memory barriers

smp_read_barrier_depends() can be used if there is data dependency between
the readers - i.e. if the read operation after the barrier uses address
that was obtained from the read operation before the barrier.

In this file, there is only control dependency, no data dependecy, so the
use of smp_read_barrier_depends() is incorrect. The code could fail in the
following way:
* the cpu predicts that idx < entries is true and starts executing the
  body of the for loop
* the cpu fetches map->extent[0].first and map->extent[0].count
* the cpu fetches map->nr_extents
* the cpu verifies that idx < extents is true, so it commits the
  instructions in the body of the for loop

The problem is that in this scenario, the cpu read map->extent[0].first
and map->nr_extents in the wrong order. We need a full read memory barrier
to prevent it.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 5 additions and 6 deletions Side-by-side Diff

kernel/user_namespace.c
... ... @@ -152,7 +152,7 @@
152 152  
153 153 /* Find the matching extent */
154 154 extents = map->nr_extents;
155   - smp_read_barrier_depends();
  155 + smp_rmb();
156 156 for (idx = 0; idx < extents; idx++) {
157 157 first = map->extent[idx].first;
158 158 last = first + map->extent[idx].count - 1;
... ... @@ -176,7 +176,7 @@
176 176  
177 177 /* Find the matching extent */
178 178 extents = map->nr_extents;
179   - smp_read_barrier_depends();
  179 + smp_rmb();
180 180 for (idx = 0; idx < extents; idx++) {
181 181 first = map->extent[idx].first;
182 182 last = first + map->extent[idx].count - 1;
... ... @@ -199,7 +199,7 @@
199 199  
200 200 /* Find the matching extent */
201 201 extents = map->nr_extents;
202   - smp_read_barrier_depends();
  202 + smp_rmb();
203 203 for (idx = 0; idx < extents; idx++) {
204 204 first = map->extent[idx].lower_first;
205 205 last = first + map->extent[idx].count - 1;
... ... @@ -615,9 +615,8 @@
615 615 * were written before the count of the extents.
616 616 *
617 617 * To achieve this smp_wmb() is used on guarantee the write
618   - * order and smp_read_barrier_depends() is guaranteed that we
619   - * don't have crazy architectures returning stale data.
620   - *
  618 + * order and smp_rmb() is guaranteed that we don't have crazy
  619 + * architectures returning stale data.
621 620 */
622 621 mutex_lock(&id_map_mutex);
623 622