| ... | @@ -64,42 +64,33 @@ const have_dl_phdr_info = posix.system.dl_phdr_info != void; | ... | @@ -64,42 +64,33 @@ const have_dl_phdr_info = posix.system.dl_phdr_info != void; |
| 64 | const dl_phdr_info = if (have_dl_phdr_info) posix.dl_phdr_info else anyopaque; | 64 | const dl_phdr_info = if (have_dl_phdr_info) posix.dl_phdr_info else anyopaque; |
| 65 | | 65 | |
| 66 | const IterFnError = error{ | 66 | const IterFnError = error{ |
| 67 | MissingPtLoadSegment, | 67 | MissingLoadSegment, |
| 68 | MissingLoad, | 68 | MissingEhdrLoadSegment, |
| 69 | BadElfMagic, | 69 | BadElfMagic, |
| 70 | FailedConsistencyCheck, | 70 | PhnumMismatch, |
| 71 | }; | 71 | }; |
| 72 | | 72 | |
| 73 | fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void { | 73 | fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void { |
| 74 | _ = size; | 74 | _ = size; |
| 75 | // Count how many libraries are loaded | 75 | // Count how many libraries are loaded |
| 76 | counter.* += @as(usize, 1); | 76 | counter.* += 1; |
| 77 | | 77 | |
| 78 | // The image should contain at least a PT.LOAD segment | 78 | // The image should contain at least one loadable segment |
| 79 | if (info.phnum < 1) return error.MissingPtLoadSegment; | 79 | if (info.phnum < 1) return error.MissingLoadSegment; |
| 80 | | | |
| 81 | // Quick & dirty validation of the phdr pointers, make sure we're not | | |
| 82 | // pointing to some random gibberish | | |
| 83 | var i: usize = 0; | | |
| 84 | var found_load = false; | | |
| 85 | while (i < info.phnum) : (i += 1) { | | |
| 86 | const phdr = info.phdr[i]; | | |
| 87 | | 80 | |
| | 81 | // For some quick and dirty validation, find the phdr which contains the ELF |
| | 82 | // header, and check it makes sense. |
| | 83 | for (info.phdr[0..info.phnum]) |phdr| { |
| 88 | if (phdr.type != .LOAD) continue; | 84 | if (phdr.type != .LOAD) continue; |
| 89 | | 85 | if (phdr.offset != 0) continue; |
| 90 | const reloc_addr = info.addr + phdr.vaddr; | 86 | // This segment holds the ELF header at the start |
| 91 | // Find the ELF header | 87 | const ehdr: *elf.Ehdr = @ptrFromInt(info.addr + phdr.vaddr); |
| 92 | const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.offset)); | 88 | if (!mem.eql(u8, ehdr.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic; |
| 93 | // Validate the magic | 89 | if (ehdr.e_phnum != info.phnum) return error.PhnumMismatch; |
| 94 | if (!mem.eql(u8, elf_header.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic; | | |
| 95 | // Consistency check | | |
| 96 | if (elf_header.e_phnum != info.phnum) return error.FailedConsistencyCheck; | | |
| 97 | | | |
| 98 | found_load = true; | | |
| 99 | break; | 90 | break; |
| | 91 | } else { |
| | 92 | return error.MissingEhdrLoadSegment; |
| 100 | } | 93 | } |
| 101 | | | |
| 102 | if (!found_load) return error.MissingLoad; | | |
| 103 | } | 94 | } |
| 104 | | 95 | |
| 105 | test "dl_iterate_phdr" { | 96 | test "dl_iterate_phdr" { |