aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-10 16:53:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-10 16:53:15 -0400
commit65c61bc5dbbcfa1ff38e58aa834cb9a88e84a886 (patch)
treeccafacfe41411a5627b02cf17e68ea98f561bdf1 /net/ipv6
parentb8889c4fc6ba03e289cec6a4d692f6f080a55e53 (diff)
parent30927520dbae297182990bb21d08762bcc35ce1d (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) Fix out-of-bounds array access in netfilter ipset, from Jozsef Kadlecsik. 2) Use correct free operation on netfilter conntrack templates, from Daniel Borkmann. 3) Fix route leak in SCTP, from Marcelo Ricardo Leitner. 4) Fix sizeof(pointer) in mac80211, from Thierry Reding. 5) Fix cache pointer comparison in ip6mr leading to missed unlock of mrt_lock. From Richard Laing. 6) rds_conn_lookup() needs to consider network namespace in key comparison, from Sowmini Varadhan. 7) Fix deadlock in TIPC code wrt broadcast link wakeups, from Kolmakov Dmitriy. 8) Fix fd leaks in bpf syscall, from Daniel Borkmann. 9) Fix error recovery when installing ipv6 multipath routes, we would delete the old route before we would know if we could fully commit to the new set of nexthops. Fix from Roopa Prabhu. 10) Fix run-time suspend problems in r8152, from Hayes Wang. 11) In fec, don't program the MAC address into the chip when the clocks are gated off. From Fugang Duan. 12) Fix poll behavior for netlink sockets when using rx ring mmap, from Daniel Borkmann. 13) Don't allocate memory with GFP_KERNEL from get_stats64 in r8169 driver, from Corinna Vinschen. 14) In TCP Cubic congestion control, handle idle periods better where we are application limited, in order to keep cwnd from growing out of control. From Eric Dumzet. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (65 commits) tcp_cubic: better follow cubic curve after idle period tcp: generate CA_EVENT_TX_START on data frames xen-netfront: respect user provided max_queues xen-netback: respect user provided max_queues r8169: Fix sleeping function called during get_stats64, v2 ether: add IEEE 1722 ethertype - TSN netlink, mmap: fix edge-case leakages in nf queue zero-copy netlink, mmap: don't walk rx ring on poll if receive queue non-empty cxgb4: changes for new firmware 1.14.4.0 net: fec: add netif status check before set mac address r8152: fix the runtime suspend issues r8152: split DRIVER_VERSION ipv6: fix ifnullfree.cocci warnings add microchip LAN88xx phy driver stmmac: fix check for phydev being open net: qlcnic: delete redundant memsets net: mv643xx_eth: use kzalloc net: jme: use kzalloc() instead of kmalloc+memset net: cavium: liquidio: use kzalloc in setup_glist() net: ipv6: use common fib_default_rule_pref ...
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/fib6_rules.c6
-rw-r--r--net/ipv6/ip6mr.c3
-rw-r--r--net/ipv6/route.c200
3 files changed, 175 insertions, 34 deletions
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 2367a16eae58..9f777ec59a59 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -258,11 +258,6 @@ nla_put_failure:
258 return -ENOBUFS; 258 return -ENOBUFS;
259} 259}
260 260
261static u32 fib6_rule_default_pref(struct fib_rules_ops *ops)
262{
263 return 0x3FFF;
264}
265
266static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) 261static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
267{ 262{
268 return nla_total_size(16) /* dst */ 263 return nla_total_size(16) /* dst */
@@ -279,7 +274,6 @@ static const struct fib_rules_ops __net_initconst fib6_rules_ops_template = {
279 .configure = fib6_rule_configure, 274 .configure = fib6_rule_configure,
280 .compare = fib6_rule_compare, 275 .compare = fib6_rule_compare,
281 .fill = fib6_rule_fill, 276 .fill = fib6_rule_fill,
282 .default_pref = fib6_rule_default_pref,
283 .nlmsg_payload = fib6_rule_nlmsg_payload, 277 .nlmsg_payload = fib6_rule_nlmsg_payload,
284 .nlgroup = RTNLGRP_IPV6_RULE, 278 .nlgroup = RTNLGRP_IPV6_RULE,
285 .policy = fib6_rule_policy, 279 .policy = fib6_rule_policy,
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 74ceb73c1c9a..0e004cc42a22 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -217,7 +217,6 @@ static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
217 .match = ip6mr_rule_match, 217 .match = ip6mr_rule_match,
218 .configure = ip6mr_rule_configure, 218 .configure = ip6mr_rule_configure,
219 .compare = ip6mr_rule_compare, 219 .compare = ip6mr_rule_compare,
220 .default_pref = fib_default_rule_pref,
221 .fill = ip6mr_rule_fill, 220 .fill = ip6mr_rule_fill,
222 .nlgroup = RTNLGRP_IPV6_RULE, 221 .nlgroup = RTNLGRP_IPV6_RULE,
223 .policy = ip6mr_rule_policy, 222 .policy = ip6mr_rule_policy,
@@ -550,7 +549,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
550 549
551 if (it->cache == &mrt->mfc6_unres_queue) 550 if (it->cache == &mrt->mfc6_unres_queue)
552 spin_unlock_bh(&mfc_unres_lock); 551 spin_unlock_bh(&mfc_unres_lock);
553 else if (it->cache == mrt->mfc6_cache_array) 552 else if (it->cache == &mrt->mfc6_cache_array[it->ct])
554 read_unlock(&mrt_lock); 553 read_unlock(&mrt_lock);
555} 554}
556 555
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index f45cac6f8356..53617d715188 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1748,7 +1748,7 @@ static int ip6_convert_metrics(struct mx6_config *mxc,
1748 return -EINVAL; 1748 return -EINVAL;
1749} 1749}
1750 1750
1751int ip6_route_add(struct fib6_config *cfg) 1751int ip6_route_info_create(struct fib6_config *cfg, struct rt6_info **rt_ret)
1752{ 1752{
1753 int err; 1753 int err;
1754 struct net *net = cfg->fc_nlinfo.nl_net; 1754 struct net *net = cfg->fc_nlinfo.nl_net;
@@ -1756,7 +1756,6 @@ int ip6_route_add(struct fib6_config *cfg)
1756 struct net_device *dev = NULL; 1756 struct net_device *dev = NULL;
1757 struct inet6_dev *idev = NULL; 1757 struct inet6_dev *idev = NULL;
1758 struct fib6_table *table; 1758 struct fib6_table *table;
1759 struct mx6_config mxc = { .mx = NULL, };
1760 int addr_type; 1759 int addr_type;
1761 1760
1762 if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128) 1761 if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
@@ -1981,6 +1980,32 @@ install_route:
1981 1980
1982 cfg->fc_nlinfo.nl_net = dev_net(dev); 1981 cfg->fc_nlinfo.nl_net = dev_net(dev);
1983 1982
1983 *rt_ret = rt;
1984
1985 return 0;
1986out:
1987 if (dev)
1988 dev_put(dev);
1989 if (idev)
1990 in6_dev_put(idev);
1991 if (rt)
1992 dst_free(&rt->dst);
1993
1994 *rt_ret = NULL;
1995
1996 return err;
1997}
1998
1999int ip6_route_add(struct fib6_config *cfg)
2000{
2001 struct mx6_config mxc = { .mx = NULL, };
2002 struct rt6_info *rt = NULL;
2003 int err;
2004
2005 err = ip6_route_info_create(cfg, &rt);
2006 if (err)
2007 goto out;
2008
1984 err = ip6_convert_metrics(&mxc, cfg); 2009 err = ip6_convert_metrics(&mxc, cfg);
1985 if (err) 2010 if (err)
1986 goto out; 2011 goto out;
@@ -1988,14 +2013,12 @@ install_route:
1988 err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, &mxc); 2013 err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, &mxc);
1989 2014
1990 kfree(mxc.mx); 2015 kfree(mxc.mx);
2016
1991 return err; 2017 return err;
1992out: 2018out:
1993 if (dev)
1994 dev_put(dev);
1995 if (idev)
1996 in6_dev_put(idev);
1997 if (rt) 2019 if (rt)
1998 dst_free(&rt->dst); 2020 dst_free(&rt->dst);
2021
1999 return err; 2022 return err;
2000} 2023}
2001 2024
@@ -2776,19 +2799,78 @@ errout:
2776 return err; 2799 return err;
2777} 2800}
2778 2801
2779static int ip6_route_multipath(struct fib6_config *cfg, int add) 2802struct rt6_nh {
2803 struct rt6_info *rt6_info;
2804 struct fib6_config r_cfg;
2805 struct mx6_config mxc;
2806 struct list_head next;
2807};
2808
2809static void ip6_print_replace_route_err(struct list_head *rt6_nh_list)
2810{
2811 struct rt6_nh *nh;
2812
2813 list_for_each_entry(nh, rt6_nh_list, next) {
2814 pr_warn("IPV6: multipath route replace failed (check consistency of installed routes): %pI6 nexthop %pI6 ifi %d\n",
2815 &nh->r_cfg.fc_dst, &nh->r_cfg.fc_gateway,
2816 nh->r_cfg.fc_ifindex);
2817 }
2818}
2819
2820static int ip6_route_info_append(struct list_head *rt6_nh_list,
2821 struct rt6_info *rt, struct fib6_config *r_cfg)
2822{
2823 struct rt6_nh *nh;
2824 struct rt6_info *rtnh;
2825 int err = -EEXIST;
2826
2827 list_for_each_entry(nh, rt6_nh_list, next) {
2828 /* check if rt6_info already exists */
2829 rtnh = nh->rt6_info;
2830
2831 if (rtnh->dst.dev == rt->dst.dev &&
2832 rtnh->rt6i_idev == rt->rt6i_idev &&
2833 ipv6_addr_equal(&rtnh->rt6i_gateway,
2834 &rt->rt6i_gateway))
2835 return err;
2836 }
2837
2838 nh = kzalloc(sizeof(*nh), GFP_KERNEL);
2839 if (!nh)
2840 return -ENOMEM;
2841 nh->rt6_info = rt;
2842 err = ip6_convert_metrics(&nh->mxc, r_cfg);
2843 if (err) {
2844 kfree(nh);
2845 return err;
2846 }
2847 memcpy(&nh->r_cfg, r_cfg, sizeof(*r_cfg));
2848 list_add_tail(&nh->next, rt6_nh_list);
2849
2850 return 0;
2851}
2852
2853static int ip6_route_multipath_add(struct fib6_config *cfg)
2780{ 2854{
2781 struct fib6_config r_cfg; 2855 struct fib6_config r_cfg;
2782 struct rtnexthop *rtnh; 2856 struct rtnexthop *rtnh;
2857 struct rt6_info *rt;
2858 struct rt6_nh *err_nh;
2859 struct rt6_nh *nh, *nh_safe;
2783 int remaining; 2860 int remaining;
2784 int attrlen; 2861 int attrlen;
2785 int err = 0, last_err = 0; 2862 int err = 1;
2863 int nhn = 0;
2864 int replace = (cfg->fc_nlinfo.nlh &&
2865 (cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_REPLACE));
2866 LIST_HEAD(rt6_nh_list);
2786 2867
2787 remaining = cfg->fc_mp_len; 2868 remaining = cfg->fc_mp_len;
2788beginning:
2789 rtnh = (struct rtnexthop *)cfg->fc_mp; 2869 rtnh = (struct rtnexthop *)cfg->fc_mp;
2790 2870
2791 /* Parse a Multipath Entry */ 2871 /* Parse a Multipath Entry and build a list (rt6_nh_list) of
2872 * rt6_info structs per nexthop
2873 */
2792 while (rtnh_ok(rtnh, remaining)) { 2874 while (rtnh_ok(rtnh, remaining)) {
2793 memcpy(&r_cfg, cfg, sizeof(*cfg)); 2875 memcpy(&r_cfg, cfg, sizeof(*cfg));
2794 if (rtnh->rtnh_ifindex) 2876 if (rtnh->rtnh_ifindex)
@@ -2808,22 +2890,32 @@ beginning:
2808 if (nla) 2890 if (nla)
2809 r_cfg.fc_encap_type = nla_get_u16(nla); 2891 r_cfg.fc_encap_type = nla_get_u16(nla);
2810 } 2892 }
2811 err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg); 2893
2894 err = ip6_route_info_create(&r_cfg, &rt);
2895 if (err)
2896 goto cleanup;
2897
2898 err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
2812 if (err) { 2899 if (err) {
2813 last_err = err; 2900 dst_free(&rt->dst);
2814 /* If we are trying to remove a route, do not stop the 2901 goto cleanup;
2815 * loop when ip6_route_del() fails (because next hop is 2902 }
2816 * already gone), we should try to remove all next hops. 2903
2817 */ 2904 rtnh = rtnh_next(rtnh, &remaining);
2818 if (add) { 2905 }
2819 /* If add fails, we should try to delete all 2906
2820 * next hops that have been already added. 2907 err_nh = NULL;
2821 */ 2908 list_for_each_entry(nh, &rt6_nh_list, next) {
2822 add = 0; 2909 err = __ip6_ins_rt(nh->rt6_info, &cfg->fc_nlinfo, &nh->mxc);
2823 remaining = cfg->fc_mp_len - remaining; 2910 /* nh->rt6_info is used or freed at this point, reset to NULL*/
2824 goto beginning; 2911 nh->rt6_info = NULL;
2825 } 2912 if (err) {
2913 if (replace && nhn)
2914 ip6_print_replace_route_err(&rt6_nh_list);
2915 err_nh = nh;
2916 goto add_errout;
2826 } 2917 }
2918
2827 /* Because each route is added like a single route we remove 2919 /* Because each route is added like a single route we remove
2828 * these flags after the first nexthop: if there is a collision, 2920 * these flags after the first nexthop: if there is a collision,
2829 * we have already failed to add the first nexthop: 2921 * we have already failed to add the first nexthop:
@@ -2833,6 +2925,62 @@ beginning:
2833 */ 2925 */
2834 cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | 2926 cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL |
2835 NLM_F_REPLACE); 2927 NLM_F_REPLACE);
2928 nhn++;
2929 }
2930
2931 goto cleanup;
2932
2933add_errout:
2934 /* Delete routes that were already added */
2935 list_for_each_entry(nh, &rt6_nh_list, next) {
2936 if (err_nh == nh)
2937 break;
2938 ip6_route_del(&nh->r_cfg);
2939 }
2940
2941cleanup:
2942 list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) {
2943 if (nh->rt6_info)
2944 dst_free(&nh->rt6_info->dst);
2945 kfree(nh->mxc.mx);
2946 list_del(&nh->next);
2947 kfree(nh);
2948 }
2949
2950 return err;
2951}
2952
2953static int ip6_route_multipath_del(struct fib6_config *cfg)
2954{
2955 struct fib6_config r_cfg;
2956 struct rtnexthop *rtnh;
2957 int remaining;
2958 int attrlen;
2959 int err = 1, last_err = 0;
2960
2961 remaining = cfg->fc_mp_len;
2962 rtnh = (struct rtnexthop *)cfg->fc_mp;
2963
2964 /* Parse a Multipath Entry */
2965 while (rtnh_ok(rtnh, remaining)) {
2966 memcpy(&r_cfg, cfg, sizeof(*cfg));
2967 if (rtnh->rtnh_ifindex)
2968 r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
2969
2970 attrlen = rtnh_attrlen(rtnh);
2971 if (attrlen > 0) {
2972 struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
2973
2974 nla = nla_find(attrs, attrlen, RTA_GATEWAY);
2975 if (nla) {
2976 nla_memcpy(&r_cfg.fc_gateway, nla, 16);
2977 r_cfg.fc_flags |= RTF_GATEWAY;
2978 }
2979 }
2980 err = ip6_route_del(&r_cfg);
2981 if (err)
2982 last_err = err;
2983
2836 rtnh = rtnh_next(rtnh, &remaining); 2984 rtnh = rtnh_next(rtnh, &remaining);
2837 } 2985 }
2838 2986
@@ -2849,7 +2997,7 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh)
2849 return err; 2997 return err;
2850 2998
2851 if (cfg.fc_mp) 2999 if (cfg.fc_mp)
2852 return ip6_route_multipath(&cfg, 0); 3000 return ip6_route_multipath_del(&cfg);
2853 else 3001 else
2854 return ip6_route_del(&cfg); 3002 return ip6_route_del(&cfg);
2855} 3003}
@@ -2864,7 +3012,7 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
2864 return err; 3012 return err;
2865 3013
2866 if (cfg.fc_mp) 3014 if (cfg.fc_mp)
2867 return ip6_route_multipath(&cfg, 1); 3015 return ip6_route_multipath_add(&cfg);
2868 else 3016 else
2869 return ip6_route_add(&cfg); 3017 return ip6_route_add(&cfg);
2870} 3018}