authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-14 15:16:51+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-14 15:16:55+02:00
log4d77ef25f948cac32e4d5fd3f9df019e728fcb45
tree919aef64f0588c0ab864ac07b51b27612948dd0e
parent7a0022725342be8d3ea555a635da51f0e8c47b25

elf: check symtab section headers size when writing globals

Without this, it may happen we write the globals without extending the symtab section header's size. This can potentially lead to clobbering some data in the file, or simply omitting the globals from the symtab when displaying with support tooling such as `readelf`.

1 files changed, 16 insertions(+), 0 deletions(-)

src/link/Elf.zig+16
......@@ -2799,6 +2799,22 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
27992799 .p32 => @sizeOf(elf.Elf32_Sym),
28002800 .p64 => @sizeOf(elf.Elf64_Sym),
28012801 };
2802 const sym_align: u16 = switch (self.ptr_width) {
2803 .p32 => @alignOf(elf.Elf32_Sym),
2804 .p64 => @alignOf(elf.Elf64_Sym),
2805 };
2806 const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size;
2807 if (needed_size > self.allocatedSize(syms_sect.sh_offset)) {
2808 // Move all the symbols to a new file location.
2809 const new_offset = self.findFreeSpace(needed_size, sym_align);
2810 const existing_size = @as(u64, syms_sect.sh_info) * sym_size;
2811 const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size);
2812 if (amt != existing_size) return error.InputOutput;
2813 syms_sect.sh_offset = new_offset;
2814 }
2815 syms_sect.sh_size = needed_size; // anticipating adding the global symbols later
2816 self.shdr_table_dirty = true; // TODO look into only writing one section
2817
28022818 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
28032819 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;
28042820 switch (self.ptr_width) {