elf: Ignore GLIBC_TUNABLES for setuid/setgid binaries
[glibc.git] / scripts / check-wx-segment.py
bloba29c833c02fc81462d72d406b2050ce2e6f04fde
1 #!/usr/bin/python3
2 # Check ELF program headers for WX segments.
3 # Copyright (C) 2020-2023 Free Software Foundation, Inc.
4 # This file is part of the GNU C Library.
6 # The GNU C Library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # The GNU C Library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with the GNU C Library; if not, see
18 # <https://www.gnu.org/licenses/>.
20 """Check that the program headers do not contain write-exec segments."""
22 import argparse
23 import os.path
24 import re
25 import sys
27 # Regular expression to extract the RWE flags field. The
28 # address/offset columns have varying width.
29 RE_LOAD = re.compile(
30 r'^ LOAD +(?:0x[0-9a-fA-F]+ +){5}([R ][W ][ E]) +0x[0-9a-fA-F]+\n\Z')
32 def process_file(path, inp, xfail):
33 """Analyze one input file."""
35 errors = 0
36 for line in inp:
37 error = None
38 if line.startswith(' LOAD '):
39 match = RE_LOAD.match(line)
40 if match is None:
41 error = 'Invalid LOAD line'
42 else:
43 flags, = match.groups()
44 if 'W' in flags and 'E' in flags:
45 if xfail:
46 print('{}: warning: WX segment (as expected)'.format(
47 path))
48 else:
49 error = 'WX segment'
51 if error is not None:
52 print('{}: error: {}: {!r}'.format(path, error, line.strip()))
53 errors += 1
55 if xfail and errors == 0:
56 print('{}: warning: missing expected WX segment'.format(path))
57 return errors
60 def main():
61 """The main entry point."""
62 parser = argparse.ArgumentParser(description=__doc__)
63 parser.add_argument('--xfail',
64 help='Mark input files as XFAILed ("*" for all)',
65 type=str, default='')
66 parser.add_argument('phdrs',
67 help='Files containing readelf -Wl output',
68 nargs='*')
69 opts = parser.parse_args(sys.argv)
71 xfails = set(opts.xfail.split(' '))
72 xfails_all = opts.xfail.strip() == '*'
74 errors = 0
75 for path in opts.phdrs:
76 xfail = ((os.path.basename(path) + '.phdrs') in xfails
77 or xfails_all)
78 with open(path) as inp:
79 errors += process_file(path, inp, xfail)
80 if errors > 0:
81 sys.exit(1)
84 if __name__ == '__main__':
85 main()