datapath: supply a dummy err_handler of gre_cisco_protocol to prevent kernel crash
authorWei Zhang <asuka.com@163.com>
Sat, 5 Apr 2014 23:17:35 +0000 (16:17 -0700)
committerJesse Gross <jesse@nicira.com>
Wed, 9 Apr 2014 00:44:46 +0000 (17:44 -0700)
When use gre vport, openvswitch register a gre_cisco_protocol but
does not supply a err_handler with it. The gre_cisco_err() in
net/ipv4/gre_demux.c expect err_handler be provided with the
gre_cisco_protocol implementation, and call ->err_handler() without
existence check, cause the kernel crash.

This patch provide a err_handler to fix this bug.

Signed-off-by: Wei Zhang <asuka.com@163.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
datapath/linux/compat/include/net/gre.h
datapath/vport-gre.c

index a6f29c4..0f7c249 100644 (file)
@@ -16,6 +16,8 @@
 
 struct gre_cisco_protocol {
        int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi);
+       int (*err_handler)(struct sk_buff *skb, u32 info,
+                          const struct tnl_ptk_info *tpi);
        u8 priority;
 };
 
index 8737b63..93869ff 100644 (file)
@@ -116,6 +116,25 @@ static int gre_rcv(struct sk_buff *skb,
        return PACKET_RCVD;
 }
 
+/* Called with rcu_read_lock and BH disabled. */
+static int gre_err(struct sk_buff *skb, u32 info,
+                  const struct tnl_ptk_info *tpi)
+{
+       struct ovs_net *ovs_net;
+       struct vport *vport;
+
+       ovs_net = net_generic(dev_net(skb->dev), ovs_net_id);
+       if ((tpi->flags & TUNNEL_KEY) && (tpi->flags & TUNNEL_SEQ))
+               vport = rcu_dereference(ovs_net->vport_net.gre64_vport);
+       else
+               vport = rcu_dereference(ovs_net->vport_net.gre_vport);
+
+       if (unlikely(!vport))
+               return PACKET_REJECT;
+       else
+               return PACKET_RCVD;
+}
+
 static int __send(struct vport *vport, struct sk_buff *skb,
                  int tunnel_hlen,
                  __be32 seq, __be16 gre64_flag)
@@ -187,6 +206,7 @@ error:
 
 static struct gre_cisco_protocol gre_protocol = {
        .handler        = gre_rcv,
+       .err_handler    = gre_err,
        .priority       = 1,
 };