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 <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)]
> +)
> +

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

Reply via email to