From 632cc66ba52eb6aa7fd3e457c64d9186389a20b4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 5 Nov 2021 23:14:42 -0400 Subject: change FS calls to use 64-bit interfaces explicitly Make sure we use 64-bit FS interfaces when accessing the FS. This is needed not only to stat or open large files, but even files with 64-bit inodes. Bug: https://bugs.gentoo.org/583282 Signed-off-by: Mike Frysinger --- configure.ac | 7 +++++++ libsandbox/canonicalize.c | 8 ++++---- libsandbox/libsandbox.c | 14 +++++++------- libsandbox/pre_check_mkdirat.c | 6 +++--- libsandbox/trace.c | 2 +- libsandbox/wrapper-funcs/__wrapper_exec.c | 4 ++-- libsbutil/include/rcscripts/util/file.h | 2 +- libsbutil/sb_close.c | 4 ++-- libsbutil/src/file.c | 24 ++++++++++++------------ src/namespaces.c | 4 ++-- tests/get-group.c | 4 ++-- tests/get-user.c | 4 ++-- tests/test-skel-0.c | 2 +- tests/trace-memory_static_tst.c | 4 ++-- 14 files changed, 48 insertions(+), 41 deletions(-) diff --git a/configure.ac b/configure.ac index 56ca87f..698051f 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,13 @@ AS_IF([test "$ac_cv_prog_cc_c99" = "no"], [AC_MSG_ERROR([A C99+ compiler is requ AM_PROG_CC_C_O AC_ISC_POSIX AC_USE_SYSTEM_EXTENSIONS +dnl http://www.gnu.org/s/libc/manual/html_node/Feature-Test-Macros.html +dnl _LARGEFILE_SOURCE: enable support for new LFS funcs (ftello/etc...) +dnl _LARGEFILE64_SOURCE: enable support for 64-bit variants (off64_t/fseeko64/etc...) +dnl NB: We do not want -D_FILE_OFFSET_BITS=64 because we need to interpose both 32-bit +dnl and 64-bit FS interfaces, and having the C library rewrite them makes that difficult. +dnl Along those lines, we do not use AC_SYS_LARGEFILE. +AS_VAR_APPEND([CPPFLAGS], [" -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE"]) dnl Checks for programs. AM_PROG_AR diff --git a/libsandbox/canonicalize.c b/libsandbox/canonicalize.c index 6519340..f742ed4 100644 --- a/libsandbox/canonicalize.c +++ b/libsandbox/canonicalize.c @@ -92,7 +92,7 @@ erealpath(const char *name, char *resolved) goto error; } - /* This stat() business uses relative paths atm */ + /* This stat business uses relative paths atm. */ if (trace_pid) goto no_recover; @@ -100,14 +100,14 @@ erealpath(const char *name, char *resolved) * If not, try a little harder to consume this path in * case it has symlinks out into a better world ... */ - struct stat st; - if (lstat(rpath, &st) == -1 && errno == EACCES) { + struct stat64 st; + if (lstat64(rpath, &st) == -1 && errno == EACCES) { char *p = rpath; strcpy(rpath, name); do { p = strchr(p, '/'); if (p) *p = '\0'; - if (lstat(rpath, &st)) + if (lstat64(rpath, &st)) break; if (S_ISLNK(st.st_mode)) { ssize_t cnt = readlink(rpath, rpath, path_max); diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c index b4db9ba..0ca2bc9 100644 --- a/libsandbox/libsandbox.c +++ b/libsandbox/libsandbox.c @@ -333,7 +333,7 @@ static char *resolve_path(const char *path, int follow_link) char *egetcwd(char *buf, size_t size) { - struct stat st; + struct stat64 st; char *tmpbuf; /* We can't let the C lib allocate memory for us since we have our @@ -376,12 +376,12 @@ char *egetcwd(char *buf, size_t size) */ if ((tmpbuf) && (errno == 0)) { save_errno(); - if (!lstat(buf, &st)) + if (!lstat64(buf, &st)) /* errno is set only on failure */ errno = 0; if (errno == ENOENT) - /* If lstat() failed with eerror = ENOENT, then its + /* If lstat failed with eerror = ENOENT, then its * possible that we are running on an older kernel * which had issues with returning invalid paths if * they got too long. Return with errno = ENAMETOOLONG, @@ -396,8 +396,8 @@ char *egetcwd(char *buf, size_t size) free(buf); /* Not sure if we should quit here, but I guess if - * lstat() fails, getcwd could have messed up. Not - * sure what to do about errno - use lstat()'s for + * lstat fails, getcwd could have messed up. Not + * sure what to do about errno - use lstat's for * now. */ return NULL; @@ -435,12 +435,12 @@ void __sb_dump_backtrace(void) static bool write_logfile(const char *logfile, const char *func, const char *path, const char *apath, const char *rpath, bool access) { - struct stat log_stat; + struct stat64 log_stat; int stat_ret; int logfd; bool ret = false; - stat_ret = lstat(logfile, &log_stat); + stat_ret = lstat64(logfile, &log_stat); /* Do not care about failure */ errno = 0; if (stat_ret == 0 && S_ISREG(log_stat.st_mode) == 0) diff --git a/libsandbox/pre_check_mkdirat.c b/libsandbox/pre_check_mkdirat.c index 8fb38bb..b1e86cf 100644 --- a/libsandbox/pre_check_mkdirat.c +++ b/libsandbox/pre_check_mkdirat.c @@ -36,8 +36,8 @@ bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) * not want to pass this attempt up to the higher levels as those * will trigger a sandbox violation. */ - struct stat st; - if (0 == lstat(canonic, &st)) { + struct stat64 st; + if (0 == lstat64(canonic, &st)) { int new_errno; sb_debug_dyn("EARLY FAIL: %s(%s[%s]) @ lstat: %s\n", func, pathname, canonic, strerror(errno)); @@ -45,7 +45,7 @@ bool sb_mkdirat_pre_check(const char *func, const char *pathname, int dirfd) new_errno = EEXIST; /* Hmm, is this a broken symlink we're trying to extend ? */ - if (S_ISLNK(st.st_mode) && stat(pathname, &st) != 0) { + if (S_ISLNK(st.st_mode) && stat64(pathname, &st) != 0) { /* XXX: This awful hack should probably be turned into a * common func that does a better job. For now, we have * enough crap to catch gnulib tests #297026. diff --git a/libsandbox/trace.c b/libsandbox/trace.c index 036d57f..d70f3bc 100644 --- a/libsandbox/trace.c +++ b/libsandbox/trace.c @@ -51,7 +51,7 @@ static int trace_yama_level(void) char ch; int fd, level; - fd = open("/proc/sys/kernel/yama/ptrace_scope", O_RDONLY | O_CLOEXEC); + fd = open64("/proc/sys/kernel/yama/ptrace_scope", O_RDONLY | O_CLOEXEC); if (fd == -1) return 0; diff --git a/libsandbox/wrapper-funcs/__wrapper_exec.c b/libsandbox/wrapper-funcs/__wrapper_exec.c index d66e3a0..f603257 100644 --- a/libsandbox/wrapper-funcs/__wrapper_exec.c +++ b/libsandbox/wrapper-funcs/__wrapper_exec.c @@ -27,7 +27,7 @@ static bool sb_check_exec(const char *filename, char *const argv[]) { int fd; unsigned char *elf; - struct stat st; + struct stat64 st; bool do_trace = false; bool run_in_process = true; sandbox_method_t method = get_sandbox_method(); @@ -38,7 +38,7 @@ static bool sb_check_exec(const char *filename, char *const argv[]) fd = sb_unwrapped_open_DEFAULT(filename, O_RDONLY|O_CLOEXEC, 0); if (fd == -1) return true; - if (fstat(fd, &st)) + if (fstat64(fd, &st)) goto out_fd; if (st.st_size < sizeof(Elf64_Ehdr)) goto out_fd; diff --git a/libsbutil/include/rcscripts/util/file.h b/libsbutil/include/rcscripts/util/file.h index 197f211..8bbde00 100644 --- a/libsbutil/include/rcscripts/util/file.h +++ b/libsbutil/include/rcscripts/util/file.h @@ -23,7 +23,7 @@ bool rc_is_dir (const char *pathname, bool follow_link); /* The following functions do not care about errors - it only returns * the size/mtime of 'pathname' if it exists, and is the type requested, * or else 0. */ -off_t rc_get_size (const char *pathname, bool follow_link); +off64_t rc_get_size (const char *pathname, bool follow_link); /* The following return a pointer on success, or NULL with errno set on error. * If it returned NULL, but errno is not set, then there was no error, but diff --git a/libsbutil/sb_close.c b/libsbutil/sb_close.c index 5379197..113deab 100644 --- a/libsbutil/sb_close.c +++ b/libsbutil/sb_close.c @@ -34,7 +34,7 @@ int sb_close(int fd) void sb_close_all_fds(void) { DIR *dirp; - struct dirent *de; + struct dirent64 *de; int dfd, fd; const char *fd_dir = sb_get_fd_dir(); @@ -43,7 +43,7 @@ void sb_close_all_fds(void) sb_ebort("could not process %s\n", fd_dir); dfd = dirfd(dirp); - while ((de = readdir(dirp)) != NULL) { + while ((de = readdir64(dirp)) != NULL) { if (de->d_name[0] == '.') continue; fd = atoi(de->d_name); diff --git a/libsbutil/src/file.c b/libsbutil/src/file.c index a1a4a0e..5a361f4 100644 --- a/libsbutil/src/file.c +++ b/libsbutil/src/file.c @@ -21,13 +21,13 @@ rc_file_exists (const char *pathname) bool rc_is_file (const char *pathname, bool follow_link) { - struct stat buf; + struct stat64 buf; int retval; if (!check_str (pathname)) return false; - retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); + retval = follow_link ? stat64 (pathname, &buf) : lstat64 (pathname, &buf); if ((-1 != retval) && (S_ISREG (buf.st_mode))) retval = true; else @@ -39,13 +39,13 @@ rc_is_file (const char *pathname, bool follow_link) bool rc_is_dir (const char *pathname, bool follow_link) { - struct stat buf; + struct stat64 buf; int retval; if (!check_str (pathname)) return false; - retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); + retval = follow_link ? stat64 (pathname, &buf) : lstat64 (pathname, &buf); if ((-1 != retval) && (S_ISDIR (buf.st_mode))) retval = true; else @@ -54,16 +54,16 @@ rc_is_dir (const char *pathname, bool follow_link) return retval; } -off_t +off64_t rc_get_size (const char *pathname, bool follow_link) { - struct stat buf; + struct stat64 buf; int retval; if (!check_str (pathname)) return 0; - retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); + retval = follow_link ? stat64 (pathname, &buf) : lstat64 (pathname, &buf); if (-1 != retval) retval = buf.st_size; else @@ -76,7 +76,7 @@ char ** rc_ls_dir (const char *pathname, bool hidden, bool sort) { DIR *dp; - struct dirent *dir_entry; + struct dirent64 *dir_entry; char **dirlist = NULL; if (!check_arg_str (pathname)) @@ -102,7 +102,7 @@ rc_ls_dir (const char *pathname, bool hidden, bool sort) { /* Clear errno to distinguish between EOF and error */ errno = 0; - dir_entry = readdir (dp); + dir_entry = readdir64 (dp); /* Only an error if 'errno' != 0, else EOF */ if ((NULL == dir_entry) && (0 != errno)) { @@ -184,10 +184,10 @@ error: int rc_file_map (const char *filename, char **buf, size_t * bufsize) { - struct stat stats; + struct stat64 stats; int fd; - fd = open (filename, O_RDONLY); + fd = open64 (filename, O_RDONLY); if (fd < 0) { rc_errno_set (errno); @@ -195,7 +195,7 @@ rc_file_map (const char *filename, char **buf, size_t * bufsize) return -1; } - if (fstat (fd, &stats) < 0) + if (fstat64 (fd, &stats) < 0) { rc_errno_set (errno); DBG_MSG ("Failed to stat file!\n"); diff --git a/src/namespaces.c b/src/namespaces.c index ee9f82a..290111a 100644 --- a/src/namespaces.c +++ b/src/namespaces.c @@ -28,7 +28,7 @@ #define xfopen(path, ...) \ ({ \ - FILE *_ret = fopen(path, __VA_ARGS__); \ + FILE *_ret = fopen64(path, __VA_ARGS__); \ if (_ret == 0) \ sb_perr("fopen(%s) failed", #path); \ _ret; \ @@ -107,7 +107,7 @@ static void ns_mount_setup(void) /* Now map in all the files/dirs we do want to expose. */ int fd; #define bind_file(node) \ - fd = open("/dev/shm/" node, O_CREAT, 0); \ + fd = open64("/dev/shm/" node, O_CREAT, 0); \ sb_assert(fd != -1); \ close(fd); \ xmount("/dev/" node, "/dev/shm/" node, NULL, MS_BIND, NULL) diff --git a/tests/get-group.c b/tests/get-group.c index 8138967..30cdfc9 100644 --- a/tests/get-group.c +++ b/tests/get-group.c @@ -31,8 +31,8 @@ int main(int argc, char *argv[]) printf("%i\n", grp->gr_gid); } else { const char *file = argv[1]; - struct stat st; - if (lstat(file, &st)) + struct stat64 st; + if (lstat64(file, &st)) errp("lstat(%s) failed", file); printf("%i\n", st.st_gid); } diff --git a/tests/get-user.c b/tests/get-user.c index f85e299..be448d7 100644 --- a/tests/get-user.c +++ b/tests/get-user.c @@ -31,8 +31,8 @@ int main(int argc, char *argv[]) printf("%i\n", pwd->pw_uid); } else { const char *file = argv[1]; - struct stat st; - if (lstat(file, &st)) + struct stat64 st; + if (lstat64(file, &st)) errp("lstat(%s) failed", file); printf("%i\n", st.st_uid); } diff --git a/tests/test-skel-0.c b/tests/test-skel-0.c index de88cf4..91128d3 100644 --- a/tests/test-skel-0.c +++ b/tests/test-skel-0.c @@ -128,7 +128,7 @@ int at_get_fd(const char *str_dirfd) } str_mode = strtok(NULL, ":"); - return open(str_path, f_get_flags(str_flags), sscanf_mode_t(str_mode)); + return open64(str_path, f_get_flags(str_flags), sscanf_mode_t(str_mode)); } #define V_TIMESPEC "NULL | NOW | #[,#]" diff --git a/tests/trace-memory_static_tst.c b/tests/trace-memory_static_tst.c index 14c6477..86a47fe 100644 --- a/tests/trace-memory_static_tst.c +++ b/tests/trace-memory_static_tst.c @@ -26,7 +26,7 @@ volatile uintptr_t offset = 0; #define check_ptr(addr) \ ({ \ printf(" open(%p)\n", addr); \ - ret = open(non_const_ptr(addr), O_RDONLY); \ + ret = open64(non_const_ptr(addr), O_RDONLY); \ assert(ret == -1 && errno == EFAULT); \ }) @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) printf(" open(%p -> %p [+%#zx])\n", p, p + len, len); memset(p, 'a', len); path[end] = '\0'; - ret = open(p, O_RDONLY); + ret = open64(p, O_RDONLY); assert(ret == -1 && (errno == ENOENT || errno == ENAMETOOLONG)); } } -- cgit v1.2.3-65-gdbad