aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Gilbert <floppym@gentoo.org>2023-06-19 11:50:46 -0400
committerMike Gilbert <floppym@gentoo.org>2023-06-21 10:40:08 -0400
commitb55840ebe3278032777a3b52cecc6dac325dcf85 (patch)
treeafc5eb7142d49b7cc915b90ae3ada5d8bf439566
parentlibsandbox: add lutimes to symlink_func (diff)
downloadsandbox-b55840ebe3278032777a3b52cecc6dac325dcf85.tar.gz
sandbox-b55840ebe3278032777a3b52cecc6dac325dcf85.tar.bz2
sandbox-b55840ebe3278032777a3b52cecc6dac325dcf85.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>
-rw-r--r--libsandbox/pre_check_openat.c2
-rw-r--r--libsandbox/wrapper-funcs/fopen_pre_check.c2
-rw-r--r--libsbutil/local.mk1
-rw-r--r--libsbutil/sb_exists.c24
-rw-r--r--libsbutil/sbutil.h1
-rw-r--r--libsbutil/src/file.c2
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 c146b80..4061dd3 100644
--- a/libsbutil/sbutil.h
+++ b/libsbutil/sbutil.h
@@ -111,6 +111,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