From patchwork Mon Dec 23 14:49:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 853074 Delivered-To: patch@linaro.org Received: by 2002:a5d:4888:0:b0:385:e875:8a9e with SMTP id g8csp3433614wrq; Mon, 23 Dec 2024 06:50:43 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVpxN7eEacXfghUka5SWxrnmM9IJ09WkmN3tPq97tO1TCuC3QVyZJJmgfW91UL0VilrnAy37w==@linaro.org X-Google-Smtp-Source: AGHT+IFDIAQ0vHLXUOVm7ajTikEBPwhDwIlnuyAHeCtK2R4OKhi5GtpsT/CBqjOYaE/xhZLjD0tH X-Received: by 2002:a05:620a:1b90:b0:7b6:704e:3529 with SMTP id af79cd13be357-7b9ba7eae91mr2208838485a.46.1734965443361; Mon, 23 Dec 2024 06:50:43 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1734965443; cv=pass; d=google.com; s=arc-20240605; b=exW6SqTCcu8qik1TahZPng0AzQLIoqWdYcj2qXgXO5wyFM7WWZjkHkrqMOv6DVTIGW WGOb/4a6RF2yy8KIRRxBr5AydY1Ja744wyIQLPsKB5hV2WjcXyFDYh5Jj/Dt40mgb+5P A+5++lKp1tr06fXH03q0drSzDC5jOZsi0LFHD6H6XT1FNMYb33djxnJDPhHZeG8x4C+x 1ut1bBiLUw/OOkQ1vdDC8cz50+S7QlAVCrLq2ISkLLsRstq+I4NN3xHpW/Yh4rV232gA lQA/E+Y49sRbkuRXY463mdXDoLC2H5LpGbvvnAqNU3WZu0xc8H5KTUs+YJrpvNYn5L+r eDqA== 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=KPzkKZl7Q8UCqb2+JcnZSk3aB4Z2gSqvQ9uUi6VJ0IQ=; fh=xV8Gp349bHw1ljD2lFQRwhGaJ4bIEzpeFyS/N97S3Sw=; b=Jy1wf0XlsVLqnCpC1efmAnNwZL9LTrpDY9kmi4BEONm8B0H4dmw+7jmiFqoDUyGJQY wRS5jZHgA+b+Ny9SPbunb9ol1zLlLwTu6vKgq0wApefFfdfe/tOiNDm4WZGcown2126p kkrVR9++JD1JjSo1d9wEnQI5ZigsUnsXpcM9EDCTDoeoWY7aF+AWgyqfKW31SQK2JlkE vzLGvUbV3buUFC857SAn1MlxxE7U5QTvw4jBrZBR4iwCN91a7LP0KktChIs6kFLziNZe 1zqml0bCWtC6Fa3TdvMjldozq2H05FvBlf55yZiV1YAKDn4JTlvV9YC/Yj+M3+ofgUzX qk0A==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=R2LhNvLS; 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 af79cd13be357-7b9ac53e6e1si1120364585a.645.2024.12.23.06.50.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Dec 2024 06:50:43 -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=R2LhNvLS; 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 DA7263858430 for ; Mon, 23 Dec 2024 14:50:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DA7263858430 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=R2LhNvLS X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by sourceware.org (Postfix) with ESMTPS id 164893858D34 for ; Mon, 23 Dec 2024 14:50:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 164893858D34 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 164893858D34 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::436 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734965407; cv=none; b=toceqBywz3mseUEMuhVMZb3+xvGbd4FGtiVdqLZeMOb9oX3ToSGFTgOQAQDL3HSq+Lf+shpVPqGL8bJCPlKKQgiSESWyZisfML2J5f37DyokSSTeDiAFME43n7rva+aY4gqWwWm+oQVbuB6e/F/cLpJ4IXhoWwnodWqQ5Dx9cUM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734965407; c=relaxed/simple; bh=O3ksFuCu2PH2q/lB8sgBBdYw/pIBdBRinclIpKbJpsc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=jK53wzDZln9CQ39fDdr2x8+Yp+tJ1kl1O8vZ7FXOLLI/BvpiuoczPcYyBanXD6YM+1Tf0Fm9LDi6mShaJzIzm2F9MVq0qy2EOBH9Bp0GrVGbSNRAinfukyylVvr6JS0KN/7joyYtB0moX9/elO8kq28pnigqKL0nAkPiNnD1ur0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 164893858D34 Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-725dbdf380aso3419643b3a.3 for ; Mon, 23 Dec 2024 06:50:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1734965406; x=1735570206; 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=KPzkKZl7Q8UCqb2+JcnZSk3aB4Z2gSqvQ9uUi6VJ0IQ=; b=R2LhNvLSbwuTM1j015ZLab4dN1677jWrTyn8C09z9VTOgrmpXtWdOapT7eMU4FScON BxwF2gpV1N9tDdIbKkidLvivYqQkMjZFBCzKwV3KCNE7hUE4xejteZtJz9wGXIyYGtjR Eanz6+puQscxKWrKZAoLYe9n65zNy6dDRhFY6EZyubR8p1eSKMyRJKKkpEqwkHubYUfA a6ndQA4ov8sjU6fM8upFBltxvDMcyJ7S4pITiz74fLL4HyUXdjBmv/5sZ3vh90bnhdDu 3hg/w0fyikqfI7Q3PH8EIe8/6Rq/IfiOMU9LZFkfEd6d/uELgrdqpYSdtLezuqQ94tR5 1FUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1734965406; x=1735570206; 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=KPzkKZl7Q8UCqb2+JcnZSk3aB4Z2gSqvQ9uUi6VJ0IQ=; b=HZPpT+EtQDgusa7sjrEdn/TmMScHbkL5LJEGWGqLyt1WCZs+bCf5OFJr0t28LXr45U P/q24i1tTOEC9GryIz7X/Mjn82pniia2rA3Cbsn3niht7cHVMWVRjJnKqwj9FFoV2s38 1wHw6R4/3uArflMm9lqudk/t6hI9vZ66X96oVtW7RsIZ124h2znetvnY6C03AtamydJw UwVO+SFd0M4pt37IU87YdwODjA1r0oxI2EiagM+dR31kO0bgSmqFxS3FAfWv/+eb6oiS 3GoZwbYEG/0DSXNduiCtPJIiuM/c1FXboYx2qijroJ24uHPIGJIpzdm5H2l2poopKKuS qLXw== X-Gm-Message-State: AOJu0YzRyEftDZmlABtwcu1JyVK29TEscOApP7+p82s8teGX7l6de/uE dvQUt7E6ahfsk1+Bbk4plOcN21Vf6N2nKKSwftJ4Wn0npCSIFRr+aCMNNHdwkg8OlFFLf0yWDCN O X-Gm-Gg: ASbGnct3jgX7vhSrHDZataEQSYtEVAwIpGkXGnQAM4jl8zY65/EDfI5rELpI0EUDDLk eKd7+2FlruehrEI1NdacbZOHxLdqxQLOZOpAV537UxQe/C9cizb8GUpp1LSnr6/T1vkJd6kQFGE BI04lK0ou710KeKXaxn5jGdpMjDGUZ4ZDzKwMrWJfUjV5/XrNCDsdHCpmttIzWTG71gJJJlnGhf KZPvXIK2IJbz/EaLH1OZODaLtFjjfahNFNF6dKCTUEanxtIQB/JJoX/FrIyblzCRpGMPJtQaBrE Ioxsk3hEPEZ/n7afDLi+w2dSGA== X-Received: by 2002:a05:6a00:398f:b0:725:e499:5b8a with SMTP id d2e1a72fcca58-72abde3335fmr16835536b3a.15.1734965404213; Mon, 23 Dec 2024 06:50:04 -0800 (PST) Received: from ubuntu-vm.. (189-69-57-246.dsl.telesp.net.br. [189.69.57.246]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72aad816187sm7930372b3a.16.2024.12.23.06.50.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Dec 2024 06:50:03 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Florian Weimer , Adhemerval Zanella Subject: [PATCH v6 1/3] elf: Do not change stack permission on dlopen/dlmopen Date: Mon, 23 Dec 2024 11:49:11 -0300 Message-ID: <20241223144954.3823971-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241223144954.3823971-1-adhemerval.zanella@linaro.org> References: <20241223144954.3823971-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 If some shared library loaded with dlopen/dlmopen requires an executable stack, either implicitly because of a missing GNU_STACK ELF header (where the ABI default flags implies in the executable bit) or explicitly because of the executable bit from GNU_STACK; the loader will try to set the both the main thread and all thread stacks (from the pthread cache) as executable. Besides the issue where any __nptl_change_stack_perm failure does not undo the previous executable transition (meaning that if the library fails to load, there can be thread stacks with executable stacks), this behavior was used on recent CVE [1] as a vector for RCE. This patch changes that if a shared library requires an executable stack, and the current stack is not executable, dlopen fails. The change is done only for dynamically loaded modules, if the program or any dependency requires an executable stack, the loader will still change the main thread before program execution and any thread created with default stack configuration. [1] https://www.qualys.com/2023/07/19/cve-2023-38408/rce-openssh-forwarded-ssh-agent.txt Checked on x86_64-linux-gnu and i686-linux-gnu. --- NEWS | 6 ++ elf/dl-load.c | 13 +-- elf/dl-support.c | 4 - elf/rtld.c | 6 -- elf/tst-execstack.c | 142 ++++++++++--------------- nptl/allocatestack.c | 19 ---- sysdeps/generic/ldsodefs.h | 22 +--- sysdeps/mach/hurd/dl-execstack.c | 1 - sysdeps/nptl/pthreadP.h | 6 -- sysdeps/unix/sysv/linux/Versions | 3 - sysdeps/unix/sysv/linux/dl-execstack.c | 67 +----------- sysdeps/unix/sysv/linux/mips/Makefile | 7 ++ 12 files changed, 80 insertions(+), 216 deletions(-) diff --git a/NEWS b/NEWS index a185f2e7ee..f91c4c2421 100644 --- a/NEWS +++ b/NEWS @@ -57,6 +57,12 @@ Deprecated and removed features, and other changes affecting compatibility: * The nios2*-*-linux-gnu configurations are no longer supported. +* dlopen and dlmopen no longer make the stack executable if a shared + library requires it, either implicitly because of a missing GNU_STACK ELF + header (and default ABI permission having the executable bit set) or + explicitly because of the executable bit in GNU_STACK, and the stack is + not already executable. + Changes to build and runtime requirements: * On recent Linux kernels with vDSO getrandom support, getrandom does not diff --git a/elf/dl-load.c b/elf/dl-load.c index 284857ddf6..a238ff4286 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1315,12 +1315,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, if (__glibc_unlikely ((stack_flags &~ GL(dl_stack_flags)) & PF_X)) { /* The stack is presently not executable, but this module - requires that it be executable. */ -#if PTHREAD_IN_LIBC - errval = _dl_make_stacks_executable (stack_endp); -#else - errval = (*GL(dl_make_stack_executable_hook)) (stack_endp); -#endif + requires that it be executable. Only tries to change the + stack protection during process startup. */ + if ((mode & __RTLD_DLOPEN) == 0) + errval = _dl_make_stack_executable (stack_endp); + else + errval = EINVAL; + if (errval) { errstring = N_("\ diff --git a/elf/dl-support.c b/elf/dl-support.c index ee590edf93..fe1f8c8f6a 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -178,10 +178,6 @@ size_t _dl_stack_cache_actsize; uintptr_t _dl_in_flight_stack; int _dl_stack_cache_lock; #else -/* If loading a shared object requires that we make the stack executable - when it was not, we do it by calling this function. - It returns an errno code or zero on success. */ -int (*_dl_make_stack_executable_hook) (void **) = _dl_make_stack_executable; void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls; #endif struct dl_scope_free_list *_dl_scope_free_list; diff --git a/elf/rtld.c b/elf/rtld.c index 0637c53017..5eb130be30 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1336,12 +1336,6 @@ dl_main (const ElfW(Phdr) *phdr, __tls_pre_init_tp (); -#if !PTHREAD_IN_LIBC - /* The explicit initialization here is cheaper than processing the reloc - in the _rtld_local definition's initializer. */ - GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable; -#endif - /* Process the environment variable which control the behaviour. */ skip_env = process_envvars (&state); diff --git a/elf/tst-execstack.c b/elf/tst-execstack.c index 560b353918..cd758c089e 100644 --- a/elf/tst-execstack.c +++ b/elf/tst-execstack.c @@ -9,6 +9,11 @@ #include #include +#include +#include +#include +#include + static void print_maps (void) { @@ -20,11 +25,21 @@ print_maps (void) #endif } -static void deeper (void (*f) (void)); +#ifndef DEFAULT_RWX_STACK +# define DEFAULT_RWX_STACK 0 +#else +static void +deeper (void (*f) (void)) +{ + char stack[1100 * 1024]; + explicit_bzero (stack, sizeof stack); + (*f) (); + memfrob (stack, sizeof stack); +} +#endif #if USE_PTHREADS -# include - +# if DEFAULT_RWX_STACK static void * tryme_thread (void *f) { @@ -32,16 +47,21 @@ tryme_thread (void *f) return 0; } +# endif static pthread_barrier_t startup_barrier, go_barrier; static void * waiter_thread (void *arg) { - void **f = arg; - pthread_barrier_wait (&startup_barrier); - pthread_barrier_wait (&go_barrier); + xpthread_barrier_wait (&startup_barrier); + xpthread_barrier_wait (&go_barrier); +# if DEFAULT_RWX_STACK + void **f = arg; (*((void (*) (void)) *f)) (); +# else + abort (); +# endif return 0; } @@ -83,52 +103,36 @@ do_test (void) printf ("executable stacks %sallowed\n", allow_execstack ? "" : "not "); +#if USE_PTHREADS || DEFAULT_RWX_STACK static void *f; /* Address of this is used in other threads. */ +#endif #if USE_PTHREADS /* Create some threads while stacks are nonexecutable. */ #define N 5 - pthread_t thr[N]; - pthread_barrier_init (&startup_barrier, NULL, N + 1); - pthread_barrier_init (&go_barrier, NULL, N + 1); + xpthread_barrier_init (&startup_barrier, NULL, N + 1); + xpthread_barrier_init (&go_barrier, NULL, N + 1); for (int i = 0; i < N; ++i) - { - int rc = pthread_create (&thr[i], NULL, &waiter_thread, &f); - if (rc) - error (1, rc, "pthread_create"); - } + xpthread_create (NULL, &waiter_thread, &f); /* Make sure they are all there using their stacks. */ - pthread_barrier_wait (&startup_barrier); + xpthread_barrier_wait (&startup_barrier); puts ("threads waiting"); #endif print_maps (); -#if USE_PTHREADS +#if USE_PTHREADS && DEFAULT_RWX_STACK void *old_stack_addr, *new_stack_addr; size_t stack_size; pthread_t me = pthread_self (); pthread_attr_t attr; - int ret = 0; - - ret = pthread_getattr_np (me, &attr); - if (ret) - { - printf ("before execstack: pthread_getattr_np returned error: %s\n", - strerror (ret)); - return 1; - } - ret = pthread_attr_getstack (&attr, &old_stack_addr, &stack_size); - if (ret) - { - printf ("before execstack: pthread_attr_getstack returned error: %s\n", - strerror (ret)); - return 1; - } + TEST_VERIFY_EXIT (pthread_getattr_np (me, &attr) == 0); + TEST_VERIFY_EXIT (pthread_attr_getstack (&attr, &old_stack_addr, + &stack_size) == 0); # if _STACK_GROWS_DOWN old_stack_addr += stack_size; # else @@ -143,18 +147,12 @@ do_test (void) const char *soname = "tst-execstack-mod.so"; #endif void *h = dlopen (soname, RTLD_LAZY); - if (h == NULL) - { - printf ("cannot load: %s\n", dlerror ()); - return allow_execstack; - } +#if !DEFAULT_RWX_STACK + TEST_VERIFY_EXIT (h == NULL); +#else + TEST_VERIFY_EXIT (h != NULL); - f = dlsym (h, "tryme"); - if (f == NULL) - { - printf ("symbol not found: %s\n", dlerror ()); - return 1; - } + f = xdlsym (h, "tryme"); /* Test if that really made our stack executable. The `tryme' function should crash if not. */ @@ -163,28 +161,15 @@ do_test (void) print_maps (); -#if USE_PTHREADS - ret = pthread_getattr_np (me, &attr); - if (ret) - { - printf ("after execstack: pthread_getattr_np returned error: %s\n", - strerror (ret)); - return 1; - } - - ret = pthread_attr_getstack (&attr, &new_stack_addr, &stack_size); - if (ret) - { - printf ("after execstack: pthread_attr_getstack returned error: %s\n", - strerror (ret)); - return 1; - } - -# if _STACK_GROWS_DOWN +# if USE_PTHREADS + TEST_VERIFY_EXIT (pthread_getattr_np (me, &attr) == 0); + TEST_VERIFY_EXIT (pthread_attr_getstack (&attr, &new_stack_addr, + &stack_size) == 0); +# if _STACK_GROWS_DOWN new_stack_addr += stack_size; -# else +# else new_stack_addr -= stack_size; -# endif +# endif /* It is possible that the dlopen'd module may have been mmapped just below the stack. The stack size is taken as MIN(stack rlimit size, end of last @@ -194,48 +179,29 @@ do_test (void) stacksize and stackaddr respectively. If the size changes due to the above, then both stacksize and stackaddr can change, but the stack bottom should remain the same, which is computed as stackaddr + stacksize. */ - if (old_stack_addr != new_stack_addr) - { - printf ("Stack end changed, old: %p, new: %p\n", - old_stack_addr, new_stack_addr); - return 1; - } + TEST_VERIFY_EXIT (old_stack_addr == new_stack_addr); printf ("Stack address remains the same: %p\n", old_stack_addr); -#endif +# endif /* Test that growing the stack region gets new executable pages too. */ deeper ((void (*) (void)) f); print_maps (); -#if USE_PTHREADS +# if USE_PTHREADS /* Test that a fresh thread now gets an executable stack. */ - { - pthread_t th; - int rc = pthread_create (&th, NULL, &tryme_thread, f); - if (rc) - error (1, rc, "pthread_create"); - } + xpthread_create (NULL, &tryme_thread, f); puts ("threads go"); /* The existing threads' stacks should have been changed. Let them run to test it. */ - pthread_barrier_wait (&go_barrier); + xpthread_barrier_wait (&go_barrier); pthread_exit ((void *) (long int) (! allow_execstack)); +# endif #endif return ! allow_execstack; } -static void -deeper (void (*f) (void)) -{ - char stack[1100 * 1024]; - explicit_bzero (stack, sizeof stack); - (*f) (); - memfrob (stack, sizeof stack); -} - - #include diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index d9adb5856c..9662b43afe 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -448,25 +448,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE); - - /* There might have been a race. Another thread might have - caused the stacks to get exec permission while this new - stack was prepared. Detect if this was possible and - change the permission if necessary. */ - if (__builtin_expect ((GL(dl_stack_flags) & PF_X) != 0 - && (prot & PROT_EXEC) == 0, 0)) - { - int err = __nptl_change_stack_perm (pd); - if (err != 0) - { - /* Free the stack memory we just allocated. */ - (void) __munmap (mem, size); - - return err; - } - } - - /* Note that all of the stack and the thread descriptor is zeroed. This means we do not have to initialize fields with initial value zero. This is specifically true for diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index cec56e2214..172bcd2cf7 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -399,13 +399,6 @@ struct rtld_global #endif #include -#if !PTHREAD_IN_LIBC - /* If loading a shared object requires that we make the stack executable - when it was not, we do it by calling this function. - It returns an errno code or zero on success. */ - EXTERN int (*_dl_make_stack_executable_hook) (void **); -#endif - /* Prevailing state of the stack, PF_X indicating it's executable. */ EXTERN ElfW(Word) _dl_stack_flags; @@ -702,17 +695,10 @@ extern const ElfW(Phdr) *_dl_phdr; extern size_t _dl_phnum; #endif -#if PTHREAD_IN_LIBC -/* This function changes the permissions of all stacks (not just those - of the main stack). */ -int _dl_make_stacks_executable (void **stack_endp) attribute_hidden; -#else -/* This is the initial value of GL(dl_make_stack_executable_hook). - A threads library can change it. The ld.so implementation changes - the permissions of the main stack only. */ -extern int _dl_make_stack_executable (void **stack_endp); -rtld_hidden_proto (_dl_make_stack_executable) -#endif +/* This function changes the permission of the memory region pointed + by STACK_ENDP to executable and update the internal memory protection + flags for future thread stack creation. */ +int _dl_make_stack_executable (void **stack_endp) attribute_hidden; /* Variable pointing to the end of the stack (or close to it). This value must be constant over the runtime of the application. Some programs diff --git a/sysdeps/mach/hurd/dl-execstack.c b/sysdeps/mach/hurd/dl-execstack.c index 31371bc6e3..0222430131 100644 --- a/sysdeps/mach/hurd/dl-execstack.c +++ b/sysdeps/mach/hurd/dl-execstack.c @@ -47,4 +47,3 @@ _dl_make_stack_executable (void **stack_endp) return ENOSYS; #endif } -rtld_hidden_def (_dl_make_stack_executable) diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h index c2db165052..a8e09bf754 100644 --- a/sysdeps/nptl/pthreadP.h +++ b/sysdeps/nptl/pthreadP.h @@ -289,12 +289,6 @@ extern _Noreturn void __syscall_do_cancel (void) attribute_hidden; extern void __nptl_free_tcb (struct pthread *pd); libc_hidden_proto (__nptl_free_tcb) -/* Change the permissions of a thread stack. Called from - _dl_make_stacks_executable and pthread_create. */ -int -__nptl_change_stack_perm (struct pthread *pd); -rtld_hidden_proto (__nptl_change_stack_perm) - /* longjmp handling. */ extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe); libc_hidden_proto (__pthread_cleanup_upto) diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions index 213ff5f1fe..55d565545a 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -360,7 +360,4 @@ ld { __rseq_offset; __rseq_size; } - GLIBC_PRIVATE { - __nptl_change_stack_perm; - } } diff --git a/sysdeps/unix/sysv/linux/dl-execstack.c b/sysdeps/unix/sysv/linux/dl-execstack.c index b986898598..68db6737f0 100644 --- a/sysdeps/unix/sysv/linux/dl-execstack.c +++ b/sysdeps/unix/sysv/linux/dl-execstack.c @@ -16,19 +16,10 @@ License along with the GNU C Library; if not, see . */ -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -static int -make_main_stack_executable (void **stack_endp) +int +_dl_make_stack_executable (void **stack_endp) { /* This gives us the highest/lowest page that needs to be changed. */ uintptr_t page = ((uintptr_t) *stack_endp @@ -52,57 +43,3 @@ make_main_stack_executable (void **stack_endp) return 0; } - -int -_dl_make_stacks_executable (void **stack_endp) -{ - /* First the main thread's stack. */ - int err = make_main_stack_executable (stack_endp); - if (err != 0) - return err; - - lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE); - - list_t *runp; - list_for_each (runp, &GL (dl_stack_used)) - { - err = __nptl_change_stack_perm (list_entry (runp, struct pthread, list)); - if (err != 0) - break; - } - - /* Also change the permission for the currently unused stacks. This - might be wasted time but better spend it here than adding a check - in the fast path. */ - if (err == 0) - list_for_each (runp, &GL (dl_stack_cache)) - { - err = __nptl_change_stack_perm (list_entry (runp, struct pthread, - list)); - if (err != 0) - break; - } - - lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE); - - return err; -} - -int -__nptl_change_stack_perm (struct pthread *pd) -{ -#if _STACK_GROWS_DOWN - void *stack = pd->stackblock + pd->guardsize; - size_t len = pd->stackblock_size - pd->guardsize; -#elif _STACK_GROWS_UP - void *stack = pd->stackblock; - size_t len = (uintptr_t) pd - pd->guardsize - (uintptr_t) pd->stackblock; -#else -# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" -#endif - if (__mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) - return errno; - - return 0; -} -rtld_hidden_def (__nptl_change_stack_perm) diff --git a/sysdeps/unix/sysv/linux/mips/Makefile b/sysdeps/unix/sysv/linux/mips/Makefile index d5725c69d8..05ec9150b2 100644 --- a/sysdeps/unix/sysv/linux/mips/Makefile +++ b/sysdeps/unix/sysv/linux/mips/Makefile @@ -61,6 +61,7 @@ ifeq ($(subdir),elf) # this test is expected to fail. ifneq ($(mips-has-gnustack),yes) test-xfail-check-execstack = yes +CFLAGS-tst-execstack.c += -DDEFAULT_RWX_STACK=1 endif endif @@ -68,6 +69,12 @@ ifeq ($(subdir),stdlib) gen-as-const-headers += ucontext_i.sym endif +ifeq ($(subdir),nptl) +ifeq ($(mips-force-execstack),yes) +CFLAGS-tst-execstack-threads.c += -DDEFAULT_RWX_STACK=1 +endif +endif + ifeq ($(mips-force-execstack),yes) CFLAGS-.o += -Wa,-execstack CFLAGS-.os += -Wa,-execstack From patchwork Mon Dec 23 14:49:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 853076 Delivered-To: patch@linaro.org Received: by 2002:a5d:4888:0:b0:385:e875:8a9e with SMTP id g8csp3435360wrq; Mon, 23 Dec 2024 06:54:10 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCU7AvsuDfcca0f/idzlx96EOw5CYZakqHZB0VDqvdBN8EDKal/PTExz3kcv6dUexHAGsljIUw==@linaro.org X-Google-Smtp-Source: AGHT+IHpRr67tFpyPrv9vlz6MML9pm8v9qgOfes6soRfkuLVWChejE8lyLNqaWXdqjp1x8w1E298 X-Received: by 2002:a05:620a:2412:b0:7b6:d5b2:e6d with SMTP id af79cd13be357-7b9ba7ac1eemr2025933785a.35.1734965650339; Mon, 23 Dec 2024 06:54:10 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1734965650; cv=pass; d=google.com; s=arc-20240605; b=ir4Ck/UQzFPBEjpdWD2XOrntNFiaabbxxHHbBm74mFdNVdWJiZ5dwAE9FPb5Fus9ZF v3dlS81KAy3RgrxW5tSrnLCTiraNccSUIqo4Z+GjPMt3aY1XBOO0e75cWIvyI/Pu0JKm 34LEGDIfFUaYxXrU3jCRDV5KskTegMyhVH2qMRqM3ymnOLxfnB0vuJLYKmpb4FrTkOtw n1866yhPfiyM9tz+JjEbsBrSAU5UB7heFVdSVL0OpAfvjr6EPrwQKIky9qesc4ixwQIw brMuCIj+QjEJLxENVNTApUDOCVYDW/aabrZsQd5aOy8ryVpux/EPzeyNNXSBqDPrPHl3 GtNQ== 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=2KIZiPYPlme8WSvRE1C5ZI0+WVUAqunh0GGKWI0hMkE=; fh=xV8Gp349bHw1ljD2lFQRwhGaJ4bIEzpeFyS/N97S3Sw=; b=KkiHv8WjaLbTv7XzzDh95981AH5JS692IRX6QsN35Znu0H/5M0OBsBQ4Yr6S2Twz+g 6dYIvSoHszPq3+ockPCAT90TseWcOmc7Oqu/ZasxtcaHbMZymPSW0psN6bl+fvhSw0Pc UNaa24PCMz2gkLihigqCcEP8DpGfnrh+ulI9xrr3CIkF+23hifKhFAW+STp2DBe1GAQV w0m/PhxJ9mdD/3R6YTkB7gxJo5bxg6Xotqdn3+j39j4eE+gimkWeI8IIgUI+a5fohOxB 5YdBB66GrhALkN8Q4ctMQzoaHmy00WuN4RKF7oHvFTVK758ptDsXSSqyFen9KHSvQNcJ m2FQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=oTNih+mp; 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-7b9ac478f2csi1098695885a.331.2024.12.23.06.54.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Dec 2024 06:54:10 -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=oTNih+mp; 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 E7EA6385843B for ; Mon, 23 Dec 2024 14:54:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E7EA6385843B 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=oTNih+mp X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) by sourceware.org (Postfix) with ESMTPS id A5AE93858C35 for ; Mon, 23 Dec 2024 14:50:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A5AE93858C35 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 A5AE93858C35 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::429 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734965407; cv=none; b=E7ojilCND6s6Q+NBDQraaI7UyE/IjcpvbX25VyFpowuICFamqMPJb8C2Ume3jhoHw/qMh1CsqnJxANa3sYm3g2Rg/xKDp/2mfBxOKiwUUW/4BKLbEaFYVyx7z03Oz14KOiCKhLvgDBGV+2lwkv4z7ugBgMSg8OMj4EjGLB3uDjE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734965407; c=relaxed/simple; bh=VxuZJLw19iUfENrl7opP9mX5iIxeBjD9gvGI696+DuY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=bEj9AIBAJce3J3Lkdb/gubqto533VyBp4LWeI/uiXgAfYIeAwrPfx+xfbJZ6O5XwXWxt0rxMAT3KJVDNXhtwQvd8dhj8e8qsrOoILDRaml7elgr86dr7DnwEljXBpl0m9gT/tbe9uMLvZMFhpKT8V3aEND4sUi7h+s841YAXPdg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A5AE93858C35 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-725ee27e905so5060214b3a.2 for ; Mon, 23 Dec 2024 06:50:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1734965406; x=1735570206; 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=2KIZiPYPlme8WSvRE1C5ZI0+WVUAqunh0GGKWI0hMkE=; b=oTNih+mpUW/aIy3TF7uKoeKB8F+QzJw39/YVEnzqaOBAs7Ze7VAUHMiQZpRtG9e+9W AvffZLHstJdJ8L6JcNSmXItIDFclJMIGXbhEVSnb7b2xmcvA8KXl26YbHb5rBLUapV6y F954V2/T1UlCtfOp7jjOqVCUnWD4Osv3tu1TqZ1nQWawbb4N5sfzmdquVsSPQ+ihyRfl b4wpHFEjLwASHDDNOO+aplSruZOTZqVAGYdFcJl04XSzjm1XBn2fLxhaaO/WnOOinTJA h6fsJPokoiSl+6P1QlbfNduv50EqO5boSdRtPG9yseBRHuQu5nomS+1rskma32D4MuPU jqjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1734965406; x=1735570206; 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=2KIZiPYPlme8WSvRE1C5ZI0+WVUAqunh0GGKWI0hMkE=; b=l43jjLpcVs3TIcs515DBMcYUgJcsKmNJ+g/px+WEi1QUTP1nvVfE65b+rkk6bgqVMr 6LLThwRN15OWq8/XZqGe/l2wjLgC397ri5nd/U5wRroMkA3oMPygF6wwDqtw7NMylZHg 0bLMpCxtXT2zaMhhOHqO9ZlBFgI3sDLTMgChkbPNk16iee3Q8Q2B2l6wF/qrQXzTSyG8 2FwOvfkIPkqmtlnVcbAv7P63Mfy5qKX67sslD32c9nJtDd0qkx0Iyf4kZcUMw8iyFN5I tEzitz07ljbECeRmIWqy7xVD7XK21DA0/SYUm1UGOF46F1IuaDdQPtpGQwfRLoivRxzH oERw== X-Gm-Message-State: AOJu0YwxkaLTi7T7Q4SNQ0u1GXyoaszJDY1qN7Ocx0SkSH/CQxMKq6Dj W+YPUtTNRiVb9xOtpkJHoGReHFZhhM/F8yXxXTuwuEE9vP8zQXYGU6m/SuGMjWq0XHBSXGawRtm 4 X-Gm-Gg: ASbGncuaW2rcgjpsj2kRKiiZV3LAC5Kz9sfsg7LlxQ7b67D3mUXdq6toF7z8cs1u9KY XGGfI8njktvjnPYibNqDpyuLgzguiscNhu+RH8HiXQZi2LuMDfwQERlHitpGIUIQWEkJCmnIUhM EDLOrGc/J5baDsyT5v3ggYepEmssOUMtAvm5n9cxbJ6cvh2wCQiSCVEFsqHhBbxQQzt3hNaO4Uz al9rLbS4KGzRJLGgFGcrAHrTqT+CUZXJvGeS1HC+y8LyVkM34WieEi1VTmd8jnxa+CMl4IjprBN GL5lmpaECMcesjnelsokKZBTWw== X-Received: by 2002:a05:6a21:2d09:b0:1e1:afa9:d397 with SMTP id adf61e73a8af0-1e5e0463addmr20705086637.15.1734965405978; Mon, 23 Dec 2024 06:50:05 -0800 (PST) Received: from ubuntu-vm.. (189-69-57-246.dsl.telesp.net.br. [189.69.57.246]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72aad816187sm7930372b3a.16.2024.12.23.06.50.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Dec 2024 06:50:05 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Florian Weimer , Adhemerval Zanella Subject: [PATCH v6 2/3] elf: Add tst-execstack-prog-static Date: Mon, 23 Dec 2024 11:49:12 -0300 Message-ID: <20241223144954.3823971-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241223144954.3823971-1-adhemerval.zanella@linaro.org> References: <20241223144954.3823971-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 Similar to tst-execstack-prog, check if executable stacks works for statically linked programs. Reviewed-by: Florian Weimer --- elf/Makefile | 7 +++++++ elf/tst-execstack-prog-static.c | 1 + 2 files changed, 8 insertions(+) create mode 100644 elf/tst-execstack-prog-static.c diff --git a/elf/Makefile b/elf/Makefile index e8fc6bd65f..cea48e9537 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -567,6 +567,9 @@ tests-execstack-yes = \ tst-execstack-needed \ tst-execstack-prog \ # tests-execstack-yes +tests-execstack-static-yes = \ + tst-execstack-prog-static + # tests-execstack-static-yes endif endif ifeq ($(have-depaudit),yes) @@ -662,6 +665,7 @@ $(objpfx)tst-rtld-dash-dash.out: tst-rtld-dash-dash.sh $(objpfx)ld.so $(evaluate-test) tests += $(tests-execstack-$(have-z-execstack)) +tests-static+= $(tests-execstack-static-$(have-z-execstack)) ifeq ($(run-built-tests),yes) tests-special += \ $(objpfx)tst-ldconfig-X.out \ @@ -1982,6 +1986,9 @@ LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack LDFLAGS-tst-execstack-prog = -Wl,-z,execstack CFLAGS-tst-execstack-prog.c += -Wno-trampolines CFLAGS-tst-execstack-mod.c += -Wno-trampolines + +LDFLAGS-tst-execstack-prog-static = -Wl,-z,execstack +CFLAGS-tst-execstack-prog-static.c += -Wno-trampolines endif LDFLAGS-tst-array2 = -Wl,--no-as-needed diff --git a/elf/tst-execstack-prog-static.c b/elf/tst-execstack-prog-static.c new file mode 100644 index 0000000000..328065dd9c --- /dev/null +++ b/elf/tst-execstack-prog-static.c @@ -0,0 +1 @@ +#include From patchwork Mon Dec 23 14:49:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 853075 Delivered-To: patch@linaro.org Received: by 2002:a5d:4888:0:b0:385:e875:8a9e with SMTP id g8csp3433807wrq; Mon, 23 Dec 2024 06:51:04 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUuKAN1W0jS8eDa+h/zcpO3Nm5EjFUpQedS0lA3NC9VSVOUOKR6VgZfv4j84nYaBAGVgC48Rw==@linaro.org X-Google-Smtp-Source: AGHT+IEsDXrZHbiXll4UU1NTeFQsw4kamFXd2LYI7YR4JY57qxIjElp6Tdsg1NdFaSfIRLvqAGuT X-Received: by 2002:a05:622a:551:b0:463:64b2:2e0d with SMTP id d75a77b69052e-46a4a96b4e0mr197792171cf.40.1734965464687; Mon, 23 Dec 2024 06:51:04 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1734965464; cv=pass; d=google.com; s=arc-20240605; b=Jo8J/jPKe3vwNOuJFabyDtTrp/ofuGUl2A8qXa6aDLgKux/WYCx91d1nq5XfXF5Tbz /OsD8IzLQs16a4SUTTnLE8wxDvKngI4gLnTMBovlkC4lfxYpTooOK4E65ALmHxqf4DqG MCqgXWkc1g+a8QaeuajtMVLcSWsERZqVVDxaoryP/nCFU7XY5XMfWiPuOU6rd99McuHb hfQSyfYOSRGMFRq4PjbYOazvJBTi8FbvbxJOkVQEPwa6psEq9LGnEM3zP1Fd15rwcOsh 4F+ZdKDE7qCp9X27/wSOeV77Js5tB4ltSuP2Ey7k4/wt8Ajxi8ZKYffrZWXsKfXku1yr w+0w== 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=pWSbi2W4U2S6ZCDZF2NTI3AKbIGISskxUHfoT0xt8b8=; fh=xV8Gp349bHw1ljD2lFQRwhGaJ4bIEzpeFyS/N97S3Sw=; b=bO43ZAAErjuTjn+JGgY/ddLtm7OQF2OOlLcJ7sKJJMawUT+08TJcYdsNCWCeSIzxsI PV3XtG48OFMzt5sTuxRwWP8745AagD0Jwgn0llTOyQTVlkHgealGVu9sfZ05LySpRJi/ cbkJyGekg/3JYC9DjvSj57fDekafl+BrbKRMFzfBSidQ8rya7K/UOZdYkFXrTCmijB54 woWSFaUGAp1T9Ntev1mz3jrGGisbLMXmhEUgdp52oe59u5/sLukV1bOML23ho8IVZy9l Zv8HybMkdzM2q5s6a05v2ZG+zP0Fn+JFnaYQNFVe+qfa7++IskbKerz6bk0U3184rSzp AtvQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=aK1rU8LA; 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 d75a77b69052e-46a3eb98047si115715061cf.301.2024.12.23.06.51.04 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Dec 2024 06:51:04 -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=aK1rU8LA; 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 0B9893858D34 for ; Mon, 23 Dec 2024 14:51:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0B9893858D34 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=aK1rU8LA X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) by sourceware.org (Postfix) with ESMTPS id E84B2385840E for ; Mon, 23 Dec 2024 14:50:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E84B2385840E 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 E84B2385840E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::429 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734965409; cv=none; b=T4GMG1tmXqG8rBbFsi/kr888VYXLqTTg8x6XT3///2vy3WgVAvxp6+wMf53SKKXlKk4e1hZMHldBMbpYG6t3dgI7Ahf7ZH9uKomCV1if2d0wg16b6FnPTzuiFJros1YdDr1Cbu/v0do59bCHhQmooJOwPTM8HdD2yDl7Z+dqSoE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734965409; c=relaxed/simple; bh=cVndp3HxdZBqMARaVukBYCfbDjox+fkLdqLM3Zl3VvM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=p+Upp9cxROkHGZ0BECtRKPtZEIKcC4ZB7nqT5AiGMQzxDYs7Wu8kBPdi3o002aLIfMBwfzoDTu++xNbaWXnTWuJRfWMpIq7uSm5TVlV4dAVy7iNC9VSnPRv1ejH5vMvkN1AGNqAESUm3T/iyARYXqVkfJpR++cIMiXnCD7HwFE4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E84B2385840E Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-725dac69699so3783357b3a.0 for ; Mon, 23 Dec 2024 06:50:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1734965408; x=1735570208; 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=pWSbi2W4U2S6ZCDZF2NTI3AKbIGISskxUHfoT0xt8b8=; b=aK1rU8LApsrCQGalfVyU95Nmrrfy2vO8ADdyQAgwPcDQnV5m13gwqL0dyb8q2gJZJr YLpGmtJcMramzVdErjtpZVE21f6lpD7Dh+FR8L5+rC0nIDEJPpB/cU7DYEOfub3mtDCy SV8qKGyho6SovnVP44vwch1+pcS9tSCg2t6wlK7e2VY3BBC6tLIgsUfZ10/UNfms7rFv jbx8qy6SUy2a5VVhNQBdKelHE7aTdxVqu0ZdWhIswn2eNxNV2YK3hXC+lda/OqgVBWwI voASM5cOhg3r0cG0LPIYrzlQBccC/YIUo+c9lDKoCSk9gkchdLP89mRMd0+pwXJP5B3x /ujQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1734965408; x=1735570208; 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=pWSbi2W4U2S6ZCDZF2NTI3AKbIGISskxUHfoT0xt8b8=; b=Ln4uzzk6oCHYzw+/bE6/MRpQkckd0xbRIwFWUdQp9tqWo7A+j+L7BrZb+te/E0PKmb o/xnOJNqa0KpsUs/OBIMK7/lVqVEQZLRzcMy0tWx+1r9Mjy8udITEeQUOUg7mCzzSP7V FBf3BuLW8Xmj0SdqmeJeaNEUHWxYy+dhLcMKImC0dtL+rH/OXFGLo61AruyhrSBXB8bd 7AGxtK6j28mWadtwLzOmD6KNTxidssyeVnvPJaUGtPFHhDql2KHzfSMvFoOeuXV2t7nL 32n/4rR7W/VsTn01161G7CpfmCWyTNB54lxgrk7se0ACiXeAUmxOX7nB1M56vxD76pz2 RqdQ== X-Gm-Message-State: AOJu0YzgQTju1+aZeo186Bqb0Hdluibb/JvPf3c9OmoFPp/q53U9WTu1 ZtGrGRfSEXcx4XeDYjXBLdQI424HldzrcTmxSbahmZBT/HtYXDKvu9S6VWLRXchxWDABO/yn0Nm a X-Gm-Gg: ASbGnct2DELeuG8vBk9SJB0w2T+XdKtL81iHCcc6UYNLGRJF8tO/t4Nt9dLIw81Nm5/ hEV3Bvc8YI0pWVFLGlF58i8qVDBrVijaWI36A8yFmpS/aJtyufbngKea16l30ENzgeJoHT5WkiS hY49w26zIOXrQhdVa77UUcAdgXqOtUMZUMa94B5t5Nxn6y4QQmhqFNE5hA/moWqfYAjHtIiVDPc mbn+hl6CWc4CGLYQxj25d74qn/Ol4zYp7PpfMb0OUl3YGQzPLNJpRtKCZPaPTaWip6FK85OHiaa c4CUM9qBk7bAzW3sRm0uS0kSFw== X-Received: by 2002:a05:6a00:8f07:b0:725:b201:2362 with SMTP id d2e1a72fcca58-72abddb0bd4mr16298137b3a.11.1734965407741; Mon, 23 Dec 2024 06:50:07 -0800 (PST) Received: from ubuntu-vm.. (189-69-57-246.dsl.telesp.net.br. [189.69.57.246]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72aad816187sm7930372b3a.16.2024.12.23.06.50.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Dec 2024 06:50:07 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Florian Weimer , Adhemerval Zanella Subject: [PATCH v6 3/3] elf: Add glibc.rtld.execstack Date: Mon, 23 Dec 2024 11:49:13 -0300 Message-ID: <20241223144954.3823971-4-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241223144954.3823971-1-adhemerval.zanella@linaro.org> References: <20241223144954.3823971-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 f91c4c2421..c0a5dd8ad3 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,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 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..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