public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Stephen Roettger <sroettger@google.com>
To: libc-alpha@sourceware.org
Cc: Stephen Roettger <sroettger@google.com>, jeffxu@chromium.org
Subject: [RFC 1/1] elf: mseal non-writable segments
Date: Wed, 22 May 2024 13:29:31 +0200	[thread overview]
Message-ID: <20240522112933.2005066-2-sroettger@google.com> (raw)
In-Reply-To: <20240522112933.2005066-1-sroettger@google.com>

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 <dl-load.h>
 
+#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);
   }
 
-- 
2.45.1.288.g0e0cd299f1-goog


  reply	other threads:[~2024-05-22 11:29 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-22 11:29 [RFC 0/1] " Stephen Roettger
2024-05-22 11:29 ` Stephen Roettger [this message]
2024-05-22 16:24   ` [RFC 1/1] " Cristian Rodríguez
     [not found]     ` <CAEAAPHaEssoE79B0vWk1S42QaUk+WVwJ0sNxnUzF3hkXNG+b9w@mail.gmail.com>
2024-05-22 18:39       ` Carlos O'Donell
2024-05-22 18:57 ` [RFC 0/1] " Carlos O'Donell
2024-05-23  9:31   ` Stephen Röttger
2024-05-23 10:38     ` Florian Weimer
2024-05-22 19:42 ` Florian Weimer
2024-05-23  9:36   ` Stephen Röttger
2024-06-04 14:19     ` Adhemerval Zanella Netto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240522112933.2005066-2-sroettger@google.com \
    --to=sroettger@google.com \
    --cc=jeffxu@chromium.org \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).