diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2024-11-08 13:53:29 +1100 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2024-11-08 08:26:17 +0100 |
commit | 14dd70e2b33941f1f7663969574278873c9e3d35 (patch) | |
tree | f87bf175430f3a90b29884681d1888462f7a315b | |
parent | d64f25724399fbb4ba9d36eda7e17984a4c6c91c (diff) | |
download | passt-14dd70e2b33941f1f7663969574278873c9e3d35.tar passt-14dd70e2b33941f1f7663969574278873c9e3d35.tar.gz passt-14dd70e2b33941f1f7663969574278873c9e3d35.tar.bz2 passt-14dd70e2b33941f1f7663969574278873c9e3d35.tar.lz passt-14dd70e2b33941f1f7663969574278873c9e3d35.tar.xz passt-14dd70e2b33941f1f7663969574278873c9e3d35.tar.zst passt-14dd70e2b33941f1f7663969574278873c9e3d35.zip |
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>
-rw-r--r-- | linux_dep.h | 12 | ||||
-rw-r--r-- | util.c | 16 |
2 files changed, 18 insertions, 10 deletions
diff --git a/linux_dep.h b/linux_dep.h index 3a41e42..240f50a 100644 --- a/linux_dep.h +++ b/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 */ @@ -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"); + } + } + } /** |