Skip to content

Commit 514c41a

Browse files
DLpangKernel Patches Daemon
authored andcommitted
bpf: Fix NULL deref in __list_del_clearprev for flush_node
#syz test Hi, This patch fixes a NULL pointer dereference in the BPF subsystem that occurs when __list_del_clearprev() is called on an already-cleared flush_node list_head. The fix includes two parts: 1. Properly initialize the flush_node list_head during per-CPU bulk queue allocation using INIT_LIST_HEAD(&bq->flush_node) 2. Add defensive checks before calling __list_del_clearprev() to ensure the node is actually in the list by checking if (bq->flush_node.prev) According to the __list_del_clearprev documentation in include/linux/list.h, 'The code that uses this needs to check the node 'prev' pointer instead of calling list_empty()'. This patch fixes the following syzbot-reported issue: https://syzkaller.appspot.com/bug?extid=2b3391f44313b3983e91 Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=2b3391f44313b3983e91 Signed-off-by: DLpang <[email protected]> Reported-by: [email protected] Tested-by: [email protected]
1 parent 162c0b3 commit 514c41a

File tree

3 files changed

+7
-3
lines changed

3 files changed

+7
-3
lines changed

kernel/bpf/cpumap.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value,
450450

451451
for_each_possible_cpu(i) {
452452
bq = per_cpu_ptr(rcpu->bulkq, i);
453+
INIT_LIST_HEAD(&bq->flush_node);
453454
bq->obj = rcpu;
454455
}
455456

@@ -742,7 +743,8 @@ static void bq_flush_to_queue(struct xdp_bulk_queue *bq)
742743
bq->count = 0;
743744
spin_unlock(&q->producer_lock);
744745

745-
__list_del_clearprev(&bq->flush_node);
746+
if (bq->flush_node.prev)
747+
__list_del_clearprev(&bq->flush_node);
746748

747749
/* Feedback loop via tracepoints */
748750
trace_xdp_cpumap_enqueue(rcpu->map_id, processed, drops, to_cpu);

kernel/bpf/devmap.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,8 @@ void __dev_flush(struct list_head *flush_list)
428428
bq_xmit_all(bq, XDP_XMIT_FLUSH);
429429
bq->dev_rx = NULL;
430430
bq->xdp_prog = NULL;
431-
__list_del_clearprev(&bq->flush_node);
431+
if (bq->flush_node.prev)
432+
__list_del_clearprev(&bq->flush_node);
432433
}
433434
}
434435

net/xdp/xsk.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,8 @@ void __xsk_map_flush(struct list_head *flush_list)
406406

407407
list_for_each_entry_safe(xs, tmp, flush_list, flush_node) {
408408
xsk_flush(xs);
409-
__list_del_clearprev(&xs->flush_node);
409+
if (xs->flush_node.prev)
410+
__list_del_clearprev(&xs->flush_node);
410411
}
411412
}
412413

0 commit comments

Comments
 (0)