NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/60577: local UDF buffer overflow with doctored image
>Number: 60577
>Category: kern
>Synopsis: local UDF buffer overflow with doctored image
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Aug 13 13:00:00 +0000 2026
>Originator: Reinoud Zandijk
>Release: NetBSD 11.99.3
>Organization:
>Environment:
System: NetBSD gorilla.13thmonkey.org 11.99.3 NetBSD 11.99.3 (GENERIC) #1: Mon Nov 24 15:09:27 CET 2025 reinoud%gorilla.13thmonkey.org@localhost:/usr/sources/cvs.netbsd.org/src-clean/obj/sys/arch/amd64/compile/GENERIC amd64
Architecture: x86_64
Machine: amd64
>Description:
Small files can be stored inside the file descriptor. A doctored image with a
file descriptor containing an invalid extended attribute length or invalid
information length could lead to a buffer overflow.
>How-To-Repeat:
Provide a doctored image with a node that that is flagged for internal
recording of data and has the length of the internal extended attributes or
its in information length set to point outside the file descriptor.
>Fix:
Apply the following fix that explicitly tests these cases.
Index: sys/fs/udf/udf_subr.c
===================================================================
RCS file: /cvsroot/src/sys/fs/udf/udf_subr.c,v
retrieving revision 1.177
diff -u -p -r1.177 udf_subr.c
--- sys/fs/udf/udf_subr.c 28 Mar 2025 19:34:35 -0000 1.177
+++ sys/fs/udf/udf_subr.c 13 Aug 2026 12:37:38 -0000
@@ -6566,33 +6566,39 @@ udf_read_internal(struct udf_node *node,
struct extfile_entry *efe = node->efe;
uint64_t inflen;
uint32_t sector_size;
- uint8_t *srcpos;
+ uint8_t *srcpos, *min_spos, *max_spos;
int icbflags, addr_type;
/* get extent and do some paranoia checks */
ump = node->ump;
sector_size = ump->discinfo.sector_size;
- /*
- * XXX there should be real bounds-checking logic here,
- * in case ->l_ea or ->inf_len contains nonsense.
- */
-
if (fe) {
inflen = udf_rw64(fe->inf_len);
srcpos = &fe->data[0] + udf_rw32(fe->l_ea);
+ min_spos = (uint8_t *) fe;
+ max_spos = (uint8_t *) fe + sector_size;
icbflags = udf_rw16(fe->icbtag.flags);
} else {
assert(node->efe);
inflen = udf_rw64(efe->inf_len);
srcpos = &efe->data[0] + udf_rw32(efe->l_ea);
+ min_spos = (uint8_t *) efe;
+ max_spos = (uint8_t *) efe + sector_size;
icbflags = udf_rw16(efe->icbtag.flags);
}
addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
assert(addr_type == UDF_ICB_INTERN_ALLOC);
__USE(addr_type);
- assert(inflen < sector_size);
+
+ /*
+ * Bound-check ->l_ea + ->inf_len to prevent buffer overflow.
+ */
+ if ((srcpos + inflen > max_spos) || (srcpos + inflen < min_spos)) {
+ memset(blob, 0, sector_size);
+ return EINVAL;
+ }
/* copy out info */
memcpy(blob, srcpos, inflen);
>Unformatted:
Home |
Main Index |
Thread Index |
Old Index