| From 48a992727d82cb7db076fa15d372178743b1f4cd Mon Sep 17 00:00:00 2001 |
| From: tim <tim.c.chen@linux.intel.com> |
| Date: Mon, 5 Dec 2016 11:46:31 -0800 |
| Subject: crypto: mcryptd - Check mcryptd algorithm compatibility |
| |
| From: tim <tim.c.chen@linux.intel.com> |
| |
| commit 48a992727d82cb7db076fa15d372178743b1f4cd upstream. |
| |
| Algorithms not compatible with mcryptd could be spawned by mcryptd |
| with a direct crypto_alloc_tfm invocation using a "mcryptd(alg)" name |
| construct. This causes mcryptd to crash the kernel if an arbitrary |
| "alg" is incompatible and not intended to be used with mcryptd. It is |
| an issue if AF_ALG tries to spawn mcryptd(alg) to expose it externally. |
| But such algorithms must be used internally and not be exposed. |
| |
| We added a check to enforce that only internal algorithms are allowed |
| with mcryptd at the time mcryptd is spawning an algorithm. |
| |
| Link: http://marc.info/?l=linux-crypto-vger&m=148063683310477&w=2 |
| Reported-by: Mikulas Patocka <mpatocka@redhat.com> |
| Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| crypto/mcryptd.c | 19 ++++++++++++------- |
| 1 file changed, 12 insertions(+), 7 deletions(-) |
| |
| --- a/crypto/mcryptd.c |
| +++ b/crypto/mcryptd.c |
| @@ -258,18 +258,22 @@ out_free_inst: |
| goto out; |
| } |
| |
| -static inline void mcryptd_check_internal(struct rtattr **tb, u32 *type, |
| +static inline bool mcryptd_check_internal(struct rtattr **tb, u32 *type, |
| u32 *mask) |
| { |
| struct crypto_attr_type *algt; |
| |
| algt = crypto_get_attr_type(tb); |
| if (IS_ERR(algt)) |
| - return; |
| - if ((algt->type & CRYPTO_ALG_INTERNAL)) |
| - *type |= CRYPTO_ALG_INTERNAL; |
| - if ((algt->mask & CRYPTO_ALG_INTERNAL)) |
| - *mask |= CRYPTO_ALG_INTERNAL; |
| + return false; |
| + |
| + *type |= algt->type & CRYPTO_ALG_INTERNAL; |
| + *mask |= algt->mask & CRYPTO_ALG_INTERNAL; |
| + |
| + if (*type & *mask & CRYPTO_ALG_INTERNAL) |
| + return true; |
| + else |
| + return false; |
| } |
| |
| static int mcryptd_hash_init_tfm(struct crypto_tfm *tfm) |
| @@ -498,7 +502,8 @@ static int mcryptd_create_hash(struct cr |
| u32 mask = 0; |
| int err; |
| |
| - mcryptd_check_internal(tb, &type, &mask); |
| + if (!mcryptd_check_internal(tb, &type, &mask)) |
| + return -EINVAL; |
| |
| salg = shash_attr_alg(tb[1], type, mask); |
| if (IS_ERR(salg)) |