Skip to content

Commit 10b899a

Browse files
committed
Don't trust closefrom() on Linux.
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.
1 parent eb1f631 commit 10b899a

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
839839
dnl Target SUSv3/POSIX.1-2001 plus BSD specifics.
840840
dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE
841841
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE"
842+
AC_DEFINE([BROKEN_CLOSEFROM], [1], [broken in chroots on older kernels])
842843
AC_DEFINE([PAM_TTY_KLUDGE], [1],
843844
[Work around problematic Linux PAM modules handling of PAM_TTY])
844845
AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"],
@@ -1820,6 +1821,7 @@ AC_CHECK_FUNCS([ \
18201821
cap_rights_limit \
18211822
clock \
18221823
closefrom \
1824+
close_range \
18231825
dirfd \
18241826
endgrent \
18251827
err \

openbsd-compat/bsd-closefrom.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#include "includes.h"
1818

19-
#ifndef HAVE_CLOSEFROM
19+
#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM)
2020

2121
#include <sys/types.h>
2222
#include <sys/param.h>
@@ -130,6 +130,11 @@ closefrom(int lowfd)
130130
DIR *dirp;
131131
int len;
132132

133+
#ifdef HAVE_CLOSE_RANGE
134+
if (close_range(lowfd, INT_MAX, 0) == 0)
135+
return;
136+
#endif
137+
133138
/* Check for a /proc/$$/fd directory. */
134139
len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
135140
if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) {

0 commit comments

Comments
 (0)