| From: Andrey Konovalov <andreyknvl@google.com> |
| Subject: lib/stackdepot: annotate racy slab_index accesses |
| Date: Mon, 30 Jan 2023 21:49:40 +0100 |
| |
| Accesses to slab_index are protected by slab_lock everywhere except in a |
| sanity check in stack_depot_fetch. The read access there can race with |
| the write access in depot_alloc_stack. |
| |
| Use WRITE/READ_ONCE() to annotate the racy accesses. |
| |
| As the sanity check is only used to print a warning in case of a violation |
| of the stack depot interface usage, it does not make a lot of sense to use |
| proper synchronization. |
| |
| Link: https://lkml.kernel.org/r/19512bb03eed27ced5abeb5bd03f9a8381742cb1.1675111415.git.andreyknvl@google.com |
| Signed-off-by: Andrey Konovalov <andreyknvl@google.com> |
| Cc: Alexander Potapenko <glider@google.com> |
| Cc: Evgenii Stepanov <eugenis@google.com> |
| Cc: Marco Elver <elver@google.com> |
| Cc: Vlastimil Babka <vbabka@suse.cz> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| |
| --- a/lib/stackdepot.c~lib-stackdepot-annotate-racy-slab_index-accesses |
| +++ a/lib/stackdepot.c |
| @@ -269,8 +269,11 @@ depot_alloc_stack(unsigned long *entries |
| return NULL; |
| } |
| |
| - /* Move on to the next slab. */ |
| - slab_index++; |
| + /* |
| + * Move on to the next slab. |
| + * WRITE_ONCE annotates a race with stack_depot_fetch. |
| + */ |
| + WRITE_ONCE(slab_index, slab_index + 1); |
| slab_offset = 0; |
| /* |
| * smp_store_release() here pairs with smp_load_acquire() in |
| @@ -492,6 +495,8 @@ unsigned int stack_depot_fetch(depot_sta |
| unsigned long **entries) |
| { |
| union handle_parts parts = { .handle = handle }; |
| + /* READ_ONCE annotates a race with depot_alloc_stack. */ |
| + int slab_index_cached = READ_ONCE(slab_index); |
| void *slab; |
| size_t offset = parts.offset << DEPOT_STACK_ALIGN; |
| struct stack_record *stack; |
| @@ -500,9 +505,9 @@ unsigned int stack_depot_fetch(depot_sta |
| if (!handle) |
| return 0; |
| |
| - if (parts.slab_index > slab_index) { |
| + if (parts.slab_index > slab_index_cached) { |
| WARN(1, "slab index %d out of bounds (%d) for stack id %08x\n", |
| - parts.slab_index, slab_index, handle); |
| + parts.slab_index, slab_index_cached, handle); |
| return 0; |
| } |
| slab = stack_slabs[parts.slab_index]; |
| _ |