Check for read-only relocations. GNU_RELRO program header must exist Dynamic section must have BIND_NOW flag
(binary)
| 17 | LIEF_ELF_ARCH_RISCV = lief.ELF.ARCH(243) |
| 18 | |
| 19 | def check_ELF_RELRO(binary) -> bool: |
| 20 | ''' |
| 21 | Check for read-only relocations. |
| 22 | GNU_RELRO program header must exist |
| 23 | Dynamic section must have BIND_NOW flag |
| 24 | ''' |
| 25 | have_gnu_relro = False |
| 26 | for segment in binary.segments: |
| 27 | # Note: not checking p_flags == PF_R: here as linkers set the permission differently |
| 28 | # This does not affect security: the permission flags of the GNU_RELRO program |
| 29 | # header are ignored, the PT_LOAD header determines the effective permissions. |
| 30 | # However, the dynamic linker need to write to this area so these are RW. |
| 31 | # Glibc itself takes care of mprotecting this area R after relocations are finished. |
| 32 | # See also https://marc.info/?l=binutils&m=1498883354122353 |
| 33 | if segment.type == lief.ELF.SEGMENT_TYPES.GNU_RELRO: |
| 34 | have_gnu_relro = True |
| 35 | |
| 36 | have_bindnow = False |
| 37 | try: |
| 38 | flags = binary.get(lief.ELF.DYNAMIC_TAGS.FLAGS) |
| 39 | if flags.value & lief.ELF.DYNAMIC_FLAGS.BIND_NOW: |
| 40 | have_bindnow = True |
| 41 | except: |
| 42 | have_bindnow = False |
| 43 | |
| 44 | return have_gnu_relro and have_bindnow |
| 45 | |
| 46 | def check_ELF_Canary(binary) -> bool: |
| 47 | ''' |