Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/stackdepot: annotate racy pool_index accesses

Accesses to pool_index are protected by pool_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.

[andreyknvl@google.com: s/pool_index/pool_index_cached/ in stack_depot_fetch()]
Link: https://lkml.kernel.org/r/95cf53f0da2c112aa2cc54456cbcd6975c3ff343.1676129911.git.andreyknvl@google.com
Link: https://lkml.kernel.org/r/359ac9c13cd0869c56740fb2029f505e41593830.1676063693.git.andreyknvl@google.com
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Reviewed-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Andrey Konovalov and committed by
Andrew Morton
beb3c23c 36aa1e67

+13 -4
+13 -4
lib/stackdepot.c
··· 278 278 return NULL; 279 279 } 280 280 281 - /* Move on to the next pool. */ 282 - pool_index++; 281 + /* 282 + * Move on to the next pool. 283 + * WRITE_ONCE pairs with potential concurrent read in 284 + * stack_depot_fetch(). 285 + */ 286 + WRITE_ONCE(pool_index, pool_index + 1); 283 287 pool_offset = 0; 284 288 /* 285 289 * If the maximum number of pools is not reached, take note ··· 506 502 unsigned long **entries) 507 503 { 508 504 union handle_parts parts = { .handle = handle }; 505 + /* 506 + * READ_ONCE pairs with potential concurrent write in 507 + * depot_alloc_stack. 508 + */ 509 + int pool_index_cached = READ_ONCE(pool_index); 509 510 void *pool; 510 511 size_t offset = parts.offset << DEPOT_STACK_ALIGN; 511 512 struct stack_record *stack; ··· 519 510 if (!handle) 520 511 return 0; 521 512 522 - if (parts.pool_index > pool_index) { 513 + if (parts.pool_index > pool_index_cached) { 523 514 WARN(1, "pool index %d out of bounds (%d) for stack id %08x\n", 524 - parts.pool_index, pool_index, handle); 515 + parts.pool_index, pool_index_cached, handle); 525 516 return 0; 526 517 } 527 518 pool = stack_pools[parts.pool_index];