| From herbert@gondor.apana.org.au Wed Sep 3 08:39:23 2008 |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| Date: Sat, 23 Aug 2008 09:36:17 +1000 |
| Subject: crypto: authenc - Avoid using clobbered request pointer |
| To: stable@kernel.org |
| Message-ID: <20080822233617.GA5309@gondor.apana.org.au> |
| Content-Disposition: inline |
| |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| |
| crypto: authenc - Avoid using clobbered request pointer |
| |
| [ Upstream commit: a697690bece75d4ba424c1318eb25c37d41d5829 ] |
| |
| Authenc works in two stages for encryption, it first encrypts and |
| then computes an ICV. The context memory of the request is used |
| by both operations. The problem is that when an asynchronous |
| encryption completes, we will compute the ICV and then reread the |
| context memory of the encryption to get the original request. |
| |
| It just happens that we have a buffer of 16 bytes in front of the |
| request pointer, so ICVs of 16 bytes (such as SHA1) do not trigger |
| the bug. However, any attempt to uses a larger ICV instantly kills |
| the machine when the first asynchronous encryption is completed. |
| |
| This patch fixes this by saving the request pointer before we start |
| the ICV computation. |
| |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| crypto/authenc.c | 10 ++++++---- |
| 1 file changed, 6 insertions(+), 4 deletions(-) |
| |
| --- a/crypto/authenc.c |
| +++ b/crypto/authenc.c |
| @@ -174,8 +174,9 @@ static int crypto_authenc_genicv(struct |
| static void crypto_authenc_encrypt_done(struct crypto_async_request *req, |
| int err) |
| { |
| + struct aead_request *areq = req->data; |
| + |
| if (!err) { |
| - struct aead_request *areq = req->data; |
| struct crypto_aead *authenc = crypto_aead_reqtfm(areq); |
| struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
| struct ablkcipher_request *abreq = aead_request_ctx(areq); |
| @@ -185,7 +186,7 @@ static void crypto_authenc_encrypt_done( |
| err = crypto_authenc_genicv(areq, iv, 0); |
| } |
| |
| - aead_request_complete(req->data, err); |
| + aead_request_complete(areq, err); |
| } |
| |
| static int crypto_authenc_encrypt(struct aead_request *req) |
| @@ -216,14 +217,15 @@ static int crypto_authenc_encrypt(struct |
| static void crypto_authenc_givencrypt_done(struct crypto_async_request *req, |
| int err) |
| { |
| + struct aead_request *areq = req->data; |
| + |
| if (!err) { |
| - struct aead_request *areq = req->data; |
| struct skcipher_givcrypt_request *greq = aead_request_ctx(areq); |
| |
| err = crypto_authenc_genicv(areq, greq->giv, 0); |
| } |
| |
| - aead_request_complete(req->data, err); |
| + aead_request_complete(areq, err); |
| } |
| |
| static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req) |