summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSona Sarmadi <sona.sarmadi@enea.com>2017-09-26 10:49:40 +0200
committerAdrian Dudau <adrian.dudau@enea.com>2017-09-26 15:36:31 +0200
commit7eddd2b6da1b1ed574e90e19c96b9497e3f59c14 (patch)
treeeda06497aaa75bf89e70a578831e95a68431ddf1
parent79b2f0f1e6b568dd5611118d7d0610e1df610e10 (diff)
downloadmeta-enea-bsp-arm-7eddd2b6da1b1ed574e90e19c96b9497e3f59c14.tar.gz
linux-cavium: CVE-2017-7618
Infinite recursion in ahash.c by triggering EBUSY on a full queue Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7618 Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
-rw-r--r--recipes-kernel/linux/linux-cavium/CVE-2017-7618.patch238
-rw-r--r--recipes-kernel/linux/linux-cavium_4.9.inc1
2 files changed, 239 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-cavium/CVE-2017-7618.patch b/recipes-kernel/linux/linux-cavium/CVE-2017-7618.patch
new file mode 100644
index 0000000..14198be
--- /dev/null
+++ b/recipes-kernel/linux/linux-cavium/CVE-2017-7618.patch
@@ -0,0 +1,238 @@
1From c10479591869177ae7ac0570b54ace6fbdeb57c2 Mon Sep 17 00:00:00 2001
2From: Herbert Xu <herbert@gondor.apana.org.au>
3Date: Mon, 10 Apr 2017 17:27:57 +0800
4Subject: [PATCH] crypto: ahash - Fix EINPROGRESS notification callback
5
6commit ef0579b64e93188710d48667cb5e014926af9f1b upstream.
7
8The ahash API modifies the request's callback function in order
9to clean up after itself in some corner cases (unaligned final
10and missing finup).
11
12When the request is complete ahash will restore the original
13callback and everything is fine. However, when the request gets
14an EBUSY on a full queue, an EINPROGRESS callback is made while
15the request is still ongoing.
16
17In this case the ahash API will incorrectly call its own callback.
18
19This patch fixes the problem by creating a temporary request
20object on the stack which is used to relay EINPROGRESS back to
21the original completion function.
22
23This patch also adds code to preserve the original flags value.
24
25CVE: CVE-2017-7618
26Upstream-Status: Backport [backport from: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit/?h=v4.9.51&id=c10479591869177ae7ac0570b54ace6fbdeb57c2]
27
28Fixes: ab6bf4e5e5e4 ("crypto: hash - Fix the pointer voodoo in...")
29Reported-by: Sabrina Dubroca <sd@queasysnail.net>
30Tested-by: Sabrina Dubroca <sd@queasysnail.net>
31Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
32Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
33Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
34---
35 crypto/ahash.c | 79 ++++++++++++++++++++++++++----------------
36 include/crypto/internal/hash.h | 10 ++++++
37 2 files changed, 60 insertions(+), 29 deletions(-)
38
39diff --git a/crypto/ahash.c b/crypto/ahash.c
40index 2ce8bcb..cce0268 100644
41--- a/crypto/ahash.c
42+++ b/crypto/ahash.c
43@@ -31,6 +31,7 @@ struct ahash_request_priv {
44 crypto_completion_t complete;
45 void *data;
46 u8 *result;
47+ u32 flags;
48 void *ubuf[] CRYPTO_MINALIGN_ATTR;
49 };
50
51@@ -252,6 +253,8 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
52 priv->result = req->result;
53 priv->complete = req->base.complete;
54 priv->data = req->base.data;
55+ priv->flags = req->base.flags;
56+
57 /*
58 * WARNING: We do not backup req->priv here! The req->priv
59 * is for internal use of the Crypto API and the
60@@ -266,38 +269,44 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
61 return 0;
62 }
63
64-static void ahash_restore_req(struct ahash_request *req)
65+static void ahash_restore_req(struct ahash_request *req, int err)
66 {
67 struct ahash_request_priv *priv = req->priv;
68
69+ if (!err)
70+ memcpy(priv->result, req->result,
71+ crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
72+
73 /* Restore the original crypto request. */
74 req->result = priv->result;
75- req->base.complete = priv->complete;
76- req->base.data = priv->data;
77+
78+ ahash_request_set_callback(req, priv->flags,
79+ priv->complete, priv->data);
80 req->priv = NULL;
81
82 /* Free the req->priv.priv from the ADJUSTED request. */
83 kzfree(priv);
84 }
85
86-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
87+static void ahash_notify_einprogress(struct ahash_request *req)
88 {
89 struct ahash_request_priv *priv = req->priv;
90+ struct crypto_async_request oreq;
91
92- if (err == -EINPROGRESS)
93- return;
94-
95- if (!err)
96- memcpy(priv->result, req->result,
97- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
98+ oreq.data = priv->data;
99
100- ahash_restore_req(req);
101+ priv->complete(&oreq, -EINPROGRESS);
102 }
103
104 static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
105 {
106 struct ahash_request *areq = req->data;
107
108+ if (err == -EINPROGRESS) {
109+ ahash_notify_einprogress(areq);
110+ return;
111+ }
112+
113 /*
114 * Restore the original request, see ahash_op_unaligned() for what
115 * goes where.
116@@ -308,7 +317,7 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
117 */
118
119 /* First copy req->result into req->priv.result */
120- ahash_op_unaligned_finish(areq, err);
121+ ahash_restore_req(areq, err);
122
123 /* Complete the ORIGINAL request. */
124 areq->base.complete(&areq->base, err);
125@@ -324,7 +333,12 @@ static int ahash_op_unaligned(struct ahash_request *req,
126 return err;
127
128 err = op(req);
129- ahash_op_unaligned_finish(req, err);
130+ if (err == -EINPROGRESS ||
131+ (err == -EBUSY && (ahash_request_flags(req) &
132+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
133+ return err;
134+
135+ ahash_restore_req(req, err);
136
137 return err;
138 }
139@@ -359,25 +373,14 @@ int crypto_ahash_digest(struct ahash_request *req)
140 }
141 EXPORT_SYMBOL_GPL(crypto_ahash_digest);
142
143-static void ahash_def_finup_finish2(struct ahash_request *req, int err)
144+static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
145 {
146- struct ahash_request_priv *priv = req->priv;
147+ struct ahash_request *areq = req->data;
148
149 if (err == -EINPROGRESS)
150 return;
151
152- if (!err)
153- memcpy(priv->result, req->result,
154- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
155-
156- ahash_restore_req(req);
157-}
158-
159-static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
160-{
161- struct ahash_request *areq = req->data;
162-
163- ahash_def_finup_finish2(areq, err);
164+ ahash_restore_req(areq, err);
165
166 areq->base.complete(&areq->base, err);
167 }
168@@ -388,11 +391,15 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err)
169 goto out;
170
171 req->base.complete = ahash_def_finup_done2;
172- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
173+
174 err = crypto_ahash_reqtfm(req)->final(req);
175+ if (err == -EINPROGRESS ||
176+ (err == -EBUSY && (ahash_request_flags(req) &
177+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
178+ return err;
179
180 out:
181- ahash_def_finup_finish2(req, err);
182+ ahash_restore_req(req, err);
183 return err;
184 }
185
186@@ -400,7 +407,16 @@ static void ahash_def_finup_done1(struct crypto_async_request *req, int err)
187 {
188 struct ahash_request *areq = req->data;
189
190+ if (err == -EINPROGRESS) {
191+ ahash_notify_einprogress(areq);
192+ return;
193+ }
194+
195+ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
196+
197 err = ahash_def_finup_finish1(areq, err);
198+ if (areq->priv)
199+ return;
200
201 areq->base.complete(&areq->base, err);
202 }
203@@ -415,6 +431,11 @@ static int ahash_def_finup(struct ahash_request *req)
204 return err;
205
206 err = tfm->update(req);
207+ if (err == -EINPROGRESS ||
208+ (err == -EBUSY && (ahash_request_flags(req) &
209+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
210+ return err;
211+
212 return ahash_def_finup_finish1(req, err);
213 }
214
215diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
216index 1d4f365..f6d9af3e 100644
217--- a/include/crypto/internal/hash.h
218+++ b/include/crypto/internal/hash.h
219@@ -166,6 +166,16 @@ static inline struct ahash_instance *ahash_alloc_instance(
220 return crypto_alloc_instance2(name, alg, ahash_instance_headroom());
221 }
222
223+static inline void ahash_request_complete(struct ahash_request *req, int err)
224+{
225+ req->base.complete(&req->base, err);
226+}
227+
228+static inline u32 ahash_request_flags(struct ahash_request *req)
229+{
230+ return req->base.flags;
231+}
232+
233 static inline struct crypto_ahash *crypto_spawn_ahash(
234 struct crypto_ahash_spawn *spawn)
235 {
236--
2371.9.1
238
diff --git a/recipes-kernel/linux/linux-cavium_4.9.inc b/recipes-kernel/linux/linux-cavium_4.9.inc
index 8b7fe31..aea3477 100644
--- a/recipes-kernel/linux/linux-cavium_4.9.inc
+++ b/recipes-kernel/linux/linux-cavium_4.9.inc
@@ -23,6 +23,7 @@ SRC_URI = "git://git@git.enea.com/linux/linux-cavium.git;protocol=ssh;name=machi
23 file://CVE-2017-8067.patch \ 23 file://CVE-2017-8067.patch \
24 file://CVE-2017-8068.patch \ 24 file://CVE-2017-8068.patch \
25 file://CVE-2017-8069.patch \ 25 file://CVE-2017-8069.patch \
26 file://CVE-2017-7618.patch \
26 " 27 "
27 28
28LINUX_KERNEL_TYPE = "tiny" 29LINUX_KERNEL_TYPE = "tiny"