summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-03-29 11:46:52 -0700
committerDavid S. Miller <davem@davemloft.net>2007-03-29 11:46:52 -0700
commitc01003c20563d1e75ec9828d21743919d2b43977 (patch)
tree21cae8933e8a4908d8e8c24244a627bf0c997e77 /include
parentdb8b22550d4b83f0910d27a34d05aa16f7f7159f (diff)
downloadlinux-c01003c20563d1e75ec9828d21743919d2b43977.tar.gz
linux-c01003c20563d1e75ec9828d21743919d2b43977.tar.bz2
linux-c01003c20563d1e75ec9828d21743919d2b43977.zip
[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> Acked-by: Jamal Hadi Salim <hadi@cyberus.ca> Signed-off-by: David S. Miller <davem@davemloft.net>
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 4ff3940210d8..82f43ad478c7 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -188,7 +188,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
@@ -235,7 +235,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;
}