On Wed, Mar 19, 2025 at 06:40:18PM +0100, Michal Sekletar wrote:
> 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 <[email protected]>
> ---
> 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)]
> +)
> +
It's always a good idea to wrap checks with AC_CACHE_CHECK,
for example (untested):
AC_CACHE_CHECK(
[for openat2 with RESOLVE_IN_ROOT support],
[eu_cv_openat2_RESOLVE_IN_ROOT],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/openat2.h>
]], [[
struct open_how how = { .flags = O_RDONLY|O_DIRECTORY, .resolve =
RESOLVE_IN_ROOT };
int dfd = open (".", O_DIRECTORY|O_PATH);
return syscall (SYS_openat2, dfd, ".", &how, sizeof(how)) < 0;
]]
)],
[eu_cv_openat2_RESOLVE_IN_ROOT=yes],
[eu_cv_openat2_RESOLVE_IN_ROOT=no]
)]
)
AS_IF([test "x$eu_cv_openat2_RESOLVE_IN_ROOT" = xyes],
[AC_DEFINE([HAVE_OPENAT2_RESOLVE_IN_ROOT], [1], [Define if openat2 is
available])]
)
This way one can set eu_cv_openat2_RESOLVE_IN_ROOT variable
for configure script invocation to override the check.
> 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
I suggest implementing a runtime fallback to the old non-openat2 code if
openat2 syscall is not available, e.g. filtered out by a seccomp filter.
--
ldv