Bug 217432 - kernel's elf_load_file function can read out of bounds and crash the kernel
Summary: kernel's elf_load_file function can read out of bounds and crash the kernel
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 10.3-RELEASE
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-02-28 19:46 UTC by Tim Newsham
Modified: 2017-02-28 19:46 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tim Newsham 2017-02-28 19:46:51 UTC
The link_elf_load_file function in sys/kern/link_elf.c performs bounds checking on the program header element in the elf header with this code:

    if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) &&
          (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) &&
          (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes)))
        link_elf_error(filename, "Unreadable program headers");

however, it does not terminate processing at this point and will continue executing with an out-of-bounds e_phoff.  Any offset larger than (PAGE_SIZE-sizeof Elf_Phdr) will cause out of bounds reads, since only one page is allocated for the elf object.  This will later result in out-of-bounds reads and potentially a panic.  For example if e_phoff is very large, then execution will crash at the switch statement:

    phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff);
    phlimit = phdr + hdr->e_phnum;
    nsegs = 0;
    phdyn = NULL;
    phphdr = NULL;
    while (phdr < phlimit) {
        switch (phdr->p_type) {  <---- crash

This issue is not very severe since it requires PRIV_KLD_LOAD to trigger, and users that have this privilege can force crashes through loading malicious code into the kernel.

The fix is simple -- terminate further processing of the elf file when link_elf_error is reported.