- Fix two possible overflows when testing if ELF program headers are on

the first page:
  1. Cast uint16_t operands in a multiplication to unsigned int because
     otherwise the implicit promotion to int results in a signed
     multiplication that can overflow and the behaviour on integer
     overflow is undefined.
  2. Replace (offset + size > PAGE_SIZE) with (size > PAGE_SIZE - offset)
     because the sum may overflow.
- Use the same tests to see if the path to the interpreter is on the first
  page. There's no overflow here because size is already limited by
  MAXPATHLEN, but the compiler optimises the new tests better. Also fix an
  off-by-one error.
- Simplify tests to see if an ELF note program header is on the first page.
  This also fixes an off-by-one error.

Reviewed by:	kib
MFC after:	1 week
This commit is contained in:
Tijl Coosemans 2013-03-13 22:01:31 +00:00
parent 3b14c753ff
commit d19d5bf443
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=248256

View file

@ -661,9 +661,8 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
}
/* Only support headers that fit within first page for now */
/* (multiplication of two Elf_Half fields will not overflow) */
if ((hdr->e_phoff > PAGE_SIZE) ||
(hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE - hdr->e_phoff) {
(u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - hdr->e_phoff) {
error = ENOEXEC;
goto fail;
}
@ -743,7 +742,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
*/
if ((hdr->e_phoff > PAGE_SIZE) ||
(hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) {
(u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - hdr->e_phoff) {
/* Only support headers in first page for now */
return (ENOEXEC);
}
@ -762,8 +761,8 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
case PT_INTERP:
/* Path to interpreter */
if (phdr[i].p_filesz > MAXPATHLEN ||
phdr[i].p_offset >= PAGE_SIZE ||
phdr[i].p_offset + phdr[i].p_filesz >= PAGE_SIZE)
phdr[i].p_offset > PAGE_SIZE ||
phdr[i].p_filesz > PAGE_SIZE - phdr[i].p_offset)
return (ENOEXEC);
interp = imgp->image_header + phdr[i].p_offset;
interp_name_len = phdr[i].p_filesz;
@ -1553,9 +1552,8 @@ __elfN(parse_notes)(struct image_params *imgp, Elf_Brandnote *checknote,
const char *note_name;
int i;
if (pnote == NULL || pnote->p_offset >= PAGE_SIZE ||
pnote->p_filesz > PAGE_SIZE ||
pnote->p_offset + pnote->p_filesz >= PAGE_SIZE)
if (pnote == NULL || pnote->p_offset > PAGE_SIZE ||
pnote->p_filesz > PAGE_SIZE - pnote->p_offset)
return (FALSE);
note = note0 = (const Elf_Note *)(imgp->image_header + pnote->p_offset);