|
|
7c0489 |
commit 0499a353a6e196f468e7ec554cb13c82011f0e36
|
|
|
7c0489 |
Author: Florian Weimer <fweimer@redhat.com>
|
|
|
7c0489 |
Date: Mon Mar 2 14:24:27 2020 +0100
|
|
|
7c0489 |
|
|
|
7c0489 |
elf: Add elf/check-wx-segment, a test for the presence of WX segments
|
|
|
7c0489 |
|
|
|
7c0489 |
Writable, executable segments defeat security hardening. The
|
|
|
7c0489 |
existing check for DT_TEXTREL does not catch this.
|
|
|
7c0489 |
|
|
|
7c0489 |
hppa and SPARC currently keep the PLT in an RWX load segment.
|
|
|
7c0489 |
|
|
|
7c0489 |
# Conflicts:
|
|
|
7c0489 |
# sysdeps/sparc/Makefile
|
|
|
7c0489 |
|
|
|
7c0489 |
diff --git a/elf/Makefile b/elf/Makefile
|
|
|
7c0489 |
index f1a16fe8ca594c57..a52d9b1f6a4364a7 100644
|
|
|
7c0489 |
--- a/elf/Makefile
|
|
|
7c0489 |
+++ b/elf/Makefile
|
|
|
7c0489 |
@@ -378,6 +378,7 @@ tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \
|
|
|
7c0489 |
$(objpfx)tst-rtld-preload.out
|
|
|
7c0489 |
endif
|
|
|
7c0489 |
tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
|
|
|
7c0489 |
+ $(objpfx)check-wx-segment.out \
|
|
|
7c0489 |
$(objpfx)check-localplt.out $(objpfx)check-initfini.out
|
|
|
7c0489 |
endif
|
|
|
7c0489 |
|
|
|
7c0489 |
@@ -1148,6 +1149,12 @@ $(objpfx)check-execstack.out: $(..)scripts/check-execstack.awk \
|
|
|
7c0489 |
$(evaluate-test)
|
|
|
7c0489 |
generated += check-execstack.out
|
|
|
7c0489 |
|
|
|
7c0489 |
+$(objpfx)check-wx-segment.out: $(..)scripts/check-wx-segment.py \
|
|
|
7c0489 |
+ $(all-built-dso:=.phdr)
|
|
|
7c0489 |
+ $(PYTHON) $^ --xfail="$(check-wx-segment-xfail)" > $@; \
|
|
|
7c0489 |
+ $(evaluate-test)
|
|
|
7c0489 |
+generated += check-wx-segment.out
|
|
|
7c0489 |
+
|
|
|
7c0489 |
$(objpfx)tst-dlmodcount: $(libdl)
|
|
|
7c0489 |
$(objpfx)tst-dlmodcount.out: $(test-modules)
|
|
|
7c0489 |
|
|
|
7c0489 |
diff --git a/scripts/check-wx-segment.py b/scripts/check-wx-segment.py
|
|
|
7c0489 |
new file mode 100644
|
|
|
7c0489 |
index 0000000000000000..e1fa79387ce22c4b
|
|
|
7c0489 |
--- /dev/null
|
|
|
7c0489 |
+++ b/scripts/check-wx-segment.py
|
|
|
7c0489 |
@@ -0,0 +1,85 @@
|
|
|
7c0489 |
+#!/usr/bin/python3
|
|
|
7c0489 |
+# Check ELF program headers for WX segments.
|
|
|
7c0489 |
+# Copyright (C) 2020 Free Software Foundation, Inc.
|
|
|
7c0489 |
+# This file is part of the GNU C Library.
|
|
|
7c0489 |
+#
|
|
|
7c0489 |
+# The GNU C Library is free software; you can redistribute it and/or
|
|
|
7c0489 |
+# modify it under the terms of the GNU Lesser General Public
|
|
|
7c0489 |
+# License as published by the Free Software Foundation; either
|
|
|
7c0489 |
+# version 2.1 of the License, or (at your option) any later version.
|
|
|
7c0489 |
+#
|
|
|
7c0489 |
+# The GNU C Library is distributed in the hope that it will be useful,
|
|
|
7c0489 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
7c0489 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
7c0489 |
+# Lesser General Public License for more details.
|
|
|
7c0489 |
+#
|
|
|
7c0489 |
+# You should have received a copy of the GNU Lesser General Public
|
|
|
7c0489 |
+# License along with the GNU C Library; if not, see
|
|
|
7c0489 |
+# <https://www.gnu.org/licenses/>.
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+"""Check that the program headers do not contain write-exec segments."""
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+import argparse
|
|
|
7c0489 |
+import os.path
|
|
|
7c0489 |
+import re
|
|
|
7c0489 |
+import sys
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+# Regular expression to extract the RWE flags field. The
|
|
|
7c0489 |
+# address/offset columns have varying width.
|
|
|
7c0489 |
+RE_LOAD = re.compile(
|
|
|
7c0489 |
+ r'^ LOAD +(?:0x[0-9a-fA-F]+ +){5}([R ][W ][ E]) +0x[0-9a-fA-F]+\n\Z')
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+def process_file(path, inp, xfail):
|
|
|
7c0489 |
+ """Analyze one input file."""
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+ errors = 0
|
|
|
7c0489 |
+ for line in inp:
|
|
|
7c0489 |
+ error = None
|
|
|
7c0489 |
+ if line.startswith(' LOAD '):
|
|
|
7c0489 |
+ match = RE_LOAD.match(line)
|
|
|
7c0489 |
+ if match is None:
|
|
|
7c0489 |
+ error = 'Invalid LOAD line'
|
|
|
7c0489 |
+ else:
|
|
|
7c0489 |
+ flags, = match.groups()
|
|
|
7c0489 |
+ if 'W' in flags and 'E' in flags:
|
|
|
7c0489 |
+ if xfail:
|
|
|
7c0489 |
+ print('{}: warning: WX segment (as expected)'.format(
|
|
|
7c0489 |
+ path))
|
|
|
7c0489 |
+ else:
|
|
|
7c0489 |
+ error = 'WX segment'
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+ if error is not None:
|
|
|
7c0489 |
+ print('{}: error: {}: {!r}'.format(path, error, line.strip()))
|
|
|
7c0489 |
+ errors += 1
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+ if xfail and errors == 0:
|
|
|
7c0489 |
+ print('{}: warning: missing expected WX segment'.format(path))
|
|
|
7c0489 |
+ return errors
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+def main():
|
|
|
7c0489 |
+ """The main entry point."""
|
|
|
7c0489 |
+ parser = argparse.ArgumentParser(description=__doc__)
|
|
|
7c0489 |
+ parser.add_argument('--xfail',
|
|
|
7c0489 |
+ help='Mark input files as XFAILed ("*" for all)',
|
|
|
7c0489 |
+ type=str, default='')
|
|
|
7c0489 |
+ parser.add_argument('phdrs',
|
|
|
7c0489 |
+ help='Files containing readelf -Wl output',
|
|
|
7c0489 |
+ nargs='*')
|
|
|
7c0489 |
+ opts = parser.parse_args(sys.argv)
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+ xfails = set(opts.xfail.split(' '))
|
|
|
7c0489 |
+ xfails_all = opts.xfail.strip() == '*'
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+ errors = 0
|
|
|
7c0489 |
+ for path in opts.phdrs:
|
|
|
7c0489 |
+ xfail = ((os.path.basename(path) + '.phdrs') in xfails
|
|
|
7c0489 |
+ or xfails_all)
|
|
|
7c0489 |
+ with open(path) as inp:
|
|
|
7c0489 |
+ errors += process_file(path, inp, xfail)
|
|
|
7c0489 |
+ if errors > 0:
|
|
|
7c0489 |
+ sys.exit(1)
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+if __name__ == '__main__':
|
|
|
7c0489 |
+ main()
|
|
|
7c0489 |
diff --git a/sysdeps/sparc/Makefile b/sysdeps/sparc/Makefile
|
|
|
7c0489 |
index 3f0c0964002560f0..a1004e819c9b0c38 100644
|
|
|
7c0489 |
--- a/sysdeps/sparc/Makefile
|
|
|
7c0489 |
+++ b/sysdeps/sparc/Makefile
|
|
|
7c0489 |
@@ -16,5 +16,14 @@ CPPFLAGS-crti.S += -fPIC
|
|
|
7c0489 |
CPPFLAGS-crtn.S += -fPIC
|
|
|
7c0489 |
endif
|
|
|
7c0489 |
|
|
|
7c0489 |
+ifeq ($(subdir),elf)
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+# Lazy binding on SPARC rewrites the PLT sequence. See the Solaris
|
|
|
7c0489 |
+# Linker and Libraries Guide, section SPARC: Procedure Linkage Table.
|
|
|
7c0489 |
+# <https://docs.oracle.com/cd/E19455-01/816-0559/chapter6-1236/index.html>
|
|
|
7c0489 |
+test-xfail-check-wx-segment = *
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+endif # $(subdir) == elf
|
|
|
7c0489 |
+
|
|
|
7c0489 |
# The assembler on SPARC needs the -fPIC flag even when it's assembler code.
|
|
|
7c0489 |
ASFLAGS-.os += -fPIC
|
|
|
7c0489 |
diff --git a/sysdeps/unix/sysv/linux/hppa/Makefile b/sysdeps/unix/sysv/linux/hppa/Makefile
|
|
|
7c0489 |
index e1637f54f508c007..c89ec8318208205d 100644
|
|
|
7c0489 |
--- a/sysdeps/unix/sysv/linux/hppa/Makefile
|
|
|
7c0489 |
+++ b/sysdeps/unix/sysv/linux/hppa/Makefile
|
|
|
7c0489 |
@@ -3,9 +3,14 @@ ifeq ($(subdir),stdlib)
|
|
|
7c0489 |
gen-as-const-headers += ucontext_i.sym
|
|
|
7c0489 |
endif
|
|
|
7c0489 |
|
|
|
7c0489 |
+ifeq ($(subdir),elf)
|
|
|
7c0489 |
# Supporting non-executable stacks on HPPA requires changes to both
|
|
|
7c0489 |
# the Linux kernel and glibc. The kernel currently needs an executable
|
|
|
7c0489 |
# stack for syscall restarts and signal returns.
|
|
|
7c0489 |
-ifeq ($(subdir),elf)
|
|
|
7c0489 |
test-xfail-check-execstack = yes
|
|
|
7c0489 |
-endif
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+# On hppa, the PLT is executable because it contains an executable
|
|
|
7c0489 |
+# trampoline used during lazy binding.
|
|
|
7c0489 |
+test-xfail-check-wx-segment = *
|
|
|
7c0489 |
+
|
|
|
7c0489 |
+endif # $(subdir) == elf
|