]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'ipsec/master'
authorStephen Rothwell <sfr@canb.auug.org.au>
Wed, 4 Nov 2015 22:59:34 +0000 (09:59 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 4 Nov 2015 22:59:34 +0000 (09:59 +1100)
1  2 
net/ipv4/xfrm4_policy.c
net/ipv6/xfrm6_policy.c
net/xfrm/xfrm_policy.c

diff --combined net/ipv4/xfrm4_policy.c
index 1e0c3c835a6349eedca54e2dff191ed56b437613,126ff9020bad25183ae5a186add0bf8e523d9c5a..7b0edb37a1150427ef3b0d9a7f2be11421ef67b0
@@@ -15,7 -15,7 +15,7 @@@
  #include <net/dst.h>
  #include <net/xfrm.h>
  #include <net/ip.h>
 -#include <net/vrf.h>
 +#include <net/l3mdev.h>
  
  static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
  
@@@ -97,7 -97,6 +97,7 @@@ static int xfrm4_fill_dst(struct xfrm_d
        xdst->u.rt.rt_gateway = rt->rt_gateway;
        xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway;
        xdst->u.rt.rt_pmtu = rt->rt_pmtu;
 +      xdst->u.rt.rt_table_id = rt->rt_table_id;
        INIT_LIST_HEAD(&xdst->u.rt.rt_uncached);
  
        return 0;
@@@ -111,8 -110,10 +111,8 @@@ _decode_session4(struct sk_buff *skb, s
        struct flowi4 *fl4 = &fl->u.ip4;
        int oif = 0;
  
 -      if (skb_dst(skb)) {
 -              oif = vrf_master_ifindex(skb_dst(skb)->dev) ?
 -                      : skb_dst(skb)->dev->ifindex;
 -      }
 +      if (skb_dst(skb))
 +              oif = l3mdev_fib_oif(skb_dst(skb)->dev);
  
        memset(fl4, 0, sizeof(struct flowi4));
        fl4->flowi4_mark = skb->mark;
                case IPPROTO_DCCP:
                        if (xprth + 4 < skb->data ||
                            pskb_may_pull(skb, xprth + 4 - skb->data)) {
 -                              __be16 *ports = (__be16 *)xprth;
 +                              __be16 *ports;
 +
 +                              xprth = skb_network_header(skb) + iph->ihl * 4;
 +                              ports = (__be16 *)xprth;
  
                                fl4->fl4_sport = ports[!!reverse];
                                fl4->fl4_dport = ports[!reverse];
                        break;
  
                case IPPROTO_ICMP:
 -                      if (pskb_may_pull(skb, xprth + 2 - skb->data)) {
 -                              u8 *icmp = xprth;
 +                      if (xprth + 2 < skb->data ||
 +                          pskb_may_pull(skb, xprth + 2 - skb->data)) {
 +                              u8 *icmp;
 +
 +                              xprth = skb_network_header(skb) + iph->ihl * 4;
 +                              icmp = xprth;
  
                                fl4->fl4_icmp_type = icmp[0];
                                fl4->fl4_icmp_code = icmp[1];
                        break;
  
                case IPPROTO_ESP:
 -                      if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
 -                              __be32 *ehdr = (__be32 *)xprth;
 +                      if (xprth + 4 < skb->data ||
 +                          pskb_may_pull(skb, xprth + 4 - skb->data)) {
 +                              __be32 *ehdr;
 +
 +                              xprth = skb_network_header(skb) + iph->ihl * 4;
 +                              ehdr = (__be32 *)xprth;
  
                                fl4->fl4_ipsec_spi = ehdr[0];
                        }
                        break;
  
                case IPPROTO_AH:
 -                      if (pskb_may_pull(skb, xprth + 8 - skb->data)) {
 -                              __be32 *ah_hdr = (__be32 *)xprth;
 +                      if (xprth + 8 < skb->data ||
 +                          pskb_may_pull(skb, xprth + 8 - skb->data)) {
 +                              __be32 *ah_hdr;
 +
 +                              xprth = skb_network_header(skb) + iph->ihl * 4;
 +                              ah_hdr = (__be32 *)xprth;
  
                                fl4->fl4_ipsec_spi = ah_hdr[1];
                        }
                        break;
  
                case IPPROTO_COMP:
 -                      if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
 -                              __be16 *ipcomp_hdr = (__be16 *)xprth;
 +                      if (xprth + 4 < skb->data ||
 +                          pskb_may_pull(skb, xprth + 4 - skb->data)) {
 +                              __be16 *ipcomp_hdr;
 +
 +                              xprth = skb_network_header(skb) + iph->ihl * 4;
 +                              ipcomp_hdr = (__be16 *)xprth;
  
                                fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
                        }
                        break;
  
                case IPPROTO_GRE:
 -                      if (pskb_may_pull(skb, xprth + 12 - skb->data)) {
 -                              __be16 *greflags = (__be16 *)xprth;
 -                              __be32 *gre_hdr = (__be32 *)xprth;
 +                      if (xprth + 12 < skb->data ||
 +                          pskb_may_pull(skb, xprth + 12 - skb->data)) {
 +                              __be16 *greflags;
 +                              __be32 *gre_hdr;
 +
 +                              xprth = skb_network_header(skb) + iph->ihl * 4;
 +                              greflags = (__be16 *)xprth;
 +                              gre_hdr = (__be32 *)xprth;
  
                                if (greflags[0] & GRE_KEY) {
                                        if (greflags[0] & GRE_CSUM)
@@@ -259,7 -236,7 +259,7 @@@ static void xfrm4_dst_ifdown(struct dst
        xfrm_dst_ifdown(dst, dev);
  }
  
- static struct dst_ops xfrm4_dst_ops = {
+ static struct dst_ops xfrm4_dst_ops_template = {
        .family =               AF_INET,
        .gc =                   xfrm4_garbage_collect,
        .update_pmtu =          xfrm4_update_pmtu,
        .destroy =              xfrm4_dst_destroy,
        .ifdown =               xfrm4_dst_ifdown,
        .local_out =            __ip_local_out,
 -      .gc_thresh =            32768,
 +      .gc_thresh =            INT_MAX,
  };
  
  static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
        .family =               AF_INET,
-       .dst_ops =              &xfrm4_dst_ops,
+       .dst_ops =              &xfrm4_dst_ops_template,
        .dst_lookup =           xfrm4_dst_lookup,
        .get_saddr =            xfrm4_get_saddr,
        .decode_session =       _decode_session4,
@@@ -295,7 -272,7 +295,7 @@@ static struct ctl_table xfrm4_policy_ta
        { }
  };
  
- static int __net_init xfrm4_net_init(struct net *net)
+ static int __net_init xfrm4_net_sysctl_init(struct net *net)
  {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@@ -323,7 -300,7 +323,7 @@@ err_alloc
        return -ENOMEM;
  }
  
- static void __net_exit xfrm4_net_exit(struct net *net)
+ static void __net_exit xfrm4_net_sysctl_exit(struct net *net)
  {
        struct ctl_table *table;
  
        if (!net_eq(net, &init_net))
                kfree(table);
  }
+ #else /* CONFIG_SYSCTL */
+ static int inline xfrm4_net_sysctl_init(struct net *net)
+ {
+       return 0;
+ }
+ static void inline xfrm4_net_sysctl_exit(struct net *net)
+ {
+ }
+ #endif
+ static int __net_init xfrm4_net_init(struct net *net)
+ {
+       int ret;
+       memcpy(&net->xfrm.xfrm4_dst_ops, &xfrm4_dst_ops_template,
+              sizeof(xfrm4_dst_ops_template));
+       ret = dst_entries_init(&net->xfrm.xfrm4_dst_ops);
+       if (ret)
+               return ret;
+       ret = xfrm4_net_sysctl_init(net);
+       if (ret)
+               dst_entries_destroy(&net->xfrm.xfrm4_dst_ops);
+       return ret;
+ }
+ static void __net_exit xfrm4_net_exit(struct net *net)
+ {
+       xfrm4_net_sysctl_exit(net);
+       dst_entries_destroy(&net->xfrm.xfrm4_dst_ops);
+ }
  
  static struct pernet_operations __net_initdata xfrm4_net_ops = {
        .init   = xfrm4_net_init,
        .exit   = xfrm4_net_exit,
  };
- #endif
  
  static void __init xfrm4_policy_init(void)
  {
  
  void __init xfrm4_init(void)
  {
-       dst_entries_init(&xfrm4_dst_ops);
        xfrm4_state_init();
        xfrm4_policy_init();
        xfrm4_protocol_init();
- #ifdef CONFIG_SYSCTL
        register_pernet_subsys(&xfrm4_net_ops);
- #endif
  }
  
diff --combined net/ipv6/xfrm6_policy.c
index 5643423fe67a238c05aee5398ac4064a77bafc16,d51a18d607acd1806ba273cc1e3157fdac1b4ba0..c074771a10f761253f99611de8294172bdb0e142
@@@ -20,7 -20,7 +20,7 @@@
  #include <net/ip.h>
  #include <net/ipv6.h>
  #include <net/ip6_route.h>
 -#include <net/vrf.h>
 +#include <net/l3mdev.h>
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
  #include <net/mip6.h>
  #endif
@@@ -133,8 -133,10 +133,8 @@@ _decode_session6(struct sk_buff *skb, s
  
        nexthdr = nh[nhoff];
  
 -      if (skb_dst(skb)) {
 -              oif = vrf_master_ifindex(skb_dst(skb)->dev) ?
 -                      : skb_dst(skb)->dev->ifindex;
 -      }
 +      if (skb_dst(skb))
 +              oif = l3mdev_fib_oif(skb_dst(skb)->dev);
  
        memset(fl6, 0, sizeof(struct flowi6));
        fl6->flowi6_mark = skb->mark;
@@@ -279,7 -281,7 +279,7 @@@ static void xfrm6_dst_ifdown(struct dst
        xfrm_dst_ifdown(dst, dev);
  }
  
- static struct dst_ops xfrm6_dst_ops = {
+ static struct dst_ops xfrm6_dst_ops_template = {
        .family =               AF_INET6,
        .gc =                   xfrm6_garbage_collect,
        .update_pmtu =          xfrm6_update_pmtu,
        .destroy =              xfrm6_dst_destroy,
        .ifdown =               xfrm6_dst_ifdown,
        .local_out =            __ip6_local_out,
 -      .gc_thresh =            32768,
 +      .gc_thresh =            INT_MAX,
  };
  
  static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
        .family =               AF_INET6,
-       .dst_ops =              &xfrm6_dst_ops,
+       .dst_ops =              &xfrm6_dst_ops_template,
        .dst_lookup =           xfrm6_dst_lookup,
        .get_saddr =            xfrm6_get_saddr,
        .decode_session =       _decode_session6,
@@@ -325,7 -327,7 +325,7 @@@ static struct ctl_table xfrm6_policy_ta
        { }
  };
  
- static int __net_init xfrm6_net_init(struct net *net)
+ static int __net_init xfrm6_net_sysctl_init(struct net *net)
  {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@@ -353,7 -355,7 +353,7 @@@ err_alloc
        return -ENOMEM;
  }
  
- static void __net_exit xfrm6_net_exit(struct net *net)
+ static void __net_exit xfrm6_net_sysctl_exit(struct net *net)
  {
        struct ctl_table *table;
  
        if (!net_eq(net, &init_net))
                kfree(table);
  }
+ #else /* CONFIG_SYSCTL */
+ static int inline xfrm6_net_sysctl_init(struct net *net)
+ {
+       return 0;
+ }
+ static void inline xfrm6_net_sysctl_exit(struct net *net)
+ {
+ }
+ #endif
+ static int __net_init xfrm6_net_init(struct net *net)
+ {
+       int ret;
+       memcpy(&net->xfrm.xfrm6_dst_ops, &xfrm6_dst_ops_template,
+              sizeof(xfrm6_dst_ops_template));
+       ret = dst_entries_init(&net->xfrm.xfrm6_dst_ops);
+       if (ret)
+               return ret;
+       ret = xfrm6_net_sysctl_init(net);
+       if (ret)
+               dst_entries_destroy(&net->xfrm.xfrm6_dst_ops);
+       return ret;
+ }
+ static void __net_exit xfrm6_net_exit(struct net *net)
+ {
+       xfrm6_net_sysctl_exit(net);
+       dst_entries_destroy(&net->xfrm.xfrm6_dst_ops);
+ }
  
  static struct pernet_operations xfrm6_net_ops = {
        .init   = xfrm6_net_init,
        .exit   = xfrm6_net_exit,
  };
- #endif
  
  int __init xfrm6_init(void)
  {
        int ret;
  
-       dst_entries_init(&xfrm6_dst_ops);
        ret = xfrm6_policy_init();
-       if (ret) {
-               dst_entries_destroy(&xfrm6_dst_ops);
+       if (ret)
                goto out;
-       }
        ret = xfrm6_state_init();
        if (ret)
                goto out_policy;
        if (ret)
                goto out_state;
  
- #ifdef CONFIG_SYSCTL
        register_pernet_subsys(&xfrm6_net_ops);
- #endif
  out:
        return ret;
  out_state:
@@@ -405,11 -433,8 +431,8 @@@ out_policy
  
  void xfrm6_fini(void)
  {
- #ifdef CONFIG_SYSCTL
        unregister_pernet_subsys(&xfrm6_net_ops);
- #endif
        xfrm6_protocol_fini();
        xfrm6_policy_fini();
        xfrm6_state_fini();
-       dst_entries_destroy(&xfrm6_dst_ops);
  }
diff --combined net/xfrm/xfrm_policy.c
index 09bfcbac63bb3f75d909aecd840b63d36b169eec,bacd30bda10df88d59a2bc5797bd91ddcf895713..aed6a84cf28e7900a120ad8a6cb408a29e5caaa9
@@@ -1208,7 -1208,7 +1208,7 @@@ static inline int policy_to_flow_dir(in
        }
  }
  
 -static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir,
 +static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
                                                 const struct flowi *fl)
  {
        struct xfrm_policy *pol;
@@@ -1583,6 -1583,8 +1583,6 @@@ static inline struct xfrm_dst *xfrm_all
  
                memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst));
                xdst->flo.ops = &xfrm_bundle_fc_ops;
 -              if (afinfo->init_dst)
 -                      afinfo->init_dst(net, xdst);
        } else
                xdst = ERR_PTR(-ENOBUFS);
  
@@@ -1887,7 -1889,6 +1887,7 @@@ static void xfrm_policy_queue_process(u
        struct sock *sk;
        struct dst_entry *dst;
        struct xfrm_policy *pol = (struct xfrm_policy *)arg;
 +      struct net *net = xp_net(pol);
        struct xfrm_policy_queue *pq = &pol->polq;
        struct flowi fl;
        struct sk_buff_head list;
        spin_unlock(&pq->hold_queue.lock);
  
        dst_hold(dst->path);
 -      dst = xfrm_lookup(xp_net(pol), dst->path, &fl,
 -                        sk, 0);
 +      dst = xfrm_lookup(net, dst->path, &fl, sk, 0);
        if (IS_ERR(dst))
                goto purge_queue;
  
  
                xfrm_decode_session(skb, &fl, skb_dst(skb)->ops->family);
                dst_hold(skb_dst(skb)->path);
 -              dst = xfrm_lookup(xp_net(pol), skb_dst(skb)->path,
 -                                &fl, skb->sk, 0);
 +              dst = xfrm_lookup(net, skb_dst(skb)->path, &fl, skb->sk, 0);
                if (IS_ERR(dst)) {
                        kfree_skb(skb);
                        continue;
                skb_dst_drop(skb);
                skb_dst_set(skb, dst);
  
 -              dst_output(skb);
 +              dst_output(net, skb->sk, skb);
        }
  
  out:
@@@ -1957,7 -1960,7 +1957,7 @@@ purge_queue
        xfrm_pol_put(pol);
  }
  
 -static int xdst_queue_output(struct sock *sk, struct sk_buff *skb)
 +static int xdst_queue_output(struct net *net, struct sock *sk, struct sk_buff *skb)
  {
        unsigned long sched_next;
        struct dst_entry *dst = skb_dst(skb);
@@@ -2184,7 -2187,7 +2184,7 @@@ static struct dst_entry *make_blackhole
   */
  struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
                              const struct flowi *fl,
 -                            struct sock *sk, int flags)
 +                            const struct sock *sk, int flags)
  {
        struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
        struct flow_cache_object *flo;
@@@ -2332,7 -2335,7 +2332,7 @@@ EXPORT_SYMBOL(xfrm_lookup)
   */
  struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
                                    const struct flowi *fl,
 -                                  struct sock *sk, int flags)
 +                                  const struct sock *sk, int flags)
  {
        struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk,
                                            flags | XFRM_LOOKUP_QUEUE |
@@@ -2804,7 -2807,6 +2804,6 @@@ static struct neighbour *xfrm_neigh_loo
  
  int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
  {
-       struct net *net;
        int err = 0;
        if (unlikely(afinfo == NULL))
                return -EINVAL;
        }
        spin_unlock(&xfrm_policy_afinfo_lock);
  
-       rtnl_lock();
-       for_each_net(net) {
-               struct dst_ops *xfrm_dst_ops;
-               switch (afinfo->family) {
-               case AF_INET:
-                       xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops;
-                       break;
- #if IS_ENABLED(CONFIG_IPV6)
-               case AF_INET6:
-                       xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops;
-                       break;
- #endif
-               default:
-                       BUG();
-               }
-               *xfrm_dst_ops = *afinfo->dst_ops;
-       }
-       rtnl_unlock();
        return err;
  }
  EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@@ -2890,22 -2872,6 +2869,6 @@@ int xfrm_policy_unregister_afinfo(struc
  }
  EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
  
- static void __net_init xfrm_dst_ops_init(struct net *net)
- {
-       struct xfrm_policy_afinfo *afinfo;
-       rcu_read_lock();
-       afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET]);
-       if (afinfo)
-               net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops;
- #if IS_ENABLED(CONFIG_IPV6)
-       afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET6]);
-       if (afinfo)
-               net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops;
- #endif
-       rcu_read_unlock();
- }
  static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
  {
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
@@@ -3054,7 -3020,6 +3017,6 @@@ static int __net_init xfrm_net_init(str
        rv = xfrm_policy_init(net);
        if (rv < 0)
                goto out_policy;
-       xfrm_dst_ops_init(net);
        rv = xfrm_sysctl_init(net);
        if (rv < 0)
                goto out_sysctl;