[PATCH 1/1] af_packet: Raw socket destruction warning fix

Subsystems: networking [general], packet sockets, the rest

STALE3836d

2 messages, 2 authors, 2016-02-10 · open the first message on its own page

[PATCH 1/1] af_packet: Raw socket destruction warning fix

From: Maninder Singh <hidden>
Date: 2016-02-10 12:06:31

This Patch fixes below warning:-
WARNING: at net/packet/af_packet.c:xxx packet_sock_destruct

There is following race between packet_rcv and packet_close
which keeps unfree packet in receive queue.

CPU 1					CPU2
packet_rcv

					packet_close                       
skb_set_owner_r(skb, sk);

					skb_queue_purge(&sk->sk_receive_queue);

spin_lock(&sk->sk_receive_queue.lock);
__skb_queue_tail(&sk->sk_receive_queue, skb);
spin_unlock(&sk->sk_receive_queue.lock);

Signed-off-by: Vaneet Narang <redacted>
Signed-off-by: Amit Nagal <redacted>
Signed-off-by: Maninder Singh <redacted>
---
 net/packet/af_packet.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 992396a..e6047e6 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1310,7 +1310,10 @@ static int packet_rcv_has_room(struct packet_sock *po, struct sk_buff *skb)
 
 static void packet_sock_destruct(struct sock *sk)
 {
+	/* Purge queues */
+
 	skb_queue_purge(&sk->sk_error_queue);
+	skb_queue_purge(&sk->sk_receive_queue);
 
 	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
 	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
@@ -1991,6 +1994,9 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (!net_eq(dev_net(dev), sock_net(sk)))
 		goto drop;
 
+	if (sock_flag(sk, SOCK_DEAD))
+		goto drop;
+
 	skb->dev = dev;
 
 	if (dev->header_ops) {
@@ -2053,7 +2059,6 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (pskb_trim(skb, snaplen))
 		goto drop_n_acct;
 
-	skb_set_owner_r(skb, sk);
 	skb->dev = NULL;
 	skb_dst_drop(skb);
 
@@ -2061,6 +2066,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
 	nf_reset(skb);
 
 	spin_lock(&sk->sk_receive_queue.lock);
+	skb_set_owner_r(skb, sk);
 	po->stats.stats1.tp_packets++;
 	sock_skb_set_dropcount(sk, skb);
 	__skb_queue_tail(&sk->sk_receive_queue, skb);
@@ -2899,9 +2905,6 @@ static int packet_release(struct socket *sock)
 	sock_orphan(sk);
 	sock->sk = NULL;
 
-	/* Purge queues */
-
-	skb_queue_purge(&sk->sk_receive_queue);
 	packet_free_pending(po);
 	sk_refcnt_debug_release(sk);
 
-- 
1.7.9.5

Re: [PATCH 1/1] af_packet: Raw socket destruction warning fix

From: Eric Dumazet <hidden>
Date: 2016-02-10 15:09:52

On Wed, 2016-02-10 at 17:35 +0530, Maninder Singh wrote:
This Patch fixes below warning:-
WARNING: at net/packet/af_packet.c:xxx packet_sock_destruct

There is following race between packet_rcv and packet_close
which keeps unfree packet in receive queue.

CPU 1					CPU2
packet_rcv

					packet_close                       
skb_set_owner_r(skb, sk);

					skb_queue_purge(&sk->sk_receive_queue);

spin_lock(&sk->sk_receive_queue.lock);
__skb_queue_tail(&sk->sk_receive_queue, skb);
spin_unlock(&sk->sk_receive_queue.lock);
This absolutely can not happen.

CPU 1 holds rcu read lock, so cpu 2 can not possibly call
skb_queue_purge()

(cpu 1 is blocked in synchronize_net(), waiting that all cpus are no
longer in packet_rcv())

This patch does not address the root cause of your problem, and only
slightly changes probability for the bug to trigger.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help