[PATCH 4.14] xfrm: Use __skb_queue_tail in xfrm_trans_queue

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

 



From: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>

commit d16b46e4fd8bc6063624605f25b8c0835bb1fbe3 upstream.

From: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>

We do not need locking in xfrm_trans_queue because it is designed
to use per-CPU buffers.  However, the original code incorrectly
used skb_queue_tail which takes the lock.  This patch switches
it to __skb_queue_tail instead.

Fixes the following stack trace seen when testing ipsec:

BUG: spinlock bad magic on CPU#1, xfrm_algorithm_/945
 lock: 0xffff8fb3dfd1fe78, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0
CPU: 1 PID: 945 Comm: xfrm_algorithm_ Not tainted 4.14.40-00047-g99a610f9568b #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
Call Trace:
 dump_stack+0xa1/0xd0
 ? spin_bug+0x99/0xb0
 do_raw_spin_lock+0x5c/0x90
 _raw_spin_lock_irqsave+0x33/0x60
 skb_queue_tail+0x17/0x40
 ? xfrm4_rcv+0x40/0x40
 xfrm_trans_queue+0x5c/0xa0
 ? nf_hook_slow+0x3d/0xb0
 xfrm4_transport_finish+0x1a1/0x1d0
 ? xfrm4_transport_finish+0x1d0/0x1d0
 xfrm_input+0x7f4/0x920
 xfrm4_esp_rcv+0x2e/0x60
 ip_local_deliver_finish+0x140/0x210
 ip_local_deliver+0xc7/0xf0
 ? ip_local_deliver+0xf0/0xf0
 ip_rcv+0x2f9/0x410
 ? ip_rcv+0x410/0x410
 __netif_receive_skb_core+0x927/0xa50
 netif_receive_skb_internal+0xef/0x190
 ? __skb_get_hash_symmetric+0xbc/0x110
 netif_receive_skb+0x90/0xc0
 tun_get_user+0xd30/0xfc0
 tun_chr_write_iter+0x5a/0x80
 __vfs_write+0x10c/0x150
 vfs_write+0xdf/0x190
 SyS_write+0x4c/0xb0
 do_syscall_64+0x59/0x70
 entry_SYSCALL_64_after_hwframe+0x3d/0xa2

Reported-and-tested-by: Artem Savkov <asavkov@xxxxxxxxxx>
Fixes: e095ecaec6d9 ("xfrm: Reinject transport-mode packets...")
Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Steffen Klassert <steffen.klassert@xxxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Cc: kernel-team@xxxxxxxxxxx
Signed-off-by: Alistair Strachan <astrachan@xxxxxxxxxx>
---
 net/xfrm/xfrm_input.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 3f6f6f8c9fa5..5b2409746ae0 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -518,7 +518,7 @@ int xfrm_trans_queue(struct sk_buff *skb,
 		return -ENOBUFS;
 
 	XFRM_TRANS_SKB_CB(skb)->finish = finish;
-	skb_queue_tail(&trans->queue, skb);
+	__skb_queue_tail(&trans->queue, skb);
 	tasklet_schedule(&trans->tasklet);
 	return 0;
 }
-- 
2.17.0.441.gb46fe60e1d-goog




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux