From patchwork Thu Nov 28 17:36:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 845952 Delivered-To: patch@linaro.org Received: by 2002:adf:f2c4:0:b0:382:43a8:7b94 with SMTP id d4csp377058wrp; Thu, 28 Nov 2024 09:39:57 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCU1TVW0+cLIutR9HoJYxEzHT4GntKL+huxi2ykICz28h8HH99/4FhhBmYH/B5Bu07r0c/4lUw==@linaro.org X-Google-Smtp-Source: AGHT+IFJsgAzZJDJMoslv0SUvwynb6NiGxXiFQe69W9h5JT6cCQtpwrLDxqAubxdUw0s12AqqbW1 X-Received: by 2002:a05:6214:2605:b0:6d4:e46:b43a with SMTP id 6a1803df08f44-6d864db421bmr142501636d6.45.1732815596874; Thu, 28 Nov 2024 09:39:56 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1732815596; cv=pass; d=google.com; s=arc-20240605; b=JNm7SY6iGFqjlue4TySyK6dsI7cfNm1FbMFnl3FmjGsfwnNGZRhsHZI9rmzZICXcE+ IBdtPz7brvfxQAHxDClx/T4IOkFToZIsMARRnfQF+Ag8C+QmBy6jNAvsVJu4iQiNZFTR e26/tH8mitypeBBVAvNmY2QhAqZaAQObEt0dLREWBnmyYPQoCboTaouOJGrZkYY7vZlm v/k+4TkwGK3xjSCkjSgBipQWQbezhvqK0HKGQ6qS7YCurb+/KXVfQGgFLUivFA7ZOoEY x5t5AfZZ9AK7lWwG45wT+mR5aoEgqcW0/Nb+kYh3oOi0RndzjuCRgxc5RuNyJtISoggA TWcg== 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=05MFVFgeMvBqYdpaoNgsoYXGQfR8IqVOMNYKgyUlvvc=; fh=5vlP+0ToNsZNUEx4IDYFBtVkL7R0+LPY9AvG1oUICyQ=; b=VHEuXvBTFDHHzIY/geHIqXQnC3q/1PMerC0UwaSjjeXJqvB/rUiu+NZcJCOw1kYv+4 7e6WtytsS7XGJh9Rb+tdb0f5OlUnKJeMCcliCpVAL6+XRlsrmlw0Da9OWj0U6rp8h1wC dsD/neLikUJwZSx5DEQEn2OuCFLFvyquK6WJ52VKOcPY1LYVPHm0krM8hgHcsrZRbfGx P/aYogFPXgFSGsolMKUQAArDsuvzXwIuFB+tFn1rSYKJv8+p+gp8croyCWZyMO8N7QJx /DIkVlmIPd5/JU6d7bTFm2kCLZHG3CGXExyqm+3Jo8PyIYy3JkpftBDnbozrGmnlLVhX xbfw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=A+u7vMSQ; 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 6a1803df08f44-6d880ea3998si4281376d6.272.2024.11.28.09.39.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Nov 2024 09:39:56 -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=A+u7vMSQ; 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 4F7B03858CDB for ; Thu, 28 Nov 2024 17:39:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4F7B03858CDB 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=A+u7vMSQ X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x441.google.com (mail-pf1-x441.google.com [IPv6:2607:f8b0:4864:20::441]) by sourceware.org (Postfix) with ESMTPS id 296A03858C53 for ; Thu, 28 Nov 2024 17:39:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 296A03858C53 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 296A03858C53 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::441 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1732815540; cv=none; b=C1Pr500GeukrI3bdMvhSqotuOUbyodQ/wtheTm1ghCipSTy/IcTk3BRDx4y9X5luBRd4GdhcGlwiTUY6HIB4IVJ5g2xXDbBlPyeEu1R5+iHxlKtLdCRaYp17guAuzKeh9p2cPcm1ZzERNJlwYrIG9IWmjuap4qw4/X6l242iGCw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1732815540; c=relaxed/simple; bh=aSxvVVO6Vga8HgJiogoeS3nLOAQVdw1CsUuE/gPe96c=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Eu0RkN+aSP1z/Yc/g+VyUpEVUU8MTiA1pvvsMDRfb/qx1+UeAVAlCuwKNy+zme9sWODYDecBnryAhJWjLRaT8uCkWuaviEnM+VxqYBpj7BH4ofMxG6NPxoIJQDZTnc4jgSyFSSsYcnwS91vBVr3hltRJ3EfC5EtRjHN7GRcy78A= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 296A03858C53 Received: by mail-pf1-x441.google.com with SMTP id d2e1a72fcca58-724e14b90cfso1048576b3a.2 for ; Thu, 28 Nov 2024 09:39:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1732815539; x=1733420339; 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=05MFVFgeMvBqYdpaoNgsoYXGQfR8IqVOMNYKgyUlvvc=; b=A+u7vMSQ4phg3Ia25z2oETFW91PnlCfokQD75FIuMCxWD6Qx1KraK8SdEpbdNuqs18 pSwDFaKViPjqWZx95fkayRh0BIH5E1jEI4LxQJAqCs1e5CYX1A7Ee4QQbo3cBVBiqpVI Oe5nPn0hMchLdwyFGnPRw2Zxz9419Y+m7yVIn5+PsFPT1EFyqSXWO9NLpYN2auhYW2l1 itbnDtPb3uqSAQqJw+cp2LPbVm669LNk5kNzQaBE0CBQh1RMI+/fYcXWeNq/Tx9D5YdO iPO/z5Rv9KVxENGBTOW8dfcuIK/8gKx7o6WUlgd52emqo9gamlwebUKaTJbwbRT6e119 iHSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732815539; x=1733420339; 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=05MFVFgeMvBqYdpaoNgsoYXGQfR8IqVOMNYKgyUlvvc=; b=JZ1w8mil5NCuvnX4bpZ/RkgHhkP93bxtm7tr+rft0lR42PCCoORhoBvENghGqemXRb GLS/ut1nNoBm4frbYslXQJoTwnX5cqmHSFuGFDcXP5i1KPKTaYNCyn1Ygnygce9/K+Bz 3FsfQc0urEFBu/+3KKSjTD1G4/Fq99/K7Lir3ov09glTFdSBzjfCYNi1AaDu0/VC+i5c OXzcm4wFOuzDhGs63+itu5T/rY3BtbtRpC2K32itoup2r8JdorVLQLayQW+ybXv0oGV8 Px7+MSzWj6H20suBxM0bjFtn4UTJYUAQ6v0Xy3x0pAwyncISxAQv7B1TP9mWJYghef4Q SzkQ== X-Gm-Message-State: AOJu0Yy7T29+lG0AsU76ECvlr/Ot5A3M/+r4himD76CL4W5zz3uzGUF5 I9FH/7MJIruP9neGKEvHhs5NkK9+BUEvqd90suJvyetaqVlJHrEzBNX/KP3xDoAUpYqheqvhqzP g9YLT4ein X-Gm-Gg: ASbGncuffvwyQ/gdNb2oOBXqP5j5wXGsk6KYmjiYpKni8XcB6f1DRgvG6Tj9TTLz1ZT RDIa0rEKTqD7577/KRs0rdyIaTv2KtduUlDWLDLvINnGOS+zSZlqP9UhHSWJXu4n4kG0ARh7avv ntqgUPKhXcxin57xRi9lueWK5NQ55O+Yp4zVTI7UE1qfgZl0L0E2Hmt5NGZZcHdapJLuhKm8L85 QOL0WSxNeUFZhInUjbsBHPuWyPxZNGTRLsrbPpWz4KVS922TwEA4UjhVsAqKOI= X-Received: by 2002:a05:6a00:1390:b0:71e:5a1d:ecdc with SMTP id d2e1a72fcca58-7253012f56dmr10609733b3a.17.1732815538414; Thu, 28 Nov 2024 09:38:58 -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.38.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Nov 2024 09:38:58 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Florian Weimer Subject: [PATCH v5 2/4] elf: Do not change stack permission on dlopen/dlmopen Date: Thu, 28 Nov 2024 14:36:43 -0300 Message-ID: <20241128173851.1920696-3-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 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 dae2332eab..8cb5597631 100644 --- a/NEWS +++ b/NEWS @@ -49,6 +49,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 e986d7faab..f525eec662 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1282,12 +1282,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 b8cc3f605f..3b232f8525 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1335,12 +1335,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 91447a5e77..b897da7e7b 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -413,13 +413,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; @@ -716,17 +709,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