* [PATCH] udf: reject descriptors with oversized CRC length
@ 2026-04-13 21:12 Michael Bommarito
2026-04-14 12:43 ` Jan Kara
0 siblings, 1 reply; 2+ messages in thread
From: Michael Bommarito @ 2026-04-13 21:12 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, stable
udf_read_tagged() skips CRC verification when descCRCLength +
sizeof(struct tag) exceeds the block size. A crafted UDF image can
set descCRCLength to an oversized value to bypass CRC validation
entirely; the descriptor is then accepted based solely on the 8-bit
tag checksum, which is trivially recomputable.
Reject such descriptors instead of silently accepting them. A
legitimate single-block descriptor should never have a CRC length that
exceeds the block.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-6
Assisted-by: Codex:gpt-5-4
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
Found during a filesystem security audit. The CRC validation
condition in udf_read_tagged() uses OR logic: the first arm
(descCRCLength too large) short-circuits the second arm (CRC
comparison), so an oversized descCRCLength causes the function to
return the buffer head without verifying the CRC. The descriptor
is accepted based solely on the 8-bit tag checksum.
A crafted UDF image with descCRCLength set to blocksize (e.g. 2048
on a 2048-byte-block filesystem, vs the 2032 limit) in both the
main and reserve Volume Descriptor Sequences mounts successfully
with corrupted descriptor bodies.
Reproduced on UML (ARCH=um, KASAN-enabled v7.0-rc7) with a
mkudffs-generated 20 MiB image, both LVD copies patched to
descCRCLength=2040, CRC left stale, body byte flipped, tag
checksum recomputed. Mount succeeds (MOUNT=0) with the corrupt
LVD accepted. With this patch applied, mount fails with EINVAL
and the new "CRC length ... exceeds block size" error is logged.
Reproducer details and UML console logs available on request.
fs/udf/misc.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/fs/udf/misc.c b/fs/udf/misc.c
index 0788593b6a1d..6928e378fbbd 100644
--- a/fs/udf/misc.c
+++ b/fs/udf/misc.c
@@ -230,8 +230,12 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
}
/* Verify the descriptor CRC */
- if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize ||
- le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
+ if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize) {
+ udf_err(sb, "block %u: CRC length %u exceeds block size\n",
+ block, le16_to_cpu(tag_p->descCRCLength));
+ goto error_out;
+ }
+ if (le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
bh->b_data + sizeof(struct tag),
le16_to_cpu(tag_p->descCRCLength)))
return bh;
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] udf: reject descriptors with oversized CRC length
2026-04-13 21:12 [PATCH] udf: reject descriptors with oversized CRC length Michael Bommarito
@ 2026-04-14 12:43 ` Jan Kara
0 siblings, 0 replies; 2+ messages in thread
From: Jan Kara @ 2026-04-14 12:43 UTC (permalink / raw)
To: Michael Bommarito; +Cc: Jan Kara, linux-fsdevel, stable
On Mon 13-04-26 17:12:40, Michael Bommarito wrote:
> udf_read_tagged() skips CRC verification when descCRCLength +
> sizeof(struct tag) exceeds the block size. A crafted UDF image can
> set descCRCLength to an oversized value to bypass CRC validation
> entirely; the descriptor is then accepted based solely on the 8-bit
> tag checksum, which is trivially recomputable.
>
> Reject such descriptors instead of silently accepting them. A
> legitimate single-block descriptor should never have a CRC length that
> exceeds the block.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@vger.kernel.org
> Assisted-by: Claude:claude-opus-4-6
> Assisted-by: Codex:gpt-5-4
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Thanks for the fix! It looks good to me. I'll merge it into my tree later
this week once the pull requests for the merge window are done.
Honza
> ---
> Found during a filesystem security audit. The CRC validation
> condition in udf_read_tagged() uses OR logic: the first arm
> (descCRCLength too large) short-circuits the second arm (CRC
> comparison), so an oversized descCRCLength causes the function to
> return the buffer head without verifying the CRC. The descriptor
> is accepted based solely on the 8-bit tag checksum.
>
> A crafted UDF image with descCRCLength set to blocksize (e.g. 2048
> on a 2048-byte-block filesystem, vs the 2032 limit) in both the
> main and reserve Volume Descriptor Sequences mounts successfully
> with corrupted descriptor bodies.
>
> Reproduced on UML (ARCH=um, KASAN-enabled v7.0-rc7) with a
> mkudffs-generated 20 MiB image, both LVD copies patched to
> descCRCLength=2040, CRC left stale, body byte flipped, tag
> checksum recomputed. Mount succeeds (MOUNT=0) with the corrupt
> LVD accepted. With this patch applied, mount fails with EINVAL
> and the new "CRC length ... exceeds block size" error is logged.
>
> Reproducer details and UML console logs available on request.
>
> fs/udf/misc.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/fs/udf/misc.c b/fs/udf/misc.c
> index 0788593b6a1d..6928e378fbbd 100644
> --- a/fs/udf/misc.c
> +++ b/fs/udf/misc.c
> @@ -230,8 +230,12 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
> }
>
> /* Verify the descriptor CRC */
> - if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize ||
> - le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
> + if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize) {
> + udf_err(sb, "block %u: CRC length %u exceeds block size\n",
> + block, le16_to_cpu(tag_p->descCRCLength));
> + goto error_out;
> + }
> + if (le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
> bh->b_data + sizeof(struct tag),
> le16_to_cpu(tag_p->descCRCLength)))
> return bh;
> --
> 2.53.0
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-04-14 12:43 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-13 21:12 [PATCH] udf: reject descriptors with oversized CRC length Michael Bommarito
2026-04-14 12:43 ` Jan Kara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox