]>
Commit | Line | Data |
---|---|---|
e24ec364 AM |
1 | commit 10b899a15c88eb40eb5f73cd0fa84ef0966f79c9 |
2 | Author: Darren Tucker <dtucker@dtucker.net> | |
3 | Date: Wed Nov 10 12:34:25 2021 +1100 | |
4 | ||
5 | Don't trust closefrom() on Linux. | |
6 | ||
7 | glibc's closefrom implementation does not work in a chroot when the kernel | |
8 | does not have close_range. It tries to read from /proc/self/fd and when | |
9 | that fails dies with an assertion of sorts. Instead, call close_range | |
10 | ourselves from our compat code and fall back if that fails. bz#3349, | |
11 | with william.wilson at canonical.com and fweimer at redhat.com. | |
12 | ||
13 | diff --git a/configure.ac b/configure.ac | |
14 | index 165b391f..cd4cadec 100644 | |
15 | --- a/configure.ac | |
16 | +++ b/configure.ac | |
17 | @@ -839,6 +839,7 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) | |
18 | dnl Target SUSv3/POSIX.1-2001 plus BSD specifics. | |
19 | dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE | |
20 | CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE" | |
21 | + AC_DEFINE([BROKEN_CLOSEFROM], [1], [broken in chroots on older kernels]) | |
22 | AC_DEFINE([PAM_TTY_KLUDGE], [1], | |
23 | [Work around problematic Linux PAM modules handling of PAM_TTY]) | |
24 | AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"], | |
25 | @@ -1820,6 +1821,7 @@ AC_CHECK_FUNCS([ \ | |
26 | cap_rights_limit \ | |
27 | clock \ | |
28 | closefrom \ | |
29 | + close_range \ | |
30 | dirfd \ | |
31 | endgrent \ | |
32 | err \ | |
33 | diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c | |
34 | index 8fadca2d..08b7da69 100644 | |
35 | --- a/openbsd-compat/bsd-closefrom.c | |
36 | +++ b/openbsd-compat/bsd-closefrom.c | |
37 | @@ -16,7 +16,7 @@ | |
38 | ||
39 | #include "includes.h" | |
40 | ||
41 | -#ifndef HAVE_CLOSEFROM | |
42 | +#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) | |
43 | ||
44 | #include <sys/types.h> | |
45 | #include <sys/param.h> | |
46 | @@ -130,6 +130,11 @@ closefrom(int lowfd) | |
47 | DIR *dirp; | |
48 | int len; | |
49 | ||
50 | +#ifdef HAVE_CLOSE_RANGE | |
51 | + if (close_range(lowfd, INT_MAX, 0) == 0) | |
52 | + return; | |
53 | +#endif | |
54 | + | |
55 | /* Check for a /proc/$$/fd directory. */ | |
56 | len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid()); | |
57 | if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) { |