diff options
author | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2017-12-19 05:27:24 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2017-12-22 03:02:40 -0500 |
commit | af955bf15d2c27496b0269b1f05c26f758c68314 (patch) | |
tree | 93a46f7d3a6038882d956007e9b8a927df37b36c | |
parent | e57121d08c38dabec15cf3e1e2ad46721af30cae (diff) |
crypto: af_alg - Fix race around ctx->rcvused by making it atomic_t
This variable was increased and decreased without any protection.
Result was an occasional misscount and negative wrap around resulting
in false resource allocation failures.
Fixes: 7d2c3f54e6f6 ("crypto: af_alg - remove locking in async callback")
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | crypto/af_alg.c | 4 | ||||
-rw-r--r-- | crypto/algif_aead.c | 2 | ||||
-rw-r--r-- | crypto/algif_skcipher.c | 2 | ||||
-rw-r--r-- | include/crypto/if_alg.h | 5 |
4 files changed, 7 insertions, 6 deletions
diff --git a/crypto/af_alg.c b/crypto/af_alg.c index f1a2caf1b59b..d3f1c431724b 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c | |||
@@ -664,7 +664,7 @@ void af_alg_free_areq_sgls(struct af_alg_async_req *areq) | |||
664 | unsigned int i; | 664 | unsigned int i; |
665 | 665 | ||
666 | list_for_each_entry_safe(rsgl, tmp, &areq->rsgl_list, list) { | 666 | list_for_each_entry_safe(rsgl, tmp, &areq->rsgl_list, list) { |
667 | ctx->rcvused -= rsgl->sg_num_bytes; | 667 | atomic_sub(rsgl->sg_num_bytes, &ctx->rcvused); |
668 | af_alg_free_sg(&rsgl->sgl); | 668 | af_alg_free_sg(&rsgl->sgl); |
669 | list_del(&rsgl->list); | 669 | list_del(&rsgl->list); |
670 | if (rsgl != &areq->first_rsgl) | 670 | if (rsgl != &areq->first_rsgl) |
@@ -1162,7 +1162,7 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, | |||
1162 | 1162 | ||
1163 | areq->last_rsgl = rsgl; | 1163 | areq->last_rsgl = rsgl; |
1164 | len += err; | 1164 | len += err; |
1165 | ctx->rcvused += err; | 1165 | atomic_add(err, &ctx->rcvused); |
1166 | rsgl->sg_num_bytes = err; | 1166 | rsgl->sg_num_bytes = err; |
1167 | iov_iter_advance(&msg->msg_iter, err); | 1167 | iov_iter_advance(&msg->msg_iter, err); |
1168 | } | 1168 | } |
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index b73db2b27656..20df8c1b6851 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c | |||
@@ -571,7 +571,7 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk) | |||
571 | INIT_LIST_HEAD(&ctx->tsgl_list); | 571 | INIT_LIST_HEAD(&ctx->tsgl_list); |
572 | ctx->len = len; | 572 | ctx->len = len; |
573 | ctx->used = 0; | 573 | ctx->used = 0; |
574 | ctx->rcvused = 0; | 574 | atomic_set(&ctx->rcvused, 0); |
575 | ctx->more = 0; | 575 | ctx->more = 0; |
576 | ctx->merge = 0; | 576 | ctx->merge = 0; |
577 | ctx->enc = 0; | 577 | ctx->enc = 0; |
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index baef9bfccdda..c5c47b680152 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c | |||
@@ -390,7 +390,7 @@ static int skcipher_accept_parent_nokey(void *private, struct sock *sk) | |||
390 | INIT_LIST_HEAD(&ctx->tsgl_list); | 390 | INIT_LIST_HEAD(&ctx->tsgl_list); |
391 | ctx->len = len; | 391 | ctx->len = len; |
392 | ctx->used = 0; | 392 | ctx->used = 0; |
393 | ctx->rcvused = 0; | 393 | atomic_set(&ctx->rcvused, 0); |
394 | ctx->more = 0; | 394 | ctx->more = 0; |
395 | ctx->merge = 0; | 395 | ctx->merge = 0; |
396 | ctx->enc = 0; | 396 | ctx->enc = 0; |
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 38d9c5861ed8..f38227a78eae 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/if_alg.h> | 18 | #include <linux/if_alg.h> |
19 | #include <linux/scatterlist.h> | 19 | #include <linux/scatterlist.h> |
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/atomic.h> | ||
21 | #include <net/sock.h> | 22 | #include <net/sock.h> |
22 | 23 | ||
23 | #include <crypto/aead.h> | 24 | #include <crypto/aead.h> |
@@ -150,7 +151,7 @@ struct af_alg_ctx { | |||
150 | struct crypto_wait wait; | 151 | struct crypto_wait wait; |
151 | 152 | ||
152 | size_t used; | 153 | size_t used; |
153 | size_t rcvused; | 154 | atomic_t rcvused; |
154 | 155 | ||
155 | bool more; | 156 | bool more; |
156 | bool merge; | 157 | bool merge; |
@@ -215,7 +216,7 @@ static inline int af_alg_rcvbuf(struct sock *sk) | |||
215 | struct af_alg_ctx *ctx = ask->private; | 216 | struct af_alg_ctx *ctx = ask->private; |
216 | 217 | ||
217 | return max_t(int, max_t(int, sk->sk_rcvbuf & PAGE_MASK, PAGE_SIZE) - | 218 | return max_t(int, max_t(int, sk->sk_rcvbuf & PAGE_MASK, PAGE_SIZE) - |
218 | ctx->rcvused, 0); | 219 | atomic_read(&ctx->rcvused), 0); |
219 | } | 220 | } |
220 | 221 | ||
221 | /** | 222 | /** |