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 <msekl...@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)

Reply via email to