From patchwork Thu Nov 28 17:36:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 845953 Delivered-To: patch@linaro.org Received: by 2002:adf:f2c4:0:b0:382:43a8:7b94 with SMTP id d4csp378806wrp; Thu, 28 Nov 2024 09:43:28 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVxH9nO5aQDKP9EkwF1rSVOcKnD5UaRpCSBMyen+YsPegUtn89WIZFYzCoLQQtO/voC7SOGKg==@linaro.org X-Google-Smtp-Source: AGHT+IEzCoCslF93BBZDC3cVWASocXVAzdx14exZDEGdpPBRijrnpEYqCz9+H2DEwbC2v9WTULZg X-Received: by 2002:a05:620a:44c9:b0:7b1:800e:ef88 with SMTP id af79cd13be357-7b67c4b481emr1042410385a.60.1732815808130; Thu, 28 Nov 2024 09:43:28 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1732815808; cv=pass; d=google.com; s=arc-20240605; b=Ji+dYphWpSddJlRLds/a3WQcrY5ZkcI+aJ+t8r48Ha2AW8HNkIXn+uH90EFQGZlHGo s1x8lb2XU1oLvRexnn3FInz1ao65cw1GzOhuA3O6dYxva9i8LcomyQHowX6lFVQ7Vzet RnsINAGFaEjosuFWf+VKkIqD5hdycu/wXD1nel5+ofDnurRk/biGYUCy/CJwNVsLz3Ld L0v4IjCRMBNKKNDbPiCEA4MbJsascH6kYe742N6oqIDH+XAzxTeSco/Cdk6urQNNH0R/ pDwCXo1ZvKbUIjN37w0UptPKHh3iMW3vbpWBhCtGXg+wI+MTQHSoCTeFTFomDIWD14G6 EryA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=+8KrnfauYaJjYtrwZ1iNVu36eg0KTS2J4b7L0CcniRE=; fh=5vlP+0ToNsZNUEx4IDYFBtVkL7R0+LPY9AvG1oUICyQ=; b=Ze1jpUwoZ1KVWFL/q2yxb27xovzTA6c8DPtDznp57YdUhGEqsfeLGDXGXI6MlbBjnX CtZApFAZwO4CHr1MCgqzKkN4QmETzQ0xSNqYg2EpfRKFsEnWacX8Aza7nqLiALkaXFky C5CG8lZvLziQh4YNefBNkmrGPk68Wg3dTeGt5Jg6l7sa/5t5nNeWU49xmKiRnEZx3r1i Bz9oX16yAUh1frK0FEP6NNcNayg96acqWeI6s9UAq1s04LVz6T/QkvZEWWzaQ0WyoNBO CxEr/LYBlrF9phN6K58EXjH/Xbdx+KRRXn3ynwV5gn7ahcxjArIxrC26C4qAcZJ8Pd+N TuuA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rtYUDeKu; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="libc-alpha-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id af79cd13be357-7b6849b2219si265264285a.264.2024.11.28.09.43.27 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Nov 2024 09:43:28 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rtYUDeKu; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="libc-alpha-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F01EC3858C2B for ; Thu, 28 Nov 2024 17:43:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F01EC3858C2B Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=rtYUDeKu X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id EFD283858D29 for ; Thu, 28 Nov 2024 17:39:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EFD283858D29 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org EFD283858D29 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::42b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1732815543; cv=none; b=IHi/G8WpqRNBRJN9mHvtZf7kvD+ddtJqjfbZEl4feGT2QT7cim5ji7hoMYpjtgWyqot49MM8FjT53viOQamK1HEe85089YPL5nViwRBw19j4CmAMN2VDjPy+0QvhOLFDToUYgnEnJ90AeQ/0LBe6n97SBw/qZC6OX9oaESC1dTI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1732815543; c=relaxed/simple; bh=pbufU+N9y0WOuCoUnB7vWE9b+KfpND/Oxhdtpjk71EY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=KTnDP+rWp8eRvJrJ3qD5aeeiZcum/0rt5/RyBZ3n6uamUjjKMLerttOAN6TA1BVG+5v/dvgwW7wPqUv9fd2cd7RzeLdSykCvdJVFYjD+3FxgsAi7BryT4Oa9dP4hPaOxqROEp+e8kr/ld82BVzyQIuqjMYjoCyY/9ZdgHkO6QTc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EFD283858D29 Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-724d8422dbaso978526b3a.0 for ; Thu, 28 Nov 2024 09:39:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1732815541; x=1733420341; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+8KrnfauYaJjYtrwZ1iNVu36eg0KTS2J4b7L0CcniRE=; b=rtYUDeKuG7CHV9QaHFbgWED4V8mj2kfGWkI/oPnmxCrJD7Y3nuZKYyprZr45W4zDlO fXZhryPFH+yJtK5da/E6UAJ7rfSwRCxw1xyPVHCjGXTPmd5xApYHyalsE/xQBAV0a5U4 6ivpemYwy3aeMITeuV4Q9zHqQJKJMXlbTp3GwOmLgIPgIDIV6HBWqhGZoTxMzU/ALwGd tHZGrQ9eqJPj8YjNzX9vGaY9mH6l/o7vWdZbqSX6tIF+YXsZEXTVphHsRPoiHj0RdJjn fB6YRhkdrs+l/mXusb6KZZHUHT74nT55ZDtgCZwtY9dW6bvFvTU7REg/cfs51wzqcCGJ msBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732815541; x=1733420341; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+8KrnfauYaJjYtrwZ1iNVu36eg0KTS2J4b7L0CcniRE=; b=i7zEvl5rmyTaKw53CmnFCMxzh9lN8Jlfc+tHSpSSkj4aNo3AaGz+ZR2J+xbju+YyFc +BdO/pmbsgI21WdxRC4ZcQZRc6NPyksoj5mdvMX0RhSuXkPF7fMpIGeYLu4rBE/Fsywh ldry+lj4dmUdyh4dAvU1gbL3Jc+xNwnbfXbVCTmexagm7uu7/S1UP8RY9Rg6dGfjPz11 9v/X79uFO66DdUyVIMMwskfu0OxUvhDrrd8yQAUlPyoHEsLB3KhDqFy8r6B6NXpEBiBc 4MAqQ//5R6NbFja+vLH+4BjS4CCUCXI8cNVxp/tGbzyklDpNcopb2G3wRKdaFeyEvYS+ 8iYw== X-Gm-Message-State: AOJu0YzLLkRIYq2hu142ZOuo1GswAF/par7rWUFV3eGP/i9BY5ju1vf9 +6aUjnORlou8cwTqxOr7t9r1QVOsy8Qn6xjlujcvds7TZ2W1TMLL48/aHuVeNt0UHM6botTDpGU oHfsBdQ== X-Gm-Gg: ASbGncsYFB+gqPjTBx97ftziGqsxKJ3JnOIJxAkTWHGBXiyIkUwo5xNFgZ2qhyl3QS3 HapvilLlUKEgjaB1i4tAcJ2eLAgozUiNRmMG5Fbjb1Nw3yW6MsbGHT0h2AXwonoLhvoptncaBY1 zGwWdqM9orCGUeiWeft5qbvKof4j+Ezl7NJgborpQgsLoPRFGHa0p+WJZm0P7sFH0KOzGqexOz+ mruHdabnr3+hxfeXKpJfKz3lfqMcDFxz+CPA/zqG6V/JjdWB0F3i1JrtdN282k= X-Received: by 2002:a05:6a00:4f93:b0:71e:4786:98ee with SMTP id d2e1a72fcca58-7253015eecdmr10909457b3a.21.1732815541494; Thu, 28 Nov 2024 09:39:01 -0800 (PST) Received: from mandiga.. ([2804:1b3:a7c1:68c8:2c85:3a76:728e:ead2]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72541849d6csm1860356b3a.182.2024.11.28.09.39.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Nov 2024 09:39:01 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Florian Weimer Subject: [PATCH v5 4/4] elf: Add glibc.rtld.execstack Date: Thu, 28 Nov 2024 14:36:45 -0300 Message-ID: <20241128173851.1920696-5-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241128173851.1920696-1-adhemerval.zanella@linaro.org> References: <20241128173851.1920696-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patch=linaro.org@sourceware.org The new tunable can be used to control whether executable stacks are allowed from either the main program or dependencies. The default is to allow executable stacks. The executable stacks default permission is checked agains the one provided by the PT_GNU_STACK from program headers (if present). The tunable also disables the stack permission change if any dependency requires an executable stack at loading time. Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. --- NEWS | 5 ++++ elf/Makefile | 44 ++++++++++++++++++++++++++++++++++ elf/dl-load.c | 4 +++- elf/dl-support.c | 5 ++++ elf/dl-tunables.list | 6 +++++ elf/rtld.c | 4 ++++ elf/tst-rtld-list-tunables.exp | 1 + manual/tunables.texi | 19 +++++++++++++++ 8 files changed, 87 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8cb5597631..c2e8bf4b34 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,11 @@ Major new features: liable to change. Features from C2Y are also enabled by _GNU_SOURCE, or by compiling with "gcc -std=gnu2y". +* A new tunable, glibc.rtld.execstack, can be used to control whether + executable stacks are allowed from main program, either implicitly due + a mising GNU_STACK ELF header or explicit explicitly because of the + executable bit in GNU_STACK. The default is to allow executable stacks. + Deprecated and removed features, and other changes affecting compatibility: * The big-endian ARC port (arceb-linux-gnu) has been removed. diff --git a/elf/Makefile b/elf/Makefile index bdd169f4e8..6dd15c63d9 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -556,6 +556,13 @@ tests-execstack-yes = \ tests-execstack-static-yes = \ tst-execstack-prog-static # tests-execstack-static-yes +ifeq (yes,$(run-built-tests)) +tests-execstack-special-yes = \ + $(objpfx)tst-execstack-needed-noexecstack.out \ + $(objpfx)tst-execstack-prog-noexecstack.out \ + $(objpfx)tst-execstack-prog-static-noexecstack.out \ + # tests-execstack-special-yes +endif # $(run-built-tests) endif ifeq ($(have-depaudit),yes) tests += \ @@ -651,6 +658,7 @@ $(objpfx)tst-rtld-dash-dash.out: tst-rtld-dash-dash.sh $(objpfx)ld.so tests += $(tests-execstack-$(have-z-execstack)) tests-static+= $(tests-execstack-static-$(have-z-execstack)) +tests-special += $(tests-execstack-special-$(have-z-execstack)) ifeq ($(run-built-tests),yes) tests-special += \ $(objpfx)tst-ldconfig-X.out \ @@ -1923,6 +1931,42 @@ CFLAGS-tst-execstack-mod.c += -Wno-trampolines LDFLAGS-tst-execstack-prog-static = -Wl,-z,execstack CFLAGS-tst-execstack-prog-static.c += -Wno-trampolines + +ifeq (yes,$(build-hardcoded-path-in-tests)) +tst-execstack-prog-noexecstack-msg = "Fatal glibc error: executable stack is not allowed$$" +else +tst-execstack-prog-noexecstack-msg = "error while loading shared libraries:.*cannot enable executable stack as shared object requires:" +endif + +$(objpfx)tst-execstack-prog-noexecstack.out: $(objpfx)tst-execstack-prog + $(test-program-cmd-before-env) \ + $(run-program-env) \ + GLIBC_TUNABLES=glibc.rtld.execstack=0 \ + $(test-program-cmd-after-env) $< \ + > $@ 2>&1; echo "status: $$?" >> $@; \ + grep -q $(tst-execstack-prog-noexecstack-msg) $@ \ + && grep -q '^status: 127$$' $@; \ + $(evaluate-test) + +$(objpfx)tst-execstack-needed-noexecstack.out: $(objpfx)tst-execstack-needed + $(test-program-cmd-before-env) \ + $(run-program-env) \ + GLIBC_TUNABLES=glibc.rtld.execstack=0 \ + $(test-program-cmd-after-env) $< \ + > $@ 2>&1; echo "status: $$?" >> $@; \ + grep -q 'error while loading shared libraries:.*cannot enable executable stack as shared object requires:' $@ \ + && grep -q '^status: 127$$' $@; \ + $(evaluate-test) + +$(objpfx)tst-execstack-prog-static-noexecstack.out: $(objpfx)tst-execstack-prog-static + $(test-program-cmd-before-env) \ + $(run-program-env) \ + GLIBC_TUNABLES=glibc.rtld.execstack=0 \ + $< \ + > $@ 2>&1; echo "status: $$?" >> $@; \ + grep -q 'Fatal glibc error: executable stack is not allowed$$' $@ \ + && grep -q '^status: 127$$' $@; \ + $(evaluate-test) endif LDFLAGS-tst-array2 = -Wl,--no-as-needed diff --git a/elf/dl-load.c b/elf/dl-load.c index f525eec662..0e402968ac 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -32,6 +32,7 @@ #include #include #include +#include /* Type for the buffer we put the ELF header and hopefully the program header. This buffer does not really have to be too large. In most @@ -1284,7 +1285,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, /* The stack is presently not executable, but this module requires that it be executable. Only tries to change the stack protection during process startup. */ - if ((mode & __RTLD_DLOPEN) == 0) + if ((mode & __RTLD_DLOPEN) == 0 + && TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 1) errval = _dl_make_stack_executable (stack_endp); else errval = EINVAL; diff --git a/elf/dl-support.c b/elf/dl-support.c index fe1f8c8f6a..73fcd33892 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -45,6 +45,7 @@ #include #include #include +#include extern char *__progname; char **_dl_argv = &__progname; /* This is checked for some error messages. */ @@ -331,6 +332,10 @@ _dl_non_dynamic_init (void) break; } + if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X) + && TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0) + _dl_fatal_printf ("Fatal glibc error: executable stack is not allowed\n"); + call_function_static_weak (_dl_find_object_init); /* Setup relro on the binary itself. */ diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list index 40ac5b3776..8e656296bb 100644 --- a/elf/dl-tunables.list +++ b/elf/dl-tunables.list @@ -135,6 +135,12 @@ glibc { maxval: 1 default: 0 } + execstack { + type: INT_32 + minval: 0 + maxval: 1 + default: 1 + } } mem { diff --git a/elf/rtld.c b/elf/rtld.c index 3b232f8525..baa39b3351 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1644,6 +1644,10 @@ dl_main (const ElfW(Phdr) *phdr, bool has_interp = rtld_setup_main_map (main_map); + if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X) + && TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0) + _dl_fatal_printf ("Fatal glibc error: executable stack is not allowed\n"); + /* If the current libname is different from the SONAME, add the latter as well. */ if (GL(dl_rtld_map).l_info[DT_SONAME] != NULL diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp index db0e1c86e9..9f5990f340 100644 --- a/elf/tst-rtld-list-tunables.exp +++ b/elf/tst-rtld-list-tunables.exp @@ -13,5 +13,6 @@ glibc.malloc.top_pad: 0x20000 (min: 0x0, max: 0x[f]+) glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+) glibc.rtld.dynamic_sort: 2 (min: 1, max: 2) glibc.rtld.enable_secure: 0 (min: 0, max: 1) +glibc.rtld.execstack: 1 (min: 0, max: 1) glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10) glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+) diff --git a/manual/tunables.texi b/manual/tunables.texi index 0b1b2898c0..c3e894f4fe 100644 --- a/manual/tunables.texi +++ b/manual/tunables.texi @@ -355,6 +355,25 @@ tests for @code{AT_SECURE} programs and not meant to be a security feature. The default value of this tunable is @samp{0}. @end deftp +@deftp Tunable glibc.rtld.execstack +@theglibc{} will use either the default architecture ABI flags (that might +contain the executable bit) or the value of @code{PT_GNU_STACK} (if present) +to define whether to mark the stack non-executable, and if the program or +any shared library dependency require an executable stack the loader will +change the main stack permission if kernel starts with a non executable stack. + +The @code{glibc.rtld.execstack} tunable allows the user to control how +to proceed regarding the stack execution bit. Setting its value to @code{0} +disables executable stacks, where @code{1} enables it. The default value +is @code{1}. + +When executable stacks are not allowed, and if the main program requires an +executable stack, the loader will fail with an error message. +@strong{NB:} Trying to load a dynamic shared library with @code{dlopen} or +@code{dlmopen} that requires an executable stack will always fail if the +default flags does not contain the executable bit. +@end deftp + @node Elision Tunables @section Elision Tunables @cindex elision tunables