forked from luck/tmp_suning_uos_patched
net: tracepoint of net_dev_xmit sees freed skb and causes panic
Because there is a possibility that skb is kfree_skb()ed and zero cleared after ndo_start_xmit, we should not see the contents of skb like skb->len and skb->dev->name after ndo_start_xmit. But trace_net_dev_xmit does that and causes panic by NULL pointer dereference. This patch fixes trace_net_dev_xmit not to see the contents of skb directly. If you want to reproduce this panic, 1. Get tracepoint of net_dev_xmit on 2. Create 2 guests on KVM 2. Make 2 guests use virtio_net 4. Execute netperf from one to another for a long time as a network burden 5. host will panic(It takes about 30 minutes) Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2e4ceec4ed
commit
ec764bf083
|
@ -12,22 +12,24 @@
|
|||
TRACE_EVENT(net_dev_xmit,
|
||||
|
||||
TP_PROTO(struct sk_buff *skb,
|
||||
int rc),
|
||||
int rc,
|
||||
struct net_device *dev,
|
||||
unsigned int skb_len),
|
||||
|
||||
TP_ARGS(skb, rc),
|
||||
TP_ARGS(skb, rc, dev, skb_len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( void *, skbaddr )
|
||||
__field( unsigned int, len )
|
||||
__field( int, rc )
|
||||
__string( name, skb->dev->name )
|
||||
__string( name, dev->name )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->skbaddr = skb;
|
||||
__entry->len = skb->len;
|
||||
__entry->len = skb_len;
|
||||
__entry->rc = rc;
|
||||
__assign_str(name, skb->dev->name);
|
||||
__assign_str(name, dev->name);
|
||||
),
|
||||
|
||||
TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
|
||||
|
|
|
@ -2096,6 +2096,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
|
|||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
int rc = NETDEV_TX_OK;
|
||||
unsigned int skb_len;
|
||||
|
||||
if (likely(!skb->next)) {
|
||||
u32 features;
|
||||
|
@ -2146,8 +2147,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
skb_len = skb->len;
|
||||
rc = ops->ndo_start_xmit(skb, dev);
|
||||
trace_net_dev_xmit(skb, rc);
|
||||
trace_net_dev_xmit(skb, rc, dev, skb_len);
|
||||
if (rc == NETDEV_TX_OK)
|
||||
txq_trans_update(txq);
|
||||
return rc;
|
||||
|
@ -2167,8 +2169,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
|
|||
if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
|
||||
skb_dst_drop(nskb);
|
||||
|
||||
skb_len = nskb->len;
|
||||
rc = ops->ndo_start_xmit(nskb, dev);
|
||||
trace_net_dev_xmit(nskb, rc);
|
||||
trace_net_dev_xmit(nskb, rc, dev, skb_len);
|
||||
if (unlikely(rc != NETDEV_TX_OK)) {
|
||||
if (rc & ~NETDEV_TX_MASK)
|
||||
goto out_kfree_gso_skb;
|
||||
|
|
Loading…
Reference in New Issue
Block a user