Patch "bpf: Avoid deadlock when using queue and stack maps from NMI" has been added to the 5.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    bpf: Avoid deadlock when using queue and stack maps from NMI

to the 5.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     bpf-avoid-deadlock-when-using-queue-and-stack-maps-f.patch
and it can be found in the queue-5.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 5e20896b0d6758a2197c3f166e0f578f1310144e
Author: Toke Høiland-Jørgensen <toke@xxxxxxxxxx>
Date:   Mon Sep 11 15:28:14 2023 +0200

    bpf: Avoid deadlock when using queue and stack maps from NMI
    
    [ Upstream commit a34a9f1a19afe9c60ca0ea61dfeee63a1c2baac8 ]
    
    Sysbot discovered that the queue and stack maps can deadlock if they are
    being used from a BPF program that can be called from NMI context (such as
    one that is attached to a perf HW counter event). To fix this, add an
    in_nmi() check and use raw_spin_trylock() in NMI context, erroring out if
    grabbing the lock fails.
    
    Fixes: f1a2e44a3aec ("bpf: add queue and stack maps")
    Reported-by: Hsin-Wei Hung <hsinweih@xxxxxxx>
    Tested-by: Hsin-Wei Hung <hsinweih@xxxxxxx>
    Co-developed-by: Hsin-Wei Hung <hsinweih@xxxxxxx>
    Signed-off-by: Toke Høiland-Jørgensen <toke@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20230911132815.717240-1-toke@xxxxxxxxxx
    Signed-off-by: Alexei Starovoitov <ast@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/bpf/queue_stack_maps.c b/kernel/bpf/queue_stack_maps.c
index 0ee2347ba510d..a047a2053d41a 100644
--- a/kernel/bpf/queue_stack_maps.c
+++ b/kernel/bpf/queue_stack_maps.c
@@ -111,7 +111,12 @@ static int __queue_map_get(struct bpf_map *map, void *value, bool delete)
 	int err = 0;
 	void *ptr;
 
-	raw_spin_lock_irqsave(&qs->lock, flags);
+	if (in_nmi()) {
+		if (!raw_spin_trylock_irqsave(&qs->lock, flags))
+			return -EBUSY;
+	} else {
+		raw_spin_lock_irqsave(&qs->lock, flags);
+	}
 
 	if (queue_stack_map_is_empty(qs)) {
 		memset(value, 0, qs->map.value_size);
@@ -141,7 +146,12 @@ static int __stack_map_get(struct bpf_map *map, void *value, bool delete)
 	void *ptr;
 	u32 index;
 
-	raw_spin_lock_irqsave(&qs->lock, flags);
+	if (in_nmi()) {
+		if (!raw_spin_trylock_irqsave(&qs->lock, flags))
+			return -EBUSY;
+	} else {
+		raw_spin_lock_irqsave(&qs->lock, flags);
+	}
 
 	if (queue_stack_map_is_empty(qs)) {
 		memset(value, 0, qs->map.value_size);
@@ -206,7 +216,12 @@ static int queue_stack_map_push_elem(struct bpf_map *map, void *value,
 	if (flags & BPF_NOEXIST || flags > BPF_EXIST)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&qs->lock, irq_flags);
+	if (in_nmi()) {
+		if (!raw_spin_trylock_irqsave(&qs->lock, irq_flags))
+			return -EBUSY;
+	} else {
+		raw_spin_lock_irqsave(&qs->lock, irq_flags);
+	}
 
 	if (queue_stack_map_is_full(qs)) {
 		if (!replace) {



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux