diff --git a/include/client/hooks.hpp b/include/client/hooks.hpp index c99f608581fb47caa3abe2c034cb40681cfb9e31..9e16287df5ccb94440a6fdfe038403a566b71e07 100644 --- a/include/client/hooks.hpp +++ b/include/client/hooks.hpp @@ -30,8 +30,13 @@ #ifndef GEKKOFS_HOOKS_HPP #define GEKKOFS_HOOKS_HPP +extern "C" { #include #include +#include +#include +} + struct statfs; struct linux_dirent; @@ -101,6 +106,11 @@ hook_access(const char* path, int mask); int hook_faccessat(int dirfd, const char* cpath, int mode); +#ifdef SYS_faccessat2 +int +hook_faccessat2(int dirfd, const char* cpath, int mode, int flags); +#endif + off_t hook_lseek(unsigned int fd, off_t offset, unsigned int whence); @@ -163,6 +173,9 @@ hook_fstatfs(unsigned int fd, struct statfs* buf); int hook_fsync(unsigned int fd); +int +hook_getxattr(const char* path, const char* name, void* value, size_t size); + } // namespace gkfs::hook #endif diff --git a/src/client/hooks.cpp b/src/client/hooks.cpp index d58302373fa97b81ac1dc5c93edff22950ffddbe..037d6c8eec7b826b975df3f451d4116843a78f2a 100644 --- a/src/client/hooks.cpp +++ b/src/client/hooks.cpp @@ -182,7 +182,6 @@ hook_lstat(const char* path, struct stat* buf) { return with_errno(gkfs::syscall::gkfs_stat(rel_path, buf)); } return syscall_no_intercept_wrapper(SYS_lstat, rel_path.c_str(), buf); - ; } int @@ -455,6 +454,40 @@ hook_faccessat(int dirfd, const char* cpath, int mode) { } } +#ifdef SYS_faccessat2 +int +hook_faccessat2(int dirfd, const char* cpath, int mode, int flags) { + + LOG(DEBUG, + "{}() called with dirfd: '{}', path: '{}', mode: '{}', flags: '{}'", + __func__, dirfd, cpath, mode, flags); + + std::string resolved; + auto rstatus = CTX->relativize_fd_path(dirfd, cpath, resolved); + switch(rstatus) { + case gkfs::preload::RelativizeStatus::fd_unknown: + return syscall_no_intercept_wrapper(SYS_faccessat2, dirfd, cpath, + mode, flags); + + case gkfs::preload::RelativizeStatus::external: + return syscall_no_intercept_wrapper(SYS_faccessat2, dirfd, + resolved.c_str(), mode, flags); + + case gkfs::preload::RelativizeStatus::fd_not_a_dir: + return -ENOTDIR; + + case gkfs::preload::RelativizeStatus::internal: + // we do not use permissions and therefore do not handle `flags` for + // now + return with_errno(gkfs::syscall::gkfs_access(resolved, mode)); + + default: + LOG(ERROR, "{}() relativize status unknown: {}", __func__); + return -EINVAL; + } +} +#endif + off_t hook_lseek(unsigned int fd, off_t offset, unsigned int whence) { @@ -921,4 +954,17 @@ hook_fsync(unsigned int fd) { return syscall_no_intercept_wrapper(SYS_fsync, fd); } +int +hook_getxattr(const char* path, const char* name, void* value, size_t size) { + + LOG(DEBUG, "{}() called with path '{}' name '{}' value '{}' size '{}'", + __func__, path, name, fmt::ptr(value), size); + + std::string rel_path; + if(CTX->relativize_path(path, rel_path)) { + return -ENOTSUP; + } + return syscall_no_intercept_wrapper(SYS_getxattr, path, name, value, size); +} + } // namespace gkfs::hook diff --git a/src/client/intercept.cpp b/src/client/intercept.cpp index a403ddd05b0232b79a6519f244dc9f51823424b7..57c587343ae186dee2c9fff1adccace5e167cb4a 100644 --- a/src/client/intercept.cpp +++ b/src/client/intercept.cpp @@ -622,7 +622,13 @@ hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, static_cast(arg0), reinterpret_cast(arg1), static_cast(arg2)); break; - +#ifdef SYS_faccessat2 + case SYS_faccessat2: + *result = gkfs::hook::hook_faccessat2( + static_cast(arg0), reinterpret_cast(arg1), + static_cast(arg2), static_cast(arg3)); + break; +#endif case SYS_lseek: *result = gkfs::hook::hook_lseek(static_cast(arg0), static_cast(arg1), @@ -768,6 +774,13 @@ hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, *result = gkfs::hook::hook_fsync(static_cast(arg0)); break; + case SYS_getxattr: + *result = gkfs::hook::hook_getxattr( + reinterpret_cast(arg0), + reinterpret_cast(arg1), + reinterpret_cast(arg2), static_cast(arg4)); + break; + default: // ignore any other syscalls, i.e.: pass them on to the kernel // (syscalls forwarded to the kernel that return are logged in diff --git a/src/client/syscalls/detail/syscall_info.c b/src/client/syscalls/detail/syscall_info.c index 29ff2c3d6c75676819b2a2f9abce017303598218..a74666da815bd994198cdb298a7106ac62ea5c1c 100644 --- a/src/client/syscalls/detail/syscall_info.c +++ b/src/client/syscalls/detail/syscall_info.c @@ -382,6 +382,9 @@ const struct syscall_info syscall_table[] = { SYSCALL(readlinkat, 4, S_RET(rdec), S_NARG(atfd, "dfd"), S_NARG(cstr, "pathname"), S_NARG(ptr, "buf"), S_NARG(arg, "bufsiz")), SYSCALL(fchmodat, 3, S_RET(rdec), S_NARG(atfd, "dfd"), S_NARG(cstr, "filename"), S_NARG(octal_mode, "mode")), SYSCALL(faccessat, 3, S_RET(rdec), S_NARG(atfd, "dfd"), S_NARG(cstr, "pathname"), S_NARG(octal_mode, "mode")), +#ifdef SYS_faccessat2 + SYSCALL(faccessat2, 4, S_RET(rdec), S_NARG(atfd, "dfd"), S_NARG(cstr, "pathname"), S_NARG(octal_mode, "mode"), S_NARG(arg, "flags")), +#endif SYSCALL(pselect6, 6, S_RET(rdec), S_NARG(dec, "nfds"), S_NARG(ptr, "readfds"), S_NARG(ptr, "writefds"), S_NARG(ptr, "exceptfds"), S_NARG(ptr, "timeval"), S_NARG(ptr, "sigmask")), SYSCALL(ppoll, 5, S_RET(rdec), S_NARG(ptr, "fds"), S_NARG(dec, "nfds"), S_NARG(ptr, "tmo_p"), S_NARG(ptr, "sigmask"), S_NARG(dec, "sigsetsize")), SYSCALL(unshare, 1, S_RET(rdec), S_NARG(arg, "unshare_flags")), @@ -658,6 +661,9 @@ const struct named_syscall_entry syscalls_by_name[] = { SYSCALL_BY_NAME(exit), SYSCALL_BY_NAME(exit_group), SYSCALL_BY_NAME(faccessat), +#ifdef SYS_faccessat2 + SYSCALL_BY_NAME(faccessat2), +#endif SYSCALL_BY_NAME(fadvise64), SYSCALL_BY_NAME(fallocate), SYSCALL_BY_NAME(fanotify_init),