crypto: af_alg - Fix race around ctx->rcvused by making it atomic_t
[ Upstream commitpull/10/headaf955bf15d
] 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:7d2c3f54e6
("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> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
parent
99b329b461
commit
36d0a678fb
|
@ -693,7 +693,7 @@ void af_alg_free_areq_sgls(struct af_alg_async_req *areq)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
list_for_each_entry_safe(rsgl, tmp, &areq->rsgl_list, list) {
|
list_for_each_entry_safe(rsgl, tmp, &areq->rsgl_list, list) {
|
||||||
ctx->rcvused -= rsgl->sg_num_bytes;
|
atomic_sub(rsgl->sg_num_bytes, &ctx->rcvused);
|
||||||
af_alg_free_sg(&rsgl->sgl);
|
af_alg_free_sg(&rsgl->sgl);
|
||||||
list_del(&rsgl->list);
|
list_del(&rsgl->list);
|
||||||
if (rsgl != &areq->first_rsgl)
|
if (rsgl != &areq->first_rsgl)
|
||||||
|
@ -1192,7 +1192,7 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
|
||||||
|
|
||||||
areq->last_rsgl = rsgl;
|
areq->last_rsgl = rsgl;
|
||||||
len += err;
|
len += err;
|
||||||
ctx->rcvused += err;
|
atomic_add(err, &ctx->rcvused);
|
||||||
rsgl->sg_num_bytes = err;
|
rsgl->sg_num_bytes = err;
|
||||||
iov_iter_advance(&msg->msg_iter, err);
|
iov_iter_advance(&msg->msg_iter, err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -571,7 +571,7 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk)
|
||||||
INIT_LIST_HEAD(&ctx->tsgl_list);
|
INIT_LIST_HEAD(&ctx->tsgl_list);
|
||||||
ctx->len = len;
|
ctx->len = len;
|
||||||
ctx->used = 0;
|
ctx->used = 0;
|
||||||
ctx->rcvused = 0;
|
atomic_set(&ctx->rcvused, 0);
|
||||||
ctx->more = 0;
|
ctx->more = 0;
|
||||||
ctx->merge = 0;
|
ctx->merge = 0;
|
||||||
ctx->enc = 0;
|
ctx->enc = 0;
|
||||||
|
|
|
@ -391,7 +391,7 @@ static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
|
||||||
INIT_LIST_HEAD(&ctx->tsgl_list);
|
INIT_LIST_HEAD(&ctx->tsgl_list);
|
||||||
ctx->len = len;
|
ctx->len = len;
|
||||||
ctx->used = 0;
|
ctx->used = 0;
|
||||||
ctx->rcvused = 0;
|
atomic_set(&ctx->rcvused, 0);
|
||||||
ctx->more = 0;
|
ctx->more = 0;
|
||||||
ctx->merge = 0;
|
ctx->merge = 0;
|
||||||
ctx->enc = 0;
|
ctx->enc = 0;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/if_alg.h>
|
#include <linux/if_alg.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/atomic.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
|
||||||
#include <crypto/aead.h>
|
#include <crypto/aead.h>
|
||||||
|
@ -155,7 +156,7 @@ struct af_alg_ctx {
|
||||||
struct af_alg_completion completion;
|
struct af_alg_completion completion;
|
||||||
|
|
||||||
size_t used;
|
size_t used;
|
||||||
size_t rcvused;
|
atomic_t rcvused;
|
||||||
|
|
||||||
bool more;
|
bool more;
|
||||||
bool merge;
|
bool merge;
|
||||||
|
@ -228,7 +229,7 @@ static inline int af_alg_rcvbuf(struct sock *sk)
|
||||||
struct af_alg_ctx *ctx = ask->private;
|
struct af_alg_ctx *ctx = ask->private;
|
||||||
|
|
||||||
return max_t(int, max_t(int, sk->sk_rcvbuf & PAGE_MASK, PAGE_SIZE) -
|
return max_t(int, max_t(int, sk->sk_rcvbuf & PAGE_MASK, PAGE_SIZE) -
|
||||||
ctx->rcvused, 0);
|
atomic_read(&ctx->rcvused), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue