diff options
author | 2023-06-19 11:50:46 -0400 | |
---|---|---|
committer | 2023-06-21 10:41:51 -0400 | |
commit | 609dd64e6e88b8abbbd424c24e5e40abe95cdb1c (patch) | |
tree | 81919d0aeab42a440cf993f0b763cd7992943fa1 | |
parent | v2.31 (diff) | |
download | sandbox-609dd64e6e88b8abbbd424c24e5e40abe95cdb1c.tar.gz sandbox-609dd64e6e88b8abbbd424c24e5e40abe95cdb1c.tar.bz2 sandbox-609dd64e6e88b8abbbd424c24e5e40abe95cdb1c.zip |
libsbutil: add sb_exists function
This provides a central place to work around a bug on musl where
faccessat sets errno to EINVAL when the kernel does not support
faccessat2.
Bug: https://bugs.gentoo.org/908765
Signed-off-by: Mike Gilbert <floppym@gentoo.org>
(cherry picked from commit b55840ebe3278032777a3b52cecc6dac325dcf85)
-rw-r--r-- | libsandbox/pre_check_openat.c | 2 | ||||
-rw-r--r-- | libsandbox/wrapper-funcs/fopen_pre_check.c | 2 | ||||
-rw-r--r-- | libsbutil/local.mk | 1 | ||||
-rw-r--r-- | libsbutil/sb_exists.c | 24 | ||||
-rw-r--r-- | libsbutil/sbutil.h | 1 | ||||
-rw-r--r-- | libsbutil/src/file.c | 2 |
6 files changed, 29 insertions, 3 deletions
diff --git a/libsandbox/pre_check_openat.c b/libsandbox/pre_check_openat.c index 8fd3b23..99c03eb 100644 --- a/libsandbox/pre_check_openat.c +++ b/libsandbox/pre_check_openat.c @@ -19,7 +19,7 @@ bool sb_openat_pre_check(const char *func, const char *pathname, int dirfd, int save_errno(); /* Doesn't exist -> skip permission checks */ - if (faccessat(dirfd, pathname, F_OK, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0) == -1) { + if (sb_exists(dirfd, pathname, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0) == -1) { sb_debug_dyn("EARLY FAIL: %s(%s): %s\n", func, pathname, strerror(errno)); return false; } diff --git a/libsandbox/wrapper-funcs/fopen_pre_check.c b/libsandbox/wrapper-funcs/fopen_pre_check.c index 95108e0..e3ed2c6 100644 --- a/libsandbox/wrapper-funcs/fopen_pre_check.c +++ b/libsandbox/wrapper-funcs/fopen_pre_check.c @@ -11,7 +11,7 @@ bool sb_fopen_pre_check(const char *func, const char *pathname, const char *mode save_errno(); /* If we're trying to read, fail normally if file does not stat */ - if (faccessat(AT_FDCWD, pathname, F_OK, 0) == -1) { + if (sb_exists(AT_FDCWD, pathname, 0) == -1) { sb_debug_dyn("EARLY FAIL: %s(%s): %s\n", func, pathname, strerror(errno)); return false; diff --git a/libsbutil/local.mk b/libsbutil/local.mk index 126c7ce..1cb5de7 100644 --- a/libsbutil/local.mk +++ b/libsbutil/local.mk @@ -16,6 +16,7 @@ noinst_LTLIBRARIES += %D%/libsbutil.la %D%/environment.c \ %D%/sb_backtrace.c \ %D%/sb_efuncs.c \ + %D%/sb_exists.c \ %D%/sb_gdb.c \ %D%/sb_method.c \ %D%/sb_open.c \ diff --git a/libsbutil/sb_exists.c b/libsbutil/sb_exists.c new file mode 100644 index 0000000..9ec7730 --- /dev/null +++ b/libsbutil/sb_exists.c @@ -0,0 +1,24 @@ +/* + * Copyright 2023 Gentoo Authors + * Distributed under the terms of the GNU General Public License v2 + */ + +#include "headers.h" +#include "sbutil.h" + +/* Wrapper for faccessat to work around buggy behavior on musl */ +int sb_exists(int dirfd, const char *pathname, int flags) +{ + struct stat64 buf; + + if (faccessat(dirfd, pathname, F_OK, flags) == 0) + return 0; + + /* musl's faccessat gives EINVAL when the kernel does not support + * faccessat2 and AT_SYMLINK_NOFOLLOW is set. + * https://www.openwall.com/lists/musl/2023/06/19/1 */ + if (errno != EINVAL) + return -1; + + return fstatat64(dirfd, pathname, &buf, flags); +} diff --git a/libsbutil/sbutil.h b/libsbutil/sbutil.h index d81543b..981fe0d 100644 --- a/libsbutil/sbutil.h +++ b/libsbutil/sbutil.h @@ -109,6 +109,7 @@ size_t sb_write(int fd, const void *buf, size_t count); int sb_close(int fd); void sb_close_all_fds(void); int sb_copy_file_to_fd(const char *file, int ofd); +int sb_exists(int dirfd, const char *pathname, int flags); /* Reliable output */ __printf(1, 2) void sb_printf(const char *format, ...); diff --git a/libsbutil/src/file.c b/libsbutil/src/file.c index 5a361f4..64a6f0e 100644 --- a/libsbutil/src/file.c +++ b/libsbutil/src/file.c @@ -15,7 +15,7 @@ bool rc_file_exists (const char *pathname) { - return faccessat(AT_FDCWD, pathname, F_OK, AT_SYMLINK_NOFOLLOW) == 0; + return sb_exists(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW) == 0; } bool |