Resolve "syscall 436 not logged / processed"

Closes #308 (closed) #307 (closed)

This MR adds support for close_range. However, as the upper limit could be "infinite"... we should stop once ge get to GKFS_****_FD. Close_range actually returns always 0, although there is some fd that does not exist.

We add support for all the new syscalls from last kernels (Although not implemented), on the other hand we include the number of syscalls to complete the logging information as in the case of unknown syscall we don't have this information.

We remove also the O_PATH check in gkfs_open, as this is used on last kernels (in cp *). It seems that it does not break anything and allows copy with *

Edited by Ramon Nou

Merge request reports

Loading
+2 −1
Changes for include/client/syscalls/decoder.hpp: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -60,7 +60,8 @@ decode(FmtBuffer& buffer, const long syscall_number,

    const auto sc = lookup_by_number(syscall_number, argv);

    fmt::format_to(std::back_inserter(buffer), "{}(", sc.name());
    fmt::format_to(std::back_inserter(buffer), "{} {}(", sc.name(),
                   syscall_number);

    for(int i = 0; i < sc.num_args(); ++i) {
        const auto arg = sc.args().at(i);
+107 −4
Changes for src/client/syscalls/detail/syscall_info.c: 107 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -478,9 +478,6 @@ SYSCALL(getpmsg, 5, S_RET(rdec), S_NARG(arg, "arg0"),
    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")),
@@ -596,8 +593,108 @@ SYSCALL(getpmsg, 5, S_RET(rdec), S_NARG(arg, "arg0"),
#endif // SYS_io_pgetevents

#ifdef SYS_rseq
    SYSCALL(rseq,                    4,  S_RET(rdec),    S_NARG(ptr, "rseq"),           S_NARG(dec, "rseq_len"),         S_NARG(arg, "flags"),             S_NARG(signum, "sig"))
    SYSCALL(rseq,                    4,  S_RET(rdec),    S_NARG(ptr, "rseq"),           S_NARG(dec, "rseq_len"),         S_NARG(arg, "flags"),             S_NARG(signum, "sig")),
#endif // SYS_rseq
// ifdef the next syscalls
#ifdef SYS_pidfd_send_signal
    SYSCALL(pidfd_send_signal,        3,  S_RET(rdec),    S_NARG(dec, "pidfd"),         S_NARG(signum, "sig"),           S_NARG(arg, "flags")),
#endif
#ifdef SYS_io_uring_setup
    SYSCALL(io_uring_setup,          2,  S_RET(rdec),    S_NARG(arg, "entries"),       S_NARG(ptr, "ring_addr")),
#endif
#ifdef SYS_io_uring_enter
    SYSCALL(io_uring_enter,          4,  S_RET(rdec),    S_NARG(arg, "ring_fd"),        S_NARG(dec, "to_submit"),       S_NARG(dec, "min_complete"),     S_NARG(arg, "flags")),
#endif
#ifdef SYS_io_uring_register
    SYSCALL(io_uring_register,       4,  S_RET(rdec),    S_NARG(arg, "ring_fd"),        S_NARG(arg, "opcode"),          S_NARG(ptr, "arg"),               S_NARG(arg, "nr_args")),
#endif
#ifdef SYS_open_tree
    SYSCALL(open_tree,               2,  S_RET(rdec),    S_NARG(cstr, "pathname"),      S_NARG(open_flags, "flags")),
#endif
#ifdef SYS_move_mount
    SYSCALL(move_mount,              3,  S_RET(rdec),    S_NARG(cstr, "src"),            S_NARG(cstr, "dst"),              S_NARG(arg, "flags")),
#endif
#ifdef SYS_fsopen
    SYSCALL(fsopen,                  3,  S_RET(rdec),    S_NARG(cstr, "fs_type"),       S_NARG(cstr, "pathname"),        S_NARG(open_flags, "flags")),
#endif
#ifdef SYS_fsconfig
    SYSCALL(fsconfig,                3,  S_RET(rdec),    S_NARG(arg, "cmd"),            S_NARG(ptr, "argp"),             S_NARG(ptr, "resp")),
#endif
#ifdef SYS_fsmount
    SYSCALL(fsmount,                 5,  S_RET(rdec),    S_NARG(cstr, "fs_type"),       S_NARG(cstr, "pathname"),        S_NARG(cstr, "type"),             S_NARG(arg, "flags"),        S_NARG(ptr, "data")),
#endif
#ifdef SYS_fspick
    SYSCALL(fspick,                  4,  S_RET(rdec),    S_NARG(arg, "arg0"),           S_NARG(arg, "arg1"),             S_NARG(arg, "arg2"),              S_NARG(arg, "arg3")),
#endif
#ifdef SYS_pidfd_open
    SYSCALL(pidfd_open,              2,  S_RET(rdec),    S_NARG(dec, "pid"),            S_NARG(arg, "flags")),
#endif
#ifdef SYS_clone3
    SYSCALL(clone3,                   4,  S_RET(rdec),    S_NARG(arg, "flags"),          S_NARG(ptr, "child_tid"),        S_NARG(ptr, "parent_tid"),       S_NARG(ptr, "tls")),
#endif
#ifdef SYS_close_range
    SYSCALL(close_range,             3,  S_RET(rdec),    S_NARG(dec, "low"),            S_NARG(dec, "high"),            S_NARG(arg, "flags")),
#endif
#ifdef SYS_openat2
    SYSCALL(openat2,                 4,  S_RET(rdec),    S_NARG(atfd, "dfd"),           S_NARG(cstr, "pathname"),        S_NARG(open_flags, "flags"),     S_NARG(ptr, "how")),
#endif
#ifdef SYS_pidfd_getfd
    SYSCALL(pidfd_getfd,             3,  S_RET(rdec),    S_NARG(dec, "pidfd"),         S_NARG(arg, "fd"),               S_NARG(arg, "flags")),
#endif
#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
#ifdef SYS_process_madvise
    SYSCALL(process_madvise,         4,  S_RET(rdec),    S_NARG(dec, "pid"),            S_NARG(ptr, "addr"),             S_NARG(dec, "length"),           S_NARG(arg, "advice")),
#endif
#ifdef SYS_epoll_pwait2
    SYSCALL(epoll_pwait2,            6,  S_RET(rdec),    S_NARG(fd, "epfd"),            S_NARG(ptr, "events"),           S_NARG(dec, "maxevents"),         S_NARG(dec, "timeout"),      S_NARG(ptr, "sigmask"),      S_NARG(dec, "sigsetsize")),
#endif
#ifdef SYS_mount_setattr
    SYSCALL(mount_setattr,          3,  S_RET(rdec),    S_NARG(cstr, "path"),          S_NARG(ptr, "attr"),             S_NARG(arg, "flags")),
#endif
#ifdef SYS_quotactl_fd
    SYSCALL(quotactl_fd,            4,  S_RET(rdec),    S_NARG(arg, "cmd"),            S_NARG(fd, "fd"),               S_NARG(arg, "id"),                S_NARG(ptr, "addr")),
#endif
#ifdef SYS_landlock_create_ruleset
    SYSCALL(landlock_create_ruleset, 1,  S_RET(rdec),    S_NARG(arg, "flags")),
#endif
#ifdef SYS_landlock_add_rule
    SYSCALL(landlock_add_rule,       3,  S_RET(rdec),    S_NARG(dec, "ruleset"),       S_NARG(arg, "rule"),             S_NARG(arg, "flags")),
#endif
#ifdef SYS_landlock_restrict_self
    SYSCALL(landlock_restrict_self,  1,  S_RET(rdec),    S_NARG(dec, "ruleset")),
#endif
#ifdef SYS_memfd_secret
    SYSCALL(memfd_secret,           3,  S_RET(rdec),    S_NARG(cstr, "name"),          S_NARG(arg, "flags"),            S_NARG(ptr, "secret")),
#endif
#ifdef SYS_process_mrelease
    SYSCALL(process_mrelease,        2,  S_RET(rdec),    S_NARG(dec, "pid"),            S_NARG(ptr, "addr")),
#endif
#ifdef SYS_futex_waitv
    SYSCALL(futex_waitv,            5,  S_RET(rdec),    S_NARG(ptr, "uaddr"),          S_NARG(arg, "op"),               S_NARG(ptr, "val"),               S_NARG(ptr, "timeout"),       S_NARG(dec, "flags")),
#endif
#ifdef SYS_set_mempolicy_home_node
    SYSCALL(set_mempolicy_home_node, 1,  S_RET(rdec),    S_NARG(arg, "node")),
#endif
#ifdef SYS_cachestat
    SYSCALL(cachestat,               1,  S_RET(rdec),    S_NARG(ptr, "cs")),
#endif
#ifdef SYS_fchmodat2
    SYSCALL(fchmodat2,               4,  S_RET(rdec),    S_NARG(atfd, "dfd"),           S_NARG(cstr, "pathname"),        S_NARG(octal_mode, "mode"),       S_NARG(arg, "flags")),
#endif
#ifdef SYS_map_shadow_stack
    SYSCALL(map_shadow_stack,        1,  S_RET(rdec),    S_NARG(arg, "flags")),
#endif
#ifdef SYS_futex_wake
    SYSCALL(futex_wake,              3,  S_RET(rdec),    S_NARG(ptr, "uaddr"),          S_NARG(dec, "nr_wake"),          S_NARG(arg, "flags")),
#endif
#ifdef SYS_futex_wait
    SYSCALL(futex_wait,              4,  S_RET(rdec),    S_NARG(ptr, "uaddr"),          S_NARG(arg, "op"),               S_NARG(ptr, "val"),               S_NARG(ptr, "timeout")),
#endif
#ifdef SYS_futex_requeue
    SYSCALL(futex_requeue,           5,  S_RET(rdec),    S_NARG(ptr, "uaddr1"),         S_NARG(ptr, "uaddr2"),          S_NARG(arg, "op"),               S_NARG(ptr, "val"),               S_NARG(ptr, "timeout"))
#endif
};

static const struct syscall_info unknown_syscall = {
@@ -742,7 +839,13 @@ const struct named_syscall_entry syscalls_by_name[] = {
    SYSCALL_BY_NAME(clock_nanosleep),
    SYSCALL_BY_NAME(clock_settime),
    SYSCALL_BY_NAME(clone),
#ifdef SYS_clone3
    SYSCALL_BY_NAME(clone3),
#endif
    SYSCALL_BY_NAME(close),
#ifdef SYS_close_range
    SYSCALL_BY_NAME(close_range),
#endif
    SYSCALL_BY_NAME(connect),
#ifdef SYS_copy_file_range
    SYSCALL_BY_NAME(copy_file_range),
+3 −7
Changes for src/client/gkfs_functions.cpp: 3 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -140,12 +140,6 @@ namespace gkfs::syscall {
int
gkfs_open(const std::string& path, mode_t mode, int flags) {

    if(flags & O_PATH) {
        LOG(ERROR, "`O_PATH` flag is not supported");
        errno = ENOTSUP;
        return -1;
    }

    // metadata object filled during create or stat
    gkfs::metadata::Metadata md{};
    if(flags & O_CREAT) {
@@ -1643,7 +1637,9 @@ gkfs_close(unsigned int fd) {
    if(CTX->is_internal_fd(fd)) {
        // the client application (for some reason) is trying to close an
        // internal fd: ignore it
        return 0;
        LOG(ERROR, "{}() closing an internal fd '{}'", __func__, fd);
        errno = EACCES;
        return -1;
    }

    return -1;
+34 −6
Changes for src/client/intercept.cpp: 34 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@
#include <client/preload.hpp>
#include <client/hooks.hpp>
#include <client/logging.hpp>

#include <client/gkfs_functions.hpp>
#include <optional>
#include <fmt/format.h>

@@ -408,11 +408,25 @@ hook_internal(long syscall_number, long arg0, long arg1, long arg2, long arg3,
                CTX->unregister_internal_fd(arg0);
            }
            break;

#ifdef SYS_close_range
        case SYS_close_range:
            *result = syscall_no_intercept_wrapper(
                    syscall_number, static_cast<int>(arg0),
                    static_cast<int>(arg1), static_cast<int>(arg2));
            if(*result >= 0) {
                for(auto i = arg0; i < arg1; i++) {
                    if(arg1 == INT_MAX or i >= GKFS_MAX_INTERNAL_FDS) {
                        break;
                    }
                    CTX->unregister_internal_fd(i);
                }
            }
            break;
#endif
        default:
            // ignore any other syscalls, i.e.: pass them on to the kernel
            // (syscalls forwarded to the kernel that return are logged in
            // hook_forwarded_syscall())
            // ignore any other syscalls, i.e.: pass them on to the
            // kernel (syscalls forwarded to the kernel that return are
            // logged in hook_forwarded_syscall())
            ::save_current_syscall_info(gkfs::syscall::from_internal_code |
                                        gkfs::syscall::to_kernel |
                                        gkfs::syscall::not_executed);
@@ -430,7 +444,8 @@ hook_internal(long syscall_number, long arg0, long arg1, long arg2, long arg3,
/*
 * hook -- interception hook for application syscalls
 *
 * This hook is used to implement any application filesystem-related syscalls.
 * This hook is used to implement any application filesystem-related
 * syscalls.
 */
inline int
hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4,
@@ -486,6 +501,19 @@ hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4,
        case SYS_close:
            *result = gkfs::hook::hook_close(static_cast<int>(arg0));
            break;
#ifdef SYS_close_range
        case SYS_close_range:
            for(auto i = arg0; i <= arg1; i++) {
                if(i >= GKFS_MAX_OPEN_FDS)
                    break;
                if(CTX->file_map()->exist(i)) {
                    gkfs::syscall::gkfs_close(i);
                }
                *result = 0;
            }
            *result = 0;
            break;
#endif // SYS_close_range
#ifdef SYS_stat
        case SYS_stat:
            *result =
+2 −1
Changes for src/client/preload_context.cpp: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -541,7 +541,8 @@ PreloadContext::register_internal_fd(int fd) {
void
PreloadContext::unregister_internal_fd(int fd) {

    LOG(DEBUG, "unregistering internal fd {}", fd);
    LOG(DEBUG, "unregistering internal fd {} >= {} -> {}'", fd, MIN_INTERNAL_FD,
        fd >= MIN_INTERNAL_FD);

    assert(fd >= MIN_INTERNAL_FD);

Loading
Loading