]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
liveupdate: synchronize lazy initialization of FLB private state
authorPasha Tatashin <pasha.tatashin@soleen.com>
Fri, 27 Mar 2026 03:33:26 +0000 (03:33 +0000)
committerAndrew Morton <akpm@linux-foundation.org>
Sat, 18 Apr 2026 07:10:49 +0000 (00:10 -0700)
The luo_flb_get_private() function, which is responsible for lazily
initializing the private state of FLB objects, can be called concurrently
from multiple threads.  This creates a data race on the 'initialized' flag
and can lead to multiple executions of mutex_init() and INIT_LIST_HEAD()
on the same memory.

Introduce a static spinlock (luo_flb_init_lock) local to the function to
synchronize the initialization path.  Use smp_load_acquire() and
smp_store_release() for memory ordering between the fast path and the slow
path.

Link: https://lore.kernel.org/20260327033335.696621-3-pasha.tatashin@soleen.com
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
Cc: David Matlack <dmatlack@google.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Samiullah Khawaja <skhawaja@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
kernel/liveupdate/luo_flb.c

index f52e8114837e312807e4b3ac0f8fe44182b0d489..cf4a8f854c831fbf15a7a60287bb5f6c7ebf3353 100644 (file)
@@ -89,13 +89,18 @@ struct luo_flb_link {
 static struct luo_flb_private *luo_flb_get_private(struct liveupdate_flb *flb)
 {
        struct luo_flb_private *private = &ACCESS_PRIVATE(flb, private);
+       static DEFINE_SPINLOCK(luo_flb_init_lock);
 
+       if (smp_load_acquire(&private->initialized))
+               return private;
+
+       guard(spinlock)(&luo_flb_init_lock);
        if (!private->initialized) {
                mutex_init(&private->incoming.lock);
                mutex_init(&private->outgoing.lock);
                INIT_LIST_HEAD(&private->list);
                private->users = 0;
-               private->initialized = true;
+               smp_store_release(&private->initialized, true);
        }
 
        return private;