Commit ecf8c354 authored by Ramon Nou's avatar Ramon Nou
Browse files

more libc calls, and some changes in resolve_new (we may deactivate FOLLOW external IMHO)

parent fb4d7bcd
Loading
Loading
Loading
Loading
+198 −41
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ std::atomic<bool> initializing{false};
// Define a debug macro, can be easily disabled

// #define GKFS_TRACE
#define PATH_SHORTCUT
// #define PATH_SHORTCUT

#ifdef GKFS_DEBUG_BUILD
#ifdef GKFS_TRACE
@@ -155,6 +155,23 @@ log_argumentsx(const char* symbol, Args&&... args) {
        return real_##func_name args;                                          \
    }

#define NOLOGDLSYM_WRAPPER(return_type, func_name, params, args, symbol_name)  \
    static return_type(*real_##func_name) params = nullptr;                    \
    return_type dlsym_##func_name params {                                     \
        if(!real_##func_name) {                                                \
            real_##func_name = reinterpret_cast<return_type(*) params>(        \
                    dlsym(RTLD_NEXT, symbol_name));                            \
            if(!real_##func_name) {                                            \
                fprintf(stderr, "dlsym failed for %s: %s\n", symbol_name,      \
                        dlerror());                                            \
                errno = ENOSYS; /* Set errno to ENOSYS to indicate function    \
                                   not supported */                            \
                return (return_type) - 1; /* Return error value */             \
            }                                                                  \
        }                                                                      \
        return real_##func_name args;                                          \
    }


