From: Ilya Dryomov <idryomov@gmail.com> stable inclusion from stable-v6.6.128 commit e1dc45d97975f9db65694d234fbddf1915176e16 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14861 CVE: CVE-2026-43304 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit ac431d597a9bdfc2ba6b314813f29a6ef2b4a3bf ] When decoding the key, verify that the key material would fit into a fixed-size buffer in process_auth_done() and generally has a sane length. The new CEPH_MAX_KEY_LEN check replaces the existing check for a key with no key material which is a) not universal since CEPH_CRYPTO_NONE has to be excluded and b) doesn't provide much value since a smaller than needed key is just as invalid as no key -- this has to be handled elsewhere anyway. Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Zhang Qilong <zhangqilong3@huawei.com> --- net/ceph/crypto.c | 8 +++++--- net/ceph/crypto.h | 2 +- net/ceph/messenger_v2.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 051d22c0e4ad..3397d105f74f 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -35,13 +35,10 @@ static int set_secret(struct ceph_crypto_key *key, void *buf) break; default: return -ENOTSUPP; } - if (!key->len) - return -EINVAL; - key->key = kmemdup(buf, key->len, GFP_NOIO); if (!key->key) { ret = -ENOMEM; goto fail; } @@ -93,10 +90,15 @@ int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end) ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad); key->type = ceph_decode_16(p); ceph_decode_copy(p, &key->created, sizeof(key->created)); key->len = ceph_decode_16(p); ceph_decode_need(p, end, key->len, bad); + if (key->len > CEPH_MAX_KEY_LEN) { + pr_err("secret too big %d\n", key->len); + return -EINVAL; + } + ret = set_secret(key, *p); memzero_explicit(*p, key->len); *p += key->len; return ret; diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index 13bd526349fa..0d32f1649f3d 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h @@ -3,11 +3,11 @@ #define _FS_CEPH_CRYPTO_H #include <linux/ceph/types.h> #include <linux/ceph/buffer.h> -#define CEPH_KEY_LEN 16 +#define CEPH_MAX_KEY_LEN 16 #define CEPH_MAX_CON_SECRET_LEN 64 /* * cryptographic secret */ diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c index 858198724439..f82029bd33db 100644 --- a/net/ceph/messenger_v2.c +++ b/net/ceph/messenger_v2.c @@ -2391,11 +2391,11 @@ static int process_auth_reply_more(struct ceph_connection *con, * setup_crypto(). __aligned(16) isn't guaranteed to work for stack * objects, so do it by hand. */ static int process_auth_done(struct ceph_connection *con, void *p, void *end) { - u8 session_key_buf[CEPH_KEY_LEN + 16]; + u8 session_key_buf[CEPH_MAX_KEY_LEN + 16]; u8 con_secret_buf[CEPH_MAX_CON_SECRET_LEN + 16]; u8 *session_key = PTR_ALIGN(&session_key_buf[0], 16); u8 *con_secret = PTR_ALIGN(&con_secret_buf[0], 16); int session_key_len, con_secret_len; int payload_len; -- 2.43.0