aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2010-04-14 08:44:44 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2010-04-14 12:22:02 +0000
commit1c6a075cc9e7b129c0d2259ee7514333acdf8246 (patch)
tree54255de442cecc3897a48369c24b429ded57d087
parentf4c1523e429f2a7e9d5c83c6d8a41b0a6fdbd2b0 (diff)
downloadalpine_aports-1c6a075cc9e7b129c0d2259ee7514333acdf8246.tar.bz2
alpine_aports-1c6a075cc9e7b129c0d2259ee7514333acdf8246.tar.xz
alpine_aports-1c6a075cc9e7b129c0d2259ee7514333acdf8246.zip
main/linux-grsec: ipsec improvement patches
backport of net-next to improve ipsec send performance (cherry picked from commit b1b9aa2787e3f40f38fbf6a258fcbd2b0a19478a)
-rw-r--r--main/linux-grsec/0001-grsec-revert-conflicting-flow-cache-changes.patch43
-rw-r--r--main/linux-grsec/0002-gre-fix-hard-header-destination-address-checking.patch44
-rw-r--r--main/linux-grsec/0003-ip_gre-include-route-header_len-in-max_headroom-calc.patch39
-rw-r--r--main/linux-grsec/0004-arp-flush-arp-cache-on-device-change.patch29
-rw-r--r--main/linux-grsec/0005-r8169-fix-broken-register-writes.patch (renamed from main/linux-grsec/net-git-78f1cd-r8169-fix-broken-register-writes.patch)17
-rw-r--r--main/linux-grsec/0006-r8169-offical-fix-for-CVE-2009-4537-overlength-frame.patch (renamed from main/linux-grsec/net-git-c0cd88-r8169-offical-fix-for-CVE-2009-4537-overlength-frame-DMAs.patch)17
-rw-r--r--main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch89
-rw-r--r--main/linux-grsec/0008-r8169-clean-up-my-printk-uglyness.patch36
-rw-r--r--main/linux-grsec/0009-ipsec-Fix-bogus-bundle-flowi.patch110
-rw-r--r--main/linux-grsec/0010-xfrm-Remove-xfrm_state_genid.patch54
-rw-r--r--main/linux-grsec/0011-xfrm_user-verify-policy-direction-at-XFRM_MSG_POLEXP.patch35
-rw-r--r--main/linux-grsec/0012-xfrm-remove-policy-lock-when-accessing-policy-walk.d.patch105
-rw-r--r--main/linux-grsec/0013-flow-structurize-flow-cache.patch395
-rw-r--r--main/linux-grsec/0014-flow-virtualize-flow-cache-entry-methods.patch513
-rw-r--r--main/linux-grsec/0015-xfrm-cache-bundles-instead-of-policies-for-outgoing-.patch1068
-rw-r--r--main/linux-grsec/0016-xfrm-remove-policy-garbage-collection.patch91
-rw-r--r--main/linux-grsec/0017-flow-delayed-deletion-of-flow-cache-entries.patch231
-rw-r--r--main/linux-grsec/0018-xfrm-Fix-crashes-in-xfrm_lookup.patch46
-rw-r--r--main/linux-grsec/APKBUILD53
-rw-r--r--main/linux-grsec/arp.patch14
-rw-r--r--main/linux-grsec/ip_gre.patch15
-rw-r--r--main/linux-grsec/ip_gre2.patch17
22 files changed, 2985 insertions, 76 deletions
diff --git a/main/linux-grsec/0001-grsec-revert-conflicting-flow-cache-changes.patch b/main/linux-grsec/0001-grsec-revert-conflicting-flow-cache-changes.patch
new file mode 100644
index 0000000000..99571657b1
--- /dev/null
+++ b/main/linux-grsec/0001-grsec-revert-conflicting-flow-cache-changes.patch
@@ -0,0 +1,43 @@
1From 5ea3677e1f26dd343ed139d2bdad23ae2f1393db Mon Sep 17 00:00:00 2001
2From: Timo Teras <timo.teras@iki.fi>
3Date: Mon, 12 Apr 2010 13:43:01 +0000
4Subject: [PATCH 01/18] grsec: revert conflicting flow cache changes
5
6---
7 net/core/flow.c | 6 +++---
8 1 files changed, 3 insertions(+), 3 deletions(-)
9
10diff --git a/net/core/flow.c b/net/core/flow.c
11index 5b27992..9601587 100644
12--- a/net/core/flow.c
13+++ b/net/core/flow.c
14@@ -39,7 +39,7 @@ atomic_t flow_cache_genid = ATOMIC_INIT(0);
15
16 static u32 flow_hash_shift;
17 #define flow_hash_size (1 << flow_hash_shift)
18-static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables);
19+static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL };
20
21 #define flow_table(cpu) (per_cpu(flow_tables, cpu))
22
23@@ -52,7 +52,7 @@ struct flow_percpu_info {
24 u32 hash_rnd;
25 int count;
26 };
27-static DEFINE_PER_CPU(struct flow_percpu_info, flow_hash_info);
28+static DEFINE_PER_CPU(struct flow_percpu_info, flow_hash_info) = { 0 };
29
30 #define flow_hash_rnd_recalc(cpu) \
31 (per_cpu(flow_hash_info, cpu).hash_rnd_recalc)
32@@ -69,7 +69,7 @@ struct flow_flush_info {
33 atomic_t cpuleft;
34 struct completion completion;
35 };
36-static DEFINE_PER_CPU(struct tasklet_struct, flow_flush_tasklets);
37+static DEFINE_PER_CPU(struct tasklet_struct, flow_flush_tasklets) = { NULL };
38
39 #define flow_flush_tasklet(cpu) (&per_cpu(flow_flush_tasklets, cpu))
40
41--
421.7.0.2
43
diff --git a/main/linux-grsec/0002-gre-fix-hard-header-destination-address-checking.patch b/main/linux-grsec/0002-gre-fix-hard-header-destination-address-checking.patch
new file mode 100644
index 0000000000..36a0ae449a
--- /dev/null
+++ b/main/linux-grsec/0002-gre-fix-hard-header-destination-address-checking.patch
@@ -0,0 +1,44 @@
1From 9082391046940c410eac3bad065c8701998b5cab Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Wed, 3 Mar 2010 04:01:13 +0000
4Subject: [PATCH 02/18] gre: fix hard header destination address checking
5
6ipgre_header() can be called with zero daddr when the gre device is
7configured as multipoint tunnel and still has the NOARP flag set (which is
8typically cleared by the userspace arp daemon). If the NOARP packets are
9not dropped, ipgre_tunnel_xmit() will take rt->rt_gateway (= NBMA IP) and
10use that for route look up (and may lead to bogus xfrm acquires).
11
12The multicast address check is removed as sending to multicast group should
13be ok. In fact, if gre device has a multicast address as destination
14ipgre_header is always called with multicast address.
15
16Signed-off-by: Timo Teras <timo.teras@iki.fi>
17Signed-off-by: David S. Miller <davem@davemloft.net>
18(cherry picked from commit 6d55cb91a0020ac0d78edcad61efd6c8cf5785a3)
19---
20 net/ipv4/ip_gre.c | 7 ++-----
21 1 files changed, 2 insertions(+), 5 deletions(-)
22
23diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
24index 1433338..ac88ce5 100644
25--- a/net/ipv4/ip_gre.c
26+++ b/net/ipv4/ip_gre.c
27@@ -1137,12 +1137,9 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
28
29 if (saddr)
30 memcpy(&iph->saddr, saddr, 4);
31-
32- if (daddr) {
33+ if (daddr)
34 memcpy(&iph->daddr, daddr, 4);
35- return t->hlen;
36- }
37- if (iph->daddr && !ipv4_is_multicast(iph->daddr))
38+ if (iph->daddr)
39 return t->hlen;
40
41 return -t->hlen;
42--
431.7.0.2
44
diff --git a/main/linux-grsec/0003-ip_gre-include-route-header_len-in-max_headroom-calc.patch b/main/linux-grsec/0003-ip_gre-include-route-header_len-in-max_headroom-calc.patch
new file mode 100644
index 0000000000..61d7c9a6c1
--- /dev/null
+++ b/main/linux-grsec/0003-ip_gre-include-route-header_len-in-max_headroom-calc.patch
@@ -0,0 +1,39 @@
1From cd0e9d08480e1e0648e17d099ecf50f6fd8714e5 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Sat, 20 Mar 2010 02:27:58 +0000
4Subject: [PATCH 03/18] ip_gre: include route header_len in max_headroom calculation
5
6Taking route's header_len into account, and updating gre device
7needed_headroom will give better hints on upper bound of required
8headroom. This is useful if the gre traffic is xfrm'ed.
9
10Signed-off-by: Timo Teras <timo.teras@iki.fi>
11Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
12Signed-off-by: David S. Miller <davem@davemloft.net>
13(cherry picked from commit 243aad830e8a4cdda261626fbaeddde16b08d04a)
14---
15 net/ipv4/ip_gre.c | 4 +++-
16 1 files changed, 3 insertions(+), 1 deletions(-)
17
18diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
19index ac88ce5..7f1ff73 100644
20--- a/net/ipv4/ip_gre.c
21+++ b/net/ipv4/ip_gre.c
22@@ -803,11 +803,13 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
23 tunnel->err_count = 0;
24 }
25
26- max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;
27+ max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->u.dst.header_len;
28
29 if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
30 (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
31 struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
32+ if (max_headroom > dev->needed_headroom)
33+ dev->needed_headroom = max_headroom;
34 if (!new_skb) {
35 ip_rt_put(rt);
36 stats->tx_dropped++;
37--
381.7.0.2
39
diff --git a/main/linux-grsec/0004-arp-flush-arp-cache-on-device-change.patch b/main/linux-grsec/0004-arp-flush-arp-cache-on-device-change.patch
new file mode 100644
index 0000000000..85161ea3a3
--- /dev/null
+++ b/main/linux-grsec/0004-arp-flush-arp-cache-on-device-change.patch
@@ -0,0 +1,29 @@
1From 8a0e3ea4924059a7268446177d6869e3399adbb2 Mon Sep 17 00:00:00 2001
2From: Timo Teras <timo.teras@iki.fi>
3Date: Mon, 12 Apr 2010 13:46:45 +0000
4Subject: [PATCH 04/18] arp: flush arp cache on device change
5
6If IFF_NOARP is changed, we must flush the arp cache.
7
8Signed-off-by: Timo Teras <timo.teras@iki.fi>
9---
10 net/ipv4/arp.c | 3 +++
11 1 files changed, 3 insertions(+), 0 deletions(-)
12
13diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
14index 4e80f33..580bfc3 100644
15--- a/net/ipv4/arp.c
16+++ b/net/ipv4/arp.c
17@@ -1200,6 +1200,9 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
18 neigh_changeaddr(&arp_tbl, dev);
19 rt_cache_flush(dev_net(dev), 0);
20 break;
21+ case NETDEV_CHANGE:
22+ neigh_changeaddr(&arp_tbl, dev);
23+ break;
24 default:
25 break;
26 }
27--
281.7.0.2
29
diff --git a/main/linux-grsec/net-git-78f1cd-r8169-fix-broken-register-writes.patch b/main/linux-grsec/0005-r8169-fix-broken-register-writes.patch
index f5f72acc4b..bfa8df2900 100644
--- a/main/linux-grsec/net-git-78f1cd-r8169-fix-broken-register-writes.patch
+++ b/main/linux-grsec/0005-r8169-fix-broken-register-writes.patch
@@ -1,9 +1,9 @@
1From 78f1cd02457252e1ffbc6caa44a17424a45286b8 Mon Sep 17 00:00:00 2001 1From 89f350c4ec426b4c1db6ef269546940365d918e1 Mon Sep 17 00:00:00 2001
2From: Francois Romieu <romieu@fr.zoreil.com> 2From: Francois Romieu <romieu@fr.zoreil.com>
3Date: Sat, 27 Mar 2010 19:35:46 -0700 3Date: Sat, 27 Mar 2010 19:35:46 -0700
4Subject: [PATCH] r8169: fix broken register writes 4Subject: [PATCH 05/18] r8169: fix broken register writes
5MIME-Version: 1.0 5MIME-Version: 1.0
6Content-Type: text/plain; charset=utf8 6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit 7Content-Transfer-Encoding: 8bit
8 8
9This is quite similar to b39fe41f481d20c201012e4483e76c203802dda7 9This is quite similar to b39fe41f481d20c201012e4483e76c203802dda7
@@ -14,19 +14,20 @@ level before being merged into a 64 bit logical entity.
14 14
15Credits go to Ben Hutchings <ben@decadent.org.uk> for the MAR 15Credits go to Ben Hutchings <ben@decadent.org.uk> for the MAR
16registers (aka "multicast is broken for ages on ARM) and to 16registers (aka "multicast is broken for ages on ARM) and to
17Timo TerĂƒÂ¤s <timo.teras@iki.fi> for the MAC registers. 17Timo Teräs <timo.teras@iki.fi> for the MAC registers.
18 18
19Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> 19Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
20Signed-off-by: David S. Miller <davem@davemloft.net> 20Signed-off-by: David S. Miller <davem@davemloft.net>
21(cherry picked from commit 78f1cd02457252e1ffbc6caa44a17424a45286b8)
21--- 22---
22 drivers/net/r8169.c | 4 ++-- 23 drivers/net/r8169.c | 4 ++--
23 1 files changed, 2 insertions(+), 2 deletions(-) 24 1 files changed, 2 insertions(+), 2 deletions(-)
24 25
25diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c 26diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
26index b93fd23..7193afc 100644 27index 0fe2fc9..24599b5 100644
27--- a/drivers/net/r8169.c 28--- a/drivers/net/r8169.c
28+++ b/drivers/net/r8169.c 29+++ b/drivers/net/r8169.c
29@@ -2820,8 +2820,8 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) 30@@ -2827,8 +2827,8 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
30 spin_lock_irq(&tp->lock); 31 spin_lock_irq(&tp->lock);
31 32
32 RTL_W8(Cfg9346, Cfg9346_Unlock); 33 RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -36,7 +37,7 @@ index b93fd23..7193afc 100644
36 RTL_W8(Cfg9346, Cfg9346_Lock); 37 RTL_W8(Cfg9346, Cfg9346_Lock);
37 38
38 spin_unlock_irq(&tp->lock); 39 spin_unlock_irq(&tp->lock);
39@@ -4747,8 +4747,8 @@ static void rtl_set_rx_mode(struct net_device *dev) 40@@ -4795,8 +4795,8 @@ static void rtl_set_rx_mode(struct net_device *dev)
40 mc_filter[1] = swab32(data); 41 mc_filter[1] = swab32(data);
41 } 42 }
42 43
@@ -47,5 +48,5 @@ index b93fd23..7193afc 100644
47 RTL_W32(RxConfig, tmp); 48 RTL_W32(RxConfig, tmp);
48 49
49-- 50--
501.7.0.3 511.7.0.2
51 52
diff --git a/main/linux-grsec/net-git-c0cd88-r8169-offical-fix-for-CVE-2009-4537-overlength-frame-DMAs.patch b/main/linux-grsec/0006-r8169-offical-fix-for-CVE-2009-4537-overlength-frame.patch
index 250c85d678..03ea13fa1e 100644
--- a/main/linux-grsec/net-git-c0cd88-r8169-offical-fix-for-CVE-2009-4537-overlength-frame-DMAs.patch
+++ b/main/linux-grsec/0006-r8169-offical-fix-for-CVE-2009-4537-overlength-frame.patch
@@ -1,7 +1,7 @@
1From c0cd884af045338476b8e69a61fceb3f34ff22f1 Mon Sep 17 00:00:00 2001 1From a60cfaf3df9cd0cddbc24695434ed5bfa917d505 Mon Sep 17 00:00:00 2001
2From: Neil Horman <nhorman@redhat.com> 2From: Neil Horman <nhorman@redhat.com>
3Date: Mon, 29 Mar 2010 13:16:02 -0700 3Date: Mon, 29 Mar 2010 13:16:02 -0700
4Subject: [PATCH] r8169: offical fix for CVE-2009-4537 (overlength frame DMAs) 4Subject: [PATCH 06/18] r8169: offical fix for CVE-2009-4537 (overlength frame DMAs)
5 5
6Official patch to fix the r8169 frame length check error. 6Official patch to fix the r8169 frame length check error.
7 7
@@ -48,15 +48,16 @@ such that performance is restored easily.
48 48
49Signed-off-by: Neil Horman <nhorman@redhat.com> 49Signed-off-by: Neil Horman <nhorman@redhat.com>
50Signed-off-by: David S. Miller <davem@davemloft.net> 50Signed-off-by: David S. Miller <davem@davemloft.net>
51(cherry picked from commit c0cd884af045338476b8e69a61fceb3f34ff22f1)
51--- 52---
52 drivers/net/r8169.c | 29 ++++++++++++++++++++++++----- 53 drivers/net/r8169.c | 29 ++++++++++++++++++++++++-----
53 1 files changed, 24 insertions(+), 5 deletions(-) 54 1 files changed, 24 insertions(+), 5 deletions(-)
54 55
55diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c 56diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
56index 7193afc..9674005 100644 57index 24599b5..1484528 100644
57--- a/drivers/net/r8169.c 58--- a/drivers/net/r8169.c
58+++ b/drivers/net/r8169.c 59+++ b/drivers/net/r8169.c
59@@ -186,7 +186,12 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { 60@@ -186,7 +186,12 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
60 61
61 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); 62 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
62 63
@@ -70,7 +71,7 @@ index 7193afc..9674005 100644
70 static int use_dac; 71 static int use_dac;
71 static struct { 72 static struct {
72 u32 msg_enable; 73 u32 msg_enable;
73@@ -3217,9 +3222,13 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) 74@@ -3245,9 +3250,13 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
74 } 75 }
75 76
76 static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, 77 static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
@@ -86,7 +87,7 @@ index 7193afc..9674005 100644
86 87
87 tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE; 88 tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE;
88 } 89 }
89@@ -3231,7 +3240,17 @@ static int rtl8169_open(struct net_device *dev) 90@@ -3259,7 +3268,17 @@ static int rtl8169_open(struct net_device *dev)
90 int retval = -ENOMEM; 91 int retval = -ENOMEM;
91 92
92 93
@@ -105,7 +106,7 @@ index 7193afc..9674005 100644
105 106
106 /* 107 /*
107 * Rx and Tx desscriptors needs 256 bytes alignment. 108 * Rx and Tx desscriptors needs 256 bytes alignment.
108@@ -3884,7 +3903,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) 109@@ -3912,7 +3931,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
109 110
110 rtl8169_down(dev); 111 rtl8169_down(dev);
111 112
@@ -115,5 +116,5 @@ index 7193afc..9674005 100644
115 ret = rtl8169_init_ring(dev); 116 ret = rtl8169_init_ring(dev);
116 if (ret < 0) 117 if (ret < 0)
117-- 118--
1181.7.0.3 1191.7.0.2
119 120
diff --git a/main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch b/main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch
new file mode 100644
index 0000000000..fad2723284
--- /dev/null
+++ b/main/linux-grsec/0007-r8169-Fix-rtl8169_rx_interrupt.patch
@@ -0,0 +1,89 @@
1From 26654a966adb674afc30d285f7e79535d03c2492 Mon Sep 17 00:00:00 2001
2From: Eric Dumazet <eric.dumazet@gmail.com>
3Date: Wed, 31 Mar 2010 02:08:31 +0000
4Subject: [PATCH 07/18] r8169: Fix rtl8169_rx_interrupt()
5
6In case a reset is performed, rtl8169_rx_interrupt() is called from
7process context instead of softirq context. Special care must be taken
8to call appropriate network core services (netif_rx() instead of
9netif_receive_skb()). VLAN handling also corrected.
10
11Reported-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
12Tested-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
13Diagnosed-by: Oleg Nesterov <oleg@redhat.com>
14Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
15Signed-off-by: David S. Miller <davem@davemloft.net>
16(cherry picked from commit 630b943c182d1aed69f244405131902fbcba7ec6)
17---
18 drivers/net/r8169.c | 22 +++++++++++++++++-----
19 1 files changed, 17 insertions(+), 5 deletions(-)
20
21diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
22index 1484528..bed1d47 100644
23--- a/drivers/net/r8169.c
24+++ b/drivers/net/r8169.c
25@@ -1047,14 +1047,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev,
26 }
27
28 static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
29- struct sk_buff *skb)
30+ struct sk_buff *skb, int polling)
31 {
32 u32 opts2 = le32_to_cpu(desc->opts2);
33 struct vlan_group *vlgrp = tp->vlgrp;
34 int ret;
35
36 if (vlgrp && (opts2 & RxVlanTag)) {
37- vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff));
38+ __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling);
39 ret = 0;
40 } else
41 ret = -1;
42@@ -1071,7 +1071,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
43 }
44
45 static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
46- struct sk_buff *skb)
47+ struct sk_buff *skb, int polling)
48 {
49 return -1;
50 }
51@@ -4480,12 +4480,20 @@ out:
52 return done;
53 }
54
55+/*
56+ * Warning : rtl8169_rx_interrupt() might be called :
57+ * 1) from NAPI (softirq) context
58+ * (polling = 1 : we should call netif_receive_skb())
59+ * 2) from process context (rtl8169_reset_task())
60+ * (polling = 0 : we must call netif_rx() instead)
61+ */
62 static int rtl8169_rx_interrupt(struct net_device *dev,
63 struct rtl8169_private *tp,
64 void __iomem *ioaddr, u32 budget)
65 {
66 unsigned int cur_rx, rx_left;
67 unsigned int delta, count;
68+ int polling = (budget != ~(u32)0) ? 1 : 0;
69
70 cur_rx = tp->cur_rx;
71 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
72@@ -4550,8 +4558,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
73 skb_put(skb, pkt_size);
74 skb->protocol = eth_type_trans(skb, dev);
75
76- if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0)
77- netif_receive_skb(skb);
78+ if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) {
79+ if (likely(polling))
80+ netif_receive_skb(skb);
81+ else
82+ netif_rx(skb);
83+ }
84
85 dev->stats.rx_bytes += pkt_size;
86 dev->stats.rx_packets++;
87--
881.7.0.2
89
diff --git a/main/linux-grsec/0008-r8169-clean-up-my-printk-uglyness.patch b/main/linux-grsec/0008-r8169-clean-up-my-printk-uglyness.patch
new file mode 100644
index 0000000000..dff3fd2112
--- /dev/null
+++ b/main/linux-grsec/0008-r8169-clean-up-my-printk-uglyness.patch
@@ -0,0 +1,36 @@
1From d1c9ac562923fa0b1738fceb4c7bafac3ab936ba Mon Sep 17 00:00:00 2001
2From: Neil Horman <nhorman@tuxdriver.com>
3Date: Thu, 1 Apr 2010 07:30:07 +0000
4Subject: [PATCH 08/18] r8169: clean up my printk uglyness
5
6Fix formatting on r8169 printk
7
8Brandon Philips noted that I had a spacing issue in my printk for the
9last r8169 patch that made it quite ugly. Fix that up and add the PFX
10macro to it as well so it looks like the other r8169 printks
11
12Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
13Signed-off-by: David S. Miller <davem@davemloft.net>
14(cherry picked from commit 93f4d91d879acfcb0ba9c2725e3133fcff2dfd1e)
15---
16 drivers/net/r8169.c | 4 ++--
17 1 files changed, 2 insertions(+), 2 deletions(-)
18
19diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
20index bed1d47..790555e 100644
21--- a/drivers/net/r8169.c
22+++ b/drivers/net/r8169.c
23@@ -3255,8 +3255,8 @@ static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
24 unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
25
26 if (max_frame != 16383)
27- printk(KERN_WARNING "WARNING! Changing of MTU on this NIC"
28- "May lead to frame reception errors!\n");
29+ printk(KERN_WARNING PFX "WARNING! Changing of MTU on this "
30+ "NIC may lead to frame reception errors!\n");
31
32 tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE;
33 }
34--
351.7.0.2
36
diff --git a/main/linux-grsec/0009-ipsec-Fix-bogus-bundle-flowi.patch b/main/linux-grsec/0009-ipsec-Fix-bogus-bundle-flowi.patch
new file mode 100644
index 0000000000..d4de0e1d58
--- /dev/null
+++ b/main/linux-grsec/0009-ipsec-Fix-bogus-bundle-flowi.patch
@@ -0,0 +1,110 @@
1From 21ee14f92ef1b6d4ca965c9b59135f3462919631 Mon Sep 17 00:00:00 2001
2From: Herbert Xu <herbert@gondor.apana.org.au>
3Date: Tue, 2 Mar 2010 02:51:56 +0000
4Subject: [PATCH 09/18] ipsec: Fix bogus bundle flowi
5
6When I merged the bundle creation code, I introduced a bogus
7flowi value in the bundle. Instead of getting from the caller,
8it was instead set to the flow in the route object, which is
9totally different.
10
11The end result is that the bundles we created never match, and
12we instead end up with an ever growing bundle list.
13
14Thanks to Jamal for find this problem.
15
16Reported-by: Jamal Hadi Salim <hadi@cyberus.ca>
17Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
18Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
19Acked-by: Jamal Hadi Salim <hadi@cyberus.ca>
20Signed-off-by: David S. Miller <davem@davemloft.net>
21(cherry picked from commit 87c1e12b5eeb7b30b4b41291bef8e0b41fc3dde9)
22---
23 include/net/xfrm.h | 3 ++-
24 net/ipv4/xfrm4_policy.c | 5 +++--
25 net/ipv6/xfrm6_policy.c | 3 ++-
26 net/xfrm/xfrm_policy.c | 7 ++++---
27 4 files changed, 11 insertions(+), 7 deletions(-)
28
29diff --git a/include/net/xfrm.h b/include/net/xfrm.h
30index 223e90a..6960be2 100644
31--- a/include/net/xfrm.h
32+++ b/include/net/xfrm.h
33@@ -273,7 +273,8 @@ struct xfrm_policy_afinfo {
34 struct dst_entry *dst,
35 int nfheader_len);
36 int (*fill_dst)(struct xfrm_dst *xdst,
37- struct net_device *dev);
38+ struct net_device *dev,
39+ struct flowi *fl);
40 };
41
42 extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
43diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
44index 74fb2eb..7009886 100644
45--- a/net/ipv4/xfrm4_policy.c
46+++ b/net/ipv4/xfrm4_policy.c
47@@ -92,11 +92,12 @@ static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,
48 return 0;
49 }
50
51-static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
52+static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
53+ struct flowi *fl)
54 {
55 struct rtable *rt = (struct rtable *)xdst->route;
56
57- xdst->u.rt.fl = rt->fl;
58+ xdst->u.rt.fl = *fl;
59
60 xdst->u.dst.dev = dev;
61 dev_hold(dev);
62diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
63index 8ec3d45..3f89ab7 100644
64--- a/net/ipv6/xfrm6_policy.c
65+++ b/net/ipv6/xfrm6_policy.c
66@@ -117,7 +117,8 @@ static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst,
67 return 0;
68 }
69
70-static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
71+static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
72+ struct flowi *fl)
73 {
74 struct rt6_info *rt = (struct rt6_info*)xdst->route;
75
76diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
77index cb81ca3..d75047c 100644
78--- a/net/xfrm/xfrm_policy.c
79+++ b/net/xfrm/xfrm_policy.c
80@@ -1341,7 +1341,8 @@ static inline int xfrm_init_path(struct xfrm_dst *path, struct dst_entry *dst,
81 return err;
82 }
83
84-static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
85+static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
86+ struct flowi *fl)
87 {
88 struct xfrm_policy_afinfo *afinfo =
89 xfrm_policy_get_afinfo(xdst->u.dst.ops->family);
90@@ -1350,7 +1351,7 @@ static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
91 if (!afinfo)
92 return -EINVAL;
93
94- err = afinfo->fill_dst(xdst, dev);
95+ err = afinfo->fill_dst(xdst, dev, fl);
96
97 xfrm_policy_put_afinfo(afinfo);
98
99@@ -1454,7 +1455,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
100 for (dst_prev = dst0; dst_prev != dst; dst_prev = dst_prev->child) {
101 struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev;
102
103- err = xfrm_fill_dst(xdst, dev);
104+ err = xfrm_fill_dst(xdst, dev, fl);
105 if (err)
106 goto free_dst;
107
108--
1091.7.0.2
110
diff --git a/main/linux-grsec/0010-xfrm-Remove-xfrm_state_genid.patch b/main/linux-grsec/0010-xfrm-Remove-xfrm_state_genid.patch
new file mode 100644
index 0000000000..8cfffd7398
--- /dev/null
+++ b/main/linux-grsec/0010-xfrm-Remove-xfrm_state_genid.patch
@@ -0,0 +1,54 @@
1From f2c59932757a06851bb740dc757ce2ba1961fc08 Mon Sep 17 00:00:00 2001
2From: Herbert Xu <herbert@gondor.apana.org.au>
3Date: Wed, 31 Mar 2010 01:19:49 +0000
4Subject: [PATCH 10/18] xfrm: Remove xfrm_state_genid
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9The xfrm state genid only needs to be matched against the copy
10saved in xfrm_dst. So we don't need a global genid at all. In
11fact, we don't even need to initialise it.
12
13Based on observation by Timo Teräs.
14
15Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
16Signed-off-by: David S. Miller <davem@davemloft.net>
17(cherry picked from commit 34996cb91dd72f0b0456d8fd3fef4aaee62232f2)
18---
19 net/xfrm/xfrm_state.c | 5 +----
20 1 files changed, 1 insertions(+), 4 deletions(-)
21
22diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
23index f2f7c63..8ee733f 100644
24--- a/net/xfrm/xfrm_state.c
25+++ b/net/xfrm/xfrm_state.c
26@@ -34,7 +34,6 @@
27 static DEFINE_SPINLOCK(xfrm_state_lock);
28
29 static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
30-static unsigned int xfrm_state_genid;
31
32 static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
33 static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
34@@ -903,8 +902,6 @@ static void __xfrm_state_insert(struct xfrm_state *x)
35 struct net *net = xs_net(x);
36 unsigned int h;
37
38- x->genid = ++xfrm_state_genid;
39-
40 list_add(&x->km.all, &net->xfrm.state_all);
41
42 h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr,
43@@ -948,7 +945,7 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
44 x->props.reqid == reqid &&
45 !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) &&
46 !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family))
47- x->genid = xfrm_state_genid;
48+ x->genid++;
49 }
50 }
51
52--
531.7.0.2
54
diff --git a/main/linux-grsec/0011-xfrm_user-verify-policy-direction-at-XFRM_MSG_POLEXP.patch b/main/linux-grsec/0011-xfrm_user-verify-policy-direction-at-XFRM_MSG_POLEXP.patch
new file mode 100644
index 0000000000..ae2a0f9100
--- /dev/null
+++ b/main/linux-grsec/0011-xfrm_user-verify-policy-direction-at-XFRM_MSG_POLEXP.patch
@@ -0,0 +1,35 @@
1From 5b3e87bccb0e48f2f8b78695e949c015a3695f8e Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Wed, 31 Mar 2010 00:17:04 +0000
4Subject: [PATCH 11/18] xfrm_user: verify policy direction at XFRM_MSG_POLEXPIRE handler
5
6Add missing check for policy direction verification. This is
7especially important since without this xfrm_user may end up
8deleting per-socket policy which is not allowed.
9
10Signed-off-by: Timo Teras <timo.teras@iki.fi>
11Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
12Signed-off-by: David S. Miller <davem@davemloft.net>
13(cherry picked from commit c8bf4d04f970fafb3430d332533e1cf103f2a018)
14---
15 net/xfrm/xfrm_user.c | 4 ++++
16 1 files changed, 4 insertions(+), 0 deletions(-)
17
18diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
19index b95a2d6..d1e9ee3 100644
20--- a/net/xfrm/xfrm_user.c
21+++ b/net/xfrm/xfrm_user.c
22@@ -1589,6 +1589,10 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
23 if (err)
24 return err;
25
26+ err = verify_policy_dir(p->dir);
27+ if (err)
28+ return err;
29+
30 if (p->index)
31 xp = xfrm_policy_byid(net, type, p->dir, p->index, 0, &err);
32 else {
33--
341.7.0.2
35
diff --git a/main/linux-grsec/0012-xfrm-remove-policy-lock-when-accessing-policy-walk.d.patch b/main/linux-grsec/0012-xfrm-remove-policy-lock-when-accessing-policy-walk.d.patch
new file mode 100644
index 0000000000..222caaddfd
--- /dev/null
+++ b/main/linux-grsec/0012-xfrm-remove-policy-lock-when-accessing-policy-walk.d.patch
@@ -0,0 +1,105 @@
1From 7a400eb025dd53883c3560d0fdb069542f7ad3db Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Wed, 31 Mar 2010 00:17:05 +0000
4Subject: [PATCH 12/18] xfrm: remove policy lock when accessing policy->walk.dead
5
6All of the code considers ->dead as a hint that the cached policy
7needs to get refreshed. The read side can just drop the read lock
8without any side effects.
9
10The write side needs to make sure that it's written only exactly
11once. Only possible race is at xfrm_policy_kill(). This is fixed
12by checking result of __xfrm_policy_unlink() when needed. It will
13always succeed if the policy object is looked up from the hash
14list (so some checks are removed), but it needs to be checked if
15we are trying to unlink policy via a reference (appropriate
16checks added).
17
18Since policy->walk.dead is written exactly once, it no longer
19needs to be protected with a write lock.
20
21Signed-off-by: Timo Teras <timo.teras@iki.fi>
22Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
23Signed-off-by: David S. Miller <davem@davemloft.net>
24(backported from commit ea2dea9dacc256fe927857feb423872051642ae7)
25---
26 net/xfrm/xfrm_policy.c | 20 +++++---------------
27 net/xfrm/xfrm_user.c | 6 +-----
28 2 files changed, 6 insertions(+), 20 deletions(-)
29
30diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
31index d75047c..110184f 100644
32--- a/net/xfrm/xfrm_policy.c
33+++ b/net/xfrm/xfrm_policy.c
34@@ -156,7 +156,7 @@ static void xfrm_policy_timer(unsigned long data)
35
36 read_lock(&xp->lock);
37
38- if (xp->walk.dead)
39+ if (unlikely(xp->walk.dead))
40 goto out;
41
42 dir = xfrm_policy_id2dir(xp->index);
43@@ -297,17 +297,7 @@ static DECLARE_WORK(xfrm_policy_gc_work, xfrm_policy_gc_task);
44
45 static void xfrm_policy_kill(struct xfrm_policy *policy)
46 {
47- int dead;
48-
49- write_lock_bh(&policy->lock);
50- dead = policy->walk.dead;
51 policy->walk.dead = 1;
52- write_unlock_bh(&policy->lock);
53-
54- if (unlikely(dead)) {
55- WARN_ON(1);
56- return;
57- }
58
59 spin_lock_bh(&xfrm_policy_gc_lock);
60 hlist_add_head(&policy->bydst, &xfrm_policy_gc_list);
61@@ -1115,6 +1105,9 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
62 __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir);
63 }
64 if (old_pol)
65+ /* Unlinking succeeds always. This is the only function
66+ * allowed to delete or replace socket policy.
67+ */
68 __xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir);
69 write_unlock_bh(&xfrm_policy_lock);
70
71@@ -1705,11 +1698,8 @@ restart:
72 goto error;
73 }
74
75- for (pi = 0; pi < npols; pi++) {
76- read_lock_bh(&pols[pi]->lock);
77+ for (pi = 0; pi < npols; pi++)
78 pol_dead |= pols[pi]->walk.dead;
79- read_unlock_bh(&pols[pi]->lock);
80- }
81
82 write_lock_bh(&policy->lock);
83 if (unlikely(pol_dead || stale_bundle(dst))) {
84diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
85index d1e9ee3..f9c56e9 100644
86--- a/net/xfrm/xfrm_user.c
87+++ b/net/xfrm/xfrm_user.c
88@@ -1617,13 +1617,9 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
89 if (xp == NULL)
90 return -ENOENT;
91
92- read_lock(&xp->lock);
93- if (xp->walk.dead) {
94- read_unlock(&xp->lock);
95+ if (unlikely(xp->walk.dead))
96 goto out;
97- }
98
99- read_unlock(&xp->lock);
100 err = 0;
101 if (up->hard) {
102 uid_t loginuid = NETLINK_CB(skb).loginuid;
103--
1041.7.0.2
105
diff --git a/main/linux-grsec/0013-flow-structurize-flow-cache.patch b/main/linux-grsec/0013-flow-structurize-flow-cache.patch
new file mode 100644
index 0000000000..68fa753a2c
--- /dev/null
+++ b/main/linux-grsec/0013-flow-structurize-flow-cache.patch
@@ -0,0 +1,395 @@
1From 884f6e44f0b405c06bd234b14cc228482291bb38 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Wed, 31 Mar 2010 00:17:06 +0000
4Subject: [PATCH 13/18] flow: structurize flow cache
5
6Group all per-cpu data to one structure instead of having many
7globals. Also prepare the internals so that we can have multiple
8instances of the flow cache if needed.
9
10Only the kmem_cache is left as a global as all flow caches share
11the same element size, and benefit from using a common cache.
12
13Signed-off-by: Timo Teras <timo.teras@iki.fi>
14Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
15Signed-off-by: David S. Miller <davem@davemloft.net>
16(cherry picked from commit d7997fe1f4584da12e9c29fb682c18e9bdc13b73)
17---
18 net/core/flow.c | 223 +++++++++++++++++++++++++++++--------------------------
19 1 files changed, 119 insertions(+), 104 deletions(-)
20
21diff --git a/net/core/flow.c b/net/core/flow.c
22index 9601587..1d27ca6 100644
23--- a/net/core/flow.c
24+++ b/net/core/flow.c
25@@ -35,104 +35,105 @@ struct flow_cache_entry {
26 atomic_t *object_ref;
27 };
28
29-atomic_t flow_cache_genid = ATOMIC_INIT(0);
30-
31-static u32 flow_hash_shift;
32-#define flow_hash_size (1 << flow_hash_shift)
33-static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL };
34-
35-#define flow_table(cpu) (per_cpu(flow_tables, cpu))
36-
37-static struct kmem_cache *flow_cachep __read_mostly;
38-
39-static int flow_lwm, flow_hwm;
40-
41-struct flow_percpu_info {
42- int hash_rnd_recalc;
43- u32 hash_rnd;
44- int count;
45+struct flow_cache_percpu {
46+ struct flow_cache_entry ** hash_table;
47+ int hash_count;
48+ u32 hash_rnd;
49+ int hash_rnd_recalc;
50+ struct tasklet_struct flush_tasklet;
51 };
52-static DEFINE_PER_CPU(struct flow_percpu_info, flow_hash_info) = { 0 };
53-
54-#define flow_hash_rnd_recalc(cpu) \
55- (per_cpu(flow_hash_info, cpu).hash_rnd_recalc)
56-#define flow_hash_rnd(cpu) \
57- (per_cpu(flow_hash_info, cpu).hash_rnd)
58-#define flow_count(cpu) \
59- (per_cpu(flow_hash_info, cpu).count)
60-
61-static struct timer_list flow_hash_rnd_timer;
62-
63-#define FLOW_HASH_RND_PERIOD (10 * 60 * HZ)
64
65 struct flow_flush_info {
66- atomic_t cpuleft;
67- struct completion completion;
68+ struct flow_cache * cache;
69+ atomic_t cpuleft;
70+ struct completion completion;
71 };
72-static DEFINE_PER_CPU(struct tasklet_struct, flow_flush_tasklets) = { NULL };
73
74-#define flow_flush_tasklet(cpu) (&per_cpu(flow_flush_tasklets, cpu))
75+struct flow_cache {
76+ u32 hash_shift;
77+ unsigned long order;
78+ struct flow_cache_percpu * percpu;
79+ struct notifier_block hotcpu_notifier;
80+ int low_watermark;
81+ int high_watermark;
82+ struct timer_list rnd_timer;
83+};
84+
85+atomic_t flow_cache_genid = ATOMIC_INIT(0);
86+static struct flow_cache flow_cache_global;
87+static struct kmem_cache *flow_cachep;
88+
89+#define flow_cache_hash_size(cache) (1 << (cache)->hash_shift)
90+#define FLOW_HASH_RND_PERIOD (10 * 60 * HZ)
91
92 static void flow_cache_new_hashrnd(unsigned long arg)
93 {
94+ struct flow_cache *fc = (void *) arg;
95 int i;
96
97 for_each_possible_cpu(i)
98- flow_hash_rnd_recalc(i) = 1;
99+ per_cpu_ptr(fc->percpu, i)->hash_rnd_recalc = 1;
100
101- flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
102- add_timer(&flow_hash_rnd_timer);
103+ fc->rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
104+ add_timer(&fc->rnd_timer);
105 }
106
107-static void flow_entry_kill(int cpu, struct flow_cache_entry *fle)
108+static void flow_entry_kill(struct flow_cache *fc,
109+ struct flow_cache_percpu *fcp,
110+ struct flow_cache_entry *fle)
111 {
112 if (fle->object)
113 atomic_dec(fle->object_ref);
114 kmem_cache_free(flow_cachep, fle);
115- flow_count(cpu)--;
116+ fcp->hash_count--;
117 }
118
119-static void __flow_cache_shrink(int cpu, int shrink_to)
120+static void __flow_cache_shrink(struct flow_cache *fc,
121+ struct flow_cache_percpu *fcp,
122+ int shrink_to)
123 {
124 struct flow_cache_entry *fle, **flp;
125 int i;
126
127- for (i = 0; i < flow_hash_size; i++) {
128+ for (i = 0; i < flow_cache_hash_size(fc); i++) {
129 int k = 0;
130
131- flp = &flow_table(cpu)[i];
132+ flp = &fcp->hash_table[i];
133 while ((fle = *flp) != NULL && k < shrink_to) {
134 k++;
135 flp = &fle->next;
136 }
137 while ((fle = *flp) != NULL) {
138 *flp = fle->next;
139- flow_entry_kill(cpu, fle);
140+ flow_entry_kill(fc, fcp, fle);
141 }
142 }
143 }
144
145-static void flow_cache_shrink(int cpu)
146+static void flow_cache_shrink(struct flow_cache *fc,
147+ struct flow_cache_percpu *fcp)
148 {
149- int shrink_to = flow_lwm / flow_hash_size;
150+ int shrink_to = fc->low_watermark / flow_cache_hash_size(fc);
151
152- __flow_cache_shrink(cpu, shrink_to);
153+ __flow_cache_shrink(fc, fcp, shrink_to);
154 }
155
156-static void flow_new_hash_rnd(int cpu)
157+static void flow_new_hash_rnd(struct flow_cache *fc,
158+ struct flow_cache_percpu *fcp)
159 {
160- get_random_bytes(&flow_hash_rnd(cpu), sizeof(u32));
161- flow_hash_rnd_recalc(cpu) = 0;
162-
163- __flow_cache_shrink(cpu, 0);
164+ get_random_bytes(&fcp->hash_rnd, sizeof(u32));
165+ fcp->hash_rnd_recalc = 0;
166+ __flow_cache_shrink(fc, fcp, 0);
167 }
168
169-static u32 flow_hash_code(struct flowi *key, int cpu)
170+static u32 flow_hash_code(struct flow_cache *fc,
171+ struct flow_cache_percpu *fcp,
172+ struct flowi *key)
173 {
174 u32 *k = (u32 *) key;
175
176- return (jhash2(k, (sizeof(*key) / sizeof(u32)), flow_hash_rnd(cpu)) &
177- (flow_hash_size - 1));
178+ return (jhash2(k, (sizeof(*key) / sizeof(u32)), fcp->hash_rnd)
179+ & (flow_cache_hash_size(fc) - 1));
180 }
181
182 #if (BITS_PER_LONG == 64)
183@@ -168,24 +169,25 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2)
184 void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
185 flow_resolve_t resolver)
186 {
187+ struct flow_cache *fc = &flow_cache_global;
188+ struct flow_cache_percpu *fcp;
189 struct flow_cache_entry *fle, **head;
190 unsigned int hash;
191- int cpu;
192
193 local_bh_disable();
194- cpu = smp_processor_id();
195+ fcp = per_cpu_ptr(fc->percpu, smp_processor_id());
196
197 fle = NULL;
198 /* Packet really early in init? Making flow_cache_init a
199 * pre-smp initcall would solve this. --RR */
200- if (!flow_table(cpu))
201+ if (!fcp->hash_table)
202 goto nocache;
203
204- if (flow_hash_rnd_recalc(cpu))
205- flow_new_hash_rnd(cpu);
206- hash = flow_hash_code(key, cpu);
207+ if (fcp->hash_rnd_recalc)
208+ flow_new_hash_rnd(fc, fcp);
209+ hash = flow_hash_code(fc, fcp, key);
210
211- head = &flow_table(cpu)[hash];
212+ head = &fcp->hash_table[hash];
213 for (fle = *head; fle; fle = fle->next) {
214 if (fle->family == family &&
215 fle->dir == dir &&
216@@ -204,8 +206,8 @@ void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
217 }
218
219 if (!fle) {
220- if (flow_count(cpu) > flow_hwm)
221- flow_cache_shrink(cpu);
222+ if (fcp->hash_count > fc->high_watermark)
223+ flow_cache_shrink(fc, fcp);
224
225 fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
226 if (fle) {
227@@ -215,7 +217,7 @@ void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
228 fle->dir = dir;
229 memcpy(&fle->key, key, sizeof(*key));
230 fle->object = NULL;
231- flow_count(cpu)++;
232+ fcp->hash_count++;
233 }
234 }
235
236@@ -249,14 +251,15 @@ nocache:
237 static void flow_cache_flush_tasklet(unsigned long data)
238 {
239 struct flow_flush_info *info = (void *)data;
240+ struct flow_cache *fc = info->cache;
241+ struct flow_cache_percpu *fcp;
242 int i;
243- int cpu;
244
245- cpu = smp_processor_id();
246- for (i = 0; i < flow_hash_size; i++) {
247+ fcp = per_cpu_ptr(fc->percpu, smp_processor_id());
248+ for (i = 0; i < flow_cache_hash_size(fc); i++) {
249 struct flow_cache_entry *fle;
250
251- fle = flow_table(cpu)[i];
252+ fle = fcp->hash_table[i];
253 for (; fle; fle = fle->next) {
254 unsigned genid = atomic_read(&flow_cache_genid);
255
256@@ -272,7 +275,6 @@ static void flow_cache_flush_tasklet(unsigned long data)
257 complete(&info->completion);
258 }
259
260-static void flow_cache_flush_per_cpu(void *) __attribute__((__unused__));
261 static void flow_cache_flush_per_cpu(void *data)
262 {
263 struct flow_flush_info *info = data;
264@@ -280,8 +282,7 @@ static void flow_cache_flush_per_cpu(void *data)
265 struct tasklet_struct *tasklet;
266
267 cpu = smp_processor_id();
268-
269- tasklet = flow_flush_tasklet(cpu);
270+ tasklet = &per_cpu_ptr(info->cache->percpu, cpu)->flush_tasklet;
271 tasklet->data = (unsigned long)info;
272 tasklet_schedule(tasklet);
273 }
274@@ -294,6 +295,7 @@ void flow_cache_flush(void)
275 /* Don't want cpus going down or up during this. */
276 get_online_cpus();
277 mutex_lock(&flow_flush_sem);
278+ info.cache = &flow_cache_global;
279 atomic_set(&info.cpuleft, num_online_cpus());
280 init_completion(&info.completion);
281
282@@ -307,62 +309,75 @@ void flow_cache_flush(void)
283 put_online_cpus();
284 }
285
286-static void __init flow_cache_cpu_prepare(int cpu)
287+static void __init flow_cache_cpu_prepare(struct flow_cache *fc,
288+ struct flow_cache_percpu *fcp)
289 {
290- struct tasklet_struct *tasklet;
291- unsigned long order;
292-
293- for (order = 0;
294- (PAGE_SIZE << order) <
295- (sizeof(struct flow_cache_entry *)*flow_hash_size);
296- order++)
297- /* NOTHING */;
298-
299- flow_table(cpu) = (struct flow_cache_entry **)
300- __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
301- if (!flow_table(cpu))
302- panic("NET: failed to allocate flow cache order %lu\n", order);
303-
304- flow_hash_rnd_recalc(cpu) = 1;
305- flow_count(cpu) = 0;
306-
307- tasklet = flow_flush_tasklet(cpu);
308- tasklet_init(tasklet, flow_cache_flush_tasklet, 0);
309+ fcp->hash_table = (struct flow_cache_entry **)
310+ __get_free_pages(GFP_KERNEL|__GFP_ZERO, fc->order);
311+ if (!fcp->hash_table)
312+ panic("NET: failed to allocate flow cache order %lu\n", fc->order);
313+
314+ fcp->hash_rnd_recalc = 1;
315+ fcp->hash_count = 0;
316+ tasklet_init(&fcp->flush_tasklet, flow_cache_flush_tasklet, 0);
317 }
318
319 static int flow_cache_cpu(struct notifier_block *nfb,
320 unsigned long action,
321 void *hcpu)
322 {
323+ struct flow_cache *fc = container_of(nfb, struct flow_cache, hotcpu_notifier);
324+ int cpu = (unsigned long) hcpu;
325+ struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu);
326+
327 if (action == CPU_DEAD || action == CPU_DEAD_FROZEN)
328- __flow_cache_shrink((unsigned long)hcpu, 0);
329+ __flow_cache_shrink(fc, fcp, 0);
330 return NOTIFY_OK;
331 }
332
333-static int __init flow_cache_init(void)
334+static int flow_cache_init(struct flow_cache *fc)
335 {
336+ unsigned long order;
337 int i;
338
339- flow_cachep = kmem_cache_create("flow_cache",
340- sizeof(struct flow_cache_entry),
341- 0, SLAB_PANIC,
342- NULL);
343- flow_hash_shift = 10;
344- flow_lwm = 2 * flow_hash_size;
345- flow_hwm = 4 * flow_hash_size;
346+ fc->hash_shift = 10;
347+ fc->low_watermark = 2 * flow_cache_hash_size(fc);
348+ fc->high_watermark = 4 * flow_cache_hash_size(fc);
349+
350+ for (order = 0;
351+ (PAGE_SIZE << order) <
352+ (sizeof(struct flow_cache_entry *)*flow_cache_hash_size(fc));
353+ order++)
354+ /* NOTHING */;
355+ fc->order = order;
356+ fc->percpu = alloc_percpu(struct flow_cache_percpu);
357
358- setup_timer(&flow_hash_rnd_timer, flow_cache_new_hashrnd, 0);
359- flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
360- add_timer(&flow_hash_rnd_timer);
361+ setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd,
362+ (unsigned long) fc);
363+ fc->rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
364+ add_timer(&fc->rnd_timer);
365
366 for_each_possible_cpu(i)
367- flow_cache_cpu_prepare(i);
368+ flow_cache_cpu_prepare(fc, per_cpu_ptr(fc->percpu, i));
369+
370+ fc->hotcpu_notifier = (struct notifier_block){
371+ .notifier_call = flow_cache_cpu,
372+ };
373+ register_hotcpu_notifier(&fc->hotcpu_notifier);
374
375- hotcpu_notifier(flow_cache_cpu, 0);
376 return 0;
377 }
378
379-module_init(flow_cache_init);
380+static int __init flow_cache_init_global(void)
381+{
382+ flow_cachep = kmem_cache_create("flow_cache",
383+ sizeof(struct flow_cache_entry),
384+ 0, SLAB_PANIC, NULL);
385+
386+ return flow_cache_init(&flow_cache_global);
387+}
388+
389+module_init(flow_cache_init_global);
390
391 EXPORT_SYMBOL(flow_cache_genid);
392 EXPORT_SYMBOL(flow_cache_lookup);
393--
3941.7.0.2
395
diff --git a/main/linux-grsec/0014-flow-virtualize-flow-cache-entry-methods.patch b/main/linux-grsec/0014-flow-virtualize-flow-cache-entry-methods.patch
new file mode 100644
index 0000000000..5c4a9ea594
--- /dev/null
+++ b/main/linux-grsec/0014-flow-virtualize-flow-cache-entry-methods.patch
@@ -0,0 +1,513 @@
1From d56cd1c538e5448fe43acc69991aa842f382a622 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Wed, 7 Apr 2010 00:30:04 +0000
4Subject: [PATCH 14/18] flow: virtualize flow cache entry methods
5
6This allows to validate the cached object before returning it.
7It also allows to destruct object properly, if the last reference
8was held in flow cache. This is also a prepartion for caching
9bundles in the flow cache.
10
11In return for virtualizing the methods, we save on:
12- not having to regenerate the whole flow cache on policy removal:
13 each flow matching a killed policy gets refreshed as the getter
14 function notices it smartly.
15- we do not have to call flow_cache_flush from policy gc, since the
16 flow cache now properly deletes the object if it had any references
17
18Signed-off-by: Timo Teras <timo.teras@iki.fi>
19Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
20Signed-off-by: David S. Miller <davem@davemloft.net>
21(backported from commit fe1a5f031e76bd8761a7803d75b95ee96e84a574)
22---
23 include/net/flow.h | 23 +++++++--
24 include/net/xfrm.h | 3 +
25 net/core/flow.c | 128 +++++++++++++++++++++++++----------------------
26 net/xfrm/xfrm_policy.c | 111 ++++++++++++++++++++++++++++--------------
27 4 files changed, 164 insertions(+), 101 deletions(-)
28
29diff --git a/include/net/flow.h b/include/net/flow.h
30index 809970b..bb08692 100644
31--- a/include/net/flow.h
32+++ b/include/net/flow.h
33@@ -86,11 +86,26 @@ struct flowi {
34
35 struct net;
36 struct sock;
37-typedef int (*flow_resolve_t)(struct net *net, struct flowi *key, u16 family,
38- u8 dir, void **objp, atomic_t **obj_refp);
39+struct flow_cache_ops;
40+
41+struct flow_cache_object {
42+ const struct flow_cache_ops *ops;
43+};
44+
45+struct flow_cache_ops {
46+ struct flow_cache_object *(*get)(struct flow_cache_object *);
47+ int (*check)(struct flow_cache_object *);
48+ void (*delete)(struct flow_cache_object *);
49+};
50+
51+typedef struct flow_cache_object *(*flow_resolve_t)(
52+ struct net *net, struct flowi *key, u16 family,
53+ u8 dir, struct flow_cache_object *oldobj, void *ctx);
54+
55+extern struct flow_cache_object *flow_cache_lookup(
56+ struct net *net, struct flowi *key, u16 family,
57+ u8 dir, flow_resolve_t resolver, void *ctx);
58
59-extern void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family,
60- u8 dir, flow_resolve_t resolver);
61 extern void flow_cache_flush(void);
62 extern atomic_t flow_cache_genid;
63
64diff --git a/include/net/xfrm.h b/include/net/xfrm.h
65index 6960be2..6023a48 100644
66--- a/include/net/xfrm.h
67+++ b/include/net/xfrm.h
68@@ -19,6 +19,8 @@
69 #include <net/route.h>
70 #include <net/ipv6.h>
71 #include <net/ip6_fib.h>
72+#include <net/flow.h>
73+
74 #ifdef CONFIG_XFRM_STATISTICS
75 #include <net/snmp.h>
76 #endif
77@@ -482,6 +484,7 @@ struct xfrm_policy
78 atomic_t refcnt;
79 struct timer_list timer;
80
81+ struct flow_cache_object flo;
82 u32 priority;
83 u32 index;
84 struct xfrm_selector selector;
85diff --git a/net/core/flow.c b/net/core/flow.c
86index 1d27ca6..521df52 100644
87--- a/net/core/flow.c
88+++ b/net/core/flow.c
89@@ -26,17 +26,16 @@
90 #include <linux/security.h>
91
92 struct flow_cache_entry {
93- struct flow_cache_entry *next;
94- u16 family;
95- u8 dir;
96- u32 genid;
97- struct flowi key;
98- void *object;
99- atomic_t *object_ref;
100+ struct flow_cache_entry *next;
101+ u16 family;
102+ u8 dir;
103+ u32 genid;
104+ struct flowi key;
105+ struct flow_cache_object *object;
106 };
107
108 struct flow_cache_percpu {
109- struct flow_cache_entry ** hash_table;
110+ struct flow_cache_entry **hash_table;
111 int hash_count;
112 u32 hash_rnd;
113 int hash_rnd_recalc;
114@@ -44,7 +43,7 @@ struct flow_cache_percpu {
115 };
116
117 struct flow_flush_info {
118- struct flow_cache * cache;
119+ struct flow_cache *cache;
120 atomic_t cpuleft;
121 struct completion completion;
122 };
123@@ -52,7 +51,7 @@ struct flow_flush_info {
124 struct flow_cache {
125 u32 hash_shift;
126 unsigned long order;
127- struct flow_cache_percpu * percpu;
128+ struct flow_cache_percpu *percpu;
129 struct notifier_block hotcpu_notifier;
130 int low_watermark;
131 int high_watermark;
132@@ -78,12 +77,21 @@ static void flow_cache_new_hashrnd(unsigned long arg)
133 add_timer(&fc->rnd_timer);
134 }
135
136+static int flow_entry_valid(struct flow_cache_entry *fle)
137+{
138+ if (atomic_read(&flow_cache_genid) != fle->genid)
139+ return 0;
140+ if (fle->object && !fle->object->ops->check(fle->object))
141+ return 0;
142+ return 1;
143+}
144+
145 static void flow_entry_kill(struct flow_cache *fc,
146 struct flow_cache_percpu *fcp,
147 struct flow_cache_entry *fle)
148 {
149 if (fle->object)
150- atomic_dec(fle->object_ref);
151+ fle->object->ops->delete(fle->object);
152 kmem_cache_free(flow_cachep, fle);
153 fcp->hash_count--;
154 }
155@@ -96,16 +104,18 @@ static void __flow_cache_shrink(struct flow_cache *fc,
156 int i;
157
158 for (i = 0; i < flow_cache_hash_size(fc); i++) {
159- int k = 0;
160+ int saved = 0;
161
162 flp = &fcp->hash_table[i];
163- while ((fle = *flp) != NULL && k < shrink_to) {
164- k++;
165- flp = &fle->next;
166- }
167 while ((fle = *flp) != NULL) {
168- *flp = fle->next;
169- flow_entry_kill(fc, fcp, fle);
170+ if (saved < shrink_to &&
171+ flow_entry_valid(fle)) {
172+ saved++;
173+ flp = &fle->next;
174+ } else {
175+ *flp = fle->next;
176+ flow_entry_kill(fc, fcp, fle);
177+ }
178 }
179 }
180 }
181@@ -166,18 +176,21 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2)
182 return 0;
183 }
184
185-void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
186- flow_resolve_t resolver)
187+struct flow_cache_object *
188+flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
189+ flow_resolve_t resolver, void *ctx)
190 {
191 struct flow_cache *fc = &flow_cache_global;
192 struct flow_cache_percpu *fcp;
193 struct flow_cache_entry *fle, **head;
194+ struct flow_cache_object *flo;
195 unsigned int hash;
196
197 local_bh_disable();
198 fcp = per_cpu_ptr(fc->percpu, smp_processor_id());
199
200 fle = NULL;
201+ flo = NULL;
202 /* Packet really early in init? Making flow_cache_init a
203 * pre-smp initcall would solve this. --RR */
204 if (!fcp->hash_table)
205@@ -185,27 +198,17 @@ void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
206
207 if (fcp->hash_rnd_recalc)
208 flow_new_hash_rnd(fc, fcp);
209- hash = flow_hash_code(fc, fcp, key);
210
211+ hash = flow_hash_code(fc, fcp, key);
212 head = &fcp->hash_table[hash];
213 for (fle = *head; fle; fle = fle->next) {
214 if (fle->family == family &&
215 fle->dir == dir &&
216- flow_key_compare(key, &fle->key) == 0) {
217- if (fle->genid == atomic_read(&flow_cache_genid)) {
218- void *ret = fle->object;
219-
220- if (ret)
221- atomic_inc(fle->object_ref);
222- local_bh_enable();
223-
224- return ret;
225- }
226+ flow_key_compare(key, &fle->key) == 0)
227 break;
228- }
229 }
230
231- if (!fle) {
232+ if (unlikely(!fle)) {
233 if (fcp->hash_count > fc->high_watermark)
234 flow_cache_shrink(fc, fcp);
235
236@@ -219,33 +222,39 @@ void *flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
237 fle->object = NULL;
238 fcp->hash_count++;
239 }
240+ } else if (likely(fle->genid == atomic_read(&flow_cache_genid))) {
241+ flo = fle->object;
242+ if (!flo)
243+ goto ret_object;
244+ flo = flo->ops->get(flo);
245+ if (flo)
246+ goto ret_object;
247+ } else if (fle->object) {
248+ flo = fle->object;
249+ flo->ops->delete(flo);
250+ fle->object = NULL;
251 }
252
253 nocache:
254- {
255- int err;
256- void *obj;
257- atomic_t *obj_ref;
258-
259- err = resolver(net, key, family, dir, &obj, &obj_ref);
260-
261- if (fle && !err) {
262- fle->genid = atomic_read(&flow_cache_genid);
263-
264- if (fle->object)
265- atomic_dec(fle->object_ref);
266-
267- fle->object = obj;
268- fle->object_ref = obj_ref;
269- if (obj)
270- atomic_inc(fle->object_ref);
271- }
272- local_bh_enable();
273-
274- if (err)
275- obj = ERR_PTR(err);
276- return obj;
277+ flo = NULL;
278+ if (fle) {
279+ flo = fle->object;
280+ fle->object = NULL;
281+ }
282+ flo = resolver(net, key, family, dir, flo, ctx);
283+ if (fle) {
284+ fle->genid = atomic_read(&flow_cache_genid);
285+ if (!IS_ERR(flo))
286+ fle->object = flo;
287+ else
288+ fle->genid--;
289+ } else {
290+ if (flo && !IS_ERR(flo))
291+ flo->ops->delete(flo);
292 }
293+ret_object:
294+ local_bh_enable();
295+ return flo;
296 }
297
298 static void flow_cache_flush_tasklet(unsigned long data)
299@@ -261,13 +270,12 @@ static void flow_cache_flush_tasklet(unsigned long data)
300
301 fle = fcp->hash_table[i];
302 for (; fle; fle = fle->next) {
303- unsigned genid = atomic_read(&flow_cache_genid);
304-
305- if (!fle->object || fle->genid == genid)
306+ if (flow_entry_valid(fle))
307 continue;
308
309+ if (fle->object)
310+ fle->object->ops->delete(fle->object);
311 fle->object = NULL;
312- atomic_dec(fle->object_ref);
313 }
314 }
315
316diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
317index 110184f..d1eb2b5 100644
318--- a/net/xfrm/xfrm_policy.c
319+++ b/net/xfrm/xfrm_policy.c
320@@ -216,6 +216,35 @@ expired:
321 xfrm_pol_put(xp);
322 }
323
324+static struct flow_cache_object *xfrm_policy_flo_get(struct flow_cache_object *flo)
325+{
326+ struct xfrm_policy *pol = container_of(flo, struct xfrm_policy, flo);
327+
328+ if (unlikely(pol->walk.dead))
329+ flo = NULL;
330+ else
331+ xfrm_pol_hold(pol);
332+
333+ return flo;
334+}
335+
336+static int xfrm_policy_flo_check(struct flow_cache_object *flo)
337+{
338+ struct xfrm_policy *pol = container_of(flo, struct xfrm_policy, flo);
339+
340+ return !pol->walk.dead;
341+}
342+
343+static void xfrm_policy_flo_delete(struct flow_cache_object *flo)
344+{
345+ xfrm_pol_put(container_of(flo, struct xfrm_policy, flo));
346+}
347+
348+static const struct flow_cache_ops xfrm_policy_fc_ops = {
349+ .get = xfrm_policy_flo_get,
350+ .check = xfrm_policy_flo_check,
351+ .delete = xfrm_policy_flo_delete,
352+};
353
354 /* Allocate xfrm_policy. Not used here, it is supposed to be used by pfkeyv2
355 * SPD calls.
356@@ -236,6 +265,7 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp)
357 atomic_set(&policy->refcnt, 1);
358 setup_timer(&policy->timer, xfrm_policy_timer,
359 (unsigned long)policy);
360+ policy->flo.ops = &xfrm_policy_fc_ops;
361 }
362 return policy;
363 }
364@@ -269,9 +299,6 @@ static void xfrm_policy_gc_kill(struct xfrm_policy *policy)
365 if (del_timer(&policy->timer))
366 atomic_dec(&policy->refcnt);
367
368- if (atomic_read(&policy->refcnt) > 1)
369- flow_cache_flush();
370-
371 xfrm_pol_put(policy);
372 }
373
374@@ -658,10 +685,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir,
375 }
376 write_unlock_bh(&xfrm_policy_lock);
377
378- if (ret && delete) {
379- atomic_inc(&flow_cache_genid);
380+ if (ret && delete)
381 xfrm_policy_kill(ret);
382- }
383 return ret;
384 }
385 EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
386@@ -699,10 +724,8 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id,
387 }
388 write_unlock_bh(&xfrm_policy_lock);
389
390- if (ret && delete) {
391- atomic_inc(&flow_cache_genid);
392+ if (ret && delete)
393 xfrm_policy_kill(ret);
394- }
395 return ret;
396 }
397 EXPORT_SYMBOL(xfrm_policy_byid);
398@@ -967,32 +990,35 @@ fail:
399 return ret;
400 }
401
402-static int xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family,
403- u8 dir, void **objp, atomic_t **obj_refp)
404+static struct flow_cache_object *
405+xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family,
406+ u8 dir, struct flow_cache_object *old_obj, void *ctx)
407 {
408 struct xfrm_policy *pol;
409- int err = 0;
410+
411+ if (old_obj)
412+ xfrm_pol_put(container_of(old_obj, struct xfrm_policy, flo));
413
414 #ifdef CONFIG_XFRM_SUB_POLICY
415 pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_SUB, fl, family, dir);
416- if (IS_ERR(pol)) {
417- err = PTR_ERR(pol);
418- pol = NULL;
419- }
420- if (pol || err)
421- goto end;
422+ if (IS_ERR(pol))
423+ return ERR_CAST(pol);
424+ if (pol)
425+ goto found;
426 #endif
427 pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir);
428- if (IS_ERR(pol)) {
429- err = PTR_ERR(pol);
430- pol = NULL;
431- }
432-#ifdef CONFIG_XFRM_SUB_POLICY
433-end:
434-#endif
435- if ((*objp = (void *) pol) != NULL)
436- *obj_refp = &pol->refcnt;
437- return err;
438+ if (IS_ERR(pol))
439+ return ERR_CAST(pol);
440+ if (pol)
441+ goto found;
442+ return NULL;
443+
444+found:
445+ /* Resolver returns two references:
446+ * one for cache and one for caller of flow_cache_lookup() */
447+ xfrm_pol_hold(pol);
448+
449+ return &pol->flo;
450 }
451
452 static inline int policy_to_flow_dir(int dir)
453@@ -1077,8 +1103,6 @@ int xfrm_policy_delete(struct xfrm_policy *pol, int dir)
454 pol = __xfrm_policy_unlink(pol, dir);
455 write_unlock_bh(&xfrm_policy_lock);
456 if (pol) {
457- if (dir < XFRM_POLICY_MAX)
458- atomic_inc(&flow_cache_genid);
459 xfrm_policy_kill(pol);
460 return 0;
461 }
462@@ -1549,18 +1573,24 @@ restart:
463 }
464
465 if (!policy) {
466+ struct flow_cache_object *flo;
467+
468 /* To accelerate a bit... */
469 if ((dst_orig->flags & DST_NOXFRM) ||
470 !net->xfrm.policy_count[XFRM_POLICY_OUT])
471 goto nopol;
472
473- policy = flow_cache_lookup(net, fl, dst_orig->ops->family,
474- dir, xfrm_policy_lookup);
475- err = PTR_ERR(policy);
476- if (IS_ERR(policy)) {
477+ flo = flow_cache_lookup(net, fl, dst_orig->ops->family,
478+ dir, xfrm_policy_lookup, NULL);
479+ err = PTR_ERR(flo);
480+ if (IS_ERR(flo)) {
481 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
482 goto dropdst;
483 }
484+ if (flo)
485+ policy = container_of(flo, struct xfrm_policy, flo);
486+ else
487+ policy = NULL;
488 }
489
490 if (!policy)
491@@ -1910,9 +1940,16 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
492 }
493 }
494
495- if (!pol)
496- pol = flow_cache_lookup(net, &fl, family, fl_dir,
497- xfrm_policy_lookup);
498+ if (!pol) {
499+ struct flow_cache_object *flo;
500+
501+ flo = flow_cache_lookup(net, &fl, family, fl_dir,
502+ xfrm_policy_lookup, NULL);
503+ if (flo == NULL || IS_ERR(flo))
504+ pol = ERR_CAST(flo);
505+ else
506+ pol = container_of(flo, struct xfrm_policy, flo);
507+ }
508
509 if (IS_ERR(pol)) {
510 XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
511--
5121.7.0.2
513
diff --git a/main/linux-grsec/0015-xfrm-cache-bundles-instead-of-policies-for-outgoing-.patch b/main/linux-grsec/0015-xfrm-cache-bundles-instead-of-policies-for-outgoing-.patch
new file mode 100644
index 0000000000..0d066c84d9
--- /dev/null
+++ b/main/linux-grsec/0015-xfrm-cache-bundles-instead-of-policies-for-outgoing-.patch
@@ -0,0 +1,1068 @@
1From f89d21648e6dc06db2aeabc8926c270894c41446 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Wed, 7 Apr 2010 00:30:05 +0000
4Subject: [PATCH 15/18] xfrm: cache bundles instead of policies for outgoing flows
5
6__xfrm_lookup() is called for each packet transmitted out of
7system. The xfrm_find_bundle() does a linear search which can
8kill system performance depending on how many bundles are
9required per policy.
10
11This modifies __xfrm_lookup() to store bundles directly in
12the flow cache. If we did not get a hit, we just create a new
13bundle instead of doing slow search. This means that we can now
14get multiple xfrm_dst's for same flow (on per-cpu basis).
15
16Signed-off-by: Timo Teras <timo.teras@iki.fi>
17Signed-off-by: David S. Miller <davem@davemloft.net>
18(backported from commit 80c802f3073e84c956846e921e8a0b02dfa3755f)
19---
20 include/net/xfrm.h | 10 +-
21 net/ipv4/xfrm4_policy.c | 22 --
22 net/ipv6/xfrm6_policy.c | 31 --
23 net/xfrm/xfrm_policy.c | 710 +++++++++++++++++++++++++----------------------
24 4 files changed, 383 insertions(+), 390 deletions(-)
25
26diff --git a/include/net/xfrm.h b/include/net/xfrm.h
27index 6023a48..d51ef61 100644
28--- a/include/net/xfrm.h
29+++ b/include/net/xfrm.h
30@@ -266,7 +266,6 @@ struct xfrm_policy_afinfo {
31 xfrm_address_t *saddr,
32 xfrm_address_t *daddr);
33 int (*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr);
34- struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy);
35 void (*decode_session)(struct sk_buff *skb,
36 struct flowi *fl,
37 int reverse);
38@@ -485,12 +484,12 @@ struct xfrm_policy
39 struct timer_list timer;
40
41 struct flow_cache_object flo;
42+ atomic_t genid;
43 u32 priority;
44 u32 index;
45 struct xfrm_selector selector;
46 struct xfrm_lifetime_cfg lft;
47 struct xfrm_lifetime_cur curlft;
48- struct dst_entry *bundles;
49 struct xfrm_policy_walk_entry walk;
50 u8 type;
51 u8 action;
52@@ -883,11 +882,15 @@ struct xfrm_dst
53 struct rt6_info rt6;
54 } u;
55 struct dst_entry *route;
56+ struct flow_cache_object flo;
57+ struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
58+ int num_pols, num_xfrms;
59 #ifdef CONFIG_XFRM_SUB_POLICY
60 struct flowi *origin;
61 struct xfrm_selector *partner;
62 #endif
63- u32 genid;
64+ u32 xfrm_genid;
65+ u32 policy_genid;
66 u32 route_mtu_cached;
67 u32 child_mtu_cached;
68 u32 route_cookie;
69@@ -897,6 +900,7 @@ struct xfrm_dst
70 #ifdef CONFIG_XFRM
71 static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
72 {
73+ xfrm_pols_put(xdst->pols, xdst->num_pols);
74 dst_release(xdst->route);
75 if (likely(xdst->u.dst.xfrm))
76 xfrm_state_put(xdst->u.dst.xfrm);
77diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
78index 7009886..651a3e7 100644
79--- a/net/ipv4/xfrm4_policy.c
80+++ b/net/ipv4/xfrm4_policy.c
81@@ -60,27 +60,6 @@ static int xfrm4_get_saddr(struct net *net,
82 return 0;
83 }
84
85-static struct dst_entry *
86-__xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
87-{
88- struct dst_entry *dst;
89-
90- read_lock_bh(&policy->lock);
91- for (dst = policy->bundles; dst; dst = dst->next) {
92- struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
93- if (xdst->u.rt.fl.oif == fl->oif && /*XXX*/
94- xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
95- xdst->u.rt.fl.fl4_src == fl->fl4_src &&
96- xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
97- xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) {
98- dst_clone(dst);
99- break;
100- }
101- }
102- read_unlock_bh(&policy->lock);
103- return dst;
104-}
105-
106 static int xfrm4_get_tos(struct flowi *fl)
107 {
108 return fl->fl4_tos;
109@@ -258,7 +237,6 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
110 .dst_ops = &xfrm4_dst_ops,
111 .dst_lookup = xfrm4_dst_lookup,
112 .get_saddr = xfrm4_get_saddr,
113- .find_bundle = __xfrm4_find_bundle,
114 .decode_session = _decode_session4,
115 .get_tos = xfrm4_get_tos,
116 .init_path = xfrm4_init_path,
117diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
118index 3f89ab7..fb2a5b7 100644
119--- a/net/ipv6/xfrm6_policy.c
120+++ b/net/ipv6/xfrm6_policy.c
121@@ -68,36 +68,6 @@ static int xfrm6_get_saddr(struct net *net,
122 return 0;
123 }
124
125-static struct dst_entry *
126-__xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
127-{
128- struct dst_entry *dst;
129-
130- /* Still not clear if we should set fl->fl6_{src,dst}... */
131- read_lock_bh(&policy->lock);
132- for (dst = policy->bundles; dst; dst = dst->next) {
133- struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
134- struct in6_addr fl_dst_prefix, fl_src_prefix;
135-
136- ipv6_addr_prefix(&fl_dst_prefix,
137- &fl->fl6_dst,
138- xdst->u.rt6.rt6i_dst.plen);
139- ipv6_addr_prefix(&fl_src_prefix,
140- &fl->fl6_src,
141- xdst->u.rt6.rt6i_src.plen);
142- if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
143- ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
144- xfrm_bundle_ok(policy, xdst, fl, AF_INET6,
145- (xdst->u.rt6.rt6i_dst.plen != 128 ||
146- xdst->u.rt6.rt6i_src.plen != 128))) {
147- dst_clone(dst);
148- break;
149- }
150- }
151- read_unlock_bh(&policy->lock);
152- return dst;
153-}
154-
155 static int xfrm6_get_tos(struct flowi *fl)
156 {
157 return 0;
158@@ -290,7 +260,6 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
159 .dst_ops = &xfrm6_dst_ops,
160 .dst_lookup = xfrm6_dst_lookup,
161 .get_saddr = xfrm6_get_saddr,
162- .find_bundle = __xfrm6_find_bundle,
163 .decode_session = _decode_session6,
164 .get_tos = xfrm6_get_tos,
165 .init_path = xfrm6_init_path,
166diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
167index d1eb2b5..0379d82 100644
168--- a/net/xfrm/xfrm_policy.c
169+++ b/net/xfrm/xfrm_policy.c
170@@ -37,6 +37,8 @@
171 DEFINE_MUTEX(xfrm_cfg_mutex);
172 EXPORT_SYMBOL(xfrm_cfg_mutex);
173
174+static DEFINE_SPINLOCK(xfrm_policy_sk_bundle_lock);
175+static struct dst_entry *xfrm_policy_sk_bundles;
176 static DEFINE_RWLOCK(xfrm_policy_lock);
177
178 static DEFINE_RWLOCK(xfrm_policy_afinfo_lock);
179@@ -50,6 +52,7 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
180 static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
181 static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
182 static void xfrm_init_pmtu(struct dst_entry *dst);
183+static int stale_bundle(struct dst_entry *dst);
184
185 static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
186 int dir);
187@@ -277,8 +280,6 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
188 {
189 BUG_ON(!policy->walk.dead);
190
191- BUG_ON(policy->bundles);
192-
193 if (del_timer(&policy->timer))
194 BUG();
195
196@@ -289,12 +290,7 @@ EXPORT_SYMBOL(xfrm_policy_destroy);
197
198 static void xfrm_policy_gc_kill(struct xfrm_policy *policy)
199 {
200- struct dst_entry *dst;
201-
202- while ((dst = policy->bundles) != NULL) {
203- policy->bundles = dst->next;
204- dst_free(dst);
205- }
206+ atomic_inc(&policy->genid);
207
208 if (del_timer(&policy->timer))
209 atomic_dec(&policy->refcnt);
210@@ -572,7 +568,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
211 struct xfrm_policy *delpol;
212 struct hlist_head *chain;
213 struct hlist_node *entry, *newpos;
214- struct dst_entry *gc_list;
215
216 write_lock_bh(&xfrm_policy_lock);
217 chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
218@@ -620,34 +615,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
219 else if (xfrm_bydst_should_resize(net, dir, NULL))
220 schedule_work(&net->xfrm.policy_hash_work);
221
222- read_lock_bh(&xfrm_policy_lock);
223- gc_list = NULL;
224- entry = &policy->bydst;
225- hlist_for_each_entry_continue(policy, entry, bydst) {
226- struct dst_entry *dst;
227-
228- write_lock(&policy->lock);
229- dst = policy->bundles;
230- if (dst) {
231- struct dst_entry *tail = dst;
232- while (tail->next)
233- tail = tail->next;
234- tail->next = gc_list;
235- gc_list = dst;
236-
237- policy->bundles = NULL;
238- }
239- write_unlock(&policy->lock);
240- }
241- read_unlock_bh(&xfrm_policy_lock);
242-
243- while (gc_list) {
244- struct dst_entry *dst = gc_list;
245-
246- gc_list = dst->next;
247- dst_free(dst);
248- }
249-
250 return 0;
251 }
252 EXPORT_SYMBOL(xfrm_policy_insert);
253@@ -990,6 +957,19 @@ fail:
254 return ret;
255 }
256
257+static struct xfrm_policy *
258+__xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family, u8 dir)
259+{
260+#ifdef CONFIG_XFRM_SUB_POLICY
261+ struct xfrm_policy *pol;
262+
263+ pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_SUB, fl, family, dir);
264+ if (pol != NULL)
265+ return pol;
266+#endif
267+ return xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir);
268+}
269+
270 static struct flow_cache_object *
271 xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family,
272 u8 dir, struct flow_cache_object *old_obj, void *ctx)
273@@ -999,21 +979,10 @@ xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family,
274 if (old_obj)
275 xfrm_pol_put(container_of(old_obj, struct xfrm_policy, flo));
276
277-#ifdef CONFIG_XFRM_SUB_POLICY
278- pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_SUB, fl, family, dir);
279- if (IS_ERR(pol))
280+ pol = __xfrm_policy_lookup(net, fl, family, dir);
281+ if (pol == NULL || IS_ERR(pol))
282 return ERR_CAST(pol);
283- if (pol)
284- goto found;
285-#endif
286- pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir);
287- if (IS_ERR(pol))
288- return ERR_CAST(pol);
289- if (pol)
290- goto found;
291- return NULL;
292
293-found:
294 /* Resolver returns two references:
295 * one for cache and one for caller of flow_cache_lookup() */
296 xfrm_pol_hold(pol);
297@@ -1299,18 +1268,6 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
298 * still valid.
299 */
300
301-static struct dst_entry *
302-xfrm_find_bundle(struct flowi *fl, struct xfrm_policy *policy, unsigned short family)
303-{
304- struct dst_entry *x;
305- struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
306- if (unlikely(afinfo == NULL))
307- return ERR_PTR(-EINVAL);
308- x = afinfo->find_bundle(fl, policy);
309- xfrm_policy_put_afinfo(afinfo);
310- return x;
311-}
312-
313 static inline int xfrm_get_tos(struct flowi *fl, int family)
314 {
315 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
316@@ -1326,6 +1283,54 @@ static inline int xfrm_get_tos(struct flowi *fl, int family)
317 return tos;
318 }
319
320+static struct flow_cache_object *xfrm_bundle_flo_get(struct flow_cache_object *flo)
321+{
322+ struct xfrm_dst *xdst = container_of(flo, struct xfrm_dst, flo);
323+ struct dst_entry *dst = &xdst->u.dst;
324+
325+ if (xdst->route == NULL) {
326+ /* Dummy bundle - if it has xfrms we were not
327+ * able to build bundle as template resolution failed.
328+ * It means we need to try again resolving. */
329+ if (xdst->num_xfrms > 0)
330+ return NULL;
331+ } else {
332+ /* Real bundle */
333+ if (stale_bundle(dst))
334+ return NULL;
335+ }
336+
337+ dst_hold(dst);
338+ return flo;
339+}
340+
341+static int xfrm_bundle_flo_check(struct flow_cache_object *flo)
342+{
343+ struct xfrm_dst *xdst = container_of(flo, struct xfrm_dst, flo);
344+ struct dst_entry *dst = &xdst->u.dst;
345+
346+ if (!xdst->route)
347+ return 0;
348+ if (stale_bundle(dst))
349+ return 0;
350+
351+ return 1;
352+}
353+
354+static void xfrm_bundle_flo_delete(struct flow_cache_object *flo)
355+{
356+ struct xfrm_dst *xdst = container_of(flo, struct xfrm_dst, flo);
357+ struct dst_entry *dst = &xdst->u.dst;
358+
359+ dst_free(dst);
360+}
361+
362+static const struct flow_cache_ops xfrm_bundle_fc_ops = {
363+ .get = xfrm_bundle_flo_get,
364+ .check = xfrm_bundle_flo_check,
365+ .delete = xfrm_bundle_flo_delete,
366+};
367+
368 static inline struct xfrm_dst *xfrm_alloc_dst(int family)
369 {
370 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
371@@ -1338,6 +1343,8 @@ static inline struct xfrm_dst *xfrm_alloc_dst(int family)
372
373 xfrm_policy_put_afinfo(afinfo);
374
375+ xdst->flo.ops = &xfrm_bundle_fc_ops;
376+
377 return xdst;
378 }
379
380@@ -1375,6 +1382,7 @@ static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
381 return err;
382 }
383
384+
385 /* Allocate chain of dst_entry's, attach known xfrm's, calculate
386 * all the metrics... Shortly, bundle a bundle.
387 */
388@@ -1437,7 +1445,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
389 dst_hold(dst);
390
391 dst1->xfrm = xfrm[i];
392- xdst->genid = xfrm[i]->genid;
393+ xdst->xfrm_genid = xfrm[i]->genid;
394
395 dst1->obsolete = -1;
396 dst1->flags |= DST_HOST;
397@@ -1530,7 +1538,186 @@ xfrm_dst_update_origin(struct dst_entry *dst, struct flowi *fl)
398 #endif
399 }
400
401-static int stale_bundle(struct dst_entry *dst);
402+static int xfrm_expand_policies(struct flowi *fl, u16 family,
403+ struct xfrm_policy **pols,
404+ int *num_pols, int *num_xfrms)
405+{
406+ int i;
407+
408+ if (*num_pols == 0 || !pols[0]) {
409+ *num_pols = 0;
410+ *num_xfrms = 0;
411+ return 0;
412+ }
413+ if (IS_ERR(pols[0]))
414+ return PTR_ERR(pols[0]);
415+
416+ *num_xfrms = pols[0]->xfrm_nr;
417+
418+#ifdef CONFIG_XFRM_SUB_POLICY
419+ if (pols[0] && pols[0]->action == XFRM_POLICY_ALLOW &&
420+ pols[0]->type != XFRM_POLICY_TYPE_MAIN) {
421+ pols[1] = xfrm_policy_lookup_bytype(xp_net(pols[0]),
422+ XFRM_POLICY_TYPE_MAIN,
423+ fl, family,
424+ XFRM_POLICY_OUT);
425+ if (pols[1]) {
426+ if (IS_ERR(pols[1])) {
427+ xfrm_pols_put(pols, *num_pols);
428+ return PTR_ERR(pols[1]);
429+ }
430+ (*num_pols) ++;
431+ (*num_xfrms) += pols[1]->xfrm_nr;
432+ }
433+ }
434+#endif
435+ for (i = 0; i < *num_pols; i++) {
436+ if (pols[i]->action != XFRM_POLICY_ALLOW) {
437+ *num_xfrms = -1;
438+ break;
439+ }
440+ }
441+
442+ return 0;
443+
444+}
445+
446+static struct xfrm_dst *
447+xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
448+ struct flowi *fl, u16 family,
449+ struct dst_entry *dst_orig)
450+{
451+ struct net *net = xp_net(pols[0]);
452+ struct xfrm_state *xfrm[XFRM_MAX_DEPTH];
453+ struct dst_entry *dst;
454+ struct xfrm_dst *xdst;
455+ int err;
456+
457+ /* Try to instantiate a bundle */
458+ err = xfrm_tmpl_resolve(pols, num_pols, fl, xfrm, family);
459+ if (err < 0) {
460+ if (err != -EAGAIN)
461+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
462+ return ERR_PTR(err);
463+ }
464+
465+ dst = xfrm_bundle_create(pols[0], xfrm, err, fl, dst_orig);
466+ if (IS_ERR(dst)) {
467+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLEGENERROR);
468+ return ERR_CAST(dst);
469+ }
470+
471+ xdst = (struct xfrm_dst *)dst;
472+ xdst->num_xfrms = err;
473+ if (num_pols > 1)
474+ err = xfrm_dst_update_parent(dst, &pols[1]->selector);
475+ else
476+ err = xfrm_dst_update_origin(dst, fl);
477+ if (unlikely(err)) {
478+ dst_free(dst);
479+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
480+ return ERR_PTR(err);
481+ }
482+
483+ xdst->num_pols = num_pols;
484+ memcpy(xdst->pols, pols, sizeof(struct xfrm_policy*) * num_pols);
485+ xdst->policy_genid = atomic_read(&pols[0]->genid);
486+
487+ return xdst;
488+}
489+
490+static struct flow_cache_object *
491+xfrm_bundle_lookup(struct net *net, struct flowi *fl, u16 family, u8 dir,
492+ struct flow_cache_object *oldflo, void *ctx)
493+{
494+ struct dst_entry *dst_orig = (struct dst_entry *)ctx;
495+ struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
496+ struct xfrm_dst *xdst, *new_xdst;
497+ int num_pols = 0, num_xfrms = 0, i, err, pol_dead;
498+
499+ /* Check if the policies from old bundle are usable */
500+ xdst = NULL;
501+ if (oldflo) {
502+ xdst = container_of(oldflo, struct xfrm_dst, flo);
503+ num_pols = xdst->num_pols;
504+ num_xfrms = xdst->num_xfrms;
505+ pol_dead = 0;
506+ for (i = 0; i < num_pols; i++) {
507+ pols[i] = xdst->pols[i];
508+ pol_dead |= pols[i]->walk.dead;
509+ }
510+ if (pol_dead) {
511+ dst_free(&xdst->u.dst);
512+ xdst = NULL;
513+ num_pols = 0;
514+ num_xfrms = 0;
515+ oldflo = NULL;
516+ }
517+ }
518+
519+ /* Resolve policies to use if we couldn't get them from
520+ * previous cache entry */
521+ if (xdst == NULL) {
522+ num_pols = 1;
523+ pols[0] = __xfrm_policy_lookup(net, fl, family, dir);
524+ err = xfrm_expand_policies(fl, family, pols,
525+ &num_pols, &num_xfrms);
526+ if (err < 0)
527+ goto inc_error;
528+ if (num_pols == 0)
529+ return NULL;
530+ if (num_xfrms <= 0)
531+ goto make_dummy_bundle;
532+ }
533+
534+ new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig);
535+ if (IS_ERR(new_xdst)) {
536+ err = PTR_ERR(new_xdst);
537+ if (err != -EAGAIN)
538+ goto error;
539+ if (oldflo == NULL)
540+ goto make_dummy_bundle;
541+ dst_hold(&xdst->u.dst);
542+ return oldflo;
543+ }
544+
545+ /* Kill the previous bundle */
546+ if (xdst) {
547+ /* The policies were stolen for newly generated bundle */
548+ xdst->num_pols = 0;
549+ dst_free(&xdst->u.dst);
550+ }
551+
552+ /* Flow cache does not have reference, it dst_free()'s,
553+ * but we do need to return one reference for original caller */
554+ dst_hold(&new_xdst->u.dst);
555+ return &new_xdst->flo;
556+
557+make_dummy_bundle:
558+ /* We found policies, but there's no bundles to instantiate:
559+ * either because the policy blocks, has no transformations or
560+ * we could not build template (no xfrm_states).*/
561+ xdst = xfrm_alloc_dst(family);
562+ if (IS_ERR(xdst)) {
563+ xfrm_pols_put(pols, num_pols);
564+ return ERR_CAST(xdst);
565+ }
566+ xdst->num_pols = num_pols;
567+ xdst->num_xfrms = num_xfrms;
568+ memcpy(xdst->pols, pols, sizeof(struct xfrm_policy*) * num_pols);
569+
570+ dst_hold(&xdst->u.dst);
571+ return &xdst->flo;
572+
573+inc_error:
574+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
575+error:
576+ if (xdst != NULL)
577+ dst_free(&xdst->u.dst);
578+ else
579+ xfrm_pols_put(pols, num_pols);
580+ return ERR_PTR(err);
581+}
582
583 /* Main function: finds/creates a bundle for given flow.
584 *
585@@ -1540,248 +1727,152 @@ static int stale_bundle(struct dst_entry *dst);
586 int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl,
587 struct sock *sk, int flags)
588 {
589- struct xfrm_policy *policy;
590 struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
591- int npols;
592- int pol_dead;
593- int xfrm_nr;
594- int pi;
595- struct xfrm_state *xfrm[XFRM_MAX_DEPTH];
596- struct dst_entry *dst, *dst_orig = *dst_p;
597- int nx = 0;
598- int err;
599- u32 genid;
600- u16 family;
601+ struct flow_cache_object *flo;
602+ struct xfrm_dst *xdst;
603+ struct dst_entry *dst, *dst_orig = *dst_p, *route;
604+ u16 family = dst_orig->ops->family;
605 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
606+ int i, err, num_pols, num_xfrms, drop_pols = 0;
607
608 restart:
609- genid = atomic_read(&flow_cache_genid);
610- policy = NULL;
611- for (pi = 0; pi < ARRAY_SIZE(pols); pi++)
612- pols[pi] = NULL;
613- npols = 0;
614- pol_dead = 0;
615- xfrm_nr = 0;
616+ dst = NULL;
617+ xdst = NULL;
618+ route = NULL;
619
620 if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
621- policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
622- err = PTR_ERR(policy);
623- if (IS_ERR(policy)) {
624- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
625+ num_pols = 1;
626+ pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
627+ err = xfrm_expand_policies(fl, family, pols,
628+ &num_pols, &num_xfrms);
629+ if (err < 0)
630 goto dropdst;
631+
632+ if (num_pols) {
633+ if (num_xfrms <= 0) {
634+ drop_pols = num_pols;
635+ goto no_transform;
636+ }
637+
638+ xdst = xfrm_resolve_and_create_bundle(
639+ pols, num_pols, fl,
640+ family, dst_orig);
641+ if (IS_ERR(xdst)) {
642+ xfrm_pols_put(pols, num_pols);
643+ err = PTR_ERR(xdst);
644+ goto dropdst;
645+ }
646+
647+ spin_lock_bh(&xfrm_policy_sk_bundle_lock);
648+ xdst->u.dst.next = xfrm_policy_sk_bundles;
649+ xfrm_policy_sk_bundles = &xdst->u.dst;
650+ spin_unlock_bh(&xfrm_policy_sk_bundle_lock);
651+
652+ route = xdst->route;
653 }
654 }
655
656- if (!policy) {
657- struct flow_cache_object *flo;
658-
659+ if (xdst == NULL) {
660 /* To accelerate a bit... */
661 if ((dst_orig->flags & DST_NOXFRM) ||
662 !net->xfrm.policy_count[XFRM_POLICY_OUT])
663 goto nopol;
664
665- flo = flow_cache_lookup(net, fl, dst_orig->ops->family,
666- dir, xfrm_policy_lookup, NULL);
667- err = PTR_ERR(flo);
668+ flo = flow_cache_lookup(net, fl, family, dir,
669+ xfrm_bundle_lookup, dst_orig);
670+ if (flo == NULL)
671+ goto nopol;
672 if (IS_ERR(flo)) {
673- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
674+ err = PTR_ERR(flo);
675 goto dropdst;
676 }
677- if (flo)
678- policy = container_of(flo, struct xfrm_policy, flo);
679- else
680- policy = NULL;
681+ xdst = container_of(flo, struct xfrm_dst, flo);
682+
683+ num_pols = xdst->num_pols;
684+ num_xfrms = xdst->num_xfrms;
685+ memcpy(pols, xdst->pols, sizeof(struct xfrm_policy*) * num_pols);
686+ route = xdst->route;
687+ }
688+
689+ dst = &xdst->u.dst;
690+ if (route == NULL && num_xfrms > 0) {
691+ /* The only case when xfrm_bundle_lookup() returns a
692+ * bundle with null route, is when the template could
693+ * not be resolved. It means policies are there, but
694+ * bundle could not be created, since we don't yet
695+ * have the xfrm_state's. We need to wait for KM to
696+ * negotiate new SA's or bail out with error.*/
697+ if (net->xfrm.sysctl_larval_drop) {
698+ /* EREMOTE tells the caller to generate
699+ * a one-shot blackhole route. */
700+ dst_release(dst);
701+ xfrm_pols_put(pols, num_pols);
702+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
703+ return -EREMOTE;
704+ }
705+ if (flags & XFRM_LOOKUP_WAIT) {
706+ DECLARE_WAITQUEUE(wait, current);
707+
708+ add_wait_queue(&net->xfrm.km_waitq, &wait);
709+ set_current_state(TASK_INTERRUPTIBLE);
710+ schedule();
711+ set_current_state(TASK_RUNNING);
712+ remove_wait_queue(&net->xfrm.km_waitq, &wait);
713+
714+ if (!signal_pending(current)) {
715+ dst_release(dst);
716+ goto restart;
717+ }
718+
719+ err = -ERESTART;
720+ } else
721+ err = -EAGAIN;
722+
723+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
724+ goto error;
725 }
726
727- if (!policy)
728+no_transform:
729+ if (num_pols == 0)
730 goto nopol;
731
732- family = dst_orig->ops->family;
733- pols[0] = policy;
734- npols ++;
735- xfrm_nr += pols[0]->xfrm_nr;
736-
737- err = -ENOENT;
738- if ((flags & XFRM_LOOKUP_ICMP) && !(policy->flags & XFRM_POLICY_ICMP))
739+ if ((flags & XFRM_LOOKUP_ICMP) &&
740+ !(pols[0]->flags & XFRM_POLICY_ICMP)) {
741+ err = -ENOENT;
742 goto error;
743+ }
744
745- policy->curlft.use_time = get_seconds();
746+ for (i = 0; i < num_pols; i++)
747+ pols[i]->curlft.use_time = get_seconds();
748
749- switch (policy->action) {
750- default:
751- case XFRM_POLICY_BLOCK:
752+ if (num_xfrms < 0) {
753 /* Prohibit the flow */
754 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK);
755 err = -EPERM;
756 goto error;
757-
758- case XFRM_POLICY_ALLOW:
759-#ifndef CONFIG_XFRM_SUB_POLICY
760- if (policy->xfrm_nr == 0) {
761- /* Flow passes not transformed. */
762- xfrm_pol_put(policy);
763- return 0;
764- }
765-#endif
766-
767- /* Try to find matching bundle.
768- *
769- * LATER: help from flow cache. It is optional, this
770- * is required only for output policy.
771- */
772- dst = xfrm_find_bundle(fl, policy, family);
773- if (IS_ERR(dst)) {
774- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
775- err = PTR_ERR(dst);
776- goto error;
777- }
778-
779- if (dst)
780- break;
781-
782-#ifdef CONFIG_XFRM_SUB_POLICY
783- if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) {
784- pols[1] = xfrm_policy_lookup_bytype(net,
785- XFRM_POLICY_TYPE_MAIN,
786- fl, family,
787- XFRM_POLICY_OUT);
788- if (pols[1]) {
789- if (IS_ERR(pols[1])) {
790- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
791- err = PTR_ERR(pols[1]);
792- goto error;
793- }
794- if (pols[1]->action == XFRM_POLICY_BLOCK) {
795- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK);
796- err = -EPERM;
797- goto error;
798- }
799- npols ++;
800- xfrm_nr += pols[1]->xfrm_nr;
801- }
802- }
803-
804- /*
805- * Because neither flowi nor bundle information knows about
806- * transformation template size. On more than one policy usage
807- * we can realize whether all of them is bypass or not after
808- * they are searched. See above not-transformed bypass
809- * is surrounded by non-sub policy configuration, too.
810- */
811- if (xfrm_nr == 0) {
812- /* Flow passes not transformed. */
813- xfrm_pols_put(pols, npols);
814- return 0;
815- }
816-
817-#endif
818- nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
819-
820- if (unlikely(nx<0)) {
821- err = nx;
822- if (err == -EAGAIN && net->xfrm.sysctl_larval_drop) {
823- /* EREMOTE tells the caller to generate
824- * a one-shot blackhole route.
825- */
826- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
827- xfrm_pol_put(policy);
828- return -EREMOTE;
829- }
830- if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) {
831- DECLARE_WAITQUEUE(wait, current);
832-
833- add_wait_queue(&net->xfrm.km_waitq, &wait);
834- set_current_state(TASK_INTERRUPTIBLE);
835- schedule();
836- set_current_state(TASK_RUNNING);
837- remove_wait_queue(&net->xfrm.km_waitq, &wait);
838-
839- nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
840-
841- if (nx == -EAGAIN && signal_pending(current)) {
842- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
843- err = -ERESTART;
844- goto error;
845- }
846- if (nx == -EAGAIN ||
847- genid != atomic_read(&flow_cache_genid)) {
848- xfrm_pols_put(pols, npols);
849- goto restart;
850- }
851- err = nx;
852- }
853- if (err < 0) {
854- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
855- goto error;
856- }
857- }
858- if (nx == 0) {
859- /* Flow passes not transformed. */
860- xfrm_pols_put(pols, npols);
861- return 0;
862- }
863-
864- dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig);
865- err = PTR_ERR(dst);
866- if (IS_ERR(dst)) {
867- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLEGENERROR);
868- goto error;
869- }
870-
871- for (pi = 0; pi < npols; pi++)
872- pol_dead |= pols[pi]->walk.dead;
873-
874- write_lock_bh(&policy->lock);
875- if (unlikely(pol_dead || stale_bundle(dst))) {
876- /* Wow! While we worked on resolving, this
877- * policy has gone. Retry. It is not paranoia,
878- * we just cannot enlist new bundle to dead object.
879- * We can't enlist stable bundles either.
880- */
881- write_unlock_bh(&policy->lock);
882- dst_free(dst);
883-
884- if (pol_dead)
885- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLDEAD);
886- else
887- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
888- err = -EHOSTUNREACH;
889- goto error;
890- }
891-
892- if (npols > 1)
893- err = xfrm_dst_update_parent(dst, &pols[1]->selector);
894- else
895- err = xfrm_dst_update_origin(dst, fl);
896- if (unlikely(err)) {
897- write_unlock_bh(&policy->lock);
898- dst_free(dst);
899- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
900- goto error;
901- }
902-
903- dst->next = policy->bundles;
904- policy->bundles = dst;
905- dst_hold(dst);
906- write_unlock_bh(&policy->lock);
907+ } else if (num_xfrms > 0) {
908+ /* Flow transformed */
909+ *dst_p = dst;
910+ dst_release(dst_orig);
911+ } else {
912+ /* Flow passes untransformed */
913+ dst_release(dst);
914 }
915- *dst_p = dst;
916- dst_release(dst_orig);
917- xfrm_pols_put(pols, npols);
918+ok:
919+ xfrm_pols_put(pols, drop_pols);
920 return 0;
921
922+nopol:
923+ if (!(flags & XFRM_LOOKUP_ICMP))
924+ goto ok;
925+ err = -ENOENT;
926 error:
927- xfrm_pols_put(pols, npols);
928+ dst_release(dst);
929 dropdst:
930 dst_release(dst_orig);
931 *dst_p = NULL;
932+ xfrm_pols_put(pols, drop_pols);
933 return err;
934-
935-nopol:
936- err = -ENOENT;
937- if (flags & XFRM_LOOKUP_ICMP)
938- goto dropdst;
939- return 0;
940 }
941 EXPORT_SYMBOL(__xfrm_lookup);
942
943@@ -2134,71 +2225,24 @@ static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst)
944 return dst;
945 }
946
947-static void prune_one_bundle(struct xfrm_policy *pol, int (*func)(struct dst_entry *), struct dst_entry **gc_list_p)
948-{
949- struct dst_entry *dst, **dstp;
950-
951- write_lock(&pol->lock);
952- dstp = &pol->bundles;
953- while ((dst=*dstp) != NULL) {
954- if (func(dst)) {
955- *dstp = dst->next;
956- dst->next = *gc_list_p;
957- *gc_list_p = dst;
958- } else {
959- dstp = &dst->next;
960- }
961- }
962- write_unlock(&pol->lock);
963-}
964-
965-static void xfrm_prune_bundles(struct net *net, int (*func)(struct dst_entry *))
966+static void __xfrm_garbage_collect(struct net *net)
967 {
968- struct dst_entry *gc_list = NULL;
969- int dir;
970+ struct dst_entry *head, *next;
971
972- read_lock_bh(&xfrm_policy_lock);
973- for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
974- struct xfrm_policy *pol;
975- struct hlist_node *entry;
976- struct hlist_head *table;
977- int i;
978+ flow_cache_flush();
979
980- hlist_for_each_entry(pol, entry,
981- &net->xfrm.policy_inexact[dir], bydst)
982- prune_one_bundle(pol, func, &gc_list);
983+ spin_lock_bh(&xfrm_policy_sk_bundle_lock);
984+ head = xfrm_policy_sk_bundles;
985+ xfrm_policy_sk_bundles = NULL;
986+ spin_unlock_bh(&xfrm_policy_sk_bundle_lock);
987
988- table = net->xfrm.policy_bydst[dir].table;
989- for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) {
990- hlist_for_each_entry(pol, entry, table + i, bydst)
991- prune_one_bundle(pol, func, &gc_list);
992- }
993- }
994- read_unlock_bh(&xfrm_policy_lock);
995-
996- while (gc_list) {
997- struct dst_entry *dst = gc_list;
998- gc_list = dst->next;
999- dst_free(dst);
1000+ while (head) {
1001+ next = head->next;
1002+ dst_free(head);
1003+ head = next;
1004 }
1005 }
1006
1007-static int unused_bundle(struct dst_entry *dst)
1008-{
1009- return !atomic_read(&dst->__refcnt);
1010-}
1011-
1012-static void __xfrm_garbage_collect(struct net *net)
1013-{
1014- xfrm_prune_bundles(net, unused_bundle);
1015-}
1016-
1017-static int xfrm_flush_bundles(struct net *net)
1018-{
1019- xfrm_prune_bundles(net, stale_bundle);
1020- return 0;
1021-}
1022-
1023 static void xfrm_init_pmtu(struct dst_entry *dst)
1024 {
1025 do {
1026@@ -2256,7 +2300,9 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
1027 return 0;
1028 if (dst->xfrm->km.state != XFRM_STATE_VALID)
1029 return 0;
1030- if (xdst->genid != dst->xfrm->genid)
1031+ if (xdst->xfrm_genid != dst->xfrm->genid)
1032+ return 0;
1033+ if (xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
1034 return 0;
1035
1036 if (strict && fl &&
1037@@ -2383,7 +2429,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
1038
1039 switch (event) {
1040 case NETDEV_DOWN:
1041- xfrm_flush_bundles(dev_net(dev));
1042+ __xfrm_garbage_collect(dev_net(dev));
1043 }
1044 return NOTIFY_DONE;
1045 }
1046@@ -2714,7 +2760,6 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
1047 struct xfrm_migrate *m, int num_migrate)
1048 {
1049 struct xfrm_migrate *mp;
1050- struct dst_entry *dst;
1051 int i, j, n = 0;
1052
1053 write_lock_bh(&pol->lock);
1054@@ -2739,10 +2784,7 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
1055 sizeof(pol->xfrm_vec[i].saddr));
1056 pol->xfrm_vec[i].encap_family = mp->new_family;
1057 /* flush bundles */
1058- while ((dst = pol->bundles) != NULL) {
1059- pol->bundles = dst->next;
1060- dst_free(dst);
1061- }
1062+ atomic_inc(&pol->genid);
1063 }
1064 }
1065
1066--
10671.7.0.2
1068
diff --git a/main/linux-grsec/0016-xfrm-remove-policy-garbage-collection.patch b/main/linux-grsec/0016-xfrm-remove-policy-garbage-collection.patch
new file mode 100644
index 0000000000..4a45c7f40d
--- /dev/null
+++ b/main/linux-grsec/0016-xfrm-remove-policy-garbage-collection.patch
@@ -0,0 +1,91 @@
1From 4c53c9239069f48ec9a86f8e596c163b72e8bc4d Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Wed, 7 Apr 2010 00:30:06 +0000
4Subject: [PATCH 16/18] xfrm: remove policy garbage collection
5
6Policies are now properly reference counted and destroyed from
7all code paths. The delayed gc is just an overhead now and can
8be removed.
9
10Signed-off-by: Timo Teras <timo.teras@iki.fi>
11Signed-off-by: David S. Miller <davem@davemloft.net>
12(cherry picked from commit 285ead175c5dd5075cab5b6c94f35a3e6c0a3ae6)
13---
14 net/xfrm/xfrm_policy.c | 39 +++++----------------------------------
15 1 files changed, 5 insertions(+), 34 deletions(-)
16
17diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
18index 0379d82..5606841 100644
19--- a/net/xfrm/xfrm_policy.c
20+++ b/net/xfrm/xfrm_policy.c
21@@ -46,9 +46,6 @@ static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
22
23 static struct kmem_cache *xfrm_dst_cache __read_mostly;
24
25-static HLIST_HEAD(xfrm_policy_gc_list);
26-static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
27-
28 static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
29 static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
30 static void xfrm_init_pmtu(struct dst_entry *dst);
31@@ -288,32 +285,6 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
32 }
33 EXPORT_SYMBOL(xfrm_policy_destroy);
34
35-static void xfrm_policy_gc_kill(struct xfrm_policy *policy)
36-{
37- atomic_inc(&policy->genid);
38-
39- if (del_timer(&policy->timer))
40- atomic_dec(&policy->refcnt);
41-
42- xfrm_pol_put(policy);
43-}
44-
45-static void xfrm_policy_gc_task(struct work_struct *work)
46-{
47- struct xfrm_policy *policy;
48- struct hlist_node *entry, *tmp;
49- struct hlist_head gc_list;
50-
51- spin_lock_bh(&xfrm_policy_gc_lock);
52- gc_list.first = xfrm_policy_gc_list.first;
53- INIT_HLIST_HEAD(&xfrm_policy_gc_list);
54- spin_unlock_bh(&xfrm_policy_gc_lock);
55-
56- hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst)
57- xfrm_policy_gc_kill(policy);
58-}
59-static DECLARE_WORK(xfrm_policy_gc_work, xfrm_policy_gc_task);
60-
61 /* Rule must be locked. Release descentant resources, announce
62 * entry dead. The rule must be unlinked from lists to the moment.
63 */
64@@ -322,11 +293,12 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
65 {
66 policy->walk.dead = 1;
67
68- spin_lock_bh(&xfrm_policy_gc_lock);
69- hlist_add_head(&policy->bydst, &xfrm_policy_gc_list);
70- spin_unlock_bh(&xfrm_policy_gc_lock);
71+ atomic_inc(&policy->genid);
72
73- schedule_work(&xfrm_policy_gc_work);
74+ if (del_timer(&policy->timer))
75+ xfrm_pol_put(policy);
76+
77+ xfrm_pol_put(policy);
78 }
79
80 static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024;
81@@ -2535,7 +2507,6 @@ static void xfrm_policy_fini(struct net *net)
82 audit_info.sessionid = -1;
83 audit_info.secid = 0;
84 xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info);
85- flush_work(&xfrm_policy_gc_work);
86
87 WARN_ON(!list_empty(&net->xfrm.policy_all));
88
89--
901.7.0.2
91
diff --git a/main/linux-grsec/0017-flow-delayed-deletion-of-flow-cache-entries.patch b/main/linux-grsec/0017-flow-delayed-deletion-of-flow-cache-entries.patch
new file mode 100644
index 0000000000..7d17d41aed
--- /dev/null
+++ b/main/linux-grsec/0017-flow-delayed-deletion-of-flow-cache-entries.patch
@@ -0,0 +1,231 @@
1From fede05e99e2d860e97bc877b8b77fb9e63f55cc8 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Wed, 7 Apr 2010 00:30:07 +0000
4Subject: [PATCH 17/18] flow: delayed deletion of flow cache entries
5
6Speed up lookups by freeing flow cache entries later. After
7virtualizing flow cache entry operations, the flow cache may now
8end up calling policy or bundle destructor which can be slowish.
9
10As gc_list is more effective with double linked list, the flow cache
11is converted to use common hlist and list macroes where appropriate.
12
13Signed-off-by: Timo Teras <timo.teras@iki.fi>
14Signed-off-by: David S. Miller <davem@davemloft.net>
15(cherry picked from commit 8e4795605d1e1b39113818ad7c147b8a867a1f6a)
16---
17 net/core/flow.c | 100 ++++++++++++++++++++++++++++++++++++++-----------------
18 1 files changed, 69 insertions(+), 31 deletions(-)
19
20diff --git a/net/core/flow.c b/net/core/flow.c
21index 521df52..1619006 100644
22--- a/net/core/flow.c
23+++ b/net/core/flow.c
24@@ -26,7 +26,10 @@
25 #include <linux/security.h>
26
27 struct flow_cache_entry {
28- struct flow_cache_entry *next;
29+ union {
30+ struct hlist_node hlist;
31+ struct list_head gc_list;
32+ } u;
33 u16 family;
34 u8 dir;
35 u32 genid;
36@@ -35,7 +38,7 @@ struct flow_cache_entry {
37 };
38
39 struct flow_cache_percpu {
40- struct flow_cache_entry **hash_table;
41+ struct hlist_head *hash_table;
42 int hash_count;
43 u32 hash_rnd;
44 int hash_rnd_recalc;
45@@ -62,6 +65,9 @@ atomic_t flow_cache_genid = ATOMIC_INIT(0);
46 static struct flow_cache flow_cache_global;
47 static struct kmem_cache *flow_cachep;
48
49+static DEFINE_SPINLOCK(flow_cache_gc_lock);
50+static LIST_HEAD(flow_cache_gc_list);
51+
52 #define flow_cache_hash_size(cache) (1 << (cache)->hash_shift)
53 #define FLOW_HASH_RND_PERIOD (10 * 60 * HZ)
54
55@@ -86,38 +92,66 @@ static int flow_entry_valid(struct flow_cache_entry *fle)
56 return 1;
57 }
58
59-static void flow_entry_kill(struct flow_cache *fc,
60- struct flow_cache_percpu *fcp,
61- struct flow_cache_entry *fle)
62+static void flow_entry_kill(struct flow_cache_entry *fle)
63 {
64 if (fle->object)
65 fle->object->ops->delete(fle->object);
66 kmem_cache_free(flow_cachep, fle);
67- fcp->hash_count--;
68+}
69+
70+static void flow_cache_gc_task(struct work_struct *work)
71+{
72+ struct list_head gc_list;
73+ struct flow_cache_entry *fce, *n;
74+
75+ INIT_LIST_HEAD(&gc_list);
76+ spin_lock_bh(&flow_cache_gc_lock);
77+ list_splice_tail_init(&flow_cache_gc_list, &gc_list);
78+ spin_unlock_bh(&flow_cache_gc_lock);
79+
80+ list_for_each_entry_safe(fce, n, &gc_list, u.gc_list)
81+ flow_entry_kill(fce);
82+}
83+static DECLARE_WORK(flow_cache_gc_work, flow_cache_gc_task);
84+
85+static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp,
86+ int deleted, struct list_head *gc_list)
87+{
88+ if (deleted) {
89+ fcp->hash_count -= deleted;
90+ spin_lock_bh(&flow_cache_gc_lock);
91+ list_splice_tail(gc_list, &flow_cache_gc_list);
92+ spin_unlock_bh(&flow_cache_gc_lock);
93+ schedule_work(&flow_cache_gc_work);
94+ }
95 }
96
97 static void __flow_cache_shrink(struct flow_cache *fc,
98 struct flow_cache_percpu *fcp,
99 int shrink_to)
100 {
101- struct flow_cache_entry *fle, **flp;
102- int i;
103+ struct flow_cache_entry *fle;
104+ struct hlist_node *entry, *tmp;
105+ LIST_HEAD(gc_list);
106+ int i, deleted = 0;
107
108 for (i = 0; i < flow_cache_hash_size(fc); i++) {
109 int saved = 0;
110
111- flp = &fcp->hash_table[i];
112- while ((fle = *flp) != NULL) {
113+ hlist_for_each_entry_safe(fle, entry, tmp,
114+ &fcp->hash_table[i], u.hlist) {
115 if (saved < shrink_to &&
116 flow_entry_valid(fle)) {
117 saved++;
118- flp = &fle->next;
119 } else {
120- *flp = fle->next;
121- flow_entry_kill(fc, fcp, fle);
122+ deleted++;
123+ hlist_del(&fle->u.hlist);
124+ list_add_tail(&fle->u.gc_list, &gc_list);
125 }
126 }
127 }
128+
129+ flow_cache_queue_garbage(fcp, deleted, &gc_list);
130 }
131
132 static void flow_cache_shrink(struct flow_cache *fc,
133@@ -182,7 +216,8 @@ flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
134 {
135 struct flow_cache *fc = &flow_cache_global;
136 struct flow_cache_percpu *fcp;
137- struct flow_cache_entry *fle, **head;
138+ struct flow_cache_entry *fle, *tfle;
139+ struct hlist_node *entry;
140 struct flow_cache_object *flo;
141 unsigned int hash;
142
143@@ -200,12 +235,13 @@ flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
144 flow_new_hash_rnd(fc, fcp);
145
146 hash = flow_hash_code(fc, fcp, key);
147- head = &fcp->hash_table[hash];
148- for (fle = *head; fle; fle = fle->next) {
149- if (fle->family == family &&
150- fle->dir == dir &&
151- flow_key_compare(key, &fle->key) == 0)
152+ hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) {
153+ if (tfle->family == family &&
154+ tfle->dir == dir &&
155+ flow_key_compare(key, &tfle->key) == 0) {
156+ fle = tfle;
157 break;
158+ }
159 }
160
161 if (unlikely(!fle)) {
162@@ -214,12 +250,11 @@ flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
163
164 fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
165 if (fle) {
166- fle->next = *head;
167- *head = fle;
168 fle->family = family;
169 fle->dir = dir;
170 memcpy(&fle->key, key, sizeof(*key));
171 fle->object = NULL;
172+ hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]);
173 fcp->hash_count++;
174 }
175 } else if (likely(fle->genid == atomic_read(&flow_cache_genid))) {
176@@ -262,23 +297,26 @@ static void flow_cache_flush_tasklet(unsigned long data)
177 struct flow_flush_info *info = (void *)data;
178 struct flow_cache *fc = info->cache;
179 struct flow_cache_percpu *fcp;
180- int i;
181+ struct flow_cache_entry *fle;
182+ struct hlist_node *entry, *tmp;
183+ LIST_HEAD(gc_list);
184+ int i, deleted = 0;
185
186 fcp = per_cpu_ptr(fc->percpu, smp_processor_id());
187 for (i = 0; i < flow_cache_hash_size(fc); i++) {
188- struct flow_cache_entry *fle;
189-
190- fle = fcp->hash_table[i];
191- for (; fle; fle = fle->next) {
192+ hlist_for_each_entry_safe(fle, entry, tmp,
193+ &fcp->hash_table[i], u.hlist) {
194 if (flow_entry_valid(fle))
195 continue;
196
197- if (fle->object)
198- fle->object->ops->delete(fle->object);
199- fle->object = NULL;
200+ deleted++;
201+ hlist_del(&fle->u.hlist);
202+ list_add_tail(&fle->u.gc_list, &gc_list);
203 }
204 }
205
206+ flow_cache_queue_garbage(fcp, deleted, &gc_list);
207+
208 if (atomic_dec_and_test(&info->cpuleft))
209 complete(&info->completion);
210 }
211@@ -320,7 +358,7 @@ void flow_cache_flush(void)
212 static void __init flow_cache_cpu_prepare(struct flow_cache *fc,
213 struct flow_cache_percpu *fcp)
214 {
215- fcp->hash_table = (struct flow_cache_entry **)
216+ fcp->hash_table = (struct hlist_head *)
217 __get_free_pages(GFP_KERNEL|__GFP_ZERO, fc->order);
218 if (!fcp->hash_table)
219 panic("NET: failed to allocate flow cache order %lu\n", fc->order);
220@@ -354,7 +392,7 @@ static int flow_cache_init(struct flow_cache *fc)
221
222 for (order = 0;
223 (PAGE_SIZE << order) <
224- (sizeof(struct flow_cache_entry *)*flow_cache_hash_size(fc));
225+ (sizeof(struct hlist_head)*flow_cache_hash_size(fc));
226 order++)
227 /* NOTHING */;
228 fc->order = order;
229--
2301.7.0.2
231
diff --git a/main/linux-grsec/0018-xfrm-Fix-crashes-in-xfrm_lookup.patch b/main/linux-grsec/0018-xfrm-Fix-crashes-in-xfrm_lookup.patch
new file mode 100644
index 0000000000..6f0dc91286
--- /dev/null
+++ b/main/linux-grsec/0018-xfrm-Fix-crashes-in-xfrm_lookup.patch
@@ -0,0 +1,46 @@
1From e0c0800740cdf64fe7b121c2ef235c01f1957af0 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
3Date: Thu, 8 Apr 2010 11:27:42 -0700
4Subject: [PATCH 18/18] xfrm: Fix crashes in xfrm_lookup()
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9From: Timo Teräs <timo.teras@iki.fi>
10
11Happens because CONFIG_XFRM_SUB_POLICY is not enabled, and one of
12the helper functions I used did unexpected things in that case.
13
14Signed-off-by: David S. Miller <davem@davemloft.net>
15(cherry picked from commit e4077e018b5ead3de9951fc01d8bf12eeeeeefed)
16---
17 include/net/xfrm.h | 7 -------
18 1 files changed, 0 insertions(+), 7 deletions(-)
19
20diff --git a/include/net/xfrm.h b/include/net/xfrm.h
21index d51ef61..280f46f 100644
22--- a/include/net/xfrm.h
23+++ b/include/net/xfrm.h
24@@ -738,19 +738,12 @@ static inline void xfrm_pol_put(struct xfrm_policy *policy)
25 xfrm_policy_destroy(policy);
26 }
27
28-#ifdef CONFIG_XFRM_SUB_POLICY
29 static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
30 {
31 int i;
32 for (i = npols - 1; i >= 0; --i)
33 xfrm_pol_put(pols[i]);
34 }
35-#else
36-static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
37-{
38- xfrm_pol_put(pols[0]);
39-}
40-#endif
41
42 extern void __xfrm_state_destroy(struct xfrm_state *);
43
44--
451.7.0.2
46
diff --git a/main/linux-grsec/APKBUILD b/main/linux-grsec/APKBUILD
index 2b81673eaf..b514a1a5d7 100644
--- a/main/linux-grsec/APKBUILD
+++ b/main/linux-grsec/APKBUILD
@@ -4,7 +4,7 @@ _flavor=grsec
4pkgname=linux-${_flavor} 4pkgname=linux-${_flavor}
5pkgver=2.6.32.11 5pkgver=2.6.32.11
6_kernver=2.6.32 6_kernver=2.6.32
7pkgrel=1 7pkgrel=2
8pkgdesc="Linux kernel with grsecurity" 8pkgdesc="Linux kernel with grsecurity"
9url=http://grsecurity.net 9url=http://grsecurity.net
10depends="mkinitfs linux-firmware" 10depends="mkinitfs linux-firmware"
@@ -15,12 +15,24 @@ install=
15source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2 15source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
16 ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2 16 ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
17 grsecurity-2.1.14-2.6.32.11-201004071936.patch 17 grsecurity-2.1.14-2.6.32.11-201004071936.patch
18 ip_gre.patch 18 0001-grsec-revert-conflicting-flow-cache-changes.patch
19 ip_gre2.patch 19 0002-gre-fix-hard-header-destination-address-checking.patch
20 arp.patch 20 0003-ip_gre-include-route-header_len-in-max_headroom-calc.patch
21 xfrm-cache-size-revert.patch 21 0004-arp-flush-arp-cache-on-device-change.patch
22 net-git-78f1cd-r8169-fix-broken-register-writes.patch 22 0005-r8169-fix-broken-register-writes.patch
23 net-git-c0cd88-r8169-offical-fix-for-CVE-2009-4537-overlength-frame-DMAs.patch 23 0006-r8169-offical-fix-for-CVE-2009-4537-overlength-frame.patch
24 0007-r8169-Fix-rtl8169_rx_interrupt.patch
25 0008-r8169-clean-up-my-printk-uglyness.patch
26 0009-ipsec-Fix-bogus-bundle-flowi.patch
27 0010-xfrm-Remove-xfrm_state_genid.patch
28 0011-xfrm_user-verify-policy-direction-at-XFRM_MSG_POLEXP.patch
29 0012-xfrm-remove-policy-lock-when-accessing-policy-walk.d.patch
30 0013-flow-structurize-flow-cache.patch
31 0014-flow-virtualize-flow-cache-entry-methods.patch
32 0015-xfrm-cache-bundles-instead-of-policies-for-outgoing-.patch
33 0016-xfrm-remove-policy-garbage-collection.patch
34 0017-flow-delayed-deletion-of-flow-cache-entries.patch
35 0018-xfrm-Fix-crashes-in-xfrm_lookup.patch
24 kernelconfig.x86 36 kernelconfig.x86
25 " 37 "
26subpackages="$pkgname-dev linux-firmware:firmware" 38subpackages="$pkgname-dev linux-firmware:firmware"
@@ -34,7 +46,8 @@ prepare() {
34 bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 -N || return 1 46 bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 -N || return 1
35 fi 47 fi
36 48
37 for i in ../*.diff ../*.patch; do 49 # first apply the grsecurity patch and then the rest
50 for i in "$srcdir"/grsecurity*.patch "$srcdir"/0[0-9]*.patch; do
38 [ -f $i ] || continue 51 [ -f $i ] || continue
39 msg "Applying $i..." 52 msg "Applying $i..."
40 patch -s -p1 -N < $i || return 1 53 patch -s -p1 -N < $i || return 1
@@ -127,10 +140,22 @@ firmware() {
127md5sums="260551284ac224c3a43c4adac7df4879 linux-2.6.32.tar.bz2 140md5sums="260551284ac224c3a43c4adac7df4879 linux-2.6.32.tar.bz2
128855c248334a71ef5ca3d8cb89d51334f patch-2.6.32.11.bz2 141855c248334a71ef5ca3d8cb89d51334f patch-2.6.32.11.bz2
1296eabb0c08a988a97a823b5462d1c5018 grsecurity-2.1.14-2.6.32.11-201004071936.patch 1426eabb0c08a988a97a823b5462d1c5018 grsecurity-2.1.14-2.6.32.11-201004071936.patch
1303ef822f3a2723b9a80c3f12954457225 ip_gre.patch 1431d247140abec49b96250aec9aa59b324 0001-grsec-revert-conflicting-flow-cache-changes.patch
13113ca9e91700e459da269c957062bbea7 ip_gre2.patch 144437317f88ec13ace8d39c31983a41696 0002-gre-fix-hard-header-destination-address-checking.patch
1324c39a161d918e7f274292ecfd168b891 arp.patch 145151b29a161178ed39d62a08f21f3484d 0003-ip_gre-include-route-header_len-in-max_headroom-calc.patch
133329fcab881425e001d3243caa4648478 xfrm-cache-size-revert.patch 146776adeeb5272093574f8836c5037dd7d 0004-arp-flush-arp-cache-on-device-change.patch
13421ed38773d846097b7315e1e0801d87a net-git-78f1cd-r8169-fix-broken-register-writes.patch 147afa06334c81f21c20571286a83d3d928 0005-r8169-fix-broken-register-writes.patch
135962a6dd7c639612fc8bdaeb836388b0b net-git-c0cd88-r8169-offical-fix-for-CVE-2009-4537-overlength-frame-DMAs.patch 148c538c0f735d79fd71b47dde02bf1f790 0006-r8169-offical-fix-for-CVE-2009-4537-overlength-frame.patch
1495f8b9a76d95319c5b1aa26b54a42e6b5 0007-r8169-Fix-rtl8169_rx_interrupt.patch
150f878c802700e3babd03be3505119c5c2 0008-r8169-clean-up-my-printk-uglyness.patch
151cf168620efa63479a6e03da78906e32f 0009-ipsec-Fix-bogus-bundle-flowi.patch
1523af4b5ae1afae3278b0070f585b874e3 0010-xfrm-Remove-xfrm_state_genid.patch
1539f284c3fd5ab38cef4544efc1f50c6ba 0011-xfrm_user-verify-policy-direction-at-XFRM_MSG_POLEXP.patch
154b035114e893883cf67530350678e00f5 0012-xfrm-remove-policy-lock-when-accessing-policy-walk.d.patch
1559dea03ec19aaf9a384e4f56f57009257 0013-flow-structurize-flow-cache.patch
156fc9ab26abbfec0d3f20000b5e695620b 0014-flow-virtualize-flow-cache-entry-methods.patch
157c09b82b89a49ba2a3836a0bc3a3312f4 0015-xfrm-cache-bundles-instead-of-policies-for-outgoing-.patch
15841618efb65ab9ddacfb59a1cde9b4edd 0016-xfrm-remove-policy-garbage-collection.patch
1593b83f0972ab715819d1119b120a987e7 0017-flow-delayed-deletion-of-flow-cache-entries.patch
16045a676c7a1759fec60b724d557b4e295 0018-xfrm-Fix-crashes-in-xfrm_lookup.patch
1367f442049b29ab749180e54ff8f20f1d0 kernelconfig.x86" 1617f442049b29ab749180e54ff8f20f1d0 kernelconfig.x86"
diff --git a/main/linux-grsec/arp.patch b/main/linux-grsec/arp.patch
deleted file mode 100644
index d2682690f5..0000000000
--- a/main/linux-grsec/arp.patch
+++ /dev/null
@@ -1,14 +0,0 @@
1diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
2index c95cd93..71ab56f 100644
3--- a/net/ipv4/arp.c
4+++ b/net/ipv4/arp.c
5@@ -1200,6 +1200,9 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
6 neigh_changeaddr(&arp_tbl, dev);
7 rt_cache_flush(dev_net(dev), 0);
8 break;
9+ case NETDEV_CHANGE:
10+ neigh_changeaddr(&arp_tbl, dev);
11+ break;
12 default:
13 break;
14 }
diff --git a/main/linux-grsec/ip_gre.patch b/main/linux-grsec/ip_gre.patch
deleted file mode 100644
index ba5f19b300..0000000000
--- a/main/linux-grsec/ip_gre.patch
+++ /dev/null
@@ -1,15 +0,0 @@
1--- a/net/ipv4/ip_gre.c.orig
2+++ b/net/ipv4/ip_gre.c
3@@ -1137,11 +1137,8 @@
4
5 if (saddr)
6 memcpy(&iph->saddr, saddr, 4);
7-
8- if (daddr) {
9+ if (daddr)
10 memcpy(&iph->daddr, daddr, 4);
11- return t->hlen;
12- }
13 if (iph->daddr && !ipv4_is_multicast(iph->daddr))
14 return t->hlen;
15
diff --git a/main/linux-grsec/ip_gre2.patch b/main/linux-grsec/ip_gre2.patch
deleted file mode 100644
index 52c44076d2..0000000000
--- a/main/linux-grsec/ip_gre2.patch
+++ /dev/null
@@ -1,17 +0,0 @@
1--- linux-2.6.32/net/ipv4/ip_gre.c.orig
2+++ linux-2.6.32/net/ipv4/ip_gre.c
3@@ -803,11 +803,13 @@
4 tunnel->err_count = 0;
5 }
6
7- max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;
8+ max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->u.dst.header_len;
9
10 if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
11 (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
12 struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
13+ if (max_headroom > dev->needed_headroom)
14+ dev->needed_headroom = max_headroom;
15 if (!new_skb) {
16 ip_rt_put(rt);
17 stats->tx_dropped++;