]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
Don't trust closefrom() on Linux.
authorDarren Tucker <dtucker@dtucker.net>
Wed, 10 Nov 2021 01:34:25 +0000 (12:34 +1100)
committerDarren Tucker <dtucker@dtucker.net>
Wed, 10 Nov 2021 01:34:25 +0000 (12:34 +1100)
glibc's closefrom implementation does not work in a chroot when the kernel
does not have close_range.  It tries to read from /proc/self/fd and when
that fails dies with an assertion of sorts.  Instead, call close_range
ourselves from our compat code and fall back if that fails.  bz#3349,
with william.wilson at canonical.com and fweimer at redhat.com.

configure.ac
openbsd-compat/bsd-closefrom.c

index 165b391f7885547b08e78b75a74e17846083d3cf..cd4cadecc9bb1250b3df4e3f31e66e6f60d02350 100644 (file)
@@ -839,6 +839,7 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
        dnl Target SUSv3/POSIX.1-2001 plus BSD specifics.
        dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE
        CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE"
+       AC_DEFINE([BROKEN_CLOSEFROM], [1], [broken in chroots on older kernels])
        AC_DEFINE([PAM_TTY_KLUDGE], [1],
                [Work around problematic Linux PAM modules handling of PAM_TTY])
        AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"],
@@ -1820,6 +1821,7 @@ AC_CHECK_FUNCS([ \
        cap_rights_limit \
        clock \
        closefrom \
+       close_range \
        dirfd \
        endgrent \
        err \
index 8fadca2dad6625931b6acb9384a8082a634424bd..08b7da6983cd81587f84de53fea6c3df33abc61f 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "includes.h"
 
-#ifndef HAVE_CLOSEFROM
+#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM)
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -130,6 +130,11 @@ closefrom(int lowfd)
     DIR *dirp;
     int len;
 
+#ifdef HAVE_CLOSE_RANGE
+       if (close_range(lowfd, INT_MAX, 0) == 0)
+               return;
+#endif
+
     /* Check for a /proc/$$/fd directory. */
     len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
     if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) {