BPF List
 help / color / mirror / Atom feed
* [BUG: 6.6.y] bpf fentry hook on _raw_spin_lock_irqsave triggers hard lockup
@ 2026-07-29  7:53 Feng Yang
  2026-07-29  8:29 ` Greg KH
  0 siblings, 1 reply; 2+ messages in thread
From: Feng Yang @ 2026-07-29  7:53 UTC (permalink / raw)
  To: bpf, stable; +Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song

When attaching fentry programs to _raw_spin_lock_irqsave/_raw_spin_unlock_irqrestore on
the v6.6 kernel and using the BPF ring buffer within BPF programs, we encounter a hard LOCKUP.

Reproducible BPF code is shown below:

static inline int test(void *ctx)
{
        struct event *event;

        event = reserve_buf(sizeof(*event));
        if (!event)
                return 0;

        submit_buf(ctx, event, sizeof(*event));

        return 0;
}

SEC("fentry/_raw_spin_lock_irqsave")
int BPF_PROG(aa)
{
        return test(ctx);
}

SEC("fentry/_raw_spin_unlock_irqrestore")
int BPF_PROG(bb)
{
        return test(ctx);
}

We suspect the hard LOCKUP is caused by the call chain:
aa->test->reserve_buf->_raw_spin_lock_irqsave->_raw_spin_unlock_irqrestore->bb->test->reserve_buf->_raw_spin_lock_irqsave.

Mainline has merged the rqspinlock patchset
(https://lore.kernel.org/all/20250411101759.4061366-1-memxor@gmail.com/)
which resolves this issue. Should we backport the fix?

Alternatively, would a fix modeled after this patch
https://lore.kernel.org/bpf/20201029071925.3103400-3-songliubraving@fb.com/
as outlined below be viable?

--- a/kernel/bpf/ringbuf.c
+++ b/kernel/bpf/ringbuf.c
@@ -30,6 +30,7 @@ struct bpf_ringbuf {
 	struct page **pages;
 	int nr_pages;
 	raw_spinlock_t spinlock ____cacheline_aligned_in_smp;
+	int __percpu *ringbuf_lock;
 	/* For user-space producer ring buffers, an atomic_t busy bit is used
 	 * to synchronize access to the ring buffers in the kernel, rather than
 	 * the spinlock that is used for kernel-producer ring buffers. This is
@@ -165,6 +166,8 @@ static void bpf_ringbuf_notify(struct irq_work *work)
  * considering that the maximum value of data_sz is (4GB - 1), there
  * will be no overflow, so just note the size limit in the comments.
  */
+static void bpf_ringbuf_free(struct bpf_ringbuf *rb);
+
 static struct bpf_ringbuf *bpf_ringbuf_alloc(size_t data_sz, int numa_node)
 {
 	struct bpf_ringbuf *rb;
@@ -178,6 +181,12 @@ static struct bpf_ringbuf *bpf_ringbuf_alloc(size_t data_sz, int numa_node)
 	init_waitqueue_head(&rb->waitq);
 	init_irq_work(&rb->work, bpf_ringbuf_notify);
 
+	rb->ringbuf_lock = __alloc_percpu_gfp(sizeof(int), sizeof(int), GFP_USER);
+	if (!rb->ringbuf_lock) {
+		bpf_ringbuf_free(rb);
+		return NULL;
+	}
+
 	rb->mask = data_sz - 1;
 	rb->consumer_pos = 0;
 	rb->producer_pos = 0;
@@ -215,6 +224,7 @@ static struct bpf_map *ringbuf_map_alloc(union bpf_attr *attr)
 
 static void bpf_ringbuf_free(struct bpf_ringbuf *rb)
 {
+	free_percpu(rb->ringbuf_lock);
 	irq_work_sync(&rb->work);
 
 	/* copy pages pointer and nr_pages to local variable, as we are going
@@ -418,9 +428,19 @@ static void *__bpf_ringbuf_reserve(struct bpf_ringbuf *rb, u64 size)
 
 	cons_pos = smp_load_acquire(&rb->consumer_pos);
 
+	preempt_disable();
+	if (unlikely(__this_cpu_inc_return(*rb->ringbuf_lock) != 1)) {
+		__this_cpu_dec(*rb->ringbuf_lock);
+		preempt_enable();
+		return NULL;
+	}
+
 	if (in_nmi()) {
-		if (!raw_spin_trylock_irqsave(&rb->spinlock, flags))
+		if (!raw_spin_trylock_irqsave(&rb->spinlock, flags)) {
+			__this_cpu_dec(*rb->ringbuf_lock);
+			preempt_enable();
 			return NULL;
+		}
 	} else {
 		raw_spin_lock_irqsave(&rb->spinlock, flags);
 	}
@@ -449,6 +469,8 @@ static void *__bpf_ringbuf_reserve(struct bpf_ringbuf *rb, u64 size)
 	if (new_prod_pos - cons_pos > rb->mask ||
 	    new_prod_pos - pend_pos > rb->mask) {
 		raw_spin_unlock_irqrestore(&rb->spinlock, flags);
+		__this_cpu_dec(*rb->ringbuf_lock);
+		preempt_enable();
 		return NULL;
 	}
 
@@ -461,6 +483,8 @@ static void *__bpf_ringbuf_reserve(struct bpf_ringbuf *rb, u64 size)
 	smp_store_release(&rb->producer_pos, new_prod_pos);
 
 	raw_spin_unlock_irqrestore(&rb->spinlock, flags);
+	__this_cpu_dec(*rb->ringbuf_lock);
+	preempt_enable();
 
 	return (void *)hdr + BPF_RINGBUF_HDR_SZ;
 }

Thanks,
Feng


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [BUG: 6.6.y] bpf fentry hook on _raw_spin_lock_irqsave triggers hard lockup
  2026-07-29  7:53 [BUG: 6.6.y] bpf fentry hook on _raw_spin_lock_irqsave triggers hard lockup Feng Yang
@ 2026-07-29  8:29 ` Greg KH
  0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2026-07-29  8:29 UTC (permalink / raw)
  To: Feng Yang
  Cc: bpf, stable, andrii, eddyz87, ast, daniel, memxor, martin.lau,
	song

On Wed, Jul 29, 2026 at 03:53:22PM +0800, Feng Yang wrote:
> When attaching fentry programs to _raw_spin_lock_irqsave/_raw_spin_unlock_irqrestore on
> the v6.6 kernel and using the BPF ring buffer within BPF programs, we encounter a hard LOCKUP.
> 
> Reproducible BPF code is shown below:
> 
> static inline int test(void *ctx)
> {
>         struct event *event;
> 
>         event = reserve_buf(sizeof(*event));
>         if (!event)
>                 return 0;
> 
>         submit_buf(ctx, event, sizeof(*event));
> 
>         return 0;
> }
> 
> SEC("fentry/_raw_spin_lock_irqsave")
> int BPF_PROG(aa)
> {
>         return test(ctx);
> }
> 
> SEC("fentry/_raw_spin_unlock_irqrestore")
> int BPF_PROG(bb)
> {
>         return test(ctx);
> }
> 
> We suspect the hard LOCKUP is caused by the call chain:
> aa->test->reserve_buf->_raw_spin_lock_irqsave->_raw_spin_unlock_irqrestore->bb->test->reserve_buf->_raw_spin_lock_irqsave.
> 
> Mainline has merged the rqspinlock patchset
> (https://lore.kernel.org/all/20250411101759.4061366-1-memxor@gmail.com/)
> which resolves this issue. Should we backport the fix?
> 
> Alternatively, would a fix modeled after this patch
> https://lore.kernel.org/bpf/20201029071925.3103400-3-songliubraving@fb.com/
> as outlined below be viable?

Do not do stable-only patches, that's not how the stable trees work.
Fix the issue in Linus's tree first, and then backport the needed
changes to the older trees.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-29  8:29 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29  7:53 [BUG: 6.6.y] bpf fentry hook on _raw_spin_lock_irqsave triggers hard lockup Feng Yang
2026-07-29  8:29 ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox