We might have a crash scenario when we have an invalid DT_STRTAB value
that is larger than the file size. I've added a test case to demonstrate.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Just to make sure I understand the issue: if DT_STRTAB is small enough to fit within a segment, according to the segment's size/offset fields, we currently crash, if the size/offset fields themselves are invalid? What about if only part of the DT_STRTAB range is within the file (i.e. DT_STRTAB is less than file size but DT_STRTAB + DT_STRSZ is past the end)?
llvm/lib/Object/ELF.cpp | ||
---|---|---|
586–589 | I wonder if this error message could be a little clearer. It's really an issue with the segment properties rather than the virtual address itself. Would something like "can't map virtual address 0x1234 to the segment with index 1: the segment goes past the end of the file" feel okay? Optionally even add in information about the segment end and file size to the message. | |
llvm/test/tools/llvm-readobj/ELF/loadname.test | ||
3–5 | this is a no-op | |
54 | contains a DT_STRTAB entry whose address is past the end of the object. |
- Addressed review comments.
Generally this bug exploits the situation when a segment's file size and DT_STRTAB together are broken in the way that allows a DT_STRTAB value to pass all current
checks, but triggers an access to area that is out of object buffer bounds.
E.g. We have VAddr == DT_STRTAB == 0xFFFE. We want to pass the last check:
uint64_t Delta = VAddr - Phdr.p_vaddr; if (Delta >= Phdr.p_filesz) return createError("virtual address is not in any segment: 0x" + Twine::utohexstr(VAddr));
So we need to have a p_filesz that is larger than 0xFFFE.
if DT_STRTAB is small enough to fit within a segment
I.e technically DT_STRTAB value kind of fits the segment (0xFFFE < 0xFFFF), but it is still broken too.
(Or, perhaps, from another POV: we have a file that is truncated, what is probably a more real case).
What about if only part of the DT_STRTAB range is within the file (i.e. DT_STRTAB is less than file size but DT_STRTAB + DT_STRSZ is past the end)?
Yes, I think this might trigger an issue too. If you do not mind I'd fix it in a follow-up. I have found a few situations (different ones, not just related to dynamic tags) where we might crash
and plan to investigate and prepare patches for all such places. I can start looking at DT_STRSZ case (and I guess some other dynamic tags) in the first place
while I am here in the code.
llvm/lib/Object/ELF.cpp | ||
---|---|---|
586–589 | I've updated the message shown to refine and include more information. What do you think about it? |
I wonder if this error message could be a little clearer. It's really an issue with the segment properties rather than the virtual address itself. Would something like "can't map virtual address 0x1234 to the segment with index 1: the segment goes past the end of the file" feel okay? Optionally even add in information about the segment end and file size to the message.