From patchwork Wed Jul 31 20:02:08 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: 1967285 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=IhPt0FDy; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WZ35803dNz1ybb for ; Thu, 1 Aug 2024 06:06:20 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 38C35385C6C1 for ; Wed, 31 Jul 2024 20:06:18 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pl1-x633.google.com (mail-pl1-x633.google.com [IPv6:2607:f8b0:4864:20::633]) by sourceware.org (Postfix) with ESMTPS id F2B743858294 for ; Wed, 31 Jul 2024 20:03:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F2B743858294 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 F2B743858294 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::633 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722456212; cv=none; b=jtRUJPoxIYChtuwp3BG8P29QBOF1Kz161i/gtcHOq2HoZ+98w4RoKjXTcLJssGEyoPbU7AEeg+IcEhUFOFLOeS1ZKBLcX6tFNn7gtqEpJTxX1Sqmt0okjob/OdLbDiDMh9EIU7IyQUPqGMYI0FQEdOn2ZPZUkdEx+C8cQcIag7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722456212; c=relaxed/simple; bh=wbhYkZR8TMP+mxDAclqevZv0tPn2P3yAW1mX6h2Vlnk=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=WMqJnVdwXM87utWsQjgxRBC3yIi/eyPPzWpaD3Hl3enSWPU0S1nTXrVkbT/mUz0xIBrCmcAtxR5h+NwcafmWGg2gBa8B5pqY1IrvfR8rmlM/sFVDCTJQ0oZ59GQY1NIy4fu3YzbIixhTHo/7KQqSUMbTw6xccOVCUtHs+54wkOQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x633.google.com with SMTP id d9443c01a7336-1fd70ba6a15so45624025ad.0 for ; Wed, 31 Jul 2024 13:03:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1722456206; x=1723061006; 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=/Lexn72Eg7QKKEKnBUx9cEEomzCRRA6drfWxU5dXw6Q=; b=IhPt0FDyp+nqNy6u3qnTL+BKanu9C9bMNKSNVGUQzhxKBz/qVXWWjSxfakmgySe0t6 qTgK0P4X4TYDGqpiUkKRWajTVbpk2L03PyO3/DX/TssIuY4bRftCh0i410zmWtj8T41p jMQTANSfO3GBqZhIDQr76O5eNZvAPdxBhq6TdhnKMl4K6QIrL0avcauFgQlw1gL+k/fe nTFH25vvRtNse7TSS0zbrV1LHG9SX04MXRrkrPDn3fuRb3DUJ0LwMYSIBQy/8N23Xfew aiKZ2SrCkSicE3Iq7frsH0LOqCX5vlvTIGYByoAppnreElBGtuN5yFxGS3Fh6Uqlk9BW N1tQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722456206; x=1723061006; 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=/Lexn72Eg7QKKEKnBUx9cEEomzCRRA6drfWxU5dXw6Q=; b=L5C/TfPWDG7Zug1fphQc0u5efkUsosyUXCpLZ4xOWuh+xTTmMqq3gT23brUSombaZA d5mu4wVN/gtTs3pE3Z+8pgxvWEUClIw5qqPpC14MQdgymdSpUhX9y9sFmMQc6IeW/Yek XmDfCt2VphDdYB1DomhBnuOmFeQ0nOT7eO8xt8wnCbvpvEgaOlohMSlIQuAKy0+2uHv5 VPBeMsx/GWwacaPIrkixFdE1rsh+QjxjCWLVOk57Xg/uBdhYJ84ZL2Q+qQZSMCTzWMTz JmMTeIQwTtQRh/2s/LZxT3ieK5kEWDp8TqAu+GJSx+TJL+rMtOagYkbFiKAG6TxiWqxj UH6A== X-Gm-Message-State: AOJu0Yxo9MuTb5EqhiQ0OwQWRaLqs35fK1hw7l8h6MlqTEAWAgGgiNL7 kRJ9Q011p4NoKfdvUuHkM2jSJ7nBij0NlQAJzajDSYtVRovFL0iv3UAfLaBPIMibo6N8CPSGQxI Y X-Google-Smtp-Source: AGHT+IFrNHggKXZAtUYxS8efGa8LdPWVH8vpUzXuIrUmy4J1kSQ0U4eWJf5qTmjMF7R7fHUVaYDsEg== X-Received: by 2002:a17:902:e542:b0:1fb:7e13:a7cd with SMTP id d9443c01a7336-1ff4ceb5bd4mr5129695ad.37.1722456205992; Wed, 31 Jul 2024 13:03:25 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c1:1944:b913:6070:fef0:3852]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fed7fbd8d4sm124106725ad.271.2024.07.31.13.03.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Jul 2024 13:03:25 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Stephen Roettger , Jeff Xu , Florian Weimer , Mike Hommey Subject: [PATCH v2 5/5] elf: Add support for GNU_PROPERTY_NO_MEMORY_SEAL Date: Wed, 31 Jul 2024 17:02:08 -0300 Message-ID: <20240731200307.2269811-6-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240731200307.2269811-1-adhemerval.zanella@linaro.org> References: <20240731200307.2269811-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org 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~incoming=patchwork.ozlabs.org@sourceware.org The GNU_PROPERTY_NO_MEMORY_SEAL is a GNU property per module instructing the glibc not to seal the object PT_LOAD. It can be used for any reason the modules require to seal not to be enabled (i.e., on Firefox hack to bypass the dynamic loader and enable DT_RELR on older glibc [1]). In this case, it is up to the module to apply memory sealing itself. The sealing is applied by default, and it is always enforced with glibc.rtld.seal=2. Checked on aarch64-linux-gnu, x86_64-linux-gnu, and powerpc64le-linux-gnu. [1] https://glandium.org/blog/?p=4297 --- configure | 35 ++++++++++ configure.ac | 5 ++ elf/dl-load.c | 4 +- elf/dl-open.c | 2 +- elf/dl-reloc.c | 18 ++--- elf/dl-support.c | 4 +- elf/elf.h | 2 + elf/rtld.c | 10 +-- include/link.h | 1 + string/strerrorname_np.c | 1 - sysdeps/aarch64/dl-prop.h | 5 ++ sysdeps/generic/dl-mseal.h | 2 - sysdeps/generic/dl-prop-mseal.h | 38 +++++++++++ sysdeps/generic/dl-prop.h | 5 ++ sysdeps/generic/ldsodefs.h | 11 ++-- sysdeps/unix/sysv/linux/Makefile | 46 +++++++++++++ sysdeps/unix/sysv/linux/dl-mseal.h | 2 - .../tst-dl_mseal-dlopen-no-memory-seal-2-1.c | 19 ++++++ .../tst-dl_mseal-dlopen-no-memory-seal-2.c | 19 ++++++ .../linux/tst-dl_mseal-mod-no-memory-seal-1.c | 19 ++++++ .../linux/tst-dl_mseal-mod-no-memory-seal-2.c | 19 ++++++ .../tst-dl_mseal-no-memory-seal-auditmod.c | 1 + .../tst-dl_mseal-no-memory-seal-preload.c | 1 + .../sysv/linux/tst-dl_mseal-no-memory-seal.c | 65 +++++++++++++++++++ .../unix/sysv/linux/tst-dl_mseal-skeleton.c | 6 +- .../tst-dl_mseal-static-no-memory-seal.c | 38 +++++++++++ sysdeps/x86/dl-prop.h | 4 ++ 27 files changed, 350 insertions(+), 32 deletions(-) create mode 100644 sysdeps/generic/dl-prop-mseal.h create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2-1.c create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2.c create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-1.c create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-2.c create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-auditmod.c create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-preload.c create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal.c create mode 100644 sysdeps/unix/sysv/linux/tst-dl_mseal-static-no-memory-seal.c diff --git a/configure b/configure index 1d543548cd..31deacc983 100755 --- a/configure +++ b/configure @@ -7102,6 +7102,41 @@ printf "%s\n" "$libc_linker_feature" >&6; } config_vars="$config_vars have-no-dynamic-linker = $libc_cv_no_dynamic_linker" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z no-memory-seal" >&5 +printf %s "checking for linker that supports -z no-memory-seal... " >&6; } +libc_linker_feature=no +cat > conftest.c <&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-z,no-memory-seal -nostdlib \ + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \ + | grep "warning: -z no-memory-seal ignored" > /dev/null 2>&1; then + true + else + libc_linker_feature=yes + fi +fi +rm -f conftest* +if test $libc_linker_feature = yes; then + libc_cv_z_no_memory_seal=yes +else + libc_cv_z_no_memory_seal=no +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +printf "%s\n" "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-z-no-memory-seal = $libc_cv_z_no_memory_seal" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5 printf %s "checking for -static-pie... " >&6; } if test ${libc_cv_static_pie+y} diff --git a/configure.ac b/configure.ac index 9cbc0bf68f..a8fc276cfb 100644 --- a/configure.ac +++ b/configure.ac @@ -1278,6 +1278,11 @@ LIBC_LINKER_FEATURE([--no-dynamic-linker], [libc_cv_no_dynamic_linker=no]) LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker]) +LIBC_LINKER_FEATURE([-z no-memory-seal], + [-Wl,-z,no-memory-seal], + [libc_cv_z_no_memory_seal=yes], [libc_cv_z_no_memory_seal=no]) +LIBC_CONFIG_VAR([have-z-no-memory-seal], [$libc_cv_z_no_memory_seal]) + AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl LIBC_TRY_CC_OPTION([-static-pie], [libc_cv_static_pie=yes], diff --git a/elf/dl-load.c b/elf/dl-load.c index 4c2371ec46..17b64363f7 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1431,7 +1431,9 @@ cannot enable executable stack as shared object requires"); /* Assign the next available module ID. */ _dl_assign_tls_modid (l); - l->l_seal = mode & RTLD_NODELETE ? lt_seal_toseal : lt_seal_dont; + /* Do not alter the sealing if the GNU property disables it. */ + if (l->l_seal == lt_seal_undefined && mode & RTLD_NODELETE) + l->l_seal = lt_seal_toseal; #ifdef DL_AFTER_LOAD DL_AFTER_LOAD (l); diff --git a/elf/dl-open.c b/elf/dl-open.c index f53b1b0572..7cc39fba5b 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -841,7 +841,7 @@ dl_open_worker (void *a) /* The seal flag is set only for NEW, however its dependencies could not be unloaded and thus can also be sealed. */ - _dl_mseal_map (new, true); + _dl_mseal_map (new, true, false); } void * diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index 6bb424f789..4a81c3914c 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -352,7 +352,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], /* Seal the memory mapping after RELRO setup, we can use the PT_LOAD segments because even if relro splits the the original RW VMA, mseal works with multiple VMAs with different flags. */ - _dl_mseal_map (l, false); + _dl_mseal_map (l, false, false); } @@ -376,11 +376,10 @@ cannot apply additional memory protection after relocation"); } static void -_dl_mseal_map_1 (struct link_map *l) +_dl_mseal_map_1 (struct link_map *l, bool force) { - /* We only checked if the map is already sealed here so we can seal audit - module dependencies after the initial audit setup. */ - if (l->l_seal == lt_seal_sealed) + if (l->l_seal == lt_seal_dont + || (!force && (l->l_seal != lt_seal_toseal))) return; int r = -1; @@ -408,16 +407,13 @@ _dl_mseal_map_1 (struct link_map *l) } void -_dl_mseal_map (struct link_map *l, bool dep) +_dl_mseal_map (struct link_map *l, bool dep, bool force) { - if (l->l_seal == lt_seal_dont || l->l_seal == lt_seal_sealed) - return; - if (l->l_searchlist.r_list == NULL || !dep) - _dl_mseal_map_1 (l); + _dl_mseal_map_1 (l, force); else for (unsigned int i = 0; i < l->l_searchlist.r_nlist; ++i) - _dl_mseal_map_1 (l->l_searchlist.r_list[i]); + _dl_mseal_map_1 (l->l_searchlist.r_list[i], force); } void diff --git a/elf/dl-support.c b/elf/dl-support.c index a02ae712b3..dd02943dd0 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -101,7 +101,7 @@ static struct link_map _dl_main_map = .l_used = 1, .l_tls_offset = NO_TLS_OFFSET, .l_serial = 1, - .l_seal = SUPPORT_MSEAL, + .l_seal = lt_seal_toseal, }; /* Namespace information. */ @@ -359,7 +359,7 @@ _dl_non_dynamic_init (void) /* Seal the memory mapping after RELRO setup, we can use the PT_LOAD segments because even if relro splits the the original RW VMA, mseal works with multiple VMAs with different flags. */ - _dl_mseal_map (&_dl_main_map, false); + _dl_mseal_map (&_dl_main_map, false, false); } #ifdef DL_SYSINFO_IMPLEMENTATION diff --git a/elf/elf.h b/elf/elf.h index 33aea7f743..62f493b9ee 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -1357,6 +1357,8 @@ typedef struct #define GNU_PROPERTY_STACK_SIZE 1 /* No copy relocation on protected data symbol. */ #define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2 +/* No memory sealing. */ +#define GNU_PROPERTY_NO_MEMORY_SEAL 3 /* A 4-byte unsigned integer property: A bit is set if it is set in all relocatable inputs. */ diff --git a/elf/rtld.c b/elf/rtld.c index efe7e97b04..23b651ee55 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -478,7 +478,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) GL(dl_rtld_map).l_real = &GL(dl_rtld_map); GL(dl_rtld_map).l_map_start = (ElfW(Addr)) &__ehdr_start; GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end; - GL(dl_rtld_map).l_seal = 1; + GL(dl_rtld_map).l_seal = lt_seal_toseal; /* Copy the TLS related data if necessary. */ #ifndef DONT_USE_BOOTSTRAP_MAP # if NO_TLS_OFFSET != 0 @@ -1046,9 +1046,9 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); /* Mark the DSO as being used for auditing. */ dlmargs.map->l_auditing = 1; - /* Seal the audit modules and their dependencies. */ - dlmargs.map->l_seal = lt_seal_toseal; - _dl_mseal_map (dlmargs.map, true); + /* Since audit modules can not be loaded with RTLD_NODELETE, force the + sealing of the modules and its dependencies. */ + _dl_mseal_map (dlmargs.map, true, true); } /* Load all audit modules. */ @@ -1131,7 +1131,7 @@ rtld_setup_main_map (struct link_map *main_map) /* And it was opened directly. */ ++main_map->l_direct_opencount; main_map->l_contiguous = 1; - main_map->l_seal = 1; + main_map->l_seal = lt_seal_toseal; /* A PT_LOAD segment at an unexpected address will clear the l_contiguous flag. The ELF specification says that PT_LOAD diff --git a/include/link.h b/include/link.h index fd8e7f25bf..176f4abddd 100644 --- a/include/link.h +++ b/include/link.h @@ -214,6 +214,7 @@ struct link_map lt_library map. */ enum /* Memory sealing status. */ { + lt_seal_undefined = 0, /* No set. */ lt_seal_dont, /* Do not seal the object. */ lt_seal_toseal, /* The library is marked to be sealed. */ lt_seal_sealed /* The library is sealed. */ diff --git a/string/strerrorname_np.c b/string/strerrorname_np.c index e0e22fa79e..042cea381c 100644 --- a/string/strerrorname_np.c +++ b/string/strerrorname_np.c @@ -17,7 +17,6 @@ . */ #include -#include const char * strerrorname_np (int errnum) diff --git a/sysdeps/aarch64/dl-prop.h b/sysdeps/aarch64/dl-prop.h index df05c0211d..c66d9a49f0 100644 --- a/sysdeps/aarch64/dl-prop.h +++ b/sysdeps/aarch64/dl-prop.h @@ -19,6 +19,8 @@ #ifndef _DL_PROP_H #define _DL_PROP_H +#include + extern void _dl_bti_protect (struct link_map *, int) attribute_hidden; extern void _dl_bti_check (struct link_map *, const char *) @@ -45,6 +47,9 @@ static inline int _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, uint32_t datasz, void *data) { + if (_dl_process_gnu_property_seal (l, fd, type, datasz, data)) + return 0; + if (!GLRO(dl_aarch64_cpu_features).bti) /* Skip note processing. */ return 0; diff --git a/sysdeps/generic/dl-mseal.h b/sysdeps/generic/dl-mseal.h index d542fcac75..dccf78ae38 100644 --- a/sysdeps/generic/dl-mseal.h +++ b/sysdeps/generic/dl-mseal.h @@ -21,5 +21,3 @@ _dl_mseal (void *addr, size_t len) { return 0; } - -#define SUPPORT_MSEAL lt_seal_dont diff --git a/sysdeps/generic/dl-prop-mseal.h b/sysdeps/generic/dl-prop-mseal.h new file mode 100644 index 0000000000..b9dbd24fa5 --- /dev/null +++ b/sysdeps/generic/dl-prop-mseal.h @@ -0,0 +1,38 @@ +/* Support for GNU properties. Generic version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _DL_PROP_MSEAL_H +#define _LD_PROP_MSEAL_H + +#include +#include + +static __always_inline bool +_dl_process_gnu_property_seal (struct link_map *l, int fd, uint32_t type, + uint32_t datasz, void *data) +{ + if (type == GNU_PROPERTY_NO_MEMORY_SEAL && datasz == 0) + { + int32_t mode = TUNABLE_GET (glibc, rtld, seal, int32_t, NULL); + l->l_seal = (mode == DL_SEAL_ENFORCE) ? lt_seal_toseal : lt_seal_dont; + return true; + } + return false; +} + +#endif diff --git a/sysdeps/generic/dl-prop.h b/sysdeps/generic/dl-prop.h index 1d92920a96..5fac690c81 100644 --- a/sysdeps/generic/dl-prop.h +++ b/sysdeps/generic/dl-prop.h @@ -19,6 +19,8 @@ #ifndef _DL_PROP_H #define _DL_PROP_H +#include + /* The following functions are used by the dynamic loader and the dlopen machinery to process PT_NOTE and PT_GNU_PROPERTY entries in the binary or shared object. The notes can be used to change the @@ -47,6 +49,9 @@ static inline int __attribute__ ((always_inline)) _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, uint32_t datasz, void *data) { + if (_dl_process_gnu_property_seal (l, fd, type, datasz, data)) + return 0; + /* Continue until GNU_PROPERTY_1_NEEDED is found. */ if (type == GNU_PROPERTY_1_NEEDED) { diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index aad5a219df..577f3ae06b 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -1017,10 +1017,13 @@ extern void _dl_relocate_object (struct link_map *map, /* Protect PT_GNU_RELRO area. */ extern void _dl_protect_relro (struct link_map *map) attribute_hidden; -/* Protect MAP with mseal. If MAP is contiguous the while region is - sealed, otherwise iterate over the phdr to seal each PT_LOAD. The DEP - specify whether to seal the dependencies as well. */ -extern void _dl_mseal_map (struct link_map *map, bool dep) +/* Issue memory sealing for the link map MAP. If MAP is contiguous the + whole region is sealed, otherwise iterate over the program headerrs and + seal each PT_LOAD segment.i + The DEP specify whether to seal the dependencies as well, while FORCE + ignores if previous seal configuration (such as + GNU_PROPERTY_NO_MEMORY_SEAL mark). */ +extern void _dl_mseal_map (struct link_map *map, bool dep, bool force) attribute_hidden; /* Call _dl_signal_error with a message about an unhandled reloc type. diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 3161363db1..c82aeb3403 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -685,6 +685,52 @@ $(objpfx)tst-dl_mseal-dlopen-2.so: $(objpfx)tst-dl_mseal-dlopen-2-1.so LDFLAGS-tst-dl_mseal-dlopen-2.so = -Wl,--no-as-needed tst-dl_mseal-static-ARGS = -- $(host-test-program-cmd) + +ifeq ($(have-z-no-memory-seal),yes) +tests-static += \ + tst-dl_mseal-static-no-memory-seal \ + # tests-static + +tests += \ + tst-dl_mseal-no-memory-seal \ + tst-dl_mseal-static-no-memory-seal \ + # tests + +modules-names += \ + tst-dl_mseal-dlopen-no-memory-seal-2 \ + tst-dl_mseal-dlopen-no-memory-seal-2-1 \ + tst-dl_mseal-mod-no-memory-seal-1 \ + tst-dl_mseal-mod-no-memory-seal-2 \ + tst-dl_mseal-no-memory-seal-auditmod \ + tst-dl_mseal-no-memory-seal-preload \ + # modules-names + +$(objpfx)tst-dl_mseal-no-memory-seal.out: \ + $(objpfx)tst-dl_mseal-no-memory-seal-auditmod.so \ + $(objpfx)tst-dl_mseal-no-memory-seal-preload.so \ + $(objpfx)tst-dl_mseal-mod-no-memory-seal-1.so \ + $(objpfx)tst-dl_mseal-mod-no-memory-seal-2.so \ + $(objpfx)tst-dl_mseal-dlopen-1.so \ + $(objpfx)tst-dl_mseal-dlopen-1-1.so \ + $(objpfx)tst-dl_mseal-dlopen-no-memory-seal-2.so \ + $(objpfx)tst-dl_mseal-dlopen-no-memory-seal-2-1.so + +tst-dl_mseal-no-memory-seal-ARGS = -- $(host-test-program-cmd) + +LDFLAGS-tst-dl_mseal-no-memory-seal-preload.so = -Wl,-z,no-memory-seal + +LDFLAGS-tst-dl_mseal-no-memory-seal-auditmod.so = -Wl,-z,no-memory-seal +$(objpfx)tst-dl_mseal-no-memory-seal: $(objpfx)tst-dl_mseal-mod-no-memory-seal-1.so +LDFLAGS-tst-dl_mseal-no-memory-seal = -Wl,-z,no-memory-seal -Wl,--no-as-needed +$(objpfx)tst-dl_mseal-mod-no-memory-seal-1.so: $(objpfx)tst-dl_mseal-mod-no-memory-seal-2.so +LDFLAGS-tst-dl_mseal-mod-no-memory-seal-1.so = -Wl,--no-as-needed +LDFLAGS-tst-dl_mseal-mod-no-memory-seal-2.so = -Wl,-z,no-memory-seal -Wl,--no-as-needed +$(objpfx)tst-dl_mseal-dlopen-no-memory-seal-2.so: $(objpfx)tst-dl_mseal-dlopen-no-memory-seal-2-1.so +LDFLAGS-tst-dl_mseal-dlopen-no-memory-seal-2.so = -Wl,--no-as-needed -Wl,-z,no-memory-seal + +LDFLAGS-tst-dl_mseal-static-no-memory-seal = -Wl,-z,no-memory-seal +tst-dl_mseal-static-no-memory-seal-ARGS = -- $(host-test-program-cmd) +endif endif ifeq ($(subdir),rt) diff --git a/sysdeps/unix/sysv/linux/dl-mseal.h b/sysdeps/unix/sysv/linux/dl-mseal.h index 89b19e33c4..25e3f724dc 100644 --- a/sysdeps/unix/sysv/linux/dl-mseal.h +++ b/sysdeps/unix/sysv/linux/dl-mseal.h @@ -25,5 +25,3 @@ Return 0 in case of success or a negative value otherwise (a negative errno). */ int _dl_mseal (void *addr, size_t len) attribute_hidden; - -#define SUPPORT_MSEAL lt_seal_toseal diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2-1.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2-1.c new file mode 100644 index 0000000000..0cd647de46 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2-1.c @@ -0,0 +1,19 @@ +/* Additional module for tst-dl_mseal test. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +int bar2_1 (void) { return 42; } diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2.c new file mode 100644 index 0000000000..f719dd3cba --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-dlopen-no-memory-seal-2.c @@ -0,0 +1,19 @@ +/* Additional module for tst-dl_mseal test. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +int bar2 (void) { return 42; } diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-1.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-1.c new file mode 100644 index 0000000000..3bd188efe8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-1.c @@ -0,0 +1,19 @@ +/* Additional module for tst-dl_mseal test. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +int foo1 (void) { return 42; } diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-2.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-2.c new file mode 100644 index 0000000000..636e9777af --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-mod-no-memory-seal-2.c @@ -0,0 +1,19 @@ +/* Additional module for tst-dl_mseal test. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +int bar1 (void) { return 42; } diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-auditmod.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-auditmod.c new file mode 100644 index 0000000000..a5b257d05e --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-auditmod.c @@ -0,0 +1 @@ +#include "tst-dl_mseal-auditmod.c" diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-preload.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-preload.c new file mode 100644 index 0000000000..32b4153e79 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal-preload.c @@ -0,0 +1 @@ +#include "tst-dl_mseal-preload.c" diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal.c new file mode 100644 index 0000000000..014a8e76c7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-no-memory-seal.c @@ -0,0 +1,65 @@ +/* Basic tests for sealing. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +/* This test checks the GNU_PROPERTY_NO_MEMORY_SEAL handling on multiple + places: + + - On the binary itself. + - On a LD_PRELOAD library. + - On a depedency module (tst-dl_mseal-mod-no-memory-seal-2.so). + - On a audit modules (tst-dl_mseal-no-memory-seal-auditmod.so). + - On a dlopen dependency opened with RTLD_NODELET + (tst-dl_mseal-dlopen-no-memory-seal-2.so). +*/ + +#define LIB_PRELOAD "tst-dl_mseal-no-memory-seal-preload.so" +#define GLIBC_RTLD_SEAL "1" + +#define LIB_DLOPEN_DEFAULT "tst-dl_mseal-dlopen-1.so" +#define LIB_DLOPEN_DEFAULT_DEP "tst-dl_mseal-dlopen-1-1.so" +#define LIB_DLOPEN_NODELETE "tst-dl_mseal-dlopen-no-memory-seal-2.so" +#define LIB_DLOPEN_NODELETE_DEP "tst-dl_mseal-dlopen-no-memory-seal-2-1.so" + +#define LIB_AUDIT "tst-dl_mseal-no-memory-seal-auditmod.so" + +/* Expected libraries that loader will seal. */ +static const char *expected_sealed_libs[] = +{ + "libc.so", + "ld.so", + "tst-dl_mseal-mod-no-memory-seal-1.so", + LIB_DLOPEN_NODELETE_DEP, + LIBGCC_S_SO, +}; + +/* Expected non sealed libraries. */ +static const char *expected_non_sealed_libs[] = +{ + "[vdso]", + "tst-dl_mseal-no-memory-seal", + LIB_PRELOAD, + LIB_AUDIT, + "tst-dl_mseal-mod-no-memory-seal-2.so", + LIB_DLOPEN_DEFAULT, + LIB_DLOPEN_DEFAULT_DEP, + LIB_DLOPEN_NODELETE, +}; + +#include "tst-dl_mseal-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c index fbf18d9b7c..6c77b14d86 100644 --- a/sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-skeleton.c @@ -1,4 +1,4 @@ -/* Basic tests for sealing. Static version. +/* Basic tests for sealing. Copyright (C) 2024 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -198,7 +198,7 @@ handle_restart (void) /* Also check if all the expected sealed maps were found. */ for (int i = 0; i < array_length (expected_sealed_libs); i++) - if (!found_expected[i]) + if (expected_sealed_libs[i][0] && !found_expected[i]) FAIL_EXIT1 ("expected VMA %s not sealed\n", expected_sealed_libs[i]); return 0; @@ -239,7 +239,7 @@ do_test (int argc, char *argv[]) spargv[i] = NULL; char *envvarss[4]; - envvarss[0] = (char *) "GLIBC_TUNABLES=glibc.rtld.seal=2"; + envvarss[0] = (char *) "GLIBC_TUNABLES=glibc.rtld.seal=" GLIBC_RTLD_SEAL; #ifndef TEST_STATIC envvarss[1] = (char *) "LD_PRELOAD=" LIB_PRELOAD; envvarss[2] = (char *) "LD_AUDIT=" LIB_AUDIT, diff --git a/sysdeps/unix/sysv/linux/tst-dl_mseal-static-no-memory-seal.c b/sysdeps/unix/sysv/linux/tst-dl_mseal-static-no-memory-seal.c new file mode 100644 index 0000000000..257500ea47 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-dl_mseal-static-no-memory-seal.c @@ -0,0 +1,38 @@ +/* Basic tests for sealing. Static version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This test checks the GNU_PROPERTY_NO_MEMORY_SEAL handling on a statically + built binary. In this case only the vDSO (if existent) will be sealed. */ + +#define GLIBC_RTLD_SEAL "1" +#define TEST_STATIC 1 + +/* Expected libraries that loader will seal. */ +static const char *expected_sealed_libs[] = +{ + "", +}; + +/* Expected non sealed libraries. */ +static const char *expected_non_sealed_libs[] = +{ + "[vdso]", + "tst-dl_mseal-static-no-memory-seal", +}; + +#include "tst-dl_mseal-skeleton.c" diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h index 08387dfaff..26a687d611 100644 --- a/sysdeps/x86/dl-prop.h +++ b/sysdeps/x86/dl-prop.h @@ -19,6 +19,7 @@ #ifndef _DL_PROP_H #define _DL_PROP_H +#include #include extern void _dl_cet_check (struct link_map *, const char *) @@ -241,6 +242,9 @@ _dl_process_gnu_property (struct link_map *l, int fd, uint32_t type, uint32_t datasz, void *data) { /* This is called on each GNU property. */ + if (_dl_process_gnu_property_seal (l, fd, type, datasz, data)) + return 0; + unsigned int needed_1 = 0; unsigned int feature_1_and = 0; unsigned int isa_1_needed = 0;