Commit 19a732c5 authored by Marc Vef's avatar Marc Vef
Browse files

Merge branch 'marc/209-faccessat2-support-missing' into 'master'

Resolve "faccessat2() and getxattr() syscall support missing"

Closes #209

See merge request !130
parents e6160b68 68be5b2d
Loading
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -30,8 +30,13 @@
#ifndef GEKKOFS_HOOKS_HPP
#define GEKKOFS_HOOKS_HPP

extern "C" {
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
}


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
+47 −1
Original line number Diff line number Diff line
@@ -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
+14 −1
Original line number Diff line number Diff line
@@ -622,7 +622,13 @@ hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4,
                    static_cast<int>(arg0), reinterpret_cast<const char*>(arg1),
                    static_cast<int>(arg2));
            break;

#ifdef SYS_faccessat2
        case SYS_faccessat2:
            *result = gkfs::hook::hook_faccessat2(
                    static_cast<int>(arg0), reinterpret_cast<const char*>(arg1),
                    static_cast<int>(arg2), static_cast<int>(arg3));
            break;
#endif
        case SYS_lseek:
            *result = gkfs::hook::hook_lseek(static_cast<unsigned int>(arg0),
                                             static_cast<off_t>(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<unsigned int>(arg0));
            break;

        case SYS_getxattr:
            *result = gkfs::hook::hook_getxattr(
                    reinterpret_cast<const char*>(arg0),
                    reinterpret_cast<const char*>(arg1),
                    reinterpret_cast<void*>(arg2), static_cast<size_t>(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
+6 −0
Original line number Diff line number Diff line
@@ -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),