Skip to content

Commit c99293d

Browse files
Hoang Huu Legregkh
authored andcommitted
tipc: fix NULL pointer dereference in tipc_named_rcv
[ Upstream commit 7b50ee3 ] In the function node_lost_contact(), we call __skb_queue_purge() without grabbing the list->lock. This can cause to a race-condition why processing the list 'namedq' in calling path tipc_named_rcv()->tipc_named_dequeue(). [] BUG: kernel NULL pointer dereference, address: 0000000000000000 [] #PF: supervisor read access in kernel mode [] #PF: error_code(0x0000) - not-present page [] PGD 7ca63067 P4D 7ca63067 PUD 6c553067 PMD 0 [] Oops: 0000 [#1] SMP NOPTI [] CPU: 1 PID: 15 Comm: ksoftirqd/1 Tainted: G O 5.9.0-rc6+ #2 [] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS [...] [] RIP: 0010:tipc_named_rcv+0x103/0x320 [tipc] [] Code: 41 89 44 24 10 49 8b 16 49 8b 46 08 49 c7 06 00 00 00 [...] [] RSP: 0018:ffffc900000a7c58 EFLAGS: 00000282 [] RAX: 00000000000012ec RBX: 0000000000000000 RCX: ffff88807bde1270 [] RDX: 0000000000002c7c RSI: 0000000000002c7c RDI: ffff88807b38f1a8 [] RBP: ffff88807b006288 R08: ffff88806a367800 R09: ffff88806a367900 [] R10: ffff88806a367a00 R11: ffff88806a367b00 R12: ffff88807b006258 [] R13: ffff88807b00628a R14: ffff888069334d00 R15: ffff88806a434600 [] FS: 0000000000000000(0000) GS:ffff888079480000(0000) knlGS:0[...] [] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [] CR2: 0000000000000000 CR3: 0000000077320000 CR4: 00000000000006e0 [] Call Trace: [] ? tipc_bcast_rcv+0x9a/0x1a0 [tipc] [] tipc_rcv+0x40d/0x670 [tipc] [] ? _raw_spin_unlock+0xa/0x20 [] tipc_l2_rcv_msg+0x55/0x80 [tipc] [] __netif_receive_skb_one_core+0x8c/0xa0 [] process_backlog+0x98/0x140 [] net_rx_action+0x13a/0x420 [] __do_softirq+0xdb/0x316 [] ? smpboot_thread_fn+0x2f/0x1e0 [] ? smpboot_thread_fn+0x74/0x1e0 [] ? smpboot_thread_fn+0x14e/0x1e0 [] run_ksoftirqd+0x1a/0x40 [] smpboot_thread_fn+0x149/0x1e0 [] ? sort_range+0x20/0x20 [] kthread+0x131/0x150 [] ? kthread_unuse_mm+0xa0/0xa0 [] ret_from_fork+0x22/0x30 [] Modules linked in: veth tipc(O) ip6_udp_tunnel udp_tunnel [...] [] CR2: 0000000000000000 [] ---[ end trace 65c276a8e2e2f310 ]--- To fix this, we need to grab the lock of the 'namedq' list on both path calling. Fixes: cad2929 ("tipc: update a binding service via broadcast") Acked-by: Jon Maloy <[email protected]> Signed-off-by: Hoang Huu Le <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent ee1f419 commit c99293d

File tree

2 files changed

+10
-2
lines changed

2 files changed

+10
-2
lines changed

net/tipc/name_distr.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,13 @@ static struct sk_buff *tipc_named_dequeue(struct sk_buff_head *namedq,
327327
struct tipc_msg *hdr;
328328
u16 seqno;
329329

330+
spin_lock_bh(&namedq->lock);
330331
skb_queue_walk_safe(namedq, skb, tmp) {
331-
skb_linearize(skb);
332+
if (unlikely(skb_linearize(skb))) {
333+
__skb_unlink(skb, namedq);
334+
kfree_skb(skb);
335+
continue;
336+
}
332337
hdr = buf_msg(skb);
333338
seqno = msg_named_seqno(hdr);
334339
if (msg_is_last_bulk(hdr)) {
@@ -338,12 +343,14 @@ static struct sk_buff *tipc_named_dequeue(struct sk_buff_head *namedq,
338343

339344
if (msg_is_bulk(hdr) || msg_is_legacy(hdr)) {
340345
__skb_unlink(skb, namedq);
346+
spin_unlock_bh(&namedq->lock);
341347
return skb;
342348
}
343349

344350
if (*open && (*rcv_nxt == seqno)) {
345351
(*rcv_nxt)++;
346352
__skb_unlink(skb, namedq);
353+
spin_unlock_bh(&namedq->lock);
347354
return skb;
348355
}
349356

@@ -353,6 +360,7 @@ static struct sk_buff *tipc_named_dequeue(struct sk_buff_head *namedq,
353360
continue;
354361
}
355362
}
363+
spin_unlock_bh(&namedq->lock);
356364
return NULL;
357365
}
358366

net/tipc/node.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ static void node_lost_contact(struct tipc_node *n,
14851485

14861486
/* Clean up broadcast state */
14871487
tipc_bcast_remove_peer(n->net, n->bc_entry.link);
1488-
__skb_queue_purge(&n->bc_entry.namedq);
1488+
skb_queue_purge(&n->bc_entry.namedq);
14891489

14901490
/* Abort any ongoing link failover */
14911491
for (i = 0; i < MAX_BEARERS; i++) {

0 commit comments

Comments
 (0)