linux_dep: Fix CLOSE_RANGE_UNSHARE availability handling
If CLOSE_RANGE_UNSHARE isn't defined, we define a fallback version of close_range() which is a (successful) no-op. This is broken in several ways: * It doesn't actually fix compile if using old kernel headers, because the caller of close_range() still directly uses CLOSE_RANGE_UNSHARE unprotected by ifdefs * Even if it did fix the compile, it means inconsistent behaviour between a compile time failure to find the value (we silently don't close files) and a runtime failure (we die with an error from close_range()) * Silently not closing the files we intend to close for security reasons is probably not a good idea in any case We don't want to simply error if close_range() or CLOSE_RANGE_UNSHARE isn't available, because that would require running on kernel >= 5.9. On the other hand there's not really any other way to flush all possible fds leaked by the parent (close() in a loop takes over a minute). So in this case print a warning and carry on. As bonus this fixes a cppcheck error I see with some different options I'm looking to apply in future. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
d64f257243
commit
14dd70e2b3
2 changed files with 18 additions and 10 deletions
12
linux_dep.h
12
linux_dep.h
|
@ -127,22 +127,18 @@ struct tcp_info_linux {
|
|||
|
||||
#include <linux/close_range.h>
|
||||
|
||||
#ifdef CLOSE_RANGE_UNSHARE /* Linux kernel >= 5.9 */
|
||||
/* glibc < 2.34 and musl as of 1.2.5 need these */
|
||||
#ifndef SYS_close_range
|
||||
#define SYS_close_range 436
|
||||
#endif
|
||||
#ifndef CLOSE_RANGE_UNSHARE /* Linux kernel < 5.9 */
|
||||
#define CLOSE_RANGE_UNSHARE (1U << 1)
|
||||
#endif
|
||||
|
||||
__attribute__ ((weak))
|
||||
/* cppcheck-suppress funcArgNamesDifferent */
|
||||
int close_range(unsigned int first, unsigned int last, int flags) {
|
||||
return syscall(SYS_close_range, first, last, flags);
|
||||
}
|
||||
#else
|
||||
/* No reasonable fallback option */
|
||||
/* cppcheck-suppress funcArgNamesDifferent */
|
||||
int close_range(unsigned int first, unsigned int last, int flags) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LINUX_DEP_H */
|
||||
|
|
16
util.c
16
util.c
|
@ -738,8 +738,20 @@ void close_open_files(int argc, char **argv)
|
|||
rc = close_range(fd + 1, ~0U, CLOSE_RANGE_UNSHARE);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
die_perror("Failed to close files leaked by parent");
|
||||
if (rc) {
|
||||
if (errno == ENOSYS || errno == EINVAL) {
|
||||
/* This probably means close_range() or the
|
||||
* CLOSE_RANGE_UNSHARE flag is not supported by the
|
||||
* kernel. Not much we can do here except carry on and
|
||||
* hope for the best.
|
||||
*/
|
||||
warn(
|
||||
"Can't use close_range() to ensure no files leaked by parent");
|
||||
} else {
|
||||
die_perror("Failed to close files leaked by parent");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue