⬢ DragonFlyBSD Kernel Audit
DF-5630 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1699,10 +1699,23 @@
 static boolean_t
 note_overflow(const Elf_Note *note, size_t maxsize)
 {
+	size_t pos;
+
 	if (sizeof(*note) > maxsize)
 		return TRUE;
 	if (note->n_namesz > maxsize - sizeof(*note))
 		return TRUE;
+	/*
+	 * DF-5630: the whole declared note (header + name + padding +
+	 * descriptor) must fit inside the segment: bsd_trans_osrel()
+	 * reads the descriptor of any note matching the brandnote
+	 * fields, so bounding only n_namesz lets that read go OOB.
+	 */
+	pos = sizeof(*note) + roundup2(note->n_namesz, sizeof(Elf32_Addr));
+	if (pos > maxsize)
+		return TRUE;
+	if (note->n_descsz > maxsize - pos)
+		return TRUE;
 	return FALSE;
 }
 
@@ -1833,10 +1846,16 @@
 	pathloc = pinterpreter->p_offset;
 	endbyte = pathloc + pathsz;
 
+	/*
+	 * DF-5629: callers treat this buffer as a C string (strcmp,
+	 * nlookup/copystr, uprintf %s).  Require the payload to be
+	 * NUL-terminated within p_filesz, otherwise those walks read
+	 * past the kmalloc'd chunk (kernel heap disclosure).
+	 */
 	limited_to_first_page = pathloc < PAGE_SIZE && endbyte < PAGE_SIZE;
 	if (limited_to_first_page) {
 	        bcopy(imgp->image_header + pathloc, data, pathsz);
-	        return (result_success);
+	        goto done;
 	}
 
 	firstloc = pathloc & PAGE_MASK;
@@ -1859,6 +1878,18 @@
 		bcopy(page + firstloc, data, pathsz);
 
 	exec_unmap_page(lwb);
+done:
+	/* DF-5629: interpreter path must be NUL-terminated in p_filesz */
+	{
+		__ElfN(Size) i;
+
+		for (i = 0; i < pathsz; i++) {
+			if (data[i] == '\0')
+				break;
+		}
+		if (i == pathsz)
+			return (result_failure);
+	}
 	return (result_success);
 }