From patchwork Thu Dec 26 17:57: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: 853701 Delivered-To: patch@linaro.org Received: by 2002:a5d:4888:0:b0:385:e875:8a9e with SMTP id g8csp4891753wrq; Thu, 26 Dec 2024 10:00:16 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVGozVl0OHo0Ia8dmAdc0gZkMgryZxG0dhQZ4nvbVuIBRRWN6eQuqHiDUOyr8e5h/Tu9IzZsA==@linaro.org X-Google-Smtp-Source: AGHT+IH6oSdpvgz2Lp0MQiri9ty8riOn8p6C7dgBjjGLY/EcXMbINoGxOADLu2zrFAt/1SBeM0zq X-Received: by 2002:a05:6214:2589:b0:6d8:7d7c:bdd5 with SMTP id 6a1803df08f44-6dd2339fe52mr382115076d6.36.1735236015857; Thu, 26 Dec 2024 10:00:15 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1735236015; cv=pass; d=google.com; s=arc-20240605; b=AoEkgbxPWA/zsH+/u8RJg8oOLFylu2Om61mJ63Gkyyzrqp7BMI8IiBJpN6lFdUfh4Z fm1F4dgyeUcRxx0wUXKHwznL+XrzENyEt/FKg9FTY1o/O0KRsgeSgEgAYauF/Gx5LI7m kb2dtxChKwhytKwREZntKlfW3egrot7j9DHq1CTb6D4sYn6ThPlZ4BDM+XOOUWeQL5kA e4Qjwiauy8qj2a8QFAcpuk85wlOkQMPQnxCeRGZmxEqlk3YrDw6azKGhjTEvyIpr4OlR nbWdbensmnIGJ7Wdn3YgktIuLnJz1LODX/ZUkwiAP4jrOHVuC2Ihx9eKpx3hQVE03Mny S/pw== 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=tDyRrIdSTi9ivAYiC1NwqgoUxluAWtbZt15rA8D0Rs8=; fh=xV8Gp349bHw1ljD2lFQRwhGaJ4bIEzpeFyS/N97S3Sw=; b=S4j6gtCdmpdj7YEmVw8tZ7eMf2k/km6bLhGzOR4W+ZX64jYCNrzgVGjjNgvZKRQ/Ja 759lBawcgI/mbWMPVbFS9gsRBQCrFhqbmjsd2wN1+y3DHNDsvSa2kaVHoerf3s3DkZCb vmTcfw9lkGymYibpyyDsHVSQ8QTn5/MYc44zawDsxTDj1//Q+ZD1DBPlA961MQsOQ9Yh pXQCVxMA0l9MWHYSZbDUZ6RGzbYmJhUB8LAZOY/o39nSp1LtloRkR8+UVu+NrvT6fhug 40v3rYQg03BaPnZJvcMrWFv1U0a3w1S5po4pLdsroRBWgP9u3H/yBqIQ1LTLQFd6xDP1 WRww==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=peVta0fH; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 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. [8.43.85.97]) by mx.google.com with ESMTPS id 6a1803df08f44-6dd18237267si207346406d6.281.2024.12.26.10.00.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Dec 2024 10:00:14 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=peVta0fH; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 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 6E76F3858C48 for ; Thu, 26 Dec 2024 18:00:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6E76F3858C48 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=peVta0fH X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by sourceware.org (Postfix) with ESMTPS id 39FC03858C5F for ; Thu, 26 Dec 2024 17:58:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 39FC03858C5F 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 39FC03858C5F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::635 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1735235931; cv=none; b=hjAdh1rZ/ZPod3SZhNEpb+mI/ZCiDhsuUKKTAjpTcWFKpFAVRRJzUmqsGC9iEyviBRT63g/vYKShlzRvTkENjEUreljgVCwEFUyhTHEYsM+AUAtW6txo0Vka1Bqf7fJAspxnw13VUC248Emk1dlSCArhnrRjQfOAR8l3ILAEcW4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1735235931; c=relaxed/simple; bh=cY4p/dwV2ejYH5jf6/F72drbOuZnTEtlVX7ciy+HQzs=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=rIitSK+qA1K+PVv5w02+g+82Vsys8kTBO3/OBThQzY2doeAo2UDIKrqX8KM01wBp4TyZW0CEtmxkbyyw6BnKSyDliqropTmTU35jDre9zsFcVye6v9XgMdYIfJE9CZSWlVuUBRrLvLNg91lDlGhi1d0IDNkl7cS2q7VcY9JIF/M= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 39FC03858C5F Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-2166651f752so86782835ad.3 for ; Thu, 26 Dec 2024 09:58:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1735235930; x=1735840730; 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=tDyRrIdSTi9ivAYiC1NwqgoUxluAWtbZt15rA8D0Rs8=; b=peVta0fHakVkZreBXpKb7559EkgK8QdJQ9lx+l3vmYfSsFY/yux0E4OREHMEovvMMX s/sZz4+fiVqWc4ue80bxHM5/6A8z1Dsa+CytEqAV8QyiBPX9uuLgGPmQrRYCqeKW3WAu wQ5s/5qLnjs1iDuVmdPU5AJZ5F90YqA62LocNO8hbayQ6A6jhz74Da4X4If5t8ptxLUz Wswfe0ksQ+rt8/vFFFmwpRZ1pRWTKCBvk6rCLf5Tib+6gNU0HWoyzemnLHEHsS6k7/C7 1P0YQvBqR+2kHVE8sHb37WONoqhTmflfpk3w01CPCPYe2rV5HDjUH76bt7YbCfXi1tKS vfBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735235930; x=1735840730; 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=tDyRrIdSTi9ivAYiC1NwqgoUxluAWtbZt15rA8D0Rs8=; b=G9LEmG985Fsk2vECzdq36ldpjP8ljTVbAa2weXAxwPYYUfKhwc2W5JJEJBcXscS318 5DOpTlFUvQvIg5pWlHE8gKOie6bdKWoSWNPiZdHQzyxXFXcSanH8b11QX8rtNeBSVTod JZB8fbl0hop5Sy6wZEMNpyh10h0PdqwXMhcntea6OSRhD9FXBFNwzjMajKp1cy4iANh+ RU+dsg5Jnf1APPETEYg0jdqFSKtQHq9vTBQ6BkHY4dgNU4lqIcWy3ISuDtbR06pFUW2K bs/NI0oxQFxtbMzllovaKpqpHUeGTar6mSW+P6+EqeFMseRNblHo1B8hyJmiClOwKVjj vSlQ== X-Gm-Message-State: AOJu0YyLEC8P8qBGA+BZ/Z/SDMcm4SujlZQJzXzrkGgOiQyxhEREliBI M00ZKwCflp9WcQ6Es8U8dGJJk9+ZBIvDzKasKqTRvENEuqpEfRAa2EUl9/bcLkIrguc/iSw0BgL S X-Gm-Gg: ASbGncvZyM3dJPEjluaeyz2GzReps8rPreNwNfuCTwoQYA5+1rK+TtIz1ugDP/xagAr 0+WZ6S47w8yGTcSjoi2160TqCIQ1iFXLM3GK3bRJ2VY2YktZVE8svaiUx7FqD1sbYWabla6GpbF PeS2VtoLWiaSkFBtSD7q0CcdPnE7Qa4eYqYkVfyzCaS6y8NC+enafkIZH9Urafu5umLinDLjuf/ Pj7ZrFMnrQx2sAGwfLyBpDk5q2KtiVwahclImRUqGTqkyoOTVCEf0NQctDgtiNx7cjfSV78wUrd KtaAtggZx6D87EoULbHtoiUgm5Ho X-Received: by 2002:a17:903:2cc:b0:212:5786:7bb6 with SMTP id d9443c01a7336-219e6e887d0mr296710185ad.3.1735235929475; Thu, 26 Dec 2024 09:58:49 -0800 (PST) Received: from ubuntu-vm.. (201-92-184-234.dsl.telesp.net.br. [201.92.184.234]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-219dca031besm119484645ad.281.2024.12.26.09.58.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Dec 2024 09:58:49 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Florian Weimer , Adhemerval Zanella Subject: [PATCH v7 4/4] elf: Add glibc.rtld.execstack Date: Thu, 26 Dec 2024 14:57:45 -0300 Message-ID: <20241226175834.2531046-5-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241226175834.2531046-1-adhemerval.zanella@linaro.org> References: <20241226175834.2531046-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. Reviewed-by: Florian Weimer --- 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 | 28 ++++++++++++++++++++++ 8 files changed, 96 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index e7975384ff..36abe588e6 100644 --- a/NEWS +++ b/NEWS @@ -57,6 +57,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 a + executable stacks is allowed from the main program, either implicitly due + to 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 cea48e9537..4874d9b59e 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -570,6 +570,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 endif ifeq ($(have-depaudit),yes) @@ -666,6 +673,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 \ @@ -1989,6 +1997,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 a238ff4286..76430e26da 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 @@ -1317,7 +1318,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 5eb130be30..8dd0381985 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1645,6 +1645,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 (_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..ea870b8156 100644 --- a/manual/tunables.texi +++ b/manual/tunables.texi @@ -355,6 +355,34 @@ 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 requires an executable stack the loader will +change the main stack permission if kernel starts with a non-executable stack. + +The @code{glibc.rtld.execstack} can be used to control whether an executable +stack is allowed from the main program. Setting the value to @code{0} disablesi +the ABI auto-negotiation (meaning no executable stacks even if the ABI or ELF +header requires it), while @code{1} enables auto-negotiation (although the +program might not need an executable stack). + +When executable stacks are not allowed, and if the main program requires it, +the loader will fail with an error message. + +Some systems do not have separate page protection flags at the hardware +level for read access and execute access (sometimes called read-implies-exec). +This mode can also be enabled on certain systems where the hardware supports +separate protection flags. The @theglibc{} tunable configuration is independent +of hardware capabilities and kernel configuration. + +@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 +main program does not require an executable stack at loading time. This +is enforced regardless of the tunable value. +@end deftp + @node Elision Tunables @section Elision Tunables @cindex elision tunables