[PATCH v2 03/16] bpf: Mark bpf_spin_lock helpers notrace
From: Song Liu
Date: Thu Oct 22 2026 - 21:13:21 EST
Commit 178c54666f9c ("bpf: Mark bpf_spin_{lock,unlock}() helpers with
notrace correctly") made bpf_spin_lock() and bpf_spin_unlock()
untraceable, so that an fentry program that also takes the lock cannot
deadlock. These helpers call the static inline functions
__bpf_spin_lock_irqsave(), __bpf_spin_unlock_irqrestore(),
__bpf_spin_lock() and __bpf_spin_unlock(). __bpf_spin_unlock() releases
the lock with queued_spin_unlock(), which is a plain inline function on
x86 with CONFIG_PARAVIRT_SPINLOCKS. The generic version is
__always_inline. __bpf_spin_unlock_irqrestore(), __bpf_spin_unlock()
and queued_spin_unlock() run with the lock held, so an fentry program
attached to an out-of-line copy of one of them can hit the same
deadlock. These copies are untraced today only because inline implies
notrace.
Mark all of these helpers notrace explicitly, so that nothing called by
bpf_spin_lock() and bpf_spin_unlock() is traceable. No functional
change.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Song Liu <song@xxxxxxxxxx>
---
arch/x86/include/asm/paravirt-spinlock.h | 2 +-
kernel/bpf/helpers.c | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/paravirt-spinlock.h b/arch/x86/include/asm/paravirt-spinlock.h
index 7beffcb08ed6..dd194646dd9a 100644
--- a/arch/x86/include/asm/paravirt-spinlock.h
+++ b/arch/x86/include/asm/paravirt-spinlock.h
@@ -66,7 +66,7 @@ static inline void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
pv_queued_spin_lock_slowpath(lock, val);
}
-static inline void queued_spin_unlock(struct qspinlock *lock)
+static inline void notrace queued_spin_unlock(struct qspinlock *lock)
{
kcsan_release();
pv_queued_spin_unlock(lock);
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index c18f1e16edee..66d5005f2260 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -283,7 +283,7 @@ const struct bpf_func_proto bpf_get_current_comm_proto = {
#if defined(CONFIG_QUEUED_SPINLOCKS) || defined(CONFIG_BPF_ARCH_SPINLOCK)
-static inline void __bpf_spin_lock(struct bpf_spin_lock *lock)
+static inline void notrace __bpf_spin_lock(struct bpf_spin_lock *lock)
{
arch_spinlock_t *l = (void *)lock;
union {
@@ -298,7 +298,7 @@ static inline void __bpf_spin_lock(struct bpf_spin_lock *lock)
arch_spin_lock(l);
}
-static inline void __bpf_spin_unlock(struct bpf_spin_lock *lock)
+static inline void notrace __bpf_spin_unlock(struct bpf_spin_lock *lock)
{
arch_spinlock_t *l = (void *)lock;
@@ -308,7 +308,7 @@ static inline void __bpf_spin_unlock(struct bpf_spin_lock *lock)
#else
-static inline void __bpf_spin_lock(struct bpf_spin_lock *lock)
+static inline void notrace __bpf_spin_lock(struct bpf_spin_lock *lock)
{
atomic_t *l = (void *)lock;
@@ -318,7 +318,7 @@ static inline void __bpf_spin_lock(struct bpf_spin_lock *lock)
} while (atomic_xchg(l, 1));
}
-static inline void __bpf_spin_unlock(struct bpf_spin_lock *lock)
+static inline void notrace __bpf_spin_unlock(struct bpf_spin_lock *lock)
{
atomic_t *l = (void *)lock;
@@ -329,7 +329,7 @@ static inline void __bpf_spin_unlock(struct bpf_spin_lock *lock)
static DEFINE_PER_CPU(unsigned long, irqsave_flags);
-static inline void __bpf_spin_lock_irqsave(struct bpf_spin_lock *lock)
+static inline void notrace __bpf_spin_lock_irqsave(struct bpf_spin_lock *lock)
{
unsigned long flags;
@@ -352,7 +352,7 @@ const struct bpf_func_proto bpf_spin_lock_proto = {
.arg1_btf_id = BPF_PTR_POISON,
};
-static inline void __bpf_spin_unlock_irqrestore(struct bpf_spin_lock *lock)
+static inline void notrace __bpf_spin_unlock_irqrestore(struct bpf_spin_lock *lock)
{
unsigned long flags;
--
2.53.0-Meta