diff mbox

[1/3] crypto: ensure algif_hash does not pass a zero-sized state

Message ID E1ZkUvo-0004QO-U8@rmk-PC.arm.linux.org.uk (mailing list archive)
State Superseded
Delegated to: Herbert Xu
Headers show

Commit Message

Russell King Oct. 9, 2015, 10:29 a.m. UTC
If the algorithm passed a zero statesize, do not pass a valid pointer
into the export/import functions.  Passing a valid pointer covers up
bugs in driver code which then go on to smash the kernel stack.
Instead, pass NULL, which will cause any attempt to write to the
pointer to fail.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 crypto/algif_hash.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Comments

Herbert Xu Oct. 9, 2015, 10:34 a.m. UTC | #1
On Fri, Oct 09, 2015 at 11:29:44AM +0100, Russell King wrote:
> If the algorithm passed a zero statesize, do not pass a valid pointer
> into the export/import functions.  Passing a valid pointer covers up
> bugs in driver code which then go on to smash the kernel stack.
> Instead, pass NULL, which will cause any attempt to write to the
> pointer to fail.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

The state size should never be zero for a hash algorithm.  Having
a zero state means that the hash output must always be identical.
Such an algorithm would be quite useless.

So how about adding a check upon hash registration to verify that
the state size is greater than zero? The place to do it would be
shash_prepare_alg and ahash_prepare_alg.

Thanks,
diff mbox

Patch

diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 1396ad0787fc..f450584cb940 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -177,12 +177,16 @@  static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
 	struct alg_sock *ask = alg_sk(sk);
 	struct hash_ctx *ctx = ask->private;
 	struct ahash_request *req = &ctx->req;
-	char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req))];
+	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+	unsigned int state_size = crypto_ahash_statesize(ahash);
+	char state_buf[state_size], *state;
 	struct sock *sk2;
 	struct alg_sock *ask2;
 	struct hash_ctx *ctx2;
 	int err;
 
+	state = state_size ? state_buf : NULL;
+
 	err = crypto_ahash_export(req, state);
 	if (err)
 		return err;