DF-5630 / fix.diff
--- 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); } |