diff mbox series

[v8,2/8] elf: Parse gnu properties for static linked binaries

Message ID 20250129172550.1119706-3-adhemerval.zanella@linaro.org
State New
Headers show
Series Add support for memory sealing | expand

Commit Message

Adhemerval Zanella Jan. 29, 2025, 5:22 p.m. UTC
So the static binary can opt-in of memory sealing.  The aarch64 already
does it for GCS, so refactor it to use __libc_process_gnu_attributes
instead.

Checked on x86_64-linux-gnu.
---
 csu/libc-start.c                             |  4 ++
 elf/dl-support.c                             | 13 ++++++
 sysdeps/generic/libc-prop.h                  | 44 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/aarch64/libc-start.h | 11 -----
 sysdeps/x86/dl-prop.h                        |  4 +-
 5 files changed, 64 insertions(+), 12 deletions(-)
 create mode 100644 sysdeps/generic/libc-prop.h
diff mbox series

Patch

diff --git a/csu/libc-start.c b/csu/libc-start.c
index 6f3d52e223..44fe5d5738 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -36,6 +36,7 @@ 
 #include <stdbool.h>
 #include <elf-initfini.h>
 #include <shlib-compat.h>
+#include <libc-prop.h>
 
 #include <elf/dl-tunables.h>
 
@@ -276,6 +277,9 @@  LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
   /* Perform IREL{,A} relocations.  */
   ARCH_SETUP_IREL ();
 
+  /* Process notes: PT_NOTE / PT_GNU_PROPERTY.  */
+  __libc_process_gnu_attributes ();
+
   /* The stack guard goes into the TCB, so initialize it early.  */
   ARCH_SETUP_TLS ();
 
diff --git a/elf/dl-support.c b/elf/dl-support.c
index a7d5a5e8ab..6daa196f12 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -46,6 +46,7 @@ 
 #include <array_length.h>
 #include <dl-symbol-redir-ifunc.h>
 #include <dl-tunables.h>
+#include <dl-prop.h>
 
 extern char *__progname;
 char **_dl_argv = &__progname;	/* This is checked for some error messages.  */
@@ -331,6 +332,18 @@  _dl_non_dynamic_init (void)
 	_dl_main_map.l_relro_size = ph->p_memsz;
 	break;
       }
+  /* Process program headers again, but scan them backwards so
+     that PT_NOTE can be skipped if PT_GNU_PROPERTY exits.  */
+  for (const ElfW(Phdr) *ph = &_dl_phdr[_dl_phnum]; ph != _dl_phdr; --ph)
+    switch (ph[-1].p_type)
+      {
+      case PT_NOTE:
+	_dl_process_pt_note (&_dl_main_map, -1, &ph[-1]);
+	break;
+      case PT_GNU_PROPERTY:
+	_dl_process_pt_gnu_property (&_dl_main_map, -1, &ph[-1]);
+	break;
+      }
 
   if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X)
       && TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL) == 0)
diff --git a/sysdeps/generic/libc-prop.h b/sysdeps/generic/libc-prop.h
new file mode 100644
index 0000000000..723575d29b
--- /dev/null
+++ b/sysdeps/generic/libc-prop.h
@@ -0,0 +1,44 @@ 
+/* Support for GNU properties for static builds.  Generic version.
+   Copyright (C) 2025 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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBC_PROP_H
+#define _LIBC_PROP_H
+
+#include <dl-prop.h>
+
+/* Called at the start of program execution to handle GNU attribute from
+   PT_NOTE / PT_GNU_PROPERTY.  Must be on a top-level stack frame that does
+   not return.  */
+static __always_inline void
+__libc_process_gnu_attributes (void)
+{
+# ifndef SHARED
+  struct link_map *main_map = _dl_get_dl_main_map ();
+  const ElfW(Phdr) *phdr = GL(dl_phdr);
+  const ElfW(Phdr) *ph;
+  for (ph = phdr; ph < phdr + GL(dl_phnum); ph++)
+    if (ph->p_type == PT_GNU_PROPERTY)
+      {
+	_dl_process_pt_gnu_property (main_map, -1, ph);
+	_rtld_main_check (main_map, _dl_argv[0]);
+	break;
+      }
+# endif
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc-start.h b/sysdeps/unix/sysv/linux/aarch64/libc-start.h
index 75ae0a884a..64acbdb533 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc-start.h
+++ b/sysdeps/unix/sysv/linux/aarch64/libc-start.h
@@ -34,17 +34,6 @@  aarch64_libc_setup_tls (void)
 {
   __libc_setup_tls ();
 
-  struct link_map *main_map = _dl_get_dl_main_map ();
-  const ElfW(Phdr) *phdr = GL(dl_phdr);
-  const ElfW(Phdr) *ph;
-  for (ph = phdr; ph < phdr + GL(dl_phnum); ph++)
-    if (ph->p_type == PT_GNU_PROPERTY)
-      {
-	_dl_process_pt_gnu_property (main_map, -1, ph);
-	_rtld_main_check (main_map, _dl_argv[0]);
-	break;
-      }
-
   if (GL(dl_aarch64_gcs) != 0)
     {
       int ret = INLINE_SYSCALL_CALL (prctl, PR_SET_SHADOW_STACK_STATUS,
diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
index 8625751427..9a5e10821c 100644
--- a/sysdeps/x86/dl-prop.h
+++ b/sysdeps/x86/dl-prop.h
@@ -66,9 +66,11 @@  dl_isa_level_check (struct link_map *m, const char *program)
 static inline void __attribute__ ((always_inline))
 _rtld_main_check (struct link_map *m, const char *program)
 {
+#ifdef SAHRED
   dl_isa_level_check (m, program);
-#if CET_ENABLED
+# if CET_ENABLED
   _dl_cet_check (m, program);
+# endif
 #endif
 }