From patchwork Fri Feb 28 10:07:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 38346 Received: (qmail 56041 invoked by alias); 28 Feb 2020 10:08:16 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 56033 invoked by uid 89); 28 Feb 2020 10:08:16 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE autolearn=unavailable version=3.3.1 spammy= X-HELO: us-smtp-1.mimecast.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1582884493; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=9VBsP+BO29d/omV/QEZmM1MITToNVeOV5XDaCplggFk=; b=Keumz3P1RHyIxoAVcq32ioS9/LLUvGRTFKhIg0yDYo5ok2iISVLmMPDoP7uhRpAS8AD1I4 o5wrh8V5y/QYvBnwnBQ00mBhx/CQFRpEX/HDOVz9xQ4tX0y2feWzeQ+rIJ/jeQzk206Ya6 lUvuzvKBN1whn+qL6Bf+6N4Eay/IbP8= From: Florian Weimer To: John David Anglin , Helge Deller , Carlos O'Donell , David S. Miller Cc: libc-alpha@sourceware.org Subject: [HELP NEEDED] elf: Add elf/check-wx-segment, a test for the presence of WX segments Date: Fri, 28 Feb 2020 11:07:52 +0100 Message-ID: <87tv3buirr.fsf@oldenburg2.str.redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Would you please help me to add proper comments to the xfails for the hppa and sparc ports? Currently, both (sets of) targets have an writable and executable load segment. Is this because the lack of secure PLT support, like originally on POWER? The new test passes everywhere else. Thanks, Florian 8<------------------------------------------------------------------8< Writable, executable segments defeat security hardening. The existing check for DT_TEXTREL does not catch this. ----- elf/Makefile | 7 +++ scripts/check-wx-segment.py | 85 +++++++++++++++++++++++++++++++++++ sysdeps/sparc/Makefile | 4 ++ sysdeps/unix/sysv/linux/hppa/Makefile | 7 ++- 4 files changed, 101 insertions(+), 2 deletions(-) diff --git a/elf/Makefile b/elf/Makefile index a137143db7..da689a2c7b 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -402,6 +402,7 @@ tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \ $(objpfx)tst-rtld-preload.out endif tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \ + $(objpfx)check-wx-segment.out \ $(objpfx)check-localplt.out $(objpfx)check-initfini.out endif @@ -1180,6 +1181,12 @@ $(objpfx)check-execstack.out: $(..)scripts/check-execstack.awk \ $(evaluate-test) generated += check-execstack.out +$(objpfx)check-wx-segment.out: $(..)scripts/check-wx-segment.py \ + $(all-built-dso:=.phdr) + $(PYTHON) $^ --xfail="$(check-wx-segment-xfail)" > $@; \ + $(evaluate-test) +generated += check-wx-segment.out + $(objpfx)tst-dlmodcount: $(libdl) $(objpfx)tst-dlmodcount.out: $(test-modules) diff --git a/scripts/check-wx-segment.py b/scripts/check-wx-segment.py new file mode 100644 index 0000000000..c3553eeef9 --- /dev/null +++ b/scripts/check-wx-segment.py @@ -0,0 +1,85 @@ +#!/usr/bin/python3 +# Check ELF program headers for WX segments. +# Copyright (C) 2020 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# . + +"""Check that the program headers do not contain write-exec segments.""" + +import argparse +import os.path +import re +import sys + +# Regular expression to extract the RWE flags field. The +# address/offset columns have varying width. +RE_LOAD = re.compile( + r'^ LOAD +(?:0x[0-9a-fA-F]+ +){5}([R ][W ][ E]) +0x[0-9a-fA-F]+\n\Z') + +def process_file(path, inp, xfail): + """Analyze one input file.""" + + errors = 0 + for line in inp: + error = None + if line.startswith(' LOAD '): + match = RE_LOAD.match(line) + if match is None: + error = 'Invalid LOAD line' + else: + flags, = match.groups() + if 'W' in flags and 'E' in flags: + if xfail: + print('{}: warning: WX segment (as expected)'.format( + path)) + else: + error = 'WX segment' + + if error is not None: + print('{}: error: {}: {!r}'.format(path, error, line.strip())) + errors += 1 + + if xfail and errors == 0: + print('{}: warning: missing expected WX segment'.format(path)) + return errors + + +def main(): + """The main entry point.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--xfail', + help='Run this number of jobs in parallel', + type=str, default='') + parser.add_argument('phdrs', + help='Files containing readelf -Wl output', + nargs='*') + opts = parser.parse_args(sys.argv) + + xfails = set(opts.xfail.split(' ')) + xfails_all = opts.xfail.strip() == '*' + + errors = 0 + for path in opts.phdrs: + xfail = ((os.path.basename(path) + '.phdrs') in xfails + or xfails_all) + with open(path) as inp: + errors += process_file(path, inp, xfail) + if errors > 0: + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/sysdeps/sparc/Makefile b/sysdeps/sparc/Makefile index 38b33af6e0..3ceb8d0298 100644 --- a/sysdeps/sparc/Makefile +++ b/sysdeps/sparc/Makefile @@ -16,6 +16,10 @@ CPPFLAGS-crti.S += -fPIC CPPFLAGS-crtn.S += -fPIC endif +ifeq ($(subdir),elf) +test-xfail-check-wx-segment = * +endif # $(subdir) == elf + # nscd uses atomic_spin_nop which in turn requires cpu_relax ifeq ($(subdir),nscd) routines += cpu_relax diff --git a/sysdeps/unix/sysv/linux/hppa/Makefile b/sysdeps/unix/sysv/linux/hppa/Makefile index e1637f54f5..1e7340418b 100644 --- a/sysdeps/unix/sysv/linux/hppa/Makefile +++ b/sysdeps/unix/sysv/linux/hppa/Makefile @@ -3,9 +3,12 @@ ifeq ($(subdir),stdlib) gen-as-const-headers += ucontext_i.sym endif +ifeq ($(subdir),elf) # Supporting non-executable stacks on HPPA requires changes to both # the Linux kernel and glibc. The kernel currently needs an executable # stack for syscall restarts and signal returns. -ifeq ($(subdir),elf) test-xfail-check-execstack = yes -endif + +test-xfail-check-wx-segment = * + +endif # $(subdir) == elf