segments.py: fix TLS checks in section_in_segment() (#275)
authorAndreas Ziegler <andreas.ziegler@fau.de>
Tue, 4 Feb 2020 13:30:09 +0000 (14:30 +0100)
committerGitHub <noreply@github.com>
Tue, 4 Feb 2020 13:30:09 +0000 (05:30 -0800)
While the comment in section_in_segment() suggests that the
logic follows the logic inside ELF_SECTION_IN_SEGMENT_1 with
the strict parameter set, all of the checks in the binutils
macro are written so that they must succeed for the section
to be contained in the current segment. In our implementation,
however, the checks were not properly negated.

This showed in the case of .tdata and .tbss which did not
appear in the section to segment mapping (these sections are
found in glibc, for example).

Fix it up by aligning the logic more closely to the binutils
macro by implementing the same logic and returning False only
if the checks fail. Additionally, introduce the third check
from the upstream binutils which checks the combination of
SHT_ALLOC sections and PT_LOAD-like segments.

Furthermore, in the original check, the PT_GNU_RELRO type was
misspelled with a 0 (zero) instead of an O so this check
could never have worked.

Fixes: #263
elftools/elf/segments.py

index 16560bcd8152462214f892d055661f33617d4cb1..0c318e171d6e07cd993525cb5b90daae17d8242b 100644 (file)
@@ -40,15 +40,23 @@ class Segment(object):
         sectype = section['sh_type']
         secflags = section['sh_flags']
 
-        # Only PT_LOAD, PT_GNU_RELR0 and PT_TLS segments can contain SHF_TLS
+        # Only PT_LOAD, PT_GNU_RELRO and PT_TLS segments can contain SHF_TLS
         # sections
         if (    secflags & SH_FLAGS.SHF_TLS and
-                segtype in ('PT_TLS', 'PT_GNU_RELR0', 'PT_LOAD')):
-            return False
+                segtype in ('PT_TLS', 'PT_GNU_RELRO', 'PT_LOAD')):
+            pass
         # PT_TLS segment contains only SHF_TLS sections, PT_PHDR no sections
         # at all
-        elif (  (secflags & SH_FLAGS.SHF_TLS) != 0 and
+        elif (  (secflags & SH_FLAGS.SHF_TLS) == 0 and
                 segtype not in ('PT_TLS', 'PT_PHDR')):
+            pass
+        else:
+            return False
+
+        # PT_LOAD and similar segments only have SHF_ALLOC sections.
+        if (    (secflags & SH_FLAGS.SHF_ALLOC) == 0 and
+                segtype in ('PT_LOAD', 'PT_DYNAMIC', 'PT_GNU_EH_FRAME',
+                            'PT_GNU_RELRO', 'PT_GNU_STACK')):
             return False
 
         # In ELF_SECTION_IN_SEGMENT_STRICT the flag check_vma is on, so if