aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-04-03 04:03:55 +0200
committerAdrian Bunk <bunk@stusta.de>2007-04-03 04:03:55 +0200
commit5f4a9d1b7a413d6aac382c51692ac0df785068c5 (patch)
tree51067f1b0f341dcebc79e5c17e88d45189e613ee /include
parentcceec5186fce242e095dc5e9496841df5d4133b9 (diff)
[IFB]: Fix crash on input device removal
The input_device pointer is not refcounted, which means the device may disappear while packets are queued, causing a crash when ifb passes packets with a stale skb->dev pointer to netif_rx(). Fix by storing the interface index instead and do a lookup where neccessary. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Adrian Bunk <bunk@stusta.de>
Diffstat (limited to 'include')
-rw-r--r--include/linux/skbuff.h5
-rw-r--r--include/net/pkt_cls.h7
2 files changed, 8 insertions, 4 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 7e631a542577..2e9eb624aaa9 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -175,7 +175,7 @@ enum {
* @sk: Socket we are owned by
* @tstamp: Time we arrived
* @dev: Device we arrived on/are leaving by
- * @input_dev: Device we arrived on
+ * @iif: ifindex of device we arrived on
* @h: Transport layer header
* @nh: Network layer header
* @mac: Link layer header
@@ -219,7 +219,8 @@ struct sk_buff {
struct sock *sk;
struct skb_timeval tstamp;
struct net_device *dev;
- struct net_device *input_dev;
+ int iif;
+ /* 4 byte hole on 64 bit*/
union {
struct tcphdr *th;
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index b902d24a3256..02647fe3d74b 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -352,10 +352,13 @@ tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv)
static inline int
tcf_match_indev(struct sk_buff *skb, char *indev)
{
+ struct net_device *dev;
+
if (indev[0]) {
- if (!skb->input_dev)
+ if (!skb->iif)
return 0;
- if (strcmp(indev, skb->input_dev->name))
+ dev = __dev_get_by_index(skb->iif);
+ if (!dev || strcmp(indev, dev->name))
return 0;
}