From ee8c85ceda4f76fc758de39b80a27449a8922186 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 15 Jul 2026 12:21:41 +0200 Subject: [PATCH] 5.15-stable patches added patches: crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps-again.patch crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps.patch crypto-drbg-fix-drbg_max_addtl-on-64-bit-kernels.patch crypto-drbg-fix-returning-success-on-failure-in-ctr_drbg.patch crypto-drbg-fix-the-fips_enabled-priority-boost.patch crypto-ecc-fix-carry-overflow-in-vli-multiplication.patch crypto-pcrypt-restore-callback-for-non-parallel-fallback.patch dm-ioctl-report-an-error-if-a-device-has-no-table.patch isofs-bound-rock-ridge-symlink-components-to-the-sl-record.patch nvme-multipath-set-bio_remapped-on-bios-remapped-to-per-path-namespace-disks.patch partitions-aix-bound-the-pp_count-scan-to-the-ppe-array.patch udf-validate-free-block-extents-against-the-partition-length.patch udf-validate-sparing-table-length-as-an-entry-count-not-a-byte-count.patch udf-validate-vat-header-length-against-the-vat-inode-size.patch --- ...p_devel-to-guard-key-hex-dumps-again.patch | 79 ++++++++ ...ex_dump_devel-to-guard-key-hex-dumps.patch | 177 ++++++++++++++++++ ...fix-drbg_max_addtl-on-64-bit-kernels.patch | 60 ++++++ ...rning-success-on-failure-in-ctr_drbg.patch | 32 ++++ ...-fix-the-fips_enabled-priority-boost.patch | 39 ++++ ...carry-overflow-in-vli-multiplication.patch | 98 ++++++++++ ...e-callback-for-non-parallel-fallback.patch | 57 ++++++ ...rt-an-error-if-a-device-has-no-table.patch | 35 ++++ ...-symlink-components-to-the-sl-record.patch | 74 ++++++++ ...remapped-to-per-path-namespace-disks.patch | 88 +++++++++ ...d-the-pp_count-scan-to-the-ppe-array.patch | 62 ++++++ queue-5.15/series | 14 ++ ...extents-against-the-partition-length.patch | 65 +++++++ ...h-as-an-entry-count-not-a-byte-count.patch | 57 ++++++ ...er-length-against-the-vat-inode-size.patch | 60 ++++++ 15 files changed, 997 insertions(+) create mode 100644 queue-5.15/crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps-again.patch create mode 100644 queue-5.15/crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps.patch create mode 100644 queue-5.15/crypto-drbg-fix-drbg_max_addtl-on-64-bit-kernels.patch create mode 100644 queue-5.15/crypto-drbg-fix-returning-success-on-failure-in-ctr_drbg.patch create mode 100644 queue-5.15/crypto-drbg-fix-the-fips_enabled-priority-boost.patch create mode 100644 queue-5.15/crypto-ecc-fix-carry-overflow-in-vli-multiplication.patch create mode 100644 queue-5.15/crypto-pcrypt-restore-callback-for-non-parallel-fallback.patch create mode 100644 queue-5.15/dm-ioctl-report-an-error-if-a-device-has-no-table.patch create mode 100644 queue-5.15/isofs-bound-rock-ridge-symlink-components-to-the-sl-record.patch create mode 100644 queue-5.15/nvme-multipath-set-bio_remapped-on-bios-remapped-to-per-path-namespace-disks.patch create mode 100644 queue-5.15/partitions-aix-bound-the-pp_count-scan-to-the-ppe-array.patch create mode 100644 queue-5.15/udf-validate-free-block-extents-against-the-partition-length.patch create mode 100644 queue-5.15/udf-validate-sparing-table-length-as-an-entry-count-not-a-byte-count.patch create mode 100644 queue-5.15/udf-validate-vat-header-length-against-the-vat-inode-size.patch diff --git a/queue-5.15/crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps-again.patch b/queue-5.15/crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps-again.patch new file mode 100644 index 0000000000..159045e234 --- /dev/null +++ b/queue-5.15/crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps-again.patch @@ -0,0 +1,79 @@ +From 8005dc808bcce7d6cc2ae015a3cde1683bee602d Mon Sep 17 00:00:00 2001 +From: Thorsten Blum +Date: Mon, 27 Apr 2026 18:39:39 +0200 +Subject: crypto: caam - use print_hex_dump_devel to guard key hex dumps again + +From: Thorsten Blum + +commit 8005dc808bcce7d6cc2ae015a3cde1683bee602d upstream. + +Use print_hex_dump_devel() for dumping sensitive key material in +*_setkey() to avoid leaking secrets at runtime when CONFIG_DYNAMIC_DEBUG +is enabled. + +Fixes: 8d818c105501 ("crypto: caam/qi2 - add DPAA2-CAAM driver") +Fixes: 226853ac3ebe ("crypto: caam/qi2 - add skcipher algorithms") +Cc: stable@vger.kernel.org +Signed-off-by: Thorsten Blum +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/caam/caamalg_qi2.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/crypto/caam/caamalg_qi2.c ++++ b/drivers/crypto/caam/caamalg_qi2.c +@@ -297,7 +297,7 @@ static int aead_setkey(struct crypto_aea + dev_dbg(dev, "keylen %d enckeylen %d authkeylen %d\n", + keys.authkeylen + keys.enckeylen, keys.enckeylen, + keys.authkeylen); +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + ctx->adata.keylen = keys.authkeylen; +@@ -311,7 +311,7 @@ static int aead_setkey(struct crypto_aea + memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); + dma_sync_single_for_device(dev, ctx->key_dma, ctx->adata.keylen_pad + + keys.enckeylen, ctx->dir); +- print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", ++ print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, + ctx->adata.keylen_pad + keys.enckeylen, 1); + +@@ -728,7 +728,7 @@ static int gcm_setkey(struct crypto_aead + ret = aes_check_keylen(keylen); + if (ret) + return ret; +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -824,7 +824,7 @@ static int rfc4106_setkey(struct crypto_ + if (ret) + return ret; + +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -923,7 +923,7 @@ static int rfc4543_setkey(struct crypto_ + if (ret) + return ret; + +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -951,7 +951,7 @@ static int skcipher_setkey(struct crypto + u32 *desc; + const bool is_rfc3686 = alg->caam.rfc3686; + +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + ctx->cdata.keylen = keylen; diff --git a/queue-5.15/crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps.patch b/queue-5.15/crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps.patch new file mode 100644 index 0000000000..19e0330397 --- /dev/null +++ b/queue-5.15/crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps.patch @@ -0,0 +1,177 @@ +From 3f57657b6ea23f933371f2c2846322f441773cee Mon Sep 17 00:00:00 2001 +From: Thorsten Blum +Date: Mon, 27 Apr 2026 18:39:37 +0200 +Subject: crypto: caam - use print_hex_dump_devel to guard key hex dumps + +From: Thorsten Blum + +commit 3f57657b6ea23f933371f2c2846322f441773cee upstream. + +Use print_hex_dump_devel() for dumping sensitive key material in +*_setkey() and gen_split_key() to avoid leaking secrets at runtime when +CONFIG_DYNAMIC_DEBUG is enabled. + +Fixes: 6e005503199b ("crypto: caam - print debug messages at debug level") +Cc: stable@vger.kernel.org +Signed-off-by: Thorsten Blum +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/caam/caamalg.c | 12 ++++++------ + drivers/crypto/caam/caamalg_qi.c | 12 ++++++------ + drivers/crypto/caam/caamhash.c | 4 ++-- + drivers/crypto/caam/key_gen.c | 4 ++-- + 4 files changed, 16 insertions(+), 16 deletions(-) + +--- a/drivers/crypto/caam/caamalg.c ++++ b/drivers/crypto/caam/caamalg.c +@@ -588,7 +588,7 @@ static int aead_setkey(struct crypto_aea + dev_dbg(jrdev, "keylen %d enckeylen %d authkeylen %d\n", + keys.authkeylen + keys.enckeylen, keys.enckeylen, + keys.authkeylen); +- print_hex_dump_debug("key in @"__stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + /* +@@ -624,7 +624,7 @@ static int aead_setkey(struct crypto_aea + dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->adata.keylen_pad + + keys.enckeylen, ctx->dir); + +- print_hex_dump_debug("ctx.key@"__stringify(__LINE__)": ", ++ print_hex_dump_devel("ctx.key@"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, + ctx->adata.keylen_pad + keys.enckeylen, 1); + +@@ -665,7 +665,7 @@ static int gcm_setkey(struct crypto_aead + if (err) + return err; + +- print_hex_dump_debug("key in @"__stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -686,7 +686,7 @@ static int rfc4106_setkey(struct crypto_ + if (err) + return err; + +- print_hex_dump_debug("key in @"__stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -712,7 +712,7 @@ static int rfc4543_setkey(struct crypto_ + if (err) + return err; + +- print_hex_dump_debug("key in @"__stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -739,7 +739,7 @@ static int skcipher_setkey(struct crypto + u32 *desc; + const bool is_rfc3686 = alg->caam.rfc3686; + +- print_hex_dump_debug("key in @"__stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + ctx->cdata.keylen = keylen; +--- a/drivers/crypto/caam/caamalg_qi.c ++++ b/drivers/crypto/caam/caamalg_qi.c +@@ -207,7 +207,7 @@ static int aead_setkey(struct crypto_aea + dev_dbg(jrdev, "keylen %d enckeylen %d authkeylen %d\n", + keys.authkeylen + keys.enckeylen, keys.enckeylen, + keys.authkeylen); +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + /* +@@ -243,7 +243,7 @@ static int aead_setkey(struct crypto_aea + ctx->adata.keylen_pad + keys.enckeylen, + ctx->dir); + +- print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", ++ print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, + ctx->adata.keylen_pad + keys.enckeylen, 1); + +@@ -366,7 +366,7 @@ static int gcm_setkey(struct crypto_aead + if (ret) + return ret; + +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -470,7 +470,7 @@ static int rfc4106_setkey(struct crypto_ + if (ret) + return ret; + +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -576,7 +576,7 @@ static int rfc4543_setkey(struct crypto_ + if (ret) + return ret; + +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + memcpy(ctx->key, key, keylen); +@@ -626,7 +626,7 @@ static int skcipher_setkey(struct crypto + const bool is_rfc3686 = alg->caam.rfc3686; + int ret = 0; + +- print_hex_dump_debug("key in @" __stringify(__LINE__)": ", ++ print_hex_dump_devel("key in @" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + ctx->cdata.keylen = keylen; +--- a/drivers/crypto/caam/caamhash.c ++++ b/drivers/crypto/caam/caamhash.c +@@ -495,7 +495,7 @@ static int axcbc_setkey(struct crypto_ah + DMA_TO_DEVICE); + ctx->adata.keylen = keylen; + +- print_hex_dump_debug("axcbc ctx.key@" __stringify(__LINE__)" : ", ++ print_hex_dump_devel("axcbc ctx.key@" __stringify(__LINE__)" : ", + DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, keylen, 1); + + return axcbc_set_sh_desc(ahash); +@@ -515,7 +515,7 @@ static int acmac_setkey(struct crypto_ah + ctx->adata.key_virt = key; + ctx->adata.keylen = keylen; + +- print_hex_dump_debug("acmac ctx.key@" __stringify(__LINE__)" : ", ++ print_hex_dump_devel("acmac ctx.key@" __stringify(__LINE__)" : ", + DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); + + return acmac_set_sh_desc(ahash); +--- a/drivers/crypto/caam/key_gen.c ++++ b/drivers/crypto/caam/key_gen.c +@@ -58,7 +58,7 @@ int gen_split_key(struct device *jrdev, + + dev_dbg(jrdev, "split keylen %d split keylen padded %d\n", + adata->keylen, adata->keylen_pad); +- print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", ++ print_hex_dump_devel("ctx.key@" __stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1); + + if (local_max > max_keylen) +@@ -113,7 +113,7 @@ int gen_split_key(struct device *jrdev, + wait_for_completion(&result.completion); + ret = result.err; + +- print_hex_dump_debug("ctx.key@"__stringify(__LINE__)": ", ++ print_hex_dump_devel("ctx.key@"__stringify(__LINE__)": ", + DUMP_PREFIX_ADDRESS, 16, 4, key_out, + adata->keylen_pad, 1); + } diff --git a/queue-5.15/crypto-drbg-fix-drbg_max_addtl-on-64-bit-kernels.patch b/queue-5.15/crypto-drbg-fix-drbg_max_addtl-on-64-bit-kernels.patch new file mode 100644 index 0000000000..490b568ffe --- /dev/null +++ b/queue-5.15/crypto-drbg-fix-drbg_max_addtl-on-64-bit-kernels.patch @@ -0,0 +1,60 @@ +From 6f49f00c981bbb9ef602966f19bfdbef46b681d2 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Sun, 19 Apr 2026 23:33:48 -0700 +Subject: crypto: drbg - Fix drbg_max_addtl() on 64-bit kernels + +From: Eric Biggers + +commit 6f49f00c981bbb9ef602966f19bfdbef46b681d2 upstream. + +On 64-bit kernels, drbg_max_addtl() returns 2**35 bytes. That's too +large, for two reasons: + +1. SP800-90A says the maximum limit is 2**35 *bits*, not 2**35 bytes. + So the implemented limit has confused bits and bytes. + +2. When drbg_kcapi_hash() calls crypto_shash_update() on the additional + information string, the length is implicitly cast to 'unsigned int'. + That truncates the additional information string to U32_MAX bytes. + +Fix the maximum additional information string length to always be +U32_MAX - 1, causing an error to be returned for any longer lengths. + +Fixes: 541af946fe13 ("crypto: drbg - SP800-90A Deterministic Random Bit Generator") +Cc: stable@vger.kernel.org +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + include/crypto/drbg.h | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +--- a/include/crypto/drbg.h ++++ b/include/crypto/drbg.h +@@ -170,19 +170,15 @@ static inline size_t drbg_max_request_by + return (1 << 16); + } + ++/* ++ * SP800-90A allows implementations to support additional info / personalization ++ * strings of up to 2**35 bits. Implementations can have a smaller maximum. We ++ * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a ++ * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement. ++ */ + static inline size_t drbg_max_addtl(struct drbg_state *drbg) + { +- /* SP800-90A requires 2**35 bytes additional info str / pers str */ +-#if (__BITS_PER_LONG == 32) +- /* +- * SP800-90A allows smaller maximum numbers to be returned -- we +- * return SIZE_MAX - 1 to allow the verification of the enforcement +- * of this value in drbg_healthcheck_sanity. +- */ +- return (SIZE_MAX - 1); +-#else +- return (1UL<<35); +-#endif ++ return U32_MAX - 1; + } + + static inline size_t drbg_max_requests(struct drbg_state *drbg) diff --git a/queue-5.15/crypto-drbg-fix-returning-success-on-failure-in-ctr_drbg.patch b/queue-5.15/crypto-drbg-fix-returning-success-on-failure-in-ctr_drbg.patch new file mode 100644 index 0000000000..f88f770c33 --- /dev/null +++ b/queue-5.15/crypto-drbg-fix-returning-success-on-failure-in-ctr_drbg.patch @@ -0,0 +1,32 @@ +From 39a31ad9e2a5ed7e9c9c6f711dca96c8c8f5f26b Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Sun, 19 Apr 2026 23:33:45 -0700 +Subject: crypto: drbg - Fix returning success on failure in CTR_DRBG + +From: Eric Biggers + +commit 39a31ad9e2a5ed7e9c9c6f711dca96c8c8f5f26b upstream. + +drbg_ctr_generate() sometimes returns success when it fails, leaving the +output buffer uninitialized. Fix it. + +Fixes: cde001e4c3c3 ("crypto: rng - RNGs must return 0 in success case") +Cc: stable@vger.kernel.org +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/drbg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/crypto/drbg.c ++++ b/crypto/drbg.c +@@ -602,7 +602,7 @@ static int drbg_ctr_generate(struct drbg + if (addtl && !list_empty(addtl)) { + ret = drbg_ctr_update(drbg, addtl, 2); + if (ret) +- return 0; ++ return ret; + } + + /* 10.2.1.5.2 step 4.1 */ diff --git a/queue-5.15/crypto-drbg-fix-the-fips_enabled-priority-boost.patch b/queue-5.15/crypto-drbg-fix-the-fips_enabled-priority-boost.patch new file mode 100644 index 0000000000..e876b77c3c --- /dev/null +++ b/queue-5.15/crypto-drbg-fix-the-fips_enabled-priority-boost.patch @@ -0,0 +1,39 @@ +From a8a1f93080efc83a9ff8452954429ae379e9e614 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Sun, 19 Apr 2026 23:33:49 -0700 +Subject: crypto: drbg - Fix the fips_enabled priority boost + +From: Eric Biggers + +commit a8a1f93080efc83a9ff8452954429ae379e9e614 upstream. + +When fips_enabled=1, it seems to have been intended for one of the +algorithms defined in crypto/drbg.c to be the highest priority "stdrng" +algorithm, so that it is what is used by "stdrng" users. + +However, the code only boosts the priority to 400, which is less than +the priority 500 used in drivers/crypto/caam/caamprng.c. Thus, the CAAM +RNG could be used instead. + +Fix this by boosting the priority by 2000 instead of 200. + +Fixes: 541af946fe13 ("crypto: drbg - SP800-90A Deterministic Random Bit Generator") +Cc: stable@vger.kernel.org +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/drbg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/crypto/drbg.c ++++ b/crypto/drbg.c +@@ -2070,7 +2070,7 @@ static inline void __init drbg_fill_arra + * it is selected. + */ + if (fips_enabled) +- alg->base.cra_priority += 200; ++ alg->base.cra_priority += 2000; + + alg->base.cra_ctxsize = sizeof(struct drbg_state); + alg->base.cra_module = THIS_MODULE; diff --git a/queue-5.15/crypto-ecc-fix-carry-overflow-in-vli-multiplication.patch b/queue-5.15/crypto-ecc-fix-carry-overflow-in-vli-multiplication.patch new file mode 100644 index 0000000000..119dfa39da --- /dev/null +++ b/queue-5.15/crypto-ecc-fix-carry-overflow-in-vli-multiplication.patch @@ -0,0 +1,98 @@ +From 27b536a2ec8e2f85a0380c2d13c9ecbc7aaab406 Mon Sep 17 00:00:00 2001 +From: Anastasia Tishchenko +Date: Wed, 13 May 2026 13:57:40 +0300 +Subject: crypto: ecc - Fix carry overflow in vli multiplication + +From: Anastasia Tishchenko + +commit 27b536a2ec8e2f85a0380c2d13c9ecbc7aaab406 upstream. + +The carry flag calculation fails when r01.m_high is saturated +(0xFFFFFFFFFFFFFFFF) and addition of lower bits overflows. + +The condition (r01.m_high < product.m_high) doesn't handle the case +where r01.m_high == product.m_high and an additional carry exists +from lower-bit overflow. + +When commit 3c4b23901a0c ("crypto: ecdh - Add ECDH software support") +introduced crypto/ecc.c, it split the muladd() function in the +micro-ecc library into separate mul_64_64() and add_128_128() helpers. +It seems the check got lost in translation. + +Add proper handling for this boundary by accounting for the carry +from the lower addition. + +Fixes: 3c4b23901a0c ("crypto: ecdh - Add ECDH software support") +Signed-off-by: Anastasia Tishchenko +Cc: stable@vger.kernel.org # v4.8+ +Reviewed-by: Lukas Wunner +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/ecc.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +--- a/crypto/ecc.c ++++ b/crypto/ecc.c +@@ -375,14 +375,26 @@ static uint128_t mul_64_64(u64 left, u64 + return result; + } + +-static uint128_t add_128_128(uint128_t a, uint128_t b) ++/* Calculate addition with overflow checking. Returns true on wrap-around, ++ * false otherwise. ++ */ ++static bool check_add_128_128_overflow(uint128_t *result, uint128_t a, ++ uint128_t b) + { +- uint128_t result; ++ bool carry; + +- result.m_low = a.m_low + b.m_low; +- result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low); ++ result->m_low = a.m_low + b.m_low; ++ carry = (result->m_low < a.m_low); + +- return result; ++ result->m_high = a.m_high + b.m_high + carry; ++ ++ /* Using constant-time bitwise arithmetic to prevent timing ++ * side-channels. ++ */ ++ carry = (result->m_high < a.m_high) | ++ ((result->m_high == a.m_high) & carry); ++ ++ return carry; + } + + static void vli_mult(u64 *result, const u64 *left, const u64 *right, +@@ -407,9 +419,7 @@ static void vli_mult(u64 *result, const + uint128_t product; + + product = mul_64_64(left[i], right[k - i]); +- +- r01 = add_128_128(r01, product); +- r2 += (r01.m_high < product.m_high); ++ r2 += check_add_128_128_overflow(&r01, r01, product); + } + + result[k] = r01.m_low; +@@ -432,7 +442,7 @@ static void vli_umult(u64 *result, const + uint128_t product; + + product = mul_64_64(left[k], right); +- r01 = add_128_128(r01, product); ++ check_add_128_128_overflow(&r01, r01, product); + /* no carry */ + result[k] = r01.m_low; + r01.m_low = r01.m_high; +@@ -469,8 +479,7 @@ static void vli_square(u64 *result, cons + product.m_low <<= 1; + } + +- r01 = add_128_128(r01, product); +- r2 += (r01.m_high < product.m_high); ++ r2 += check_add_128_128_overflow(&r01, r01, product); + } + + result[k] = r01.m_low; diff --git a/queue-5.15/crypto-pcrypt-restore-callback-for-non-parallel-fallback.patch b/queue-5.15/crypto-pcrypt-restore-callback-for-non-parallel-fallback.patch new file mode 100644 index 0000000000..b390475070 --- /dev/null +++ b/queue-5.15/crypto-pcrypt-restore-callback-for-non-parallel-fallback.patch @@ -0,0 +1,57 @@ +From ed459fe319376e876de433d12b6c6772e612ca36 Mon Sep 17 00:00:00 2001 +From: Ruijie Li +Date: Mon, 25 May 2026 19:45:21 +0800 +Subject: crypto: pcrypt - restore callback for non-parallel fallback + +From: Ruijie Li + +commit ed459fe319376e876de433d12b6c6772e612ca36 upstream. + +pcrypt installs pcrypt_aead_done() on the child AEAD request before +trying to submit it through padata. If padata_do_parallel() returns +-EBUSY, pcrypt falls back to calling the child AEAD directly. + +That fallback must not keep the padata completion callback. Otherwise +an asynchronous completion runs pcrypt_aead_done() even though the +request was never enrolled in padata. + +Restore the original request callback and callback data before calling +the child AEAD directly. This keeps the fallback path aligned with a +direct AEAD request while leaving the parallel path unchanged. + +Fixes: 662f2f13e66d ("crypto: pcrypt - Call crypto layer directly when padata_do_parallel() return -EBUSY") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Zhengchuan Liang +Reported-by: Xin Liu +Assisted-by: Codex:gpt-5.4 +Signed-off-by: Ruijie Li +Signed-off-by: Ren Wei +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/pcrypt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/crypto/pcrypt.c ++++ b/crypto/pcrypt.c +@@ -122,6 +122,8 @@ static int pcrypt_aead_encrypt(struct ae + return -EINPROGRESS; + if (err == -EBUSY) { + /* try non-parallel mode */ ++ aead_request_set_callback(creq, flags, req->base.complete, ++ req->base.data); + return crypto_aead_encrypt(creq); + } + +@@ -173,6 +175,8 @@ static int pcrypt_aead_decrypt(struct ae + return -EINPROGRESS; + if (err == -EBUSY) { + /* try non-parallel mode */ ++ aead_request_set_callback(creq, flags, req->base.complete, ++ req->base.data); + return crypto_aead_decrypt(creq); + } + diff --git a/queue-5.15/dm-ioctl-report-an-error-if-a-device-has-no-table.patch b/queue-5.15/dm-ioctl-report-an-error-if-a-device-has-no-table.patch new file mode 100644 index 0000000000..09b810b53e --- /dev/null +++ b/queue-5.15/dm-ioctl-report-an-error-if-a-device-has-no-table.patch @@ -0,0 +1,35 @@ +From 457e32348d606a77f9b20e25e989734189834c07 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Mon, 11 May 2026 13:04:16 +0200 +Subject: dm-ioctl: report an error if a device has no table + +From: Mikulas Patocka + +commit 457e32348d606a77f9b20e25e989734189834c07 upstream. + +When we send a message to a device that has no table, the return code was +not set. The code would return "2", which is not considered a valid return value. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Reviewed-by: Benjamin Marzinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-ioctl.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -1732,8 +1732,11 @@ static int target_message(struct file *f + goto out_argv; + + table = dm_get_live_table(md, &srcu_idx); +- if (!table) ++ if (!table) { ++ DMERR("The device has no table."); ++ r = -EINVAL; + goto out_table; ++ } + + if (dm_deleting_md(md)) { + r = -ENXIO; diff --git a/queue-5.15/isofs-bound-rock-ridge-symlink-components-to-the-sl-record.patch b/queue-5.15/isofs-bound-rock-ridge-symlink-components-to-the-sl-record.patch new file mode 100644 index 0000000000..220298acc5 --- /dev/null +++ b/queue-5.15/isofs-bound-rock-ridge-symlink-components-to-the-sl-record.patch @@ -0,0 +1,74 @@ +From 5fa1d6a5ec2356d2107dead614437c66fa7138b1 Mon Sep 17 00:00:00 2001 +From: Bryam Vargas +Date: Sun, 7 Jun 2026 01:18:27 +0000 +Subject: isofs: bound Rock Ridge symlink components to the SL record + +From: Bryam Vargas + +commit 5fa1d6a5ec2356d2107dead614437c66fa7138b1 upstream. + +get_symlink_chunk() and the SL handling in +parse_rock_ridge_inode_internal() walk the variable-length components of +a Rock Ridge "SL" (symbolic link) record. Each component is a two-byte +header (flags, len) followed by len bytes of text, so it occupies +slp->len + 2 bytes. Both loops read slp->len and advance to the next +component, and get_symlink_chunk() additionally does +memcpy(rpnt, slp->text, slp->len), but neither checks that the component +lies within the SL record before dereferencing it. + +A crafted SL record whose component declares a len that runs past the +record (rr->len) therefore triggers an out-of-bounds read of up to 255 +bytes. When the record sits at the tail of its backing buffer - for +example a small kmalloc()ed continuation block reached through a CE +record - the read crosses the allocation; get_symlink_chunk() then +copies the out-of-bounds bytes into the symlink body returned to user +space by readlink(), disclosing adjacent kernel memory. + +ISO 9660 images are routinely mounted from untrusted removable media - +desktop environments auto-mount them (e.g. via udisks2) without +CAP_SYS_ADMIN - so the record contents are attacker-controlled. + +Reject any component that does not fit in the remaining record bytes +before using it. In get_symlink_chunk() return NULL, like the existing +output-buffer (plimit) checks, so a malformed record makes readlink() +fail with -EIO rather than silently returning a truncated target; in +parse_rock_ridge_inode_internal() stop the inode-size walk. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Suggested-by: Michael Bommarito +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260607011823.217748-1-hexlabsecurity@proton.me +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/isofs/rock.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -464,6 +464,9 @@ repeat: + inode->i_size = symlink_len; + while (slen > 1) { + rootflag = 0; ++ /* keep the component within the SL record */ ++ if (slp->len + 2 > slen) ++ goto eio; + switch (slp->flags & ~1) { + case 0: + inode->i_size += +@@ -619,6 +622,14 @@ static char *get_symlink_chunk(char *rpn + slp = &rr->u.SL.link; + while (slen > 1) { + rootflag = 0; ++ /* ++ * A component is slp->len + 2 bytes (a two-byte header plus ++ * len bytes of text). If it does not fit in the bytes left in ++ * the SL record the record is malformed: fail like the plimit ++ * checks below so readlink() returns -EIO, not a truncated path. ++ */ ++ if (slp->len + 2 > slen) ++ return NULL; + switch (slp->flags & ~1) { + case 0: + if (slp->len > plimit - rpnt) diff --git a/queue-5.15/nvme-multipath-set-bio_remapped-on-bios-remapped-to-per-path-namespace-disks.patch b/queue-5.15/nvme-multipath-set-bio_remapped-on-bios-remapped-to-per-path-namespace-disks.patch new file mode 100644 index 0000000000..7a270d7894 --- /dev/null +++ b/queue-5.15/nvme-multipath-set-bio_remapped-on-bios-remapped-to-per-path-namespace-disks.patch @@ -0,0 +1,88 @@ +From 88bac2c1a72b8f4f71e9845699aa872df04e5850 Mon Sep 17 00:00:00 2001 +From: "Achkinazi, Igor" +Date: Thu, 28 May 2026 15:24:27 +0000 +Subject: nvme-multipath: set BIO_REMAPPED on bios remapped to per-path namespace disks + +From: Achkinazi, Igor + +commit 88bac2c1a72b8f4f71e9845699aa872df04e5850 upstream. + +When nvme_ns_head_submit_bio() remaps a bio from the multipath head to a +per-path namespace, bio_set_dev() clears BIO_REMAPPED. The remapped bio +is then resubmitted through submit_bio_noacct() which calls +bio_check_eod() because BIO_REMAPPED is not set. + +This races with nvme_ns_remove() which zeroes the per-path capacity +before synchronize_srcu(): + + CPU 0 (IO submission) + --------------------- + srcu_read_lock() + nvme_find_path() -> ns + [NVME_NS_READY is set] + + CPU 1 (namespace removal) + ------------------------- + clear_bit(NVME_NS_READY) + set_capacity(ns->disk, 0) + synchronize_srcu() <- blocks + + CPU 0 (IO submission) + --------------------- + bio_set_dev(bio, ns->disk->part0) + [clears BIO_REMAPPED] + submit_bio_noacct(bio) + -> bio_check_eod() sees capacity=0 + -> bio fails with IO error + +The SRCU read lock prevents synchronize_srcu() from completing, but does +not prevent set_capacity(0) from executing. The bio fails the EOD check +before it reaches the NVMe driver, so nvme_failover_req() never gets a +chance to redirect it to another path of multipath. IO errors are +reported to the application despite another path being available. + +On older kernels (before commit 0b64682e78f7 "block: skip unnecessary +checks for split bio"), the same race was also reachable through split +remainders resubmitted via submit_bio_noacct(). + +Fix this by setting BIO_REMAPPED after bio_set_dev() in +nvme_ns_head_submit_bio(). This skips bio_check_eod() on the per-path +device; the EOD check already passed on the multipath head. + +NVMe per-path namespace devices are always whole disks (bd_partno=0), so +the blk_partition_remap() skip also gated by BIO_REMAPPED is a no-op. +The flag does not persist across failover and cannot go stale if the +namespace geometry changes between attempts: nvme_failover_req() calls +bio_set_dev() to redirect the bio back to the multipath head, which +clears BIO_REMAPPED. When nvme_requeue_work() resubmits through +submit_bio_noacct(), bio_check_eod() runs normally against the current +capacity. + +Same approach as commit 3a905c37c351 ("block: skip bio_check_eod for +partition-remapped bios"). + +Fixes: a7c7f7b2b641 ("nvme: use bio_set_dev to assign ->bi_bdev") +Cc: stable@vger.kernel.org +Reviewed-by: Christoph Hellwig +Signed-off-by: Igor Achkinazi +Signed-off-by: Keith Busch +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvme/host/multipath.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -337,6 +337,12 @@ static blk_qc_t nvme_ns_head_submit_bio( + ns = nvme_find_path(head); + if (likely(ns)) { + bio_set_dev(bio, ns->disk->part0); ++ /* ++ * Use BIO_REMAPPED to skip bio_check_eod() when this bio ++ * enters submit_bio_noacct() for the per-path device. The EOD ++ * check already passed on the multipath head. ++ */ ++ bio_set_flag(bio, BIO_REMAPPED); + bio->bi_opf |= REQ_NVME_MPATH; + trace_block_bio_remap(bio, disk_devt(ns->head->disk), + bio->bi_iter.bi_sector); diff --git a/queue-5.15/partitions-aix-bound-the-pp_count-scan-to-the-ppe-array.patch b/queue-5.15/partitions-aix-bound-the-pp_count-scan-to-the-ppe-array.patch new file mode 100644 index 0000000000..acf5b89ba1 --- /dev/null +++ b/queue-5.15/partitions-aix-bound-the-pp_count-scan-to-the-ppe-array.patch @@ -0,0 +1,62 @@ +From 2dc0bfd2fe355fb930de63c2f2eb8ced8570c579 Mon Sep 17 00:00:00 2001 +From: Bryam Vargas +Date: Sun, 7 Jun 2026 06:41:43 +0000 +Subject: partitions: aix: bound the pp_count scan to the ppe array + +From: Bryam Vargas + +commit 2dc0bfd2fe355fb930de63c2f2eb8ced8570c579 upstream. + +aix_partition() reads the physical volume descriptor into a fixed-size +struct pvd and then scans its physical-partition-extent array: + + int numpps = be16_to_cpu(pvd->pp_count); + ... + for (i = 0; i < numpps; i += 1) { + struct ppe *p = pvd->ppe + i; + ... + lp_ix = be16_to_cpu(p->lp_ix); + +pvd points at a single kmalloc()'d struct pvd whose ppe[] member holds a +fixed ARRAY_SIZE(pvd->ppe) (1016) entries, but the loop runs up to the +on-disk pp_count. pp_count is an unvalidated __be16 read straight from +the descriptor, so a crafted AIX image with pp_count larger than 1016 +drives the loop to read pvd->ppe[i] past the end of the allocation (up +to 65535 entries, ~2 MB out of bounds). + +The partition scan runs without mounting anything, when a block device +with a crafted AIX/IBM partition table appears (an attacker-supplied +image attached with losetup -P, or a device auto-scanned by udev), via +msdos_partition() -> aix_partition(). + +Clamp the scan to the number of entries the ppe[] array can hold. + +Fixes: 6ceea22bbbc8 ("partitions: add aix lvm partition support files") +Cc: stable@vger.kernel.org +Signed-off-by: Bryam Vargas +Acked-by: Philippe De Muyter +Link: https://patch.msgid.link/20260607064137.302574-1-hexlabsecurity@proton.me +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/partitions/aix.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/block/partitions/aix.c ++++ b/block/partitions/aix.c +@@ -228,6 +228,15 @@ int aix_partition(struct parsed_partitio + int next_lp_ix = 1; + int lp_ix; + ++ /* ++ * pvd was read into a fixed-size struct pvd whose ppe[] array ++ * holds ARRAY_SIZE(pvd->ppe) entries. pp_count is an ++ * unvalidated on-disk __be16, so clamp the scan to the array ++ * size to avoid walking past the allocation. ++ */ ++ if (numpps > ARRAY_SIZE(pvd->ppe)) ++ numpps = ARRAY_SIZE(pvd->ppe); ++ + for (i = 0; i < numpps; i += 1) { + struct ppe *p = pvd->ppe + i; + unsigned int lv_ix; diff --git a/queue-5.15/series b/queue-5.15/series index 31b0edd6fe..189fc86d1c 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -153,3 +153,17 @@ usb-typec-tcpm-validate-svid-index-in-svdm_consume_modes.patch usb-typec-ucsi-invert-displayport-role-assignment.patch usb-typec-ucsi-pass-full-dp-config-payload-in-set_new_cam-for-dp-alt-mode.patch iio-temperature-ltc2983-fix-n_wires-default-bypassin.patch +udf-validate-free-block-extents-against-the-partition-length.patch +udf-validate-vat-header-length-against-the-vat-inode-size.patch +udf-validate-sparing-table-length-as-an-entry-count-not-a-byte-count.patch +dm-ioctl-report-an-error-if-a-device-has-no-table.patch +nvme-multipath-set-bio_remapped-on-bios-remapped-to-per-path-namespace-disks.patch +partitions-aix-bound-the-pp_count-scan-to-the-ppe-array.patch +isofs-bound-rock-ridge-symlink-components-to-the-sl-record.patch +crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps.patch +crypto-caam-use-print_hex_dump_devel-to-guard-key-hex-dumps-again.patch +crypto-ecc-fix-carry-overflow-in-vli-multiplication.patch +crypto-pcrypt-restore-callback-for-non-parallel-fallback.patch +crypto-drbg-fix-returning-success-on-failure-in-ctr_drbg.patch +crypto-drbg-fix-drbg_max_addtl-on-64-bit-kernels.patch +crypto-drbg-fix-the-fips_enabled-priority-boost.patch diff --git a/queue-5.15/udf-validate-free-block-extents-against-the-partition-length.patch b/queue-5.15/udf-validate-free-block-extents-against-the-partition-length.patch new file mode 100644 index 0000000000..67d5cd185f --- /dev/null +++ b/queue-5.15/udf-validate-free-block-extents-against-the-partition-length.patch @@ -0,0 +1,65 @@ +From 5f0419457f89dce1a3f1c8e62a3adf2f39ab8168 Mon Sep 17 00:00:00 2001 +From: Michael Bommarito +Date: Fri, 15 May 2026 10:23:27 -0400 +Subject: udf: validate free block extents against the partition length + +From: Michael Bommarito + +commit 5f0419457f89dce1a3f1c8e62a3adf2f39ab8168 upstream. + +udf_free_blocks() checks the logical block number and count against the +partition length, but drops the extent offset from that final bound. A +crafted extent can pass the guard while logicalBlockNum + offset + count +points past the partition, which later indexes past the space bitmap +array. + +A single ftruncate(2) on a file backed by such an extent reliably +panics the kernel. This is a local availability issue. On desktop +systems where UDisks/polkit allows the active user to mount removable +UDF media without CAP_SYS_ADMIN, an unprivileged local user can supply +the crafted filesystem and trigger the panic by truncating a writable +file on it. Systems that require root or CAP_SYS_ADMIN to mount the +image have a higher prerequisite. + +No confidentiality or integrity impact is claimed: the reproduced +primitive is an out-of-bounds read of a bitmap pointer slot followed by +a kernel panic. + +Use the already computed logicalBlockNum + offset + count value for the +partition length check. Also make load_block_bitmap() reject an +out-of-range block group before indexing s_block_bitmap[], so corrupted +callers cannot walk past the flexible array. + +Fixes: 56e69e59751d ("udf: prevent integer overflow in udf_bitmap_free_blocks()") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Link: https://patch.msgid.link/20260515142327.1120767-1-michael.bommarito@gmail.com +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/balloc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/fs/udf/balloc.c ++++ b/fs/udf/balloc.c +@@ -86,8 +86,9 @@ static int __load_block_bitmap(struct su + int nr_groups = bitmap->s_nr_groups; + + if (block_group >= nr_groups) { +- udf_debug("block_group (%u) > nr_groups (%d)\n", ++ udf_debug("block_group (%u) >= nr_groups (%d)\n", + block_group, nr_groups); ++ return -EFSCORRUPTED; + } + + if (bitmap->s_block_bitmap[block_group]) { +@@ -671,7 +672,7 @@ void udf_free_blocks(struct super_block + + if (check_add_overflow(bloc->logicalBlockNum, offset, &blk) || + check_add_overflow(blk, count, &blk) || +- bloc->logicalBlockNum + count > map->s_partition_len) { ++ blk > map->s_partition_len) { + udf_debug("Invalid request to free blocks: (%d, %u), off %u, " + "len %u, partition len %u\n", + partition, bloc->logicalBlockNum, offset, count, diff --git a/queue-5.15/udf-validate-sparing-table-length-as-an-entry-count-not-a-byte-count.patch b/queue-5.15/udf-validate-sparing-table-length-as-an-entry-count-not-a-byte-count.patch new file mode 100644 index 0000000000..871cb7fec4 --- /dev/null +++ b/queue-5.15/udf-validate-sparing-table-length-as-an-entry-count-not-a-byte-count.patch @@ -0,0 +1,57 @@ +From 3ec997bd5508e9b25210b5bbec89031629cdb093 Mon Sep 17 00:00:00 2001 +From: Bryam Vargas +Date: Fri, 12 Jun 2026 01:40:01 -0500 +Subject: udf: validate sparing table length as an entry count, not a byte count + +From: Bryam Vargas + +commit 3ec997bd5508e9b25210b5bbec89031629cdb093 upstream. + +udf_load_sparable_map() accepts a sparing table when + + sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > sb->s_blocksize + +is false, i.e. it treats reallocationTableLen as a number of BYTES that +must fit in the block. But the table is walked as an array of 8-byte +sparingEntry elements: + + for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) { + struct sparingEntry *entry = &st->mapEntry[i]; + ... entry->origLocation ... + } + +in udf_get_pblock_spar15() and udf_relocate_blocks(). A +reallocationTableLen of N therefore passes the check whenever +sizeof(*st) + N <= blocksize, yet the consumers index +sizeof(*st) + N * sizeof(struct sparingEntry) bytes -- up to ~8x the +block. On a crafted UDF image this is an out-of-bounds read in +udf_get_pblock_spar15(); udf_relocate_blocks() additionally feeds the +same length to udf_update_tag(), whose crc_itu_t() reads far past the +block, and its memmove() through st->mapEntry[] is an out-of-bounds +write. + +Validate reallocationTableLen as the entry count it is, with +struct_size(). + +Fixes: 1df2ae31c724 ("udf: Fortify loading of sparing table") +Cc: stable@vger.kernel.org +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260612-b4-disp-91780c4e-v1-1-f15112ff6882@proton.me +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/super.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/udf/super.c ++++ b/fs/udf/super.c +@@ -1397,7 +1397,8 @@ static int udf_load_sparable_map(struct + if (ident != 0 || + strncmp(st->sparingIdent.ident, UDF_ID_SPARING, + strlen(UDF_ID_SPARING)) || +- sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > ++ struct_size(st, mapEntry, ++ le16_to_cpu(st->reallocationTableLen)) > + sb->s_blocksize) { + brelse(bh); + continue; diff --git a/queue-5.15/udf-validate-vat-header-length-against-the-vat-inode-size.patch b/queue-5.15/udf-validate-vat-header-length-against-the-vat-inode-size.patch new file mode 100644 index 0000000000..a0b854b7f6 --- /dev/null +++ b/queue-5.15/udf-validate-vat-header-length-against-the-vat-inode-size.patch @@ -0,0 +1,60 @@ +From d8202786b3d75125c84ebc4de6d946f92fde0ee8 Mon Sep 17 00:00:00 2001 +From: Bryam Vargas +Date: Fri, 12 Jun 2026 02:53:31 -0500 +Subject: udf: validate VAT header length against the VAT inode size + +From: Bryam Vargas + +commit d8202786b3d75125c84ebc4de6d946f92fde0ee8 upstream. + +udf_load_vat() takes the virtual partition's start offset straight from +the on-disk VAT 2.0 header without checking it against the VAT inode +size: + + map->s_type_specific.s_virtual.s_start_offset = + le16_to_cpu(vat20->lengthHeader); + map->s_type_specific.s_virtual.s_num_entries = + (sbi->s_vat_inode->i_size - + map->s_type_specific.s_virtual.s_start_offset) >> 2; + +lengthHeader is a fully attacker-controlled 16-bit value. If it exceeds +the VAT inode size, the s_num_entries subtraction underflows to a huge +count, which defeats the "block > s_num_entries" bound in +udf_get_pblock_virt15(); and on the ICB-inline path that function reads + + ((__le32 *)(iinfo->i_data + s_start_offset))[block] + +so a large s_start_offset indexes past the inode's in-ICB data. Mounting +a crafted UDF image with a virtual (VAT) partition then triggers an +out-of-bounds read. + +Reject a VAT whose header length does not leave room for at least one +entry within the VAT inode. + +Fixes: fa5e08156335 ("udf: Handle VAT packed inside inode properly") +Cc: stable@vger.kernel.org +Signed-off-by: Bryam Vargas +Link: https://patch.msgid.link/20260612-b4-disp-9a2317ee-v1-1-fefef5736154@proton.me +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/super.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/udf/super.c ++++ b/fs/udf/super.c +@@ -1234,6 +1234,14 @@ static int udf_load_vat(struct super_blo + + map->s_type_specific.s_virtual.s_start_offset = + le16_to_cpu(vat20->lengthHeader); ++ if (map->s_type_specific.s_virtual.s_start_offset ++ > sbi->s_vat_inode->i_size) { ++ udf_err(sb, "Corrupted VAT header length %u (VAT inode size %lld)\n", ++ map->s_type_specific.s_virtual.s_start_offset, ++ sbi->s_vat_inode->i_size); ++ brelse(bh); ++ return -EFSCORRUPTED; ++ } + map->s_type_specific.s_virtual.s_num_entries = + (sbi->s_vat_inode->i_size - + map->s_type_specific.s_virtual. -- 2.47.3