#define CDLSYM_WRAPPER(return_type, func_name, params, args, symbol_name)      \
    static return_type(*real_##func_name) params = nullptr;                    \
@@ -225,10 +242,15 @@ DLSYM_WRAPPER(int, fxstat64, (int ver, int fd, struct stat64* buf),
              (ver, fd, buf), "__fxstat64")
DLSYM_WRAPPER(int, lstat, (int ver, const char* path, struct stat* buf),
              (ver, path, buf), "__lxstat")

DLSYM_WRAPPER(int, lstat64, (const char* path, struct stat64* buf), (path, buf),
              "lstat64")

DLSYM_WRAPPER(int, stat, (int ver, const char* path, struct stat* buf),
              (ver, path, buf), "__xstat")
DLSYM_WRAPPER(int, fstat, (int ver, int fd, struct stat* buf), (ver, fd, buf),
              "__fxstat")
DLSYM_WRAPPER(int, __fxstat, (int ver, int fd, struct stat* buf),
              (ver, fd, buf), "__fxstat")
DLSYM_WRAPPER(int, fstat, (int fd, struct stat* buf), (fd, buf), "fstat")
DLSYM_WRAPPER(int, fstat64, (int fd, struct stat64* buf), (fd, buf), "fstat64")
DLSYM_WRAPPER(int, fxstatat,
              (int ver, int dfd, const char* path, struct stat* buf, int flags),
@@ -333,15 +355,34 @@ DLSYM_WRAPPER(void, rewind, (FILE * stream), (stream), "rewind")
DLSYM_WRAPPER(int, feof, (FILE * stream), (stream), "feof")
DLSYM_WRAPPER(int, fputs, (const char* str, FILE* stream), (str, stream),
              "fputs")
DLSYM_WRAPPER(char*, fgets, (char* str, int n, FILE* stream), (str, n, stream),
              "fgets")
DLSYM_WRAPPER(int, fflush, (FILE * stream), (stream), "fflush")
NOLOGDLSYM_WRAPPER(char*, fgets, (char* str, int n, FILE* stream),
                   (str, n, stream), "fgets")
NOLOGDLSYM_WRAPPER(int, fflush, (FILE * stream), (stream), "fflush")
DLSYM_WRAPPER(int, fchown, (int fd, uid_t owner, gid_t group),
              (fd, owner, group), "fchown")
DLSYM_WRAPPER(int, futimes, (int fd, const struct timeval times[2]),
              (fd, times), "futimes")
DLSYM_WRAPPER(int, utimes, (const char* path, const struct timeval times[2]),
              (path, times), "utimes")
// listxattr
DLSYM_WRAPPER(ssize_t, listxattr, (const char* path, char* list, size_t size),
              (path, list, size), "listxattr")
DLSYM_WRAPPER(ssize_t, llistxattr, (const char* path, char* list, size_t size),
              (path, list, size), "llistxattr")
DLSYM_WRAPPER(ssize_t, flistxattr, (int fd, char* list, size_t size),
              (fd, list, size), "flistxattr")

//DLSYM_WRAPPER(long, syscall, (long number, char* cmd, void* arg, void* env),
//              (number, cmd, arg, env), "syscall")

DLSYM_WRAPPER(DIR*, fdopendir, (int fd), (fd), "fdopendir")

DLSYM_WRAPPER(int, scandir,
              (const char* dirp, struct dirent*** namelist,
               typeof(int(const struct dirent*))* filter,
               typeof(int(const struct dirent**,
                          const struct dirent**))* compar),
              (dirp, namelist, filter, compar), "scandir")

/*CDLSYM_WRAPPER(ssize_t, readlink, (const char* path, char* buf, size_t
bufsize), (path, buf, bufsize), "readlink")
@@ -377,23 +418,7 @@ argv[]), (filename, argv), "execvp")



DLSYM_WRAPPER(long, syscall, (long number, char* cmd, void* arg, void* env),
              (number, cmd, arg, env), "syscall")


long
syscall(long number, ...) {

    if(number == SYS_execve or number == SYS_execveat) {
        DEBUG_INFO("execve {}", number);
    }
    va_list myargs;
    va_start(myargs, number);

    auto res = syscall_no_intercept_wrapper(number, myargs);
    va_end(myargs);
    return res;
}
    */
/* not used */
/*static void
@@ -811,10 +836,11 @@ unlink(const char* path) {
int
__xstat(int ver, const char* path, struct stat* buf) {
    GKFS_PATH_OPERATION(stat, AT_FDCWD, path, buf)
    auto res = dlsym_stat(_STAT_VER, path, buf);
    auto res = dlsym_stat(ver, path, buf);
    return res;
}


int
__xstat64(int ver, const char* path, struct stat64* buf) {
    struct stat st;
@@ -835,7 +861,7 @@ __xstat64(int ver, const char* path, struct stat64* buf) {
            }
        }
    }
    auto res = dlsym_stat(_STAT_VER, path, &st);
    auto res = dlsym_stat(ver, path, &st);
    convert(&st, buf);
    return res;
}
@@ -910,7 +936,7 @@ __fxstat(int ver, int fd, struct stat* buf) {
        DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
        return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf);
    }
    GKFS_FALLBACK(fstat, ver, fd, buf);
    GKFS_FALLBACK(__fxstat, ver, fd, buf);
}

int
@@ -950,6 +976,17 @@ fstat64(int fd, struct stat64* buf) {
    GKFS_FALLBACK(fstat64, fd, buf);
}

int
fstat(int fd, struct stat* buf) {
    initializeGekko();
    if(is_gkfs_fd(fd)) {
        DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
        int res =
                gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf);
        return res;
    }
    GKFS_FALLBACK(fstat, fd, buf);
}

int
__fxstatat64(int ver, int dfd, const char* path, struct stat64* buf,
@@ -1008,16 +1045,6 @@ stat64(const char* path, struct stat64* buf) {
    return ret;
}

int
fstat(int fd, struct stat* buf) {
    initializeGekko();
    if(is_gkfs_fd(fd)) {
        DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
        return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf);
    }
    GKFS_FALLBACK(fstat, _STAT_VER, fd, buf);
}

int
fstatat(int dfd, const char* path, struct stat* buf, int flags) {
    initializeGekko();
@@ -1182,19 +1209,21 @@ chdir(const char* path) {

    initializeGekko();
    // is the path from gekkofs
    //   return gkfs::hook::hook_chdir(path);


    if(CTX->interception_enabled()) {
        std::string resolved;

        auto rstatus = CTX->relativize_fd_path(AT_FDCWD, path, resolved);
        DEBUG_INFO("[GKFS] chdir status {} {} --> {}", (int) rstatus, resolved,
                   path);
        switch(rstatus) {

            case gkfs::preload::RelativizeStatus::fd_not_a_dir:
                return -ENOTDIR;

            case gkfs::preload::RelativizeStatus::internal:
                DEBUG_INFO("[GKFS] NOT IMPLEMENTED {}", path);
                return gkfs::hook::hook_chdir(path);
                break;

            default:
@@ -1202,7 +1231,7 @@ chdir(const char* path) {
                break;
        }
    }

    CTX->cwd(path);
    GKFS_FALLBACK(chdir, const_cast<char*>(path));
}

@@ -1390,6 +1419,19 @@ opendir64(const char* dirname) {

    return dlsym_opendir64(const_cast<char*>(dirname));
}

DIR*
fdopendir(int fd) {
    if(CTX->interception_enabled()) {
        if(is_gkfs_fd(fd)) {
            DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
            return gekko_opendir(CTX->file_map()->get(fd)->path());
        }
    }
    GKFS_FALLBACK(fdopendir, fd);
}


// clang-format off

#ifndef __ALIGN_KERNEL_MASK
@@ -1748,7 +1790,7 @@ fgets(char* str, int n, FILE* stream) {
    GKFS_FALLBACK(fgets, str, n, stream)
}

// implement fflush and bypass if gekko
// implement fflush and bypass if gekko (no need to log)
int
fflush(FILE* stream) {
    initializeGekko();
@@ -1756,7 +1798,7 @@ fflush(FILE* stream) {
        // flush stream with gkfs_fsync
        return 0;
    }
    GKFS_FALLBACK(fflush, stream)
    return dlsym_fflush(stream);
}


@@ -1870,3 +1912,118 @@ utimes(const char* path, const struct timeval tv[2]) {
    }
    GKFS_FALLBACK(utimes, path, tv);
}

// Without use... goes directly to the syscall (ls -l)
ssize_t
listxattr(const char* path, char* list, size_t size) {
    initializeGekko();
    if(CTX->interception_enabled()) {
        std::string resolved;
        if(resolve_gkfs_path(AT_FDCWD, path, resolved) ==
           PathStatus::Internal) {
            DEBUG_INFO("[GKFS] {}", resolved);
            return 0;
        }
    }
    GKFS_FALLBACK(listxattr, path, list, size);
}

ssize_t
flistxattr(int fd, char* list, size_t size) {
    initializeGekko();
    if(is_gkfs_fd(fd)) {
        DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
        return 0;
    }
    GKFS_FALLBACK(flistxattr, fd, list, size);
}

ssize_t
llistxattr(const char* path, char* list, size_t size) {
    initializeGekko();
    return 0;
    if(CTX->interception_enabled()) {
        std::string resolved;
        if(resolve_gkfs_path(AT_FDCWD, path, resolved) ==
           PathStatus::Internal) {
            DEBUG_INFO("[GKFS] {}", resolved);
            return 0;
        }
    }
    GKFS_FALLBACK(llistxattr, path, list, size);
}


int
lstat64(const char* path, struct stat64* buf) {
    initializeGekko();
    if(CTX->interception_enabled()) {
        std::string resolved;
        struct stat st;
        if(resolve_gkfs_path(AT_FDCWD, path, resolved) ==
           PathStatus::Internal) {
            DEBUG_INFO("[GKFS] {}", resolved);
            auto res = gkfs::syscall::gkfs_stat(resolved, &st);
            convert(&st, buf);
            return res;
        }
    }
    GKFS_FALLBACK(lstat64, path, buf);
}

int
scandir(const char* dirname, struct dirent*** namelist,
        int (*filter)(const struct dirent*),
        int (*compar)(const struct dirent**, const struct dirent**)) {
    initializeGekko();
    if(CTX->interception_enabled()) {
        std::string resolved;
        if(resolve_gkfs_path(AT_FDCWD, dirname, resolved) ==
           PathStatus::Internal) {
            DEBUG_INFO("[GKFS] {}", resolved);
            // implement scandir : The  scandir()  function scans the directory
            // dirp, calling filter() on each directory entry.  Entries for
            // which filter() returns nonzero are stored in strings allocated
            // via malloc(3), sorted using qsort(3) with the comparison function
            // compar(), and collected in
            //       array namelist which is allocated via malloc(3).  If filter
            //       is NULL, all entries are selected.

            DIR* dirp = gekko_opendir(resolved);
            if(dirp == nullptr) {
                return -1;
            }
            std::vector<struct dirent*> entries;
            struct dirent* entry;
            while((entry = readdir(dirp)) != nullptr) {
                if(filter == nullptr || filter(entry) != 0) {
                    entries.push_back(entry);
                }
            }
            closedir(dirp);
            if(entries.empty()) {
                *namelist = nullptr;
                return 0;
            }
            if(compar != nullptr) {
                qsort(entries.data(), entries.size(), sizeof(struct dirent*),
                      reinterpret_cast<int (*)(const void*, const void*)>(
                              compar));
            }
            *namelist = static_cast<struct dirent**>(
                    malloc(sizeof(struct dirent*) * (entries.size() + 1)));
            if(*namelist == nullptr) {
                for(auto e : entries) {
                    free(e);
                }
                return -1;
            }
            for(size_t i = 0; i < entries.size(); ++i) {
                (*namelist)[i] = entries[i];
            }
            (*namelist)[entries.size()] = nullptr;
            return entries.size();
        }
    }
    GKFS_FALLBACK(scandir, dirname, namelist, filter, compar);
}
+14 −2
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@

extern "C" {
#include <sys/stat.h>
#include <dlfcn.h>
}

using namespace std;
@@ -208,9 +209,20 @@ resolve_new(const string& path, bool resolve_last_link) {
    if(resolved.empty()) {
        resolved.push_back(path::separator);
    }
    // TODO: redo
    auto real =
            reinterpret_cast<char* (*) (const char* path, char* resolved_path)>(
                    dlsym(((void*) -1l), "realpath"));
    auto link_resolved = ::unique_ptr<char[]>(new char[PATH_MAX]);
    if(real(path.c_str(), link_resolved.get()) == nullptr) {
        LOG(DEBUG, "nonresolved: \"{}\"", resolved);
        return make_pair(false, resolved);
    } else {
        resolved = link_resolved.get();
        LOG(DEBUG, "external: \"{}\"", resolved);
        return make_pair(false, resolved);
    }
}

/** Resolve path to its canonical representation
 *