Skip to content

Commit ec764bf

Browse files
KSanagidavem330
authored andcommitted
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>
1 parent 2e4ceec commit ec764bf

File tree

2 files changed

+12
-7
lines changed

2 files changed

+12
-7
lines changed

include/trace/events/net.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,24 @@
1212
TRACE_EVENT(net_dev_xmit,
1313

1414
TP_PROTO(struct sk_buff *skb,
15-
int rc),
15+
int rc,
16+
struct net_device *dev,
17+
unsigned int skb_len),
1618

17-
TP_ARGS(skb, rc),
19+
TP_ARGS(skb, rc, dev, skb_len),
1820

1921
TP_STRUCT__entry(
2022
__field( void *, skbaddr )
2123
__field( unsigned int, len )
2224
__field( int, rc )
23-
__string( name, skb->dev->name )
25+
__string( name, dev->name )
2426
),
2527

2628
TP_fast_assign(
2729
__entry->skbaddr = skb;
28-
__entry->len = skb->len;
30+
__entry->len = skb_len;
2931
__entry->rc = rc;
30-
__assign_str(name, skb->dev->name);
32+
__assign_str(name, dev->name);
3133
),
3234

3335
TP_printk("dev=%s skbaddr=%p len=%u rc=%d",

net/core/dev.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,6 +2096,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
20962096
{
20972097
const struct net_device_ops *ops = dev->netdev_ops;
20982098
int rc = NETDEV_TX_OK;
2099+
unsigned int skb_len;
20992100

21002101
if (likely(!skb->next)) {
21012102
u32 features;
@@ -2146,8 +2147,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
21462147
}
21472148
}
21482149

2150+
skb_len = skb->len;
21492151
rc = ops->ndo_start_xmit(skb, dev);
2150-
trace_net_dev_xmit(skb, rc);
2152+
trace_net_dev_xmit(skb, rc, dev, skb_len);
21512153
if (rc == NETDEV_TX_OK)
21522154
txq_trans_update(txq);
21532155
return rc;
@@ -2167,8 +2169,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
21672169
if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
21682170
skb_dst_drop(nskb);
21692171

2172+
skb_len = nskb->len;
21702173
rc = ops->ndo_start_xmit(nskb, dev);
2171-
trace_net_dev_xmit(nskb, rc);
2174+
trace_net_dev_xmit(nskb, rc, dev, skb_len);
21722175
if (unlikely(rc != NETDEV_TX_OK)) {
21732176
if (rc & ~NETDEV_TX_MASK)
21742177
goto out_kfree_gso_skb;

0 commit comments

Comments
 (0)