crypto: algif_skcipher - Do not assume that req is unchanged
The async path in algif_skcipher assumes that the crypto completion function will be called with the original request. This is not necessarily the case. In fact there is no need for this anyway since we already embed information into the request with struct skcipher_async_req. This patch adds a pointer to that struct and then passes it as the data to the callback function. Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Tested-by: Tadeusz Struk <tadeusz.struk@intel.com>
This commit is contained in:
parent
63e41ebc66
commit
ec69bbfb99
1 changed files with 30 additions and 34 deletions
|
@ -65,18 +65,10 @@ struct skcipher_async_req {
|
||||||
struct skcipher_async_rsgl first_sgl;
|
struct skcipher_async_rsgl first_sgl;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct scatterlist *tsg;
|
struct scatterlist *tsg;
|
||||||
char iv[];
|
atomic_t *inflight;
|
||||||
|
struct skcipher_request req;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_SREQ(areq, ctx) (struct skcipher_async_req *)((char *)areq + \
|
|
||||||
crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req)))
|
|
||||||
|
|
||||||
#define GET_REQ_SIZE(ctx) \
|
|
||||||
crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req))
|
|
||||||
|
|
||||||
#define GET_IV_SIZE(ctx) \
|
|
||||||
crypto_skcipher_ivsize(crypto_skcipher_reqtfm(&ctx->req))
|
|
||||||
|
|
||||||
#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
|
#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
|
||||||
sizeof(struct scatterlist) - 1)
|
sizeof(struct scatterlist) - 1)
|
||||||
|
|
||||||
|
@ -102,15 +94,12 @@ static void skcipher_free_async_sgls(struct skcipher_async_req *sreq)
|
||||||
|
|
||||||
static void skcipher_async_cb(struct crypto_async_request *req, int err)
|
static void skcipher_async_cb(struct crypto_async_request *req, int err)
|
||||||
{
|
{
|
||||||
struct sock *sk = req->data;
|
struct skcipher_async_req *sreq = req->data;
|
||||||
struct alg_sock *ask = alg_sk(sk);
|
|
||||||
struct skcipher_ctx *ctx = ask->private;
|
|
||||||
struct skcipher_async_req *sreq = GET_SREQ(req, ctx);
|
|
||||||
struct kiocb *iocb = sreq->iocb;
|
struct kiocb *iocb = sreq->iocb;
|
||||||
|
|
||||||
atomic_dec(&ctx->inflight);
|
atomic_dec(sreq->inflight);
|
||||||
skcipher_free_async_sgls(sreq);
|
skcipher_free_async_sgls(sreq);
|
||||||
kfree(req);
|
kzfree(sreq);
|
||||||
iocb->ki_complete(iocb, err, err);
|
iocb->ki_complete(iocb, err, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,37 +498,42 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
struct alg_sock *ask = alg_sk(sk);
|
struct alg_sock *ask = alg_sk(sk);
|
||||||
|
struct sock *psk = ask->parent;
|
||||||
|
struct alg_sock *pask = alg_sk(psk);
|
||||||
struct skcipher_ctx *ctx = ask->private;
|
struct skcipher_ctx *ctx = ask->private;
|
||||||
|
struct skcipher_tfm *skc = pask->private;
|
||||||
|
struct crypto_skcipher *tfm = skc->skcipher;
|
||||||
struct skcipher_sg_list *sgl;
|
struct skcipher_sg_list *sgl;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
struct skcipher_async_req *sreq;
|
struct skcipher_async_req *sreq;
|
||||||
struct skcipher_request *req;
|
struct skcipher_request *req;
|
||||||
struct skcipher_async_rsgl *last_rsgl = NULL;
|
struct skcipher_async_rsgl *last_rsgl = NULL;
|
||||||
unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
|
unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
|
||||||
unsigned int reqlen = sizeof(struct skcipher_async_req) +
|
unsigned int reqsize = crypto_skcipher_reqsize(tfm);
|
||||||
GET_REQ_SIZE(ctx) + GET_IV_SIZE(ctx);
|
unsigned int ivsize = crypto_skcipher_ivsize(tfm);
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
bool mark = false;
|
bool mark = false;
|
||||||
|
char *iv;
|
||||||
|
|
||||||
|
sreq = kzalloc(sizeof(*sreq) + reqsize + ivsize, GFP_KERNEL);
|
||||||
|
if (unlikely(!sreq))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
req = &sreq->req;
|
||||||
|
iv = (char *)(req + 1) + reqsize;
|
||||||
|
sreq->iocb = msg->msg_iocb;
|
||||||
|
INIT_LIST_HEAD(&sreq->list);
|
||||||
|
sreq->inflight = &ctx->inflight;
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
req = kmalloc(reqlen, GFP_KERNEL);
|
|
||||||
if (unlikely(!req))
|
|
||||||
goto unlock;
|
|
||||||
|
|
||||||
sreq = GET_SREQ(req, ctx);
|
|
||||||
sreq->iocb = msg->msg_iocb;
|
|
||||||
memset(&sreq->first_sgl, '\0', sizeof(struct skcipher_async_rsgl));
|
|
||||||
INIT_LIST_HEAD(&sreq->list);
|
|
||||||
sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
|
sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
|
||||||
if (unlikely(!sreq->tsg)) {
|
if (unlikely(!sreq->tsg))
|
||||||
kfree(req);
|
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
|
||||||
sg_init_table(sreq->tsg, tx_nents);
|
sg_init_table(sreq->tsg, tx_nents);
|
||||||
memcpy(sreq->iv, ctx->iv, GET_IV_SIZE(ctx));
|
memcpy(iv, ctx->iv, ivsize);
|
||||||
skcipher_request_set_tfm(req, crypto_skcipher_reqtfm(&ctx->req));
|
skcipher_request_set_tfm(req, tfm);
|
||||||
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
||||||
skcipher_async_cb, sk);
|
skcipher_async_cb, sreq);
|
||||||
|
|
||||||
while (iov_iter_count(&msg->msg_iter)) {
|
while (iov_iter_count(&msg->msg_iter)) {
|
||||||
struct skcipher_async_rsgl *rsgl;
|
struct skcipher_async_rsgl *rsgl;
|
||||||
|
@ -615,20 +609,22 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
|
||||||
sg_mark_end(sreq->tsg + txbufs - 1);
|
sg_mark_end(sreq->tsg + txbufs - 1);
|
||||||
|
|
||||||
skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
|
skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
|
||||||
len, sreq->iv);
|
len, iv);
|
||||||
err = ctx->enc ? crypto_skcipher_encrypt(req) :
|
err = ctx->enc ? crypto_skcipher_encrypt(req) :
|
||||||
crypto_skcipher_decrypt(req);
|
crypto_skcipher_decrypt(req);
|
||||||
if (err == -EINPROGRESS) {
|
if (err == -EINPROGRESS) {
|
||||||
atomic_inc(&ctx->inflight);
|
atomic_inc(&ctx->inflight);
|
||||||
err = -EIOCBQUEUED;
|
err = -EIOCBQUEUED;
|
||||||
|
sreq = NULL;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
free:
|
free:
|
||||||
skcipher_free_async_sgls(sreq);
|
skcipher_free_async_sgls(sreq);
|
||||||
kfree(req);
|
|
||||||
unlock:
|
unlock:
|
||||||
skcipher_wmem_wakeup(sk);
|
skcipher_wmem_wakeup(sk);
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
|
kzfree(sreq);
|
||||||
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue