From patchwork Wed May 22 11:29:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Roettger X-Patchwork-Id: 90682 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 080503865487 for ; Wed, 22 May 2024 11:30:53 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by sourceware.org (Postfix) with ESMTPS id CD6EA3858CD1 for ; Wed, 22 May 2024 11:29:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CD6EA3858CD1 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=flex--sroettger.bounces.google.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CD6EA3858CD1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::b49 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1716377391; cv=none; b=IES84D+QEIUbY3DEYBOnGtBikrnq8QhQcqSM1CFZ+gqPv0ebVbhNtXSL/VqkE5JVwFL2cPuBvRb2cxL7IE8pkUv2X7hgJxKrMDNGUSRk4h8sn6dP4Qym/S6O3/U/jLsh9b6bPsUFpVip2u63Kz4MSxx4MHsGWWVsWGsokhEzvnA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1716377391; c=relaxed/simple; bh=rfOLk+XKnJxUjel0PTE+oYpQ+twHsJTuflBe9GlYPVY=; h=DKIM-Signature:Date:Mime-Version:Message-ID:Subject:From:To; b=l/d3Xl09JTU7TRliGuFKp0KHf38/PPTw8qghWtmeHstKYzTbpPcTpZy7FkdHDCtuMfNYuCk2o2Ce0UOOq2xZePuzOUQjbNnzTiF57FlQ0s/ePEKfIG+fvYmj+Kmgo+y46xzSdmcLmyjHP73x+qTA9O7zCLF5DAYbTmjBzagjzEw= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-dc6b269686aso21643088276.1 for ; Wed, 22 May 2024 04:29:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1716377388; x=1716982188; darn=sourceware.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=akTMkVYkbkoE/ue59sQ/awpgSy6g60awT/F0ig4CzqM=; b=KJjnt3TZYJOcV6yb3ZDL/tMLkStiskr1ZoSn3IA+Wq9dJLTsuouOw5Jx6lNeslqqrG NKZokCXRVXkxl3cLjK7sNgnu2PFlHV2EEFn5BoT5x0HqUmY27UgC74i7TeW8x6wzyhHV OrdhaH58spI3q6aI2p+2xXnW3JjKQjpJ5jIcP3xEUeWBSwGWp+1JZsG1HTycdGi4W3zf P0p5LvEAFt0SdulBAJjzuInWuNyAvL/ilLZWFRhHATD7zdu/wkbP7iOfK+A1ZNj5E5Ym gzKov40RLcot9xdhNO/+Hwkpy0WpF+ag6s5eFunE4lTtqMfbY4Fd8fF97cX0me3CDq42 gg7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1716377388; x=1716982188; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=akTMkVYkbkoE/ue59sQ/awpgSy6g60awT/F0ig4CzqM=; b=iWGCyF+Ko3abjduUHFE8RMLWU9OSD6Mv/sRT6mgI/tCdO9rAWEN5wAA+dsJqiTShDp tt8aQB1EFYb7lGmlgHxtZhAo+RHq2+7fO4hQXFD8pFwzDBv2TZ3rt3jiiUJq8cXvX5jj QexVieUsANVoEqQR3a+u7JKguhGBfWvNXXBMv45yJGP1RUJD9O71ig7dCwLve9zo3wyV 35n8KzjqZj7o5RzNCaTILhn7WST0J/W0xKijOXGkQFy7znDtOnIVjYoJQxZ1OcFK+dG6 mBoWIFagUoY82sap8AhtKiiPQRw8q454Nk3H9lVWEfWwZJ5IBhZamgdY+o2Adu10A7mx oW6g== X-Gm-Message-State: AOJu0YxrHYCIoZ7/5mzNlyGc2/azofOvM+d3vXFZM3X+t6ofC8XoFHue 9aVUeKCvhdxgeoqvj/27ervvTvn5Ag8KXFE6m0nBob0Mn9qx+TxTMltFfYWCZ8C48cVlR5D7MYu c3v0OV1Q0G+hyaaTkJvtdGxH9mfCuWANbuh6R/TIZVgwOuNePFZtFGepF6w6TQbR4ThxUT3mA7w ObMu0RTIeC9t+7diqxwjf2y1MrYUr+cXpw/bJrTIiQvs5jtLVSEkR+ X-Google-Smtp-Source: AGHT+IF0CLqw775BCpScUx9ygQSr+OgkheN41TWflbcaCKhVRKEgKa51jvxSkfgqR+zUAQTkd11/qpQofBLaVmM= X-Received: from sroettger.zrh.corp.google.com ([2a00:79e0:9d:4:d50a:4c46:2093:8151]) (user=sroettger job=sendgmr) by 2002:a05:6902:2b8d:b0:de5:bc2f:72bb with SMTP id 3f1490d57ef6-df4e0d9af22mr174877276.12.1716377388128; Wed, 22 May 2024 04:29:48 -0700 (PDT) Date: Wed, 22 May 2024 13:29:31 +0200 In-Reply-To: <20240522112933.2005066-1-sroettger@google.com> Mime-Version: 1.0 References: <20240522112933.2005066-1-sroettger@google.com> X-Mailer: git-send-email 2.45.1.288.g0e0cd299f1-goog Message-ID: <20240522112933.2005066-2-sroettger@google.com> Subject: [RFC 1/1] elf: mseal non-writable segments From: Stephen Roettger To: libc-alpha@sourceware.org Cc: Stephen Roettger , jeffxu@chromium.org X-Spam-Status: No, score=-20.7 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, USER_IN_DEF_DKIM_WL 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+patchwork=sourceware.org@sourceware.org Mseal is a new Linux syscall that blocks any modifications to given memory mappings like unmapping them or changing the permission bits. This patch applies mseal to segments during loading if: * the writable bit is not set * mode is RTLD_NODELETE In addition, it adds RTLD_NODELETE to the main binary/libraries and propagates the RTLD_NODELETE to auxialliary library loads. --- elf/dl-load.c | 6 ++++++ elf/dl-load.h | 1 + elf/dl-map-segments.h | 6 ++++++ elf/dl-open.c | 3 ++- elf/rtld.c | 12 +++++++++--- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index a34cb3559c..638028d6da 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1136,6 +1136,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize)); c->dataend = ph->p_vaddr + ph->p_filesz; c->allocend = ph->p_vaddr + ph->p_memsz; + c->seal = false; /* Remember the maximum p_align. */ if (powerof2 (ph->p_align) && ph->p_align > p_align_max) p_align_max = ph->p_align; @@ -1169,6 +1170,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, if (ph->p_flags & PF_X) c->prot |= PROT_EXEC; #endif + + if (mode & RTLD_NODELETE && ((c->prot & PROT_WRITE) == 0)) { + c->seal = true; + } + break; case PT_TLS: diff --git a/elf/dl-load.h b/elf/dl-load.h index 656ec229bf..040e744908 100644 --- a/elf/dl-load.h +++ b/elf/dl-load.h @@ -78,6 +78,7 @@ struct loadcmd ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign; ElfW(Off) mapoff; int prot; /* PROT_* bits. */ + bool seal; }; diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h index 30977cf800..4cddb4b294 100644 --- a/elf/dl-map-segments.h +++ b/elf/dl-map-segments.h @@ -19,6 +19,8 @@ #include +#define SYS_mseal 462 + /* Map a segment and align it properly. */ static __always_inline ElfW(Addr) @@ -143,6 +145,10 @@ _dl_map_segments (struct link_map *l, int fd, == MAP_FAILED)) return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT; + if (c->seal) { + syscall(SYS_mseal, (void*) mm, map_size, 0); + } + postmap: _dl_postprocess_loadcmd (l, header, c); diff --git a/elf/dl-open.c b/elf/dl-open.c index c378da16c0..a6c89134f8 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -636,7 +636,8 @@ dl_open_worker_begin (void *a) /* Load that object's dependencies. */ _dl_map_object_deps (new, NULL, 0, 0, - mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT)); + mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | + __RTLD_AUDIT | RTLD_NODELETE)); /* So far, so good. Now check the versions. */ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) diff --git a/elf/rtld.c b/elf/rtld.c index e9525ea987..b471e4c0af 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -79,6 +79,8 @@ # define RTLD_TIMING_SET(var, value) (var) = (value) # define RTLD_TIMING_REF(var) &(var) +#define SYS_mseal 462 + static inline void rtld_timer_start (hp_timing_t *var) { @@ -809,7 +811,7 @@ do_preload (const char *fname, struct link_map *main_map, const char *where) args.str = fname; args.loader = main_map; - args.mode = __RTLD_SECURE; + args.mode = __RTLD_SECURE | RTLD_NODELETE; unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded; @@ -1214,6 +1216,10 @@ rtld_setup_main_map (struct link_map *main_map) segment. */ expected_load_address = ((allocend + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1)); + + if ((ph->p_flags & PF_W) == 0) { + syscall(SYS_mseal, mapstart, expected_load_address - mapstart, 0); + } } break; @@ -1636,7 +1642,7 @@ dl_main (const ElfW(Phdr) *phdr, /* Create a link_map for the executable itself. This will be what dlopen on "" returns. */ main_map = _dl_new_object ((char *) "", "", lt_executable, NULL, - __RTLD_OPENEXEC, LM_ID_BASE); + __RTLD_OPENEXEC | RTLD_NODELETE, LM_ID_BASE); assert (main_map != NULL); main_map->l_phdr = phdr; main_map->l_phnum = phnum; @@ -1964,7 +1970,7 @@ dl_main (const ElfW(Phdr) *phdr, RTLD_TIMING_VAR (start); rtld_timer_start (&start); _dl_map_object_deps (main_map, preloads, npreloads, - state.mode == rtld_mode_trace, 0); + state.mode == rtld_mode_trace, RTLD_NODELETE); rtld_timer_accum (&load_time, start); }