Verified Commit a745b58d authored by Marc Vef's avatar Marc Vef
Browse files

working prototype squash

parent f020cf23
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ unsigned int match_components(const std::string& path, unsigned int& path_compon

bool resolve(const std::string& path, std::string& resolved, bool resolve_last_link = true);

std::string normalize(const std::string& path);

std::string get_sys_cwd();

void set_sys_cwd(const std::string& path);
+7 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ struct FsConfig {
};

enum class RelativizeStatus {
    ok,
    internal,
    external,
    fd_unknown,
@@ -123,6 +124,12 @@ public:

    void local_host_id(uint64_t id);

    bool is_gkfs_path(std::string& path);

    RelativizeStatus normalize_path(int dirfd, const char* raw_path, std::string& normalized_path);

    RelativizeStatus normalize_path(const char* raw_path, std::string& normalized_path);

    RelativizeStatus relativize_fd_path(int dirfd,
                                        const char* raw_path,
                                        std::string& relative_path,
+32 −10
Original line number Diff line number Diff line
@@ -43,28 +43,50 @@ namespace hook {

int hook_openat(int dirfd, const char* cpath, int flags, mode_t mode) {

    LOG(DEBUG, "{}() called with fd: {}, path: \"{}\", flags: {}, mode: {}",
    LOG(INFO, "{}() called with fd: {}, path: \"{}\", flags: {}, mode: {}",
        __func__, dirfd, cpath, flags, mode);

    std::string resolved;
    auto rstatus = CTX->relativize_fd_path(dirfd, cpath, resolved);
    switch (rstatus) {
    std::string normalized_path{};
    auto status = CTX->normalize_path(dirfd, cpath, normalized_path);

    switch (status) {
        case gkfs::preload::RelativizeStatus::fd_unknown:
            return syscall_no_intercept(SYS_openat, dirfd, cpath, flags, mode);

        case gkfs::preload::RelativizeStatus::external:
            return syscall_no_intercept(SYS_openat, dirfd, resolved.c_str(), flags, mode);

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

        case gkfs::preload::RelativizeStatus::internal:
            return with_errno(gkfs::syscall::gkfs_open(resolved, mode, flags));

        case gkfs::preload::RelativizeStatus::ok:
            if (CTX->is_gkfs_path(normalized_path))
                return with_errno(gkfs::syscall::gkfs_open(normalized_path, mode, flags));
            else
                return syscall_no_intercept(SYS_openat, dirfd, normalized_path.c_str(), flags, mode);
        default:
            LOG(ERROR, "{}() relativize status unknown: {}", __func__);
            return -EINVAL;
    }
//
//
//
//    std::string resolved;
//    auto rstatus = CTX->relativize_fd_path(dirfd, cpath, resolved);
//    switch (rstatus) {
//        case gkfs::preload::RelativizeStatus::fd_unknown:
//            return syscall_no_intercept(SYS_openat, dirfd, cpath, flags, mode);
//
//        case gkfs::preload::RelativizeStatus::external:
//            return syscall_no_intercept(SYS_openat, dirfd, resolved.c_str(), flags, mode);
//
//        case gkfs::preload::RelativizeStatus::fd_not_a_dir:
//            return -ENOTDIR;
//
//        case gkfs::preload::RelativizeStatus::internal:
//            return with_errno(gkfs::syscall::gkfs_open(resolved, mode, flags));
//
//        default:
//            LOG(ERROR, "{}() relativize status unknown: {}", __func__);
//            return -EINVAL;
//    }
}

int hook_close(int fd) {
+55 −1
Original line number Diff line number Diff line
@@ -78,6 +78,60 @@ unsigned int match_components(const string& path, unsigned int& path_components,
    return matched;
}


/**
 * Normalize a given path with `.` and `..` components. This will not resolve symlinks
 * @param path
 * @return normalized path
 */
string normalize(const string& path) {

    string normalized{}; // final normalized path
    normalized.reserve(path.size());
    string::size_type comp_size = 0; // size of current component
    string::size_type start = 0; // start index of curr component
    string::size_type end = 0; // end index of curr component (last processed Path Separator "separator")
    stack<string::size_type> slash_idx{};
    slash_idx.push(0); // index of all slashes in resolved path (used for rollback due to `..`)

    while (++end < path.size()) {
        start = end;
        // Skip sequence of multiple path-separators.
        while (start < path.size() && path[start] == path::separator) {
            start++;
        }
        // Find next component
        end = path.find_first_of(path::separator, start);
        if (end == string::npos) {
            end = path.size();
        }
        comp_size = end - start;

        // component is empty (this must be the last component)
        if (comp_size == 0) {
            break;
        }
        // component is '.', we skip it
        if (comp_size == 1 && path.at(start) == '.') {
            continue;
        }
        // component is '..' we need to rollback normalized path
        if (comp_size == 2 && path.at(start) == '.' && path.at(start + 1) == '.') {
            if (!normalized.empty()) {
                normalized.erase(slash_idx.top());
                slash_idx.pop();
            }
            continue;
        }
        // add `/<component>` to the normalized path
        normalized.push_back(path::separator);
        slash_idx.push(normalized.size() - 1);
        normalized.append(path, start, comp_size);
    }
    LOG(INFO, "path: '{}', normalized: '{}'", path, normalized);
    return normalized;
}

/** Resolve path to its canonical representation
 *
 * Populate `resolved` with the canonical representation of `path`.
@@ -126,7 +180,7 @@ bool resolve(const string& path, string& resolved, bool resolve_last_link) {
        }

        // Find next component
        end = path.find(path::separator, start);
        end = path.find_first_of(path::separator, start);
        if (end == string::npos) {
            end = path.size();
        }
+66 −0
Original line number Diff line number Diff line
@@ -121,6 +121,72 @@ void PreloadContext::local_host_id(uint64_t id) {
    local_host_id_ = id;
}

bool PreloadContext::is_gkfs_path(std::string& path) {
    return path.rfind(mountdir_, 0) != std::string::npos;
}

RelativizeStatus PreloadContext::normalize_path(int dirfd, const char* raw_path, std::string& normalized_path) {
    // TODO when LEAF is available: return concated path and throw Status instead.
    // Relativize path should be called only after the library constructor has been executed
    assert(interception_enabled_);
    // If we run the constructor we also already setup the mountdir
    assert(!mountdir_.empty());

    // We assume raw path is valid
    assert(raw_path != nullptr);

    std::string path{};

    if (raw_path[0] != gkfs::path::separator) {
        // path is relative
        if (dirfd == AT_FDCWD) {
            // path is relative to cwd
            path = gkfs::path::prepend_path(cwd_, raw_path);
        } else {
            if (!ofm_->exist(dirfd)) {
                return RelativizeStatus::fd_unknown;
            }
            // path is relative to fd
            auto dir = ofm_->get_dir(dirfd);
            if (dir == nullptr) {
                return RelativizeStatus::fd_not_a_dir;
            }
            path = mountdir_;
            path.append(dir->path());
            path.push_back(gkfs::path::separator);
            path.append(raw_path);
        }
    } else {
        path = raw_path;
    }
    normalized_path = gkfs::path::normalize(path);
    return RelativizeStatus::ok;
}

RelativizeStatus PreloadContext::normalize_path(const char* raw_path, std::string& normalized_path) {
    // TODO when LEAF is available: return concated path and throw Status instead.
    // Relativize path should be called only after the library constructor has been executed
    assert(interception_enabled_);
    // If we run the constructor we also already setup the mountdir
    assert(!mountdir_.empty());

    // We assume raw path is valid
    assert(raw_path != nullptr);

    std::string path;

    if (raw_path[0] != gkfs::path::separator) {
        /* Path is not absolute, we need to prepend CWD;
         * First reserve enough space to minimize memory copy
         */
        path = gkfs::path::prepend_path(cwd_, raw_path);
    } else {
        path = raw_path;
    }
    normalized_path = gkfs::path::normalize(path);
    return RelativizeStatus::ok;
}

RelativizeStatus PreloadContext::relativize_fd_path(int dirfd,
                                                    const char* raw_path,
                                                    std::string& relative_path,