From f1a697a8fff5f1ff2a15a9d8eeebb056aae90a96 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 1 Mar 2022 09:54:23 -0700 Subject: [PATCH] Use close_range(2) in closefrom() emulation if available. On Linux, prefer our own closefrom() emulation since the glibc version may fail if /proc is not present and close_range() is not supported. On FreeBSD, closefrom(3) will either call the closefrom or close_range system call, depending on which is available. --- NEWS | 5 +++++ config.h.in | 6 ++++++ configure | 29 +++++++++++++++++++++++++++++ configure.ac | 13 ++++++++++++- lib/util/closefrom.c | 8 +++++++- 5 files changed, 59 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index ea13fa8d3..ba78c3137 100644 --- a/NEWS +++ b/NEWS @@ -67,6 +67,11 @@ What's new in Sudo 1.9.10 that don't interact with the user via a terminal do not trigger the lecture. + * Sudo now uses its own closefrom() emulation on Linux systems. + The glibc version may not work in a chroot jail where /proc is + not available. If close_range(2) is present, it will be used + in preference to /proc/self/fd. + What's new in Sudo 1.9.9 * Sudo can now be built with OpenSSL 3.0 without generating warnings diff --git a/config.h.in b/config.h.in index 098edd32f..da1cf40ba 100644 --- a/config.h.in +++ b/config.h.in @@ -100,6 +100,9 @@ /* Define to 1 if you have the `closefrom' function. */ #undef HAVE_CLOSEFROM +/* Define to 1 if you have the `close_range' function. */ +#undef HAVE_CLOSE_RANGE + /* Define to 1 if you have the `crypt' function. */ #undef HAVE_CRYPT @@ -548,6 +551,9 @@ /* Define to 1 to enable Linux audit support. */ #undef HAVE_LINUX_AUDIT +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_CLOSE_RANGE_H + /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_RANDOM_H diff --git a/configure b/configure index 4608e2e67..fcd4d0239 100755 --- a/configure +++ b/configure @@ -17687,6 +17687,10 @@ fi # The glibc getentropy() emulation may fail on older kernels. # We use our own getentropy() by default on Linux. : ${ac_cv_func_getentropy='no'} + + # The glibc closefrom() emulation may fail in chroot. + # We use our own closefrom() by default on Linux. + : ${ac_cv_func_closefrom='no'} ;; *-*-gnu*) # lockf() is broken on the Hurd @@ -23081,6 +23085,31 @@ if test "x$ac_cv_have_decl_F_CLOSEM" = xyes then : printf "%s\n" "#define HAVE_FCNTL_CLOSEM 1" >>confdefs.h +else $as_nop + + # Linux has a special header for close_range(2). + + for ac_func in close_range +do : + ac_fn_c_check_func "$LINENO" "close_range" "ac_cv_func_close_range" +if test "x$ac_cv_func_close_range" = xyes +then : + printf "%s\n" "#define HAVE_CLOSE_RANGE 1" >>confdefs.h + + case "$host_os" in + linux*) ac_fn_c_check_header_compile "$LINENO" "linux/close_range.h" "ac_cv_header_linux_close_range_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_close_range_h" = xyes +then : + printf "%s\n" "#define HAVE_LINUX_CLOSE_RANGE_H 1" >>confdefs.h + +fi +;; + esac + +fi + +done + fi fi diff --git a/configure.ac b/configure.ac index b283f3d82..23c18614d 100644 --- a/configure.ac +++ b/configure.ac @@ -2066,6 +2066,10 @@ case "$host" in # The glibc getentropy() emulation may fail on older kernels. # We use our own getentropy() by default on Linux. : ${ac_cv_func_getentropy='no'} + + # The glibc closefrom() emulation may fail in chroot. + # We use our own closefrom() by default on Linux. + : ${ac_cv_func_closefrom='no'} ;; *-*-gnu*) # lockf() is broken on the Hurd @@ -2909,7 +2913,14 @@ AC_CHECK_FUNCS([getopt_long], [], [ ]) AC_CHECK_FUNCS([closefrom], [], [AC_LIBOBJ(closefrom) SUDO_APPEND_COMPAT_EXP(sudo_closefrom) - AC_CHECK_DECL(F_CLOSEM, AC_DEFINE(HAVE_FCNTL_CLOSEM), [], [ + AC_CHECK_DECL(F_CLOSEM, AC_DEFINE(HAVE_FCNTL_CLOSEM), [ + # Linux has a special header for close_range(2). + AC_CHECK_FUNCS([close_range], [ + case "$host_os" in + linux*) AC_CHECK_HEADERS([linux/close_range.h]);; + esac + ]) + ], [ # include # include ]) ]) diff --git a/lib/util/closefrom.c b/lib/util/closefrom.c index 8608e68c5..64e9826b1 100644 --- a/lib/util/closefrom.c +++ b/lib/util/closefrom.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: ISC * - * Copyright (c) 2004-2005, 2007, 2010, 2012-2015, 2017-2021 + * Copyright (c) 2004-2005, 2007, 2010, 2012-2015, 2017-2022 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -39,6 +39,9 @@ #ifdef HAVE_LIBPROC_H # include #endif +#ifdef HAVE_LINUX_CLOSE_RANGE_H +# include +#endif #include "sudo_compat.h" #include "sudo_util.h" @@ -107,6 +110,9 @@ sudo_closefrom(int lowfd) #if defined(HAVE_FCNTL_CLOSEM) if (fcntl(lowfd, F_CLOSEM, 0) != -1) return; +#elif defined(HAVE_CLOSE_RANGE) + if (close_range(lowfd, ~0U, 0) != -1) + return; #elif defined(HAVE_PROC_PIDINFO) len = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); switch (len) {