kern/60577: local UDF buffer overflow with doctored image

"[email protected] via gnats" <[email protected]>
Newsgroups gmane.os.netbsd.bugs
Message-ID <[email protected]>
>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 [email protected]:/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:
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.