The callers of dwfl_elf_phdr_memory_callback assume at least minread bytes are read and available. Make sure to check start is smaller than elf->maximum_size before reading more. Return false if end - start is smaller than minread.
Found by afl-fuzz. Signed-off-by: Mark Wielaard <m...@klomp.org> --- libdwfl/ChangeLog | 5 +++++ libdwfl/core-file.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index abd5c34a..49a35e41 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2021-12-23 Mark Wielaard <m...@klomp.org> + + * core-file.c (dwfl_elf_phdr_memory_callback): Check start < + elf->maximum_size and end - start < minread. + 2021-12-20 Mark Wielaard <m...@klomp.org> * dwfl_segment_report_module.c (dwfl_segment_report_module): Move diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c index b04d1d18..d5be771f 100644 --- a/libdwfl/core-file.c +++ b/libdwfl/core-file.c @@ -1,5 +1,6 @@ /* Core file handling. Copyright (C) 2008-2010, 2013, 2015 Red Hat, Inc. + Copyright (C) 2011 Mark J. Wielaard <m...@klomp.org> This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -320,7 +321,7 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx, (void) more (*buffer_available); /* If it's already on hand anyway, use as much as there is. */ - if (elf->map_address != NULL) + if (elf->map_address != NULL && start < elf->maximum_size) (void) more (elf->maximum_size - start); /* Make sure we don't look past the end of the actual file, @@ -332,6 +333,9 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx, if (unlikely (start >= end)) return false; + if (end - start < minread) + return false; + if (elf->map_address != NULL) { void *contents = elf->map_address + elf->start_offset + start; -- 2.30.2