netpoll: Fix missing TXQ unlock and and OOPS.
authorDavid S. Miller <davem@davemloft.net>
Fri, 3 Jan 2014 00:50:52 +0000 (19:50 -0500)
committerDavid S. Miller <davem@davemloft.net>
Fri, 3 Jan 2014 00:50:52 +0000 (19:50 -0500)
The VLAN tag handling code in netpoll_send_skb_on_dev() has two problems.

1) It exits without unlocking the TXQ.

2) It then tries to queue a NULL skb to npinfo->txq.

Reported-by: Ahmed Tamrawi <atamrawi@iastate.edu>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/netpoll.c

index 8f971990677cd48026f651b2dba01d01190bfff6..3030978746332246878598df7db62ce190607cbe 100644 (file)
@@ -386,8 +386,14 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                            !vlan_hw_offload_capable(netif_skb_features(skb),
                                                                     skb->vlan_proto)) {
                                                skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb));
-                                               if (unlikely(!skb))
-                                                       break;
+                                               if (unlikely(!skb)) {
+                                                       /* This is actually a packet drop, but we
+                                                        * don't want the code at the end of this
+                                                        * function to try and re-queue a NULL skb.
+                                                        */
+                                                       status = NETDEV_TX_OK;
+                                                       goto unlock_txq;
+                                               }
                                                skb->vlan_tci = 0;
                                        }
 
@@ -395,6 +401,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                        if (status == NETDEV_TX_OK)
                                                txq_trans_update(txq);
                                }
+                       unlock_txq:
                                __netif_tx_unlock(txq);
 
                                if (status == NETDEV_TX_OK)