[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