Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto fixes from Herbert Xu: "This fixes the following problems: - regression in new XTS/LRW code when used with async crypto - long-standing bug in ahash API when used with certain algos - bogus memory dereference in async algif_aead with certain algos" * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: crypto: algif_aead - Fix bogus request dereference in completion function crypto: ahash - Fix EINPROGRESS notification callback crypto: lrw - Fix use-after-free on EINPROGRESS crypto: xts - Fix use-after-free on EINPROGRESS
This commit is contained in:
commit
5ee4c5a929
|
@ -32,6 +32,7 @@ struct ahash_request_priv {
|
|||
crypto_completion_t complete;
|
||||
void *data;
|
||||
u8 *result;
|
||||
u32 flags;
|
||||
void *ubuf[] CRYPTO_MINALIGN_ATTR;
|
||||
};
|
||||
|
||||
|
@ -253,6 +254,8 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
|
|||
priv->result = req->result;
|
||||
priv->complete = req->base.complete;
|
||||
priv->data = req->base.data;
|
||||
priv->flags = req->base.flags;
|
||||
|
||||
/*
|
||||
* WARNING: We do not backup req->priv here! The req->priv
|
||||
* is for internal use of the Crypto API and the
|
||||
|
@ -267,38 +270,44 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ahash_restore_req(struct ahash_request *req)
|
||||
static void ahash_restore_req(struct ahash_request *req, int err)
|
||||
{
|
||||
struct ahash_request_priv *priv = req->priv;
|
||||
|
||||
if (!err)
|
||||
memcpy(priv->result, req->result,
|
||||
crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
|
||||
|
||||
/* Restore the original crypto request. */
|
||||
req->result = priv->result;
|
||||
req->base.complete = priv->complete;
|
||||
req->base.data = priv->data;
|
||||
|
||||
ahash_request_set_callback(req, priv->flags,
|
||||
priv->complete, priv->data);
|
||||
req->priv = NULL;
|
||||
|
||||
/* Free the req->priv.priv from the ADJUSTED request. */
|
||||
kzfree(priv);
|
||||
}
|
||||
|
||||
static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
|
||||
static void ahash_notify_einprogress(struct ahash_request *req)
|
||||
{
|
||||
struct ahash_request_priv *priv = req->priv;
|
||||
struct crypto_async_request oreq;
|
||||
|
||||
if (err == -EINPROGRESS)
|
||||
return;
|
||||
oreq.data = priv->data;
|
||||
|
||||
if (!err)
|
||||
memcpy(priv->result, req->result,
|
||||
crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
|
||||
|
||||
ahash_restore_req(req);
|
||||
priv->complete(&oreq, -EINPROGRESS);
|
||||
}
|
||||
|
||||
static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
|
||||
{
|
||||
struct ahash_request *areq = req->data;
|
||||
|
||||
if (err == -EINPROGRESS) {
|
||||
ahash_notify_einprogress(areq);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the original request, see ahash_op_unaligned() for what
|
||||
* goes where.
|
||||
|
@ -309,7 +318,7 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
|
|||
*/
|
||||
|
||||
/* First copy req->result into req->priv.result */
|
||||
ahash_op_unaligned_finish(areq, err);
|
||||
ahash_restore_req(areq, err);
|
||||
|
||||
/* Complete the ORIGINAL request. */
|
||||
areq->base.complete(&areq->base, err);
|
||||
|
@ -325,7 +334,12 @@ static int ahash_op_unaligned(struct ahash_request *req,
|
|||
return err;
|
||||
|
||||
err = op(req);
|
||||
ahash_op_unaligned_finish(req, err);
|
||||
if (err == -EINPROGRESS ||
|
||||
(err == -EBUSY && (ahash_request_flags(req) &
|
||||
CRYPTO_TFM_REQ_MAY_BACKLOG)))
|
||||
return err;
|
||||
|
||||
ahash_restore_req(req, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -360,25 +374,14 @@ int crypto_ahash_digest(struct ahash_request *req)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_ahash_digest);
|
||||
|
||||
static void ahash_def_finup_finish2(struct ahash_request *req, int err)
|
||||
{
|
||||
struct ahash_request_priv *priv = req->priv;
|
||||
|
||||
if (err == -EINPROGRESS)
|
||||
return;
|
||||
|
||||
if (!err)
|
||||
memcpy(priv->result, req->result,
|
||||
crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
|
||||
|
||||
ahash_restore_req(req);
|
||||
}
|
||||
|
||||
static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
|
||||
{
|
||||
struct ahash_request *areq = req->data;
|
||||
|
||||
ahash_def_finup_finish2(areq, err);
|
||||
if (err == -EINPROGRESS)
|
||||
return;
|
||||
|
||||
ahash_restore_req(areq, err);
|
||||
|
||||
areq->base.complete(&areq->base, err);
|
||||
}
|
||||
|
@ -389,11 +392,15 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err)
|
|||
goto out;
|
||||
|
||||
req->base.complete = ahash_def_finup_done2;
|
||||
req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
err = crypto_ahash_reqtfm(req)->final(req);
|
||||
if (err == -EINPROGRESS ||
|
||||
(err == -EBUSY && (ahash_request_flags(req) &
|
||||
CRYPTO_TFM_REQ_MAY_BACKLOG)))
|
||||
return err;
|
||||
|
||||
out:
|
||||
ahash_def_finup_finish2(req, err);
|
||||
ahash_restore_req(req, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -401,7 +408,16 @@ static void ahash_def_finup_done1(struct crypto_async_request *req, int err)
|
|||
{
|
||||
struct ahash_request *areq = req->data;
|
||||
|
||||
if (err == -EINPROGRESS) {
|
||||
ahash_notify_einprogress(areq);
|
||||
return;
|
||||
}
|
||||
|
||||
areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
err = ahash_def_finup_finish1(areq, err);
|
||||
if (areq->priv)
|
||||
return;
|
||||
|
||||
areq->base.complete(&areq->base, err);
|
||||
}
|
||||
|
@ -416,6 +432,11 @@ static int ahash_def_finup(struct ahash_request *req)
|
|||
return err;
|
||||
|
||||
err = tfm->update(req);
|
||||
if (err == -EINPROGRESS ||
|
||||
(err == -EBUSY && (ahash_request_flags(req) &
|
||||
CRYPTO_TFM_REQ_MAY_BACKLOG)))
|
||||
return err;
|
||||
|
||||
return ahash_def_finup_finish1(req, err);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ struct aead_async_req {
|
|||
struct aead_async_rsgl first_rsgl;
|
||||
struct list_head list;
|
||||
struct kiocb *iocb;
|
||||
struct sock *sk;
|
||||
unsigned int tsgls;
|
||||
char iv[];
|
||||
};
|
||||
|
@ -379,12 +380,10 @@ unlock:
|
|||
|
||||
static void aead_async_cb(struct crypto_async_request *_req, int err)
|
||||
{
|
||||
struct sock *sk = _req->data;
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct aead_ctx *ctx = ask->private;
|
||||
struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req);
|
||||
struct aead_request *req = aead_request_cast(_req);
|
||||
struct aead_request *req = _req->data;
|
||||
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
|
||||
struct aead_async_req *areq = GET_ASYM_REQ(req, tfm);
|
||||
struct sock *sk = areq->sk;
|
||||
struct scatterlist *sg = areq->tsgl;
|
||||
struct aead_async_rsgl *rsgl;
|
||||
struct kiocb *iocb = areq->iocb;
|
||||
|
@ -447,11 +446,12 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
|
|||
memset(&areq->first_rsgl, '\0', sizeof(areq->first_rsgl));
|
||||
INIT_LIST_HEAD(&areq->list);
|
||||
areq->iocb = msg->msg_iocb;
|
||||
areq->sk = sk;
|
||||
memcpy(areq->iv, ctx->iv, crypto_aead_ivsize(tfm));
|
||||
aead_request_set_tfm(req, tfm);
|
||||
aead_request_set_ad(req, ctx->aead_assoclen);
|
||||
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
||||
aead_async_cb, sk);
|
||||
aead_async_cb, req);
|
||||
used -= ctx->aead_assoclen;
|
||||
|
||||
/* take over all tx sgls from ctx */
|
||||
|
|
16
crypto/lrw.c
16
crypto/lrw.c
|
@ -345,6 +345,13 @@ static void encrypt_done(struct crypto_async_request *areq, int err)
|
|||
struct rctx *rctx;
|
||||
|
||||
rctx = skcipher_request_ctx(req);
|
||||
|
||||
if (err == -EINPROGRESS) {
|
||||
if (rctx->left != req->cryptlen)
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
subreq = &rctx->subreq;
|
||||
subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
|
||||
|
||||
|
@ -352,6 +359,7 @@ static void encrypt_done(struct crypto_async_request *areq, int err)
|
|||
if (rctx->left)
|
||||
return;
|
||||
|
||||
out:
|
||||
skcipher_request_complete(req, err);
|
||||
}
|
||||
|
||||
|
@ -389,6 +397,13 @@ static void decrypt_done(struct crypto_async_request *areq, int err)
|
|||
struct rctx *rctx;
|
||||
|
||||
rctx = skcipher_request_ctx(req);
|
||||
|
||||
if (err == -EINPROGRESS) {
|
||||
if (rctx->left != req->cryptlen)
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
subreq = &rctx->subreq;
|
||||
subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
|
||||
|
||||
|
@ -396,6 +411,7 @@ static void decrypt_done(struct crypto_async_request *areq, int err)
|
|||
if (rctx->left)
|
||||
return;
|
||||
|
||||
out:
|
||||
skcipher_request_complete(req, err);
|
||||
}
|
||||
|
||||
|
|
16
crypto/xts.c
16
crypto/xts.c
|
@ -286,6 +286,13 @@ static void encrypt_done(struct crypto_async_request *areq, int err)
|
|||
struct rctx *rctx;
|
||||
|
||||
rctx = skcipher_request_ctx(req);
|
||||
|
||||
if (err == -EINPROGRESS) {
|
||||
if (rctx->left != req->cryptlen)
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
subreq = &rctx->subreq;
|
||||
subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
|
||||
|
||||
|
@ -293,6 +300,7 @@ static void encrypt_done(struct crypto_async_request *areq, int err)
|
|||
if (rctx->left)
|
||||
return;
|
||||
|
||||
out:
|
||||
skcipher_request_complete(req, err);
|
||||
}
|
||||
|
||||
|
@ -330,6 +338,13 @@ static void decrypt_done(struct crypto_async_request *areq, int err)
|
|||
struct rctx *rctx;
|
||||
|
||||
rctx = skcipher_request_ctx(req);
|
||||
|
||||
if (err == -EINPROGRESS) {
|
||||
if (rctx->left != req->cryptlen)
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
subreq = &rctx->subreq;
|
||||
subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
|
||||
|
||||
|
@ -337,6 +352,7 @@ static void decrypt_done(struct crypto_async_request *areq, int err)
|
|||
if (rctx->left)
|
||||
return;
|
||||
|
||||
out:
|
||||
skcipher_request_complete(req, err);
|
||||
}
|
||||
|
||||
|
|
|
@ -166,6 +166,16 @@ static inline struct ahash_instance *ahash_alloc_instance(
|
|||
return crypto_alloc_instance2(name, alg, ahash_instance_headroom());
|
||||
}
|
||||
|
||||
static inline void ahash_request_complete(struct ahash_request *req, int err)
|
||||
{
|
||||
req->base.complete(&req->base, err);
|
||||
}
|
||||
|
||||
static inline u32 ahash_request_flags(struct ahash_request *req)
|
||||
{
|
||||
return req->base.flags;
|
||||
}
|
||||
|
||||
static inline struct crypto_ahash *crypto_spawn_ahash(
|
||||
struct crypto_ahash_spawn *spawn)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue