[PATCH] libdwfl: resolve all paths relative to sysroot

Michal Sekletar msekleta@redhat.com
Wed Mar 19 17:40:18 GMT 2025


Whenever possible, resolve all symlinks as if the sysroot path were a
chroot environment. This prevents potential interactions with files from
the host filesystem.

Signed-off-by: Michal Sekletar <msekleta@redhat.com>
---
 configure.ac                         | 17 +++++++++++++++++
 libdwfl/dwfl_segment_report_module.c | 21 +++++++++++++++++++++
 libdwfl/link_map.c                   | 27 ++++++++++++++++++++++++++-
 3 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 3298f7fc..22f7258a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -283,6 +283,23 @@ case "$CFLAGS" in
     ;;
 esac
 
+AC_MSG_CHECKING([for openat2 with RESOLVE_IN_ROOT support])
+AC_LINK_IFELSE(
+  [AC_LANG_PROGRAM([[
+    #include <fcntl.h>
+    #include <linux/openat2.h>
+    #include <sys/syscall.h>
+    #include <unistd.h>
+    #include <stdlib.h>
+  ]], [[
+    struct open_how how = { .flags = O_RDONLY|O_DIRECTORY, .resolve = RESOLVE_IN_ROOT };
+    return syscall (SYS_openat2, AT_FDCWD, ".", &how, sizeof(how)) >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+  ]])],
+  [AC_DEFINE([HAVE_OPENAT2_RESOLVE_IN_ROOT], [1], [Define if openat2 is available])
+   AC_MSG_RESULT(yes)],
+  [AC_MSG_RESULT(no)]
+)
+
 dnl enable debugging of branch prediction.
 AC_ARG_ENABLE([debugpred],
 AS_HELP_STRING([--enable-debugpred],[build binaries with support to debug branch prediction]),
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 32f44af8..53b938b9 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -37,6 +37,12 @@
 #include <inttypes.h>
 #include <fcntl.h>
 
+#if HAVE_OPENAT2_RESOLVE_IN_ROOT
+#include <linux/openat2.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#endif
+
 #include <system.h>
 
 
@@ -784,6 +790,19 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	 sysroot if it is set.  */
       if (dwfl->sysroot && !executable)
         {
+#if HAVE_OPENAT2_RESOLVE_IN_ROOT
+	  int sysrootfd;
+	  struct open_how how = {
+	    .flags = O_RDONLY,
+	    .resolve = RESOLVE_IN_ROOT,
+	  };
+
+	  sysrootfd = open (dwfl->sysroot, O_DIRECTORY|O_PATH);
+	  if (sysrootfd < 0)
+	    return -1;
+	  fd = syscall (SYS_openat2, sysrootfd, name, &how, sizeof(how));
+	  close (sysrootfd);
+#else
 	  int r;
 	  char *n;
 
@@ -793,6 +812,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	      fd = open (n, O_RDONLY);
 	      free (n);
 	    }
+
+#endif
         }
       else
 	  fd = open (name, O_RDONLY);
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 8ab14862..761e9b03 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -34,6 +34,12 @@
 
 #include <fcntl.h>
 
+#if HAVE_OPENAT2_RESOLVE_IN_ROOT
+#include <linux/openat2.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#endif
+
 /* This element is always provided and always has a constant value.
    This makes it an easy thing to scan for to discern the format.  */
 #define PROBE_TYPE	AT_PHENT
@@ -418,7 +424,25 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 	  /* This code is mostly inlined dwfl_report_elf.  */
 	  char *sysroot_name = NULL;
 	  const char *sysroot = dwfl->sysroot;
+	  int fd;
 
+#if HAVE_OPENAT2_RESOLVE_IN_ROOT
+	  if (sysroot)
+	    {
+	      int sysrootfd;
+
+	      struct open_how how = {
+		.flags = O_RDONLY,
+		.resolve = RESOLVE_IN_ROOT,
+	      };
+
+	      sysrootfd = open (sysroot, O_DIRECTORY|O_PATH);
+	      if (sysrootfd < 0)
+		return -1;
+	      fd = syscall (SYS_openat2, sysrootfd, name, &how, sizeof(how));
+	      close (sysrootfd);
+	    }
+#else
 	  /* Don't use the sysroot if the path is already inside it.  */
 	  bool name_in_sysroot = sysroot && startswith (name, sysroot);
 
@@ -430,7 +454,8 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 	      name = sysroot_name;
 	    }
 
-	  int fd = open (name, O_RDONLY);
+	  fd = open (name, O_RDONLY);
+#endif
 	  if (fd >= 0)
 	    {
 	      Elf *elf;
-- 
2.39.5 (Apple Git-154)



More information about the Elfutils-devel mailing list