| From 09d05a45400cf89fa93369a5802cd7e06c8619e0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 10 Jun 2021 08:21:50 +0200 |
| Subject: crypto: shash - avoid comparing pointers to exported functions under |
| CFI |
| |
| From: Ard Biesheuvel <ardb@kernel.org> |
| |
| [ Upstream commit 22ca9f4aaf431a9413dcc115dd590123307f274f ] |
| |
| crypto_shash_alg_has_setkey() is implemented by testing whether the |
| .setkey() member of a struct shash_alg points to the default version, |
| called shash_no_setkey(). As crypto_shash_alg_has_setkey() is a static |
| inline, this requires shash_no_setkey() to be exported to modules. |
| |
| Unfortunately, when building with CFI, function pointers are routed |
| via CFI stubs which are private to each module (or to the kernel proper) |
| and so this function pointer comparison may fail spuriously. |
| |
| Let's fix this by turning crypto_shash_alg_has_setkey() into an out of |
| line function. |
| |
| Cc: Sami Tolvanen <samitolvanen@google.com> |
| Cc: Eric Biggers <ebiggers@kernel.org> |
| Signed-off-by: Ard Biesheuvel <ardb@kernel.org> |
| Reviewed-by: Eric Biggers <ebiggers@google.com> |
| Reviewed-by: Sami Tolvanen <samitolvanen@google.com> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| crypto/shash.c | 18 +++++++++++++++--- |
| include/crypto/internal/hash.h | 8 +------- |
| 2 files changed, 16 insertions(+), 10 deletions(-) |
| |
| diff --git a/crypto/shash.c b/crypto/shash.c |
| index 2e3433ad9762..0a0a50cb694f 100644 |
| --- a/crypto/shash.c |
| +++ b/crypto/shash.c |
| @@ -20,12 +20,24 @@ |
| |
| static const struct crypto_type crypto_shash_type; |
| |
| -int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, |
| - unsigned int keylen) |
| +static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, |
| + unsigned int keylen) |
| { |
| return -ENOSYS; |
| } |
| -EXPORT_SYMBOL_GPL(shash_no_setkey); |
| + |
| +/* |
| + * Check whether an shash algorithm has a setkey function. |
| + * |
| + * For CFI compatibility, this must not be an inline function. This is because |
| + * when CFI is enabled, modules won't get the same address for shash_no_setkey |
| + * (if it were exported, which inlining would require) as the core kernel will. |
| + */ |
| +bool crypto_shash_alg_has_setkey(struct shash_alg *alg) |
| +{ |
| + return alg->setkey != shash_no_setkey; |
| +} |
| +EXPORT_SYMBOL_GPL(crypto_shash_alg_has_setkey); |
| |
| static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, |
| unsigned int keylen) |
| diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h |
| index 0a288dddcf5b..25806141db59 100644 |
| --- a/include/crypto/internal/hash.h |
| +++ b/include/crypto/internal/hash.h |
| @@ -75,13 +75,7 @@ void crypto_unregister_ahashes(struct ahash_alg *algs, int count); |
| int ahash_register_instance(struct crypto_template *tmpl, |
| struct ahash_instance *inst); |
| |
| -int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, |
| - unsigned int keylen); |
| - |
| -static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) |
| -{ |
| - return alg->setkey != shash_no_setkey; |
| -} |
| +bool crypto_shash_alg_has_setkey(struct shash_alg *alg); |
| |
| static inline bool crypto_shash_alg_needs_key(struct shash_alg *alg) |
| { |
| -- |
| 2.30.2 |
| |