diff options
author | Leonardo Arena <rnalrd@alpinelinux.org> | 2013-06-11 09:48:45 +0000 |
---|---|---|
committer | Leonardo Arena <rnalrd@alpinelinux.org> | 2013-06-11 09:48:59 +0000 |
commit | f3dd5095137cc77d9c634e5bb670b6f024d499ad (patch) | |
tree | fb32417505a0420cf7120a337181d5c4e5523b3c /main/linux-virt-grsec/0006-ipv4-use-next-hop-exceptions-also-for-input-routes.patch | |
parent | 47bb9d7aa2cac0320a6bbe5d052af53c3d57a9f1 (diff) | |
download | aports-f3dd5095137cc77d9c634e5bb670b6f024d499ad.tar.bz2 aports-f3dd5095137cc77d9c634e5bb670b6f024d499ad.tar.xz |
main/linux-virt-grsec: upgrade to 3.9.5
Diffstat (limited to 'main/linux-virt-grsec/0006-ipv4-use-next-hop-exceptions-also-for-input-routes.patch')
-rw-r--r-- | main/linux-virt-grsec/0006-ipv4-use-next-hop-exceptions-also-for-input-routes.patch | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/main/linux-virt-grsec/0006-ipv4-use-next-hop-exceptions-also-for-input-routes.patch b/main/linux-virt-grsec/0006-ipv4-use-next-hop-exceptions-also-for-input-routes.patch new file mode 100644 index 0000000000..9b78e76b2c --- /dev/null +++ b/main/linux-virt-grsec/0006-ipv4-use-next-hop-exceptions-also-for-input-routes.patch @@ -0,0 +1,213 @@ +From 87151ab93a08bcc4abe23aa2e87fbc2b956ae2cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Mon, 27 May 2013 08:40:22 +0300 +Subject: [PATCH 6/6] ipv4: use next hop exceptions also for input routes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Commit d2d68ba9 (ipv4: Cache input routes in fib_info nexthops) +assmued that "locally destined, and routed packets, never trigger +PMTU events or redirects that will be processed by us". + +However, it seems that tunnel devices do trigger PMTU events in certain +cases. At least ip_gre, ip6_gre, sit, and ipip do use the inner flow's +skb_dst(skb)->ops->update_pmtu to propage mtu information from the +outer flows. These can cause the inner flow mtu to be decreased. If +next hop exceptions are not consulted for pmtu, IP fragmentation will +not be done properly for these routes. + +It also seems that we really need to have the PMTU information always +for netfilter TCPMSS clamp-to-pmtu feature to work properly. + +So for the time being, cache separate copies of input routes for +each next hop exception. + +Signed-off-by: Timo Teräs <timo.teras@iki.fi> +--- + include/net/ip_fib.h | 3 ++- + net/ipv4/fib_semantics.c | 3 ++- + net/ipv4/route.c | 65 +++++++++++++++++++++++++++++++++++++----------- + 3 files changed, 54 insertions(+), 17 deletions(-) + +diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h +index 44424e9..aac8553 100644 +--- a/include/net/ip_fib.h ++++ b/include/net/ip_fib.h +@@ -56,7 +56,8 @@ struct fib_nh_exception { + u32 fnhe_pmtu; + __be32 fnhe_gw; + unsigned long fnhe_expires; +- struct rtable __rcu *fnhe_rth; ++ struct rtable __rcu *fnhe_rth_input; ++ struct rtable __rcu *fnhe_rth_output; + unsigned long fnhe_stamp; + }; + +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 8f6cb7a..d5dbca5 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -169,7 +169,8 @@ static void free_nh_exceptions(struct fib_nh *nh) + + next = rcu_dereference_protected(fnhe->fnhe_next, 1); + +- rt_fibinfo_free(&fnhe->fnhe_rth); ++ rt_fibinfo_free(&fnhe->fnhe_rth_input); ++ rt_fibinfo_free(&fnhe->fnhe_rth_output); + + kfree(fnhe); + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index f44a4bb..a7a36f7 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -565,10 +565,25 @@ static inline void rt_free(struct rtable *rt) + + static DEFINE_SPINLOCK(fnhe_lock); + ++static void fnhe_flush_routes(struct fib_nh_exception *fnhe) ++{ ++ struct rtable *rt; ++ ++ rt = rcu_dereference(fnhe->fnhe_rth_input); ++ if (rt) { ++ RCU_INIT_POINTER(fnhe->fnhe_rth_input, NULL); ++ rt_free(rt); ++ } ++ rt = rcu_dereference(fnhe->fnhe_rth_output); ++ if (rt) { ++ RCU_INIT_POINTER(fnhe->fnhe_rth_output, NULL); ++ rt_free(rt); ++ } ++} ++ + static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash) + { + struct fib_nh_exception *fnhe, *oldest; +- struct rtable *orig; + + oldest = rcu_dereference(hash->chain); + for (fnhe = rcu_dereference(oldest->fnhe_next); fnhe; +@@ -576,11 +591,7 @@ static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash) + if (time_before(fnhe->fnhe_stamp, oldest->fnhe_stamp)) + oldest = fnhe; + } +- orig = rcu_dereference(oldest->fnhe_rth); +- if (orig) { +- RCU_INIT_POINTER(oldest->fnhe_rth, NULL); +- rt_free(orig); +- } ++ fnhe_flush_routes(oldest); + return oldest; + } + +@@ -644,7 +655,10 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, + fnhe->fnhe_expires = max(1UL, expires); + } + /* Update all cached dsts too */ +- rt = rcu_dereference(fnhe->fnhe_rth); ++ rt = rcu_dereference(fnhe->fnhe_rth_input); ++ if (rt) ++ fill_route_from_fnhe(rt, fnhe); ++ rt = rcu_dereference(fnhe->fnhe_rth_output); + if (rt) + fill_route_from_fnhe(rt, fnhe); + } else { +@@ -668,6 +682,10 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, + * stale, so anyone caching it rechecks if this exception + * applies to them. + */ ++ rt = rcu_dereference(nh->nh_rth_input); ++ if (rt) ++ rt->dst.obsolete = DST_OBSOLETE_KILL; ++ + for_each_possible_cpu(i) { + struct rtable __rcu **prt; + prt = per_cpu_ptr(nh->nh_pcpu_rth_output, i); +@@ -1237,25 +1255,36 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, + spin_lock_bh(&fnhe_lock); + + if (daddr == fnhe->fnhe_daddr) { ++ struct rtable __rcu **porig; ++ struct rtable *orig; + int genid = fnhe_genid(dev_net(rt->dst.dev)); +- struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); ++ ++ if (rt_is_input_route(rt)) ++ porig = &fnhe->fnhe_rth_input; ++ else ++ porig = &fnhe->fnhe_rth_output; ++ orig = rcu_dereference(*porig); + + if (fnhe->fnhe_genid != genid) { + fnhe->fnhe_genid = genid; + fnhe->fnhe_gw = 0; + fnhe->fnhe_pmtu = 0; + fnhe->fnhe_expires = 0; ++ fnhe_flush_routes(fnhe); ++ orig = NULL; + } + fill_route_from_fnhe(rt, fnhe); + if (!rt->rt_gateway) + rt->rt_gateway = daddr; + +- rcu_assign_pointer(fnhe->fnhe_rth, rt); +- if (orig) +- rt_free(orig); ++ if (!(rt->dst.flags & DST_NOCACHE)) { ++ rcu_assign_pointer(*porig, rt); ++ if (orig) ++ rt_free(orig); ++ ret = true; ++ } + + fnhe->fnhe_stamp = jiffies; +- ret = true; + } + spin_unlock_bh(&fnhe_lock); + +@@ -1487,6 +1516,7 @@ static int __mkroute_input(struct sk_buff *skb, + struct in_device *in_dev, + __be32 daddr, __be32 saddr, u32 tos) + { ++ struct fib_nh_exception *fnhe; + struct rtable *rth; + int err; + struct in_device *out_dev; +@@ -1533,8 +1563,13 @@ static int __mkroute_input(struct sk_buff *skb, + } + } + ++ fnhe = find_exception(&FIB_RES_NH(*res), daddr); + if (do_cache) { +- rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); ++ if (fnhe != NULL) ++ rth = rcu_dereference(fnhe->fnhe_rth_input); ++ else ++ rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); ++ + if (rt_cache_valid(rth)) { + skb_dst_set_noref(skb, &rth->dst); + goto out; +@@ -1562,7 +1597,7 @@ static int __mkroute_input(struct sk_buff *skb, + rth->dst.input = ip_forward; + rth->dst.output = ip_output; + +- rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag); ++ rt_set_nexthop(rth, daddr, res, fnhe, res->fi, res->type, itag); + skb_dst_set(skb, &rth->dst); + out: + err = 0; +@@ -1877,7 +1912,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, + + fnhe = find_exception(nh, fl4->daddr); + if (fnhe) +- prth = &fnhe->fnhe_rth; ++ prth = &fnhe->fnhe_rth_output; + else { + if (unlikely(fl4->flowi4_flags & + FLOWI_FLAG_KNOWN_NH && +-- +1.8.2.3 + |