From: Barret Rhoden <brho@google.com>
To: Siddharth Chintamaneni <sidchintamaneni@gmail.com>
Cc: bpf@vger.kernel.org, alexei.starovoitov@gmail.com,
daniel@iogearbox.net, olsajiri@gmail.com, andrii@kernel.org,
yonghong.song@linux.dev, rjsu26@vt.edu, sairoop@vt.edu,
miloc@vt.edu, memxor@gmail.com,
syzbot+8bdfc2c53fb2b63e1871@syzkaller.appspotmail.com
Subject: Re: [PATCH v3 bpf-next 1/2] bpf: Patch to Fix deadlocks in queue and stack maps
Date: Thu, 16 May 2024 10:04:57 -0400 [thread overview]
Message-ID: <55b6e3cc-3809-448e-9603-951dc0693c0c@google.com> (raw)
In-Reply-To: <20240514124052.1240266-2-sidchintamaneni@gmail.com>
On 5/14/24 08:40, Siddharth Chintamaneni wrote:
[...]
> +static inline int map_lock_inc(struct bpf_queue_stack *qs)
> +{
> + unsigned long flags;
> +
> + preempt_disable();
> + local_irq_save(flags);
> + if (unlikely(__this_cpu_inc_return(*(qs->map_locked)) != 1)) {
> + __this_cpu_dec(*(qs->map_locked));
> + local_irq_restore(flags);
> + preempt_enable();
> + return -EBUSY;
> + }
> +
> + local_irq_restore(flags);
> + preempt_enable();
it looks like you're taking the approach from kernel/bpf/hashtab.c to
use a per-cpu lock before grabbing the real lock. but in the success
case here (where you incremented the percpu counter), you're enabling
irqs and preemption.
what happens if you get preempted right after this? you've left the
per-cpu bit set, but then you run on another cpu.
possible alternative: instead of splitting the overall lock into "grab
percpu lock, then grab real lock", have a single function for both,
similar to htab_lock_bucket(). and keep irqs and preemption off from
the moment you start attempting the overall lock until you completely
unlock.
barret
> +
> + return 0;
> +}
> +
> +static inline void map_unlock_dec(struct bpf_queue_stack *qs)
> +{
> + unsigned long flags;
> +
> + preempt_disable();
> + local_irq_save(flags);
> + __this_cpu_dec(*(qs->map_locked));
> + local_irq_restore(flags);
> + preempt_enable();
> +}
> +
> static long __queue_map_get(struct bpf_map *map, void *value, bool delete)
> {
> struct bpf_queue_stack *qs = bpf_queue_stack(map);
> unsigned long flags;
> int err = 0;
> void *ptr;
> + int ret;
> +
> + ret = map_lock_inc(qs);
> + if (ret)
> + return ret;
>
> if (in_nmi()) {
> - if (!raw_spin_trylock_irqsave(&qs->lock, flags))
> + if (!raw_spin_trylock_irqsave(&qs->lock, flags)) {
> + map_unlock_dec(qs);
> return -EBUSY;
> + }
> } else {
> raw_spin_lock_irqsave(&qs->lock, flags);
> }
> @@ -121,6 +170,8 @@ static long __queue_map_get(struct bpf_map *map, void *value, bool delete)
>
> out:
> raw_spin_unlock_irqrestore(&qs->lock, flags);
> + map_unlock_dec(qs);
> +
> return err;
> }
>
> @@ -132,10 +183,17 @@ static long __stack_map_get(struct bpf_map *map, void *value, bool delete)
> int err = 0;
> void *ptr;
> u32 index;
> + int ret;
> +
> + ret = map_lock_inc(qs);
> + if (ret)
> + return ret;
>
> if (in_nmi()) {
> - if (!raw_spin_trylock_irqsave(&qs->lock, flags))
> + if (!raw_spin_trylock_irqsave(&qs->lock, flags)) {
> + map_unlock_dec(qs);
> return -EBUSY;
> + }
> } else {
> raw_spin_lock_irqsave(&qs->lock, flags);
> }
> @@ -158,6 +216,8 @@ static long __stack_map_get(struct bpf_map *map, void *value, bool delete)
>
> out:
> raw_spin_unlock_irqrestore(&qs->lock, flags);
> + map_unlock_dec(qs);
> +
> return err;
> }
>
> @@ -193,6 +253,7 @@ static long queue_stack_map_push_elem(struct bpf_map *map, void *value,
> unsigned long irq_flags;
> int err = 0;
> void *dst;
> + int ret;
>
> /* BPF_EXIST is used to force making room for a new element in case the
> * map is full
> @@ -203,9 +264,16 @@ static long queue_stack_map_push_elem(struct bpf_map *map, void *value,
> if (flags & BPF_NOEXIST || flags > BPF_EXIST)
> return -EINVAL;
>
> +
> + ret = map_lock_inc(qs);
> + if (ret)
> + return ret;
> +
> if (in_nmi()) {
> - if (!raw_spin_trylock_irqsave(&qs->lock, irq_flags))
> + if (!raw_spin_trylock_irqsave(&qs->lock, irq_flags)) {
> + map_unlock_dec(qs);
> return -EBUSY;
> + }
> } else {
> raw_spin_lock_irqsave(&qs->lock, irq_flags);
> }
> @@ -228,6 +296,8 @@ static long queue_stack_map_push_elem(struct bpf_map *map, void *value,
>
> out:
> raw_spin_unlock_irqrestore(&qs->lock, irq_flags);
> + map_unlock_dec(qs);
> +
> return err;
> }
>
next prev parent reply other threads:[~2024-05-16 14:05 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-14 12:40 [PATCH v3 bpf-next 2/2] selftests/bpf: Added selftests to check deadlocks in queue and stack map Siddharth Chintamaneni
2024-05-14 12:40 ` [PATCH v3 bpf-next 1/2] bpf: Patch to Fix deadlocks in queue and stack maps Siddharth Chintamaneni
2024-05-15 17:32 ` Kumar Kartikeya Dwivedi
2024-05-16 14:04 ` Barret Rhoden [this message]
2024-05-16 14:34 ` Kumar Kartikeya Dwivedi
2024-05-16 15:31 ` Siddharth Chintamaneni
2024-05-17 1:53 ` Hou Tao
2024-05-17 3:32 ` Siddharth Chintamaneni
2024-05-15 17:02 ` [PATCH v3 bpf-next 2/2] selftests/bpf: Added selftests to check deadlocks in queue and stack map Kumar Kartikeya Dwivedi
2024-05-15 17:44 ` Siddharth Chintamaneni
2024-05-15 17:56 ` Kumar Kartikeya Dwivedi
2024-05-15 17:58 ` Kumar Kartikeya Dwivedi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55b6e3cc-3809-448e-9603-951dc0693c0c@google.com \
--to=brho@google.com \
--cc=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=memxor@gmail.com \
--cc=miloc@vt.edu \
--cc=olsajiri@gmail.com \
--cc=rjsu26@vt.edu \
--cc=sairoop@vt.edu \
--cc=sidchintamaneni@gmail.com \
--cc=syzbot+8bdfc2c53fb2b63e1871@syzkaller.appspotmail.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox