summaryrefslogtreecommitdiffstats
path: root/main/linux-grsec/0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2013-05-27 11:33:43 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2013-05-27 12:05:29 +0000
commita43c9a4092402400bd3f008d2841a468773ddad0 (patch)
treef1264d71f92081b3916c18bd7edc07a014f0973f /main/linux-grsec/0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch
parent3f54f79dddeca6c7d8bac4ade9257f8a65855bda (diff)
downloadaports-a43c9a4092402400bd3f008d2841a468773ddad0.tar.bz2
aports-a43c9a4092402400bd3f008d2841a468773ddad0.tar.xz
main/linux-grsec: upgrade to 3.9.4 and use reworked arp and frag patches
Diffstat (limited to 'main/linux-grsec/0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch')
-rw-r--r--main/linux-grsec/0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch201
1 files changed, 201 insertions, 0 deletions
diff --git a/main/linux-grsec/0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch b/main/linux-grsec/0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch
new file mode 100644
index 000000000..807dba0b3
--- /dev/null
+++ b/main/linux-grsec/0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch
@@ -0,0 +1,201 @@
+From 777eadba40c19bcfdb48807e7b0547ef30555671 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
+Date: Sat, 25 May 2013 15:42:30 +0300
+Subject: [PATCH 3/6] ipv4: properly refresh rtable entries on pmtu/redirect
+ events
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This reverts commit 05ab86c5 (xfrm4: Invalidate all ipv4 routes on
+IPsec pmtu events). Flushing all cached entries is not needed.
+
+Instead, invalidate only the related next hop dsts to recheck for
+the added next hop exception where needed. This also fixes a subtle
+race due to bumping generation id's before updating the pmtu.
+
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Timo Teräs <timo.teras@iki.fi>
+---
+ net/ipv4/ah4.c | 7 ++-----
+ net/ipv4/esp4.c | 7 ++-----
+ net/ipv4/ipcomp.c | 7 ++-----
+ net/ipv4/route.c | 63 ++++++++++++++++++++++++++++++++-----------------------
+ 4 files changed, 43 insertions(+), 41 deletions(-)
+
+diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
+index 2e7f194..7179026 100644
+--- a/net/ipv4/ah4.c
++++ b/net/ipv4/ah4.c
+@@ -419,12 +419,9 @@ static void ah4_err(struct sk_buff *skb, u32 info)
+ if (!x)
+ return;
+
+- if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+- atomic_inc_unchecked(&flow_cache_genid);
+- rt_genid_bump(net);
+-
++ if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+ ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0);
+- } else
++ else
+ ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0);
+ xfrm_state_put(x);
+ }
+diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
+index 4cfe34d..ab3d814 100644
+--- a/net/ipv4/esp4.c
++++ b/net/ipv4/esp4.c
+@@ -502,12 +502,9 @@ static void esp4_err(struct sk_buff *skb, u32 info)
+ if (!x)
+ return;
+
+- if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+- atomic_inc_unchecked(&flow_cache_genid);
+- rt_genid_bump(net);
+-
++ if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+ ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0);
+- } else
++ else
+ ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0);
+ xfrm_state_put(x);
+ }
+diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
+index f01d1b1..48b3f0b 100644
+--- a/net/ipv4/ipcomp.c
++++ b/net/ipv4/ipcomp.c
+@@ -47,12 +47,9 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
+ if (!x)
+ return;
+
+- if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+- atomic_inc_unchecked(&flow_cache_genid);
+- rt_genid_bump(net);
+-
++ if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+ ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0);
+- } else
++ else
+ ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0);
+ xfrm_state_put(x);
+ }
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index 6e28514..8dedfeb 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -594,11 +594,25 @@ static inline u32 fnhe_hashfun(__be32 daddr)
+ return hval & (FNHE_HASH_SIZE - 1);
+ }
+
++static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnhe)
++{
++ rt->rt_pmtu = fnhe->fnhe_pmtu;
++ rt->dst.expires = fnhe->fnhe_expires;
++
++ if (fnhe->fnhe_gw) {
++ rt->rt_flags |= RTCF_REDIRECTED;
++ rt->rt_gateway = fnhe->fnhe_gw;
++ rt->rt_uses_gateway = 1;
++ }
++}
++
+ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
+ u32 pmtu, unsigned long expires)
+ {
+ struct fnhe_hash_bucket *hash;
+ struct fib_nh_exception *fnhe;
++ struct rtable *rt;
++ unsigned int i;
+ int depth;
+ u32 hval = fnhe_hashfun(daddr);
+
+@@ -627,8 +641,12 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
+ fnhe->fnhe_gw = gw;
+ if (pmtu) {
+ fnhe->fnhe_pmtu = pmtu;
+- fnhe->fnhe_expires = expires;
++ fnhe->fnhe_expires = max(1UL, expires);
+ }
++ /* Update all cached dsts too */
++ rt = rcu_dereference(fnhe->fnhe_rth);
++ if (rt)
++ fill_route_from_fnhe(rt, fnhe);
+ } else {
+ if (depth > FNHE_RECLAIM_DEPTH)
+ fnhe = fnhe_oldest(hash);
+@@ -644,6 +662,18 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
+ fnhe->fnhe_gw = gw;
+ fnhe->fnhe_pmtu = pmtu;
+ fnhe->fnhe_expires = expires;
++
++ /* Exception created; mark the cached routes for the nexthop
++ * stale, so anyone caching it rechecks if this exception
++ * applies to them.
++ */
++ for_each_possible_cpu(i) {
++ struct rtable __rcu **prt;
++ prt = per_cpu_ptr(nh->nh_pcpu_rth_output, i);
++ rt = rcu_dereference(*prt);
++ if (rt)
++ rt->dst.obsolete = DST_OBSOLETE_KILL;
++ }
+ }
+
+ fnhe->fnhe_stamp = jiffies;
+@@ -917,13 +947,6 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
+ if (mtu < ip_rt_min_pmtu)
+ mtu = ip_rt_min_pmtu;
+
+- if (!rt->rt_pmtu) {
+- dst->obsolete = DST_OBSOLETE_KILL;
+- } else {
+- rt->rt_pmtu = mtu;
+- dst->expires = max(1UL, jiffies + ip_rt_mtu_expires);
+- }
+-
+ rcu_read_lock();
+ if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) {
+ struct fib_nh *nh = &FIB_RES_NH(res);
+@@ -1063,11 +1086,11 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
+ * DST_OBSOLETE_FORCE_CHK which forces validation calls down
+ * into this function always.
+ *
+- * When a PMTU/redirect information update invalidates a
+- * route, this is indicated by setting obsolete to
+- * DST_OBSOLETE_KILL.
++ * When a PMTU/redirect information update invalidates a route,
++ * this is indicated by setting obsolete to DST_OBSOLETE_KILL or
++ * DST_OBSOLETE_DEAD by dst_free().
+ */
+- if (dst->obsolete == DST_OBSOLETE_KILL || rt_is_expired(rt))
++ if (dst->obsolete != DST_OBSOLETE_FORCE_CHK || rt_is_expired(rt))
+ return NULL;
+ return dst;
+ }
+@@ -1215,20 +1238,8 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
+ fnhe->fnhe_pmtu = 0;
+ fnhe->fnhe_expires = 0;
+ }
+- if (fnhe->fnhe_pmtu) {
+- unsigned long expires = fnhe->fnhe_expires;
+- unsigned long diff = expires - jiffies;
+-
+- if (time_before(jiffies, expires)) {
+- rt->rt_pmtu = fnhe->fnhe_pmtu;
+- dst_set_expires(&rt->dst, diff);
+- }
+- }
+- if (fnhe->fnhe_gw) {
+- rt->rt_flags |= RTCF_REDIRECTED;
+- rt->rt_gateway = fnhe->fnhe_gw;
+- rt->rt_uses_gateway = 1;
+- } else if (!rt->rt_gateway)
++ fill_route_from_fnhe(rt, fnhe);
++ if (!rt->rt_gateway)
+ rt->rt_gateway = daddr;
+
+ rcu_assign_pointer(fnhe->fnhe_rth, rt);
+--
+1.8.2.3
+