mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
lib/buildid: reject file offsets that do not fit in pgoff_t
On a 32-bit kernel, parsing the build ID of a crafted ELF file can copy
far more than the intended bytes into a 64-byte on-stack buffer in
__build_id_parse(), corrupting the stack of whatever context fetches the
build ID. This might be reachable without privilege: perf records a build ID
for PERF_RECORD_MMAP2 on the no-fault path when a process mmaps its own file
(build_id_parse_nofault() from perf_event_mmap()), and BPF build-id stack
maps do the same.
freader_get_folio() turns a 64-bit file offset into a page cache index
with file_off >> PAGE_SHIFT and passes it to filemap_get_folio().
pgoff_t is unsigned long, 32-bit on a 32-bit kernel, so an ELF64 e_phoff
of 2^44 + k * PAGE_SIZE truncates to index k. filemap_get_folio()
returns the cached folio at index k, whose folio_pos() is far below the
requested file_off. In freader_fetch() the folio does not contain
file_off, so the "crossing folio boundaries" path computes
part_sz = folio_off + folio_sz - file_off as a large u64 (file_off is
much larger), and the following memcpy() truncates it to size_t and
copies a page into the 64-byte buffer. On a 64-bit kernel the index is
not truncated, the folio is not cached and the fetch returns -EFAULT, so
only 32-bit kernels are affected.
Reject a file offset that cannot be represented as a page cache index
before the lookup, so such a file fails the build ID parse cleanly as it
already does on 64-bit.
Reproduced on i386 under QEMU with CONFIG_STACKPROTECTOR_STRONG: mmapping
a crafted ELF (ELFCLASS64, e_phoff = 2^44) while a perf event with
attr.build_id is open panics with "stack-protector: Kernel stack is
corrupted in: __build_id_parse"; with this patch the parse returns
-EFAULT and the mmap completes cleanly. Built for i386 with W=1, no new
warnings.
Fixes: de3ec364c3 ("lib/buildid: add single folio-based file reader abstraction")
Assisted-by: LLM
Cc: stable@vger.kernel.org
Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
This commit is contained in:
parent
2c79356007
commit
0007654a7b
|
|
@ -47,6 +47,10 @@ static int freader_get_folio(struct freader *r, loff_t file_off)
|
|||
|
||||
freader_put_folio(r);
|
||||
|
||||
/* the page index must fit in pgoff_t */
|
||||
if (file_off < 0 || file_off > MAX_LFS_FILESIZE)
|
||||
return -EFAULT;
|
||||
|
||||
/* only use page cache lookup - fail if not already cached */
|
||||
r->folio = filemap_get_folio(r->file->f_mapping, file_off >> PAGE_SHIFT);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user