summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDragos Motrea <Dragos.Motrea@enea.com>2017-11-02 18:04:12 +0100
committerAdrian Dudau <adrian.dudau@enea.com>2017-11-03 14:02:40 +0100
commit0695cdbd10b0252be0e6e4a594c35f6be1b9cc63 (patch)
treeaa5a9e85bebf973eb0abbb25453776ae38ff34a9
parent00cb87844588928469c40444402c270a25dd4b55 (diff)
downloadmeta-enea-bsp-arm-0695cdbd10b0252be0e6e4a594c35f6be1b9cc63.tar.gz
openvswitch: fixed kernel crash
Signed-off-by: Dragos Motrea <Dragos.Motrea@enea.com> Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
-rw-r--r--recipes-kernel/linux/linux-cavium/0001-openvswitch-fixed-kernel-crash.patch241
-rw-r--r--recipes-kernel/linux/linux-cavium_4.9.inc1
2 files changed, 242 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-cavium/0001-openvswitch-fixed-kernel-crash.patch b/recipes-kernel/linux/linux-cavium/0001-openvswitch-fixed-kernel-crash.patch
new file mode 100644
index 0000000..ba631ea
--- /dev/null
+++ b/recipes-kernel/linux/linux-cavium/0001-openvswitch-fixed-kernel-crash.patch
@@ -0,0 +1,241 @@
1From 65693212754e9f97d29504219327ce4807780c48 Mon Sep 17 00:00:00 2001
2From: Dragos Motrea <Dragos.Motrea@enea.com>
3Date: Tue, 24 Oct 2017 13:10:10 +0200
4Subject: [meta-enea-bsp-arm][cavium-4.9][LXCR-8050][PATCHv1 1/1] openvswitch:
5 fixed kernel crash
6
7Inserting the openvswitch.ko is causing a kernel crash in
8__percpu_counter_sum function. Applying this patch will replace the percpu
9counter API with the atomic operations for fragmentation mem accounting.
10The atomic operations should be used on architecture with many CPUs.
11
12The revert is made in kernel upstream by the commit:
13fb452a1aa3fd4034d7999e309c5466ff2d7005aa
14
15Upstream-Status: Backport
16
17Signed-off-by: Dragos Motrea <Dragos.Motrea@enea.com>
18---
19 include/net/inet_frag.h | 40 ++++++++-------------------------
20 net/ieee802154/6lowpan/reassembly.c | 12 +++-------
21 net/ipv4/inet_fragment.c | 4 +---
22 net/ipv4/ip_fragment.c | 15 ++++---------
23 net/ipv6/netfilter/nf_conntrack_reasm.c | 12 +++-------
24 net/ipv6/reassembly.c | 12 +++-------
25 6 files changed, 23 insertions(+), 72 deletions(-)
26
27diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
28index 909972a..38beec0 100644
29--- a/include/net/inet_frag.h
30+++ b/include/net/inet_frag.h
31@@ -1,14 +1,9 @@
32 #ifndef __NET_FRAG_H__
33 #define __NET_FRAG_H__
34
35-#include <linux/percpu_counter.h>
36-
37 struct netns_frags {
38- /* The percpu_counter "mem" need to be cacheline aligned.
39- * mem.count must not share cacheline with other writers
40- */
41- struct percpu_counter mem ____cacheline_aligned_in_smp;
42-
43+ /* Keep atomic mem on separate cachelines in structs that include it */
44+ atomic_t mem ____cacheline_aligned_in_smp;
45 /* sysctls */
46 int timeout;
47 int high_thresh;
48@@ -108,13 +103,9 @@ struct inet_frags {
49 int inet_frags_init(struct inet_frags *);
50 void inet_frags_fini(struct inet_frags *);
51
52-static inline int inet_frags_init_net(struct netns_frags *nf)
53-{
54- return percpu_counter_init(&nf->mem, 0, GFP_KERNEL);
55-}
56-static inline void inet_frags_uninit_net(struct netns_frags *nf)
57+static inline void inet_frags_init_net(struct netns_frags *nf)
58 {
59- percpu_counter_destroy(&nf->mem);
60+ atomic_set(&nf->mem, 0);
61 }
62
63 void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
64@@ -140,37 +131,24 @@ static inline bool inet_frag_evicting(struct inet_frag_queue *q)
65
66 /* Memory Tracking Functions. */
67
68-/* The default percpu_counter batch size is not big enough to scale to
69- * fragmentation mem acct sizes.
70- * The mem size of a 64K fragment is approx:
71- * (44 fragments * 2944 truesize) + frag_queue struct(200) = 129736 bytes
72- */
73-static unsigned int frag_percpu_counter_batch = 130000;
74-
75 static inline int frag_mem_limit(struct netns_frags *nf)
76 {
77- return percpu_counter_read(&nf->mem);
78+ return atomic_read(&nf->mem);
79 }
80
81 static inline void sub_frag_mem_limit(struct netns_frags *nf, int i)
82 {
83- __percpu_counter_add(&nf->mem, -i, frag_percpu_counter_batch);
84+ atomic_sub(i, &nf->mem);
85 }
86
87 static inline void add_frag_mem_limit(struct netns_frags *nf, int i)
88 {
89- __percpu_counter_add(&nf->mem, i, frag_percpu_counter_batch);
90+ atomic_add(i, &nf->mem);
91 }
92
93-static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf)
94+static inline int sum_frag_mem_limit(struct netns_frags *nf)
95 {
96- unsigned int res;
97-
98- local_bh_disable();
99- res = percpu_counter_sum_positive(&nf->mem);
100- local_bh_enable();
101-
102- return res;
103+ return atomic_read(&nf->mem);
104 }
105
106 /* RFC 3168 support :
107diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
108index 30d875d..fb28a06 100644
109--- a/net/ieee802154/6lowpan/reassembly.c
110+++ b/net/ieee802154/6lowpan/reassembly.c
111@@ -580,21 +580,15 @@ static int __net_init lowpan_frags_init_net(struct net *net)
112 {
113 struct netns_ieee802154_lowpan *ieee802154_lowpan =
114 net_ieee802154_lowpan(net);
115- int res;
116
117 ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
118 ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH;
119 ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT;
120
121- res = inet_frags_init_net(&ieee802154_lowpan->frags);
122- if (res)
123- return res;
124- res = lowpan_frags_ns_sysctl_register(net);
125- if (res)
126- inet_frags_uninit_net(&ieee802154_lowpan->frags);
127- return res;
128-}
129+ inet_frags_init_net(&ieee802154_lowpan->frags);
130
131+ return lowpan_frags_ns_sysctl_register(net);
132+}
133 static void __net_exit lowpan_frags_exit_net(struct net *net)
134 {
135 struct netns_ieee802154_lowpan *ieee802154_lowpan =
136diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
137index b5e9317..631c0d0 100644
138--- a/net/ipv4/inet_fragment.c
139+++ b/net/ipv4/inet_fragment.c
140@@ -234,10 +234,8 @@ evict_again:
141 cond_resched();
142
143 if (read_seqretry(&f->rnd_seqlock, seq) ||
144- percpu_counter_sum(&nf->mem))
145+ sum_frag_mem_limit(nf))
146 goto evict_again;
147-
148- percpu_counter_destroy(&nf->mem);
149 }
150 EXPORT_SYMBOL(inet_frags_exit_net);
151
152diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
153index bbe7f72..0f0d89e 100644
154--- a/net/ipv4/ip_fragment.c
155+++ b/net/ipv4/ip_fragment.c
156@@ -835,8 +835,6 @@ static void __init ip4_frags_ctl_register(void)
157
158 static int __net_init ipv4_frags_init_net(struct net *net)
159 {
160- int res;
161-
162 /* Fragment cache limits.
163 *
164 * The fragment memory accounting code, (tries to) account for
165@@ -861,16 +859,11 @@ static int __net_init ipv4_frags_init_net(struct net *net)
166 net->ipv4.frags.timeout = IP_FRAG_TIME;
167
168 net->ipv4.frags.max_dist = 64;
169-
170- res = inet_frags_init_net(&net->ipv4.frags);
171- if (res)
172- return res;
173- res = ip4_frags_ns_ctl_register(net);
174- if (res)
175- inet_frags_uninit_net(&net->ipv4.frags);
176- return res;
177+
178+ inet_frags_init_net(&net->ipv4.frags);
179+
180+ return ip4_frags_ns_ctl_register(net);
181 }
182-
183 static void __net_exit ipv4_frags_exit_net(struct net *net)
184 {
185 ip4_frags_ns_ctl_unregister(net);
186diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
187index 9948b5c..8734e2c 100644
188--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
189+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
190@@ -621,18 +621,12 @@ EXPORT_SYMBOL_GPL(nf_ct_frag6_gather);
191
192 static int nf_ct_net_init(struct net *net)
193 {
194- int res;
195-
196 net->nf_frag.frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
197 net->nf_frag.frags.low_thresh = IPV6_FRAG_LOW_THRESH;
198 net->nf_frag.frags.timeout = IPV6_FRAG_TIMEOUT;
199- res = inet_frags_init_net(&net->nf_frag.frags);
200- if (res)
201- return res;
202- res = nf_ct_frag6_sysctl_register(net);
203- if (res)
204- inet_frags_uninit_net(&net->nf_frag.frags);
205- return res;
206+
207+ inet_frags_init_net(&net->nf_frag.frags);
208+ return nf_ct_frag6_sysctl_register(net);
209 }
210
211 static void nf_ct_net_exit(struct net *net)
212diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
213index 3815e85..fe67cf4 100644
214--- a/net/ipv6/reassembly.c
215+++ b/net/ipv6/reassembly.c
216@@ -709,19 +709,13 @@ static void ip6_frags_sysctl_unregister(void)
217
218 static int __net_init ipv6_frags_init_net(struct net *net)
219 {
220- int res;
221-
222 net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
223 net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH;
224 net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT;
225
226- res = inet_frags_init_net(&net->ipv6.frags);
227- if (res)
228- return res;
229- res = ip6_frags_ns_sysctl_register(net);
230- if (res)
231- inet_frags_uninit_net(&net->ipv6.frags);
232- return res;
233+ inet_frags_init_net(&net->ipv6.frags);
234+
235+ return ip6_frags_ns_sysctl_register(net);
236 }
237
238 static void __net_exit ipv6_frags_exit_net(struct net *net)
239--
2402.7.4
241
diff --git a/recipes-kernel/linux/linux-cavium_4.9.inc b/recipes-kernel/linux/linux-cavium_4.9.inc
index 0089d62..1c504fe 100644
--- a/recipes-kernel/linux/linux-cavium_4.9.inc
+++ b/recipes-kernel/linux/linux-cavium_4.9.inc
@@ -38,6 +38,7 @@ SRC_URI = "git://git@git.enea.com/linux/linux-cavium.git;protocol=ssh;name=machi
38 file://CVE-2017-8069.patch \ 38 file://CVE-2017-8069.patch \
39 file://CVE-2017-8831.patch \ 39 file://CVE-2017-8831.patch \
40 file://CVE-2017-1000364.patch \ 40 file://CVE-2017-1000364.patch \
41 file://0001-openvswitch-fixed-kernel-crash.patch \
41 " 42 "
42 43
43LINUX_KERNEL_TYPE = "tiny" 44LINUX_KERNEL_TYPE = "tiny"