 ec764bf083
			
		
	
	
	ec764bf083
	
	
	
		
			
			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>
		
			
				
	
	
		
			84 lines
		
	
	
	
		
			1.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
	
		
			1.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| #undef TRACE_SYSTEM
 | |
| #define TRACE_SYSTEM net
 | |
| 
 | |
| #if !defined(_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
 | |
| #define _TRACE_NET_H
 | |
| 
 | |
| #include <linux/skbuff.h>
 | |
| #include <linux/netdevice.h>
 | |
| #include <linux/ip.h>
 | |
| #include <linux/tracepoint.h>
 | |
| 
 | |
| TRACE_EVENT(net_dev_xmit,
 | |
| 
 | |
| 	TP_PROTO(struct sk_buff *skb,
 | |
| 		 int rc,
 | |
| 		 struct net_device *dev,
 | |
| 		 unsigned int skb_len),
 | |
| 
 | |
| 	TP_ARGS(skb, rc, dev, skb_len),
 | |
| 
 | |
| 	TP_STRUCT__entry(
 | |
| 		__field(	void *,		skbaddr		)
 | |
| 		__field(	unsigned int,	len		)
 | |
| 		__field(	int,		rc		)
 | |
| 		__string(	name,		dev->name	)
 | |
| 	),
 | |
| 
 | |
| 	TP_fast_assign(
 | |
| 		__entry->skbaddr = skb;
 | |
| 		__entry->len = skb_len;
 | |
| 		__entry->rc = rc;
 | |
| 		__assign_str(name, dev->name);
 | |
| 	),
 | |
| 
 | |
| 	TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
 | |
| 		__get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
 | |
| );
 | |
| 
 | |
| DECLARE_EVENT_CLASS(net_dev_template,
 | |
| 
 | |
| 	TP_PROTO(struct sk_buff *skb),
 | |
| 
 | |
| 	TP_ARGS(skb),
 | |
| 
 | |
| 	TP_STRUCT__entry(
 | |
| 		__field(	void *,		skbaddr		)
 | |
| 		__field(	unsigned int,	len		)
 | |
| 		__string(	name,		skb->dev->name	)
 | |
| 	),
 | |
| 
 | |
| 	TP_fast_assign(
 | |
| 		__entry->skbaddr = skb;
 | |
| 		__entry->len = skb->len;
 | |
| 		__assign_str(name, skb->dev->name);
 | |
| 	),
 | |
| 
 | |
| 	TP_printk("dev=%s skbaddr=%p len=%u",
 | |
| 		__get_str(name), __entry->skbaddr, __entry->len)
 | |
| )
 | |
| 
 | |
| DEFINE_EVENT(net_dev_template, net_dev_queue,
 | |
| 
 | |
| 	TP_PROTO(struct sk_buff *skb),
 | |
| 
 | |
| 	TP_ARGS(skb)
 | |
| );
 | |
| 
 | |
| DEFINE_EVENT(net_dev_template, netif_receive_skb,
 | |
| 
 | |
| 	TP_PROTO(struct sk_buff *skb),
 | |
| 
 | |
| 	TP_ARGS(skb)
 | |
| );
 | |
| 
 | |
| DEFINE_EVENT(net_dev_template, netif_rx,
 | |
| 
 | |
| 	TP_PROTO(struct sk_buff *skb),
 | |
| 
 | |
| 	TP_ARGS(skb)
 | |
| );
 | |
| #endif /* _TRACE_NET_H */
 | |
| 
 | |
| /* This part must be outside protection */
 | |
| #include <trace/define_trace.h>
 |