summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Wellving <andreas.wellving@enea.com>2018-10-17 14:27:23 +0200
committerAndreas Wellving <andreas.wellving@enea.com>2018-10-17 14:27:23 +0200
commit5004d0b1d0556e1da7a4adcafcaf3a583c83b1de (patch)
tree178753c404c25264d18333dbf00dba5fed83a737
parent9663eadc371fa93896030458718a49672f9783d8 (diff)
downloadenea-kernel-cache-5004d0b1d0556e1da7a4adcafcaf3a583c83b1de.tar.gz
crypto: CVE-2017-7618
crypto: ahash - Fix EINPROGRESS notification callback References: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.1.y&id=ce0e21e44f9766aeef6a8c18a750ef9d94c1ca8c Change-Id: Ifdaf7c4025023947250ee94443d555ad3b0852bc Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
-rw-r--r--patches/cve/4.1.x.scc1
-rw-r--r--patches/cve/CVE-2017-7618-crypto-ahash-Fix-EINPROGRESS-notification-callback.patch239
2 files changed, 240 insertions, 0 deletions
diff --git a/patches/cve/4.1.x.scc b/patches/cve/4.1.x.scc
index 96110a0..5722514 100644
--- a/patches/cve/4.1.x.scc
+++ b/patches/cve/4.1.x.scc
@@ -5,3 +5,4 @@ patch CVE-2016-8655-packet-fix-race-condition-in-packet_set_ring.patch
5 5
6#fixed in 4.1.40 6#fixed in 4.1.40
7patch CVE-2016-10229-udp-properly-support-MSG_PEEK-with-truncated-buffers.patch 7patch CVE-2016-10229-udp-properly-support-MSG_PEEK-with-truncated-buffers.patch
8patch CVE-2017-7618-crypto-ahash-Fix-EINPROGRESS-notification-callback.patch
diff --git a/patches/cve/CVE-2017-7618-crypto-ahash-Fix-EINPROGRESS-notification-callback.patch b/patches/cve/CVE-2017-7618-crypto-ahash-Fix-EINPROGRESS-notification-callback.patch
new file mode 100644
index 0000000..f6e0982
--- /dev/null
+++ b/patches/cve/CVE-2017-7618-crypto-ahash-Fix-EINPROGRESS-notification-callback.patch
@@ -0,0 +1,239 @@
1From ce0e21e44f9766aeef6a8c18a750ef9d94c1ca8c 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
6[ Upstream commit ef0579b64e93188710d48667cb5e014926af9f1b ]
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
27
28Fixes: ab6bf4e5e5e4 ("crypto: hash - Fix the pointer voodoo in...")
29Cc: <stable@vger.kernel.org>
30Reported-by: Sabrina Dubroca <sd@queasysnail.net>
31Tested-by: Sabrina Dubroca <sd@queasysnail.net>
32Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
33Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
34Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
35---
36 crypto/ahash.c | 79 ++++++++++++++++++++++++++----------------
37 include/crypto/internal/hash.h | 10 ++++++
38 2 files changed, 60 insertions(+), 29 deletions(-)
39
40diff --git a/crypto/ahash.c b/crypto/ahash.c
41index dac1c24..f9caf0f 100644
42--- a/crypto/ahash.c
43+++ b/crypto/ahash.c
44@@ -31,6 +31,7 @@ struct ahash_request_priv {
45 crypto_completion_t complete;
46 void *data;
47 u8 *result;
48+ u32 flags;
49 void *ubuf[] CRYPTO_MINALIGN_ATTR;
50 };
51
52@@ -270,6 +271,8 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
53 priv->result = req->result;
54 priv->complete = req->base.complete;
55 priv->data = req->base.data;
56+ priv->flags = req->base.flags;
57+
58 /*
59 * WARNING: We do not backup req->priv here! The req->priv
60 * is for internal use of the Crypto API and the
61@@ -284,38 +287,44 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
62 return 0;
63 }
64
65-static void ahash_restore_req(struct ahash_request *req)
66+static void ahash_restore_req(struct ahash_request *req, int err)
67 {
68 struct ahash_request_priv *priv = req->priv;
69
70+ if (!err)
71+ memcpy(priv->result, req->result,
72+ crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
73+
74 /* Restore the original crypto request. */
75 req->result = priv->result;
76- req->base.complete = priv->complete;
77- req->base.data = priv->data;
78+
79+ ahash_request_set_callback(req, priv->flags,
80+ priv->complete, priv->data);
81 req->priv = NULL;
82
83 /* Free the req->priv.priv from the ADJUSTED request. */
84 kzfree(priv);
85 }
86
87-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
88+static void ahash_notify_einprogress(struct ahash_request *req)
89 {
90 struct ahash_request_priv *priv = req->priv;
91+ struct crypto_async_request oreq;
92
93- if (err == -EINPROGRESS)
94- return;
95-
96- if (!err)
97- memcpy(priv->result, req->result,
98- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
99+ oreq.data = priv->data;
100
101- ahash_restore_req(req);
102+ priv->complete(&oreq, -EINPROGRESS);
103 }
104
105 static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
106 {
107 struct ahash_request *areq = req->data;
108
109+ if (err == -EINPROGRESS) {
110+ ahash_notify_einprogress(areq);
111+ return;
112+ }
113+
114 /*
115 * Restore the original request, see ahash_op_unaligned() for what
116 * goes where.
117@@ -326,7 +335,7 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
118 */
119
120 /* First copy req->result into req->priv.result */
121- ahash_op_unaligned_finish(areq, err);
122+ ahash_restore_req(areq, err);
123
124 /* Complete the ORIGINAL request. */
125 areq->base.complete(&areq->base, err);
126@@ -342,7 +351,12 @@ static int ahash_op_unaligned(struct ahash_request *req,
127 return err;
128
129 err = op(req);
130- ahash_op_unaligned_finish(req, err);
131+ if (err == -EINPROGRESS ||
132+ (err == -EBUSY && (ahash_request_flags(req) &
133+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
134+ return err;
135+
136+ ahash_restore_req(req, err);
137
138 return err;
139 }
140@@ -377,25 +391,14 @@ int crypto_ahash_digest(struct ahash_request *req)
141 }
142 EXPORT_SYMBOL_GPL(crypto_ahash_digest);
143
144-static void ahash_def_finup_finish2(struct ahash_request *req, int err)
145+static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
146 {
147- struct ahash_request_priv *priv = req->priv;
148+ struct ahash_request *areq = req->data;
149
150 if (err == -EINPROGRESS)
151 return;
152
153- if (!err)
154- memcpy(priv->result, req->result,
155- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
156-
157- ahash_restore_req(req);
158-}
159-
160-static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
161-{
162- struct ahash_request *areq = req->data;
163-
164- ahash_def_finup_finish2(areq, err);
165+ ahash_restore_req(areq, err);
166
167 areq->base.complete(&areq->base, err);
168 }
169@@ -406,11 +409,15 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err)
170 goto out;
171
172 req->base.complete = ahash_def_finup_done2;
173- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
174+
175 err = crypto_ahash_reqtfm(req)->final(req);
176+ if (err == -EINPROGRESS ||
177+ (err == -EBUSY && (ahash_request_flags(req) &
178+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
179+ return err;
180
181 out:
182- ahash_def_finup_finish2(req, err);
183+ ahash_restore_req(req, err);
184 return err;
185 }
186
187@@ -418,7 +425,16 @@ static void ahash_def_finup_done1(struct crypto_async_request *req, int err)
188 {
189 struct ahash_request *areq = req->data;
190
191+ if (err == -EINPROGRESS) {
192+ ahash_notify_einprogress(areq);
193+ return;
194+ }
195+
196+ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
197+
198 err = ahash_def_finup_finish1(areq, err);
199+ if (areq->priv)
200+ return;
201
202 areq->base.complete(&areq->base, err);
203 }
204@@ -433,6 +449,11 @@ static int ahash_def_finup(struct ahash_request *req)
205 return err;
206
207 err = tfm->update(req);
208+ if (err == -EINPROGRESS ||
209+ (err == -EBUSY && (ahash_request_flags(req) &
210+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
211+ return err;
212+
213 return ahash_def_finup_finish1(req, err);
214 }
215
216diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
217index 3b4af1d..a25414c 100644
218--- a/include/crypto/internal/hash.h
219+++ b/include/crypto/internal/hash.h
220@@ -173,6 +173,16 @@ static inline struct ahash_instance *ahash_alloc_instance(
221 return crypto_alloc_instance2(name, alg, ahash_instance_headroom());
222 }
223
224+static inline void ahash_request_complete(struct ahash_request *req, int err)
225+{
226+ req->base.complete(&req->base, err);
227+}
228+
229+static inline u32 ahash_request_flags(struct ahash_request *req)
230+{
231+ return req->base.flags;
232+}
233+
234 static inline struct crypto_ahash *crypto_spawn_ahash(
235 struct crypto_ahash_spawn *spawn)
236 {
237--
2382.7.4
239