Hi,
Against development versions of gcc/binutils elflint gives some complaints like:
section [24] '.tm_clone_table': alloc flag set but section not in any loaded segment
This is because that section's size is zero. So it is somewhat reasonable IMHO that the linker doesn't put it in any segment.
Is the following patch to elflint OK?
Thanks,
Mark
Can you show an example of eu-readelf -Sl output for an affected binary?
On Thu, 2012-04-26 at 09:50 -0700, Roland McGrath wrote:
Can you show an example of eu-readelf -Sl output for an affected binary?
Here is an example. The issue is section 24, which is the last PROGBITS alloc one, and is of size zero, it shares its offset with the NOBITS section right after it.
There are 38 section headers, starting at offset 0xb638:
Section Headers: [Nr] Name Type Addr Off Size ES Flags Lk Inf Al [ 0] NULL 0000000000000000 00000000 00000000 0 0 0 0 [ 1] .interp PROGBITS 0000000000400200 00000200 0000001c 0 A 0 0 1 [ 2] .note.ABI-tag NOTE 000000000040021c 0000021c 00000020 0 A 0 0 4 [ 3] .dynsym DYNSYM 0000000000400240 00000240 00000438 24 A 4 1 8 [ 4] .dynstr STRTAB 0000000000400678 00000678 0000026b 0 A 0 0 1 [ 5] .hash HASH 00000000004008e8 000008e8 00000150 4 A 3 0 8 [ 6] .gnu.version GNU_versym 0000000000400a38 00000a38 0000005a 2 A 3 0 2 [ 7] .gnu.version_r GNU_verneed 0000000000400a94 00000a94 00000060 0 A 4 2 4 [ 8] .rela.dyn RELA 0000000000400af8 00000af8 00000060 24 A 3 0 8 [ 9] .rela.plt RELA 0000000000400b58 00000b58 00000348 24 AI 3 11 8 [10] .init PROGBITS 0000000000400ea0 00000ea0 00000018 0 AX 0 0 4 [11] .plt PROGBITS 0000000000400ec0 00000ec0 00000240 16 AX 0 0 16 [12] .text PROGBITS 0000000000401100 00001100 00001548 0 AX 0 0 16 [13] .fini PROGBITS 0000000000402648 00002648 0000000e 0 AX 0 0 4 [14] .rodata PROGBITS 0000000000402660 00002660 000008a0 0 A 0 0 32 [15] .eh_frame PROGBITS 0000000000402f00 00002f00 000001bc 0 A 0 0 8 [16] .eh_frame_hdr PROGBITS 00000000004030bc 000030bc 00000054 0 A 0 0 4 [17] .dynamic DYNAMIC 0000000000404120 00003120 000001a0 16 WA 4 0 8 [18] .got PROGBITS 00000000004042c0 000032c0 00000008 0 WA 0 0 8 [19] .got.plt PROGBITS 00000000004042c8 000032c8 00000130 0 WA 0 0 8 [20] .data PROGBITS 0000000000404400 00003400 00000058 0 WA 0 0 32 [21] .ctors PROGBITS 0000000000404458 00003458 00000010 0 WA 0 0 8 [22] .dtors PROGBITS 0000000000404468 00003468 00000010 0 WA 0 0 8 [23] .jcr PROGBITS 0000000000404478 00003478 00000008 0 WA 0 0 8 [24] .tm_clone_table PROGBITS 0000000000404480 00003480 00000000 0 WA 0 0 8 [25] .bss NOBITS 0000000000404480 00003480 00000058 0 WA 0 0 16 [26] .comment PROGBITS 0000000000000000 00003480 00000056 1 MS 0 0 1 [27] .debug_info PROGBITS 0000000000000000 000034d6 00003120 0 0 0 1 [28] .debug_abbrev PROGBITS 0000000000000000 000065f6 0000047e 0 0 0 1 [29] .debug_loc PROGBITS 0000000000000000 00006a74 000022ce 0 0 0 1 [30] .debug_aranges PROGBITS 0000000000000000 00008d42 00000040 0 0 0 1 [31] .debug_ranges PROGBITS 0000000000000000 00008d82 00000690 0 0 0 1 [32] .debug_line PROGBITS 0000000000000000 00009412 00000623 0 0 0 1 [33] .debug_str PROGBITS 0000000000000000 00009a35 00000c67 1 MS 0 0 1 [34] .note.gnu.gold-version NOTE 0000000000000000 0000a69c 0000001c 0 0 0 4 [35] .symtab SYMTAB 0000000000000000 0000a6b8 00000960 24 36 44 8 [36] .strtab STRTAB 0000000000000000 0000b018 000004b6 0 0 0 1 [37] .shstrtab STRTAB 0000000000000000 0000b4ce 00000167 0 0 0 1
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000040 0x0000000000400040 0x0000000000400040 0x0001c0 0x0001c0 R 0x8 INTERP 0x000200 0x0000000000400200 0x0000000000400200 0x00001c 0x00001c R 0x1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x003110 0x003110 R E 0x1000 LOAD 0x003120 0x0000000000404120 0x0000000000404120 0x000360 0x0003b8 RW 0x1000 DYNAMIC 0x003120 0x0000000000404120 0x0000000000404120 0x0001a0 0x0001a0 RW 0x8 NOTE 0x00021c 0x000000000040021c 0x000000000040021c 0x000020 0x000020 R 0x4 GNU_EH_FRAME 0x0030bc 0x00000000004030bc 0x00000000004030bc 0x000054 0x000054 R 0x4 GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x0
Section to Segment mapping: Segment Sections... 00 01 [RO: .interp] 02 [RO: .interp .note.ABI-tag .dynsym .dynstr .hash .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame .eh_frame_hdr] 03 .dynamic .got .got.plt .data .ctors .dtors .jcr .bss 04 .dynamic 05 [RO: .note.ABI-tag] 06 [RO: .eh_frame_hdr] 07
But it *is* clearly inside the second PT_LOAD segment. It's just that the check is:
&& (phdr->p_offset + phdr->p_filesz > shdr->sh_offset || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset && shdr->sh_type == SHT_NOBITS)))
and it's on the cusp between p_filesz and p_memsz. So:
&& (phdr->p_offset + phdr->p_filesz > shdr->sh_offset || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset && shdr->sh_type == SHT_NOBITS) || (phdr->p_offset + phdr->p_filesz == shdr->sh_offset && shdr->sh_size == 0)))
or perhaps better overflow-proofed:
&& ((shdr->sh_offset - phdr->p_offset <= phdr->p_filesz && (shdr->sh_offset - phdr->p_offset < phdr->p_filesz || shdr->sh_size == 0)) || (shdr->sh_offset - phdr->p_offset < phdr->p_memsz && shdr->sh_type == SHT_NOBITS)))
I think we should accept these corner cases but not accept wild sh_addr or sh_offset values just because they are technically meaningless with a zero sh_size.
Thanks, Roland
On Fri, 2012-04-27 at 15:43 -0700, Roland McGrath wrote:
or perhaps better overflow-proofed:
&& ((shdr->sh_offset - phdr->p_offset <= phdr->p_filesz && (shdr->sh_offset - phdr->p_offset < phdr->p_filesz || shdr->sh_size == 0)) || (shdr->sh_offset - phdr->p_offset < phdr->p_memsz && shdr->sh_type == SHT_NOBITS)))
I think we should accept these corner cases but not accept wild sh_addr or sh_offset values just because they are technically meaningless with a zero sh_size.
That does make sense, and works for me. I have checked in the following:
diff --git a/src/ChangeLog b/src/ChangeLog index cae5e6b..af1d92b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2012-05-09 Roland McGrath roland@hack.frob.com + + * elflint (check_sections): Allow zero sized sections at (filesz) end + of segment. And make check overflow-proofed. + 2012-04-24 Mark Wielaard mjw@redhat.com
* readelf.c (print_ops): Add DW_OP_GNU_push_tls_address, diff --git a/src/elflint.c b/src/elflint.c index a03caac..7c56069 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -3716,8 +3716,10 @@ section [%2zu] '%s' is both executable and writable\n"), || (phdr->p_type == PT_TLS && (shdr->sh_flags & SHF_TLS) != 0)) && phdr->p_offset <= shdr->sh_offset - && (phdr->p_offset + phdr->p_filesz > shdr->sh_offset - || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset + && ((shdr->sh_offset - phdr->p_offset <= phdr->p_filesz + && (shdr->sh_offset - phdr->p_offset < phdr->p_filesz + || shdr->sh_size == 0)) + || (shdr->sh_offset - phdr->p_offset < phdr->p_memsz && shdr->sh_type == SHT_NOBITS))) { /* Found the segment. */
elfutils-devel@lists.fedorahosted.org