Commit 58341373 authored by Jakub Sitnicki's avatar Jakub Sitnicki Committed by Liu Jian
Browse files

bpf, sockmap: Prevent lock inversion deadlock in map delete elem

stable inclusion
from stable-v5.10.215
commit dd54b48db0c822ae7b520bc80751f0a0a173ef75
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9QG7M
CVE: CVE-2024-35895

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=dd54b48db0c822ae7b520bc80751f0a0a173ef75



---------------------------

commit ff91059932401894e6c86341915615c5eb0eca48 upstream.

syzkaller started using corpuses where a BPF tracing program deletes
elements from a sockmap/sockhash map. Because BPF tracing programs can be
invoked from any interrupt context, locks taken during a map_delete_elem
operation must be hardirq-safe. Otherwise a deadlock due to lock inversion
is possible, as reported by lockdep:

       CPU0                    CPU1
       ----                    ----
  lock(&htab->buckets[i].lock);
                               local_irq_disable();
                               lock(&host->lock);
                               lock(&htab->buckets[i].lock);
  <Interrupt>
    lock(&host->lock);

Locks in sockmap are hardirq-unsafe by design. We expects elements to be
deleted from sockmap/sockhash only in task (normal) context with interrupts
enabled, or in softirq context.

Detect when map_delete_elem operation is invoked from a context which is
_not_ hardirq-unsafe, that is interrupts are disabled, and bail out with an
error.

Note that map updates are not affected by this issue. BPF verifier does not
allow updating sockmap/sockhash from a BPF tracing program today.

Fixes: 604326b4 ("bpf, sockmap: convert to generic sk_msg interface")
Reported-by: default avatarxingwei lee <xrivendell7@gmail.com>
Reported-by: default avataryue sun <samsun1006219@gmail.com>
Reported-by: default avatar <syzbot+bc922f476bd65abbd466@syzkaller.appspotmail.com>
Reported-by: default avatar <syzbot+d4066896495db380182e@syzkaller.appspotmail.com>
Signed-off-by: default avatarJakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Tested-by: default avatar <syzbot+d4066896495db380182e@syzkaller.appspotmail.com>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=d4066896495db380182e
Closes: https://syzkaller.appspot.com/bug?extid=bc922f476bd65abbd466
Link: https://lore.kernel.org/bpf/20240402104621.1050319-1-jakub@cloudflare.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarLiu Jian <liujian56@huawei.com>
parent 83e8197d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -434,6 +434,9 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
	struct sock *sk;
	int err = 0;

	if (irqs_disabled())
		return -EOPNOTSUPP; /* locks here are hardirq-unsafe */

	raw_spin_lock_bh(&stab->lock);
	sk = *psk;
	if (!sk_test || sk_test == sk)
@@ -967,6 +970,9 @@ static int sock_hash_delete_elem(struct bpf_map *map, void *key)
	struct bpf_shtab_elem *elem;
	int ret = -ENOENT;

	if (irqs_disabled())
		return -EOPNOTSUPP; /* locks here are hardirq-unsafe */

	hash = sock_hash_bucket_hash(key, key_size);
	bucket = sock_hash_select_bucket(htab, hash);