Verified Commit 1cf0930a authored by Tommaso Tocci's avatar Tommaso Tocci
Browse files

bugfix: do not always follow last link in path

when resolving path we don't want always
to resolve also the last components if it is a link. Cause in some cases
we want exactly the path of that link and not the one it points to.

lstat and readlink are some example of functions that don't want to
resolve the last link.
parent 030e3cbd
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -78,9 +78,10 @@ class PreloadContext {

    RelativizeStatus relativize_fd_path(int dirfd,
                                        const char * raw_path,
                                        std::string& relative_path) const;
                                        std::string& relative_path,
                                        bool resolve_last_link = true) const;

    bool relativize_path(const char * raw_path, std::string& relative_path) const;
    bool relativize_path(const char * raw_path, std::string& relative_path, bool resolve_last_link = true) const;
    const std::shared_ptr<OpenFileMap>& file_map() const;

    void distributor(std::shared_ptr<Distributor> distributor);
+1 −1
Original line number Diff line number Diff line
#include <string>

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

std::string get_sys_cwd();
void set_sys_cwd(const std::string& path);
+2 −2
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ int hook_stat(const char* path, struct stat* buf) {
int hook_lstat(const char* path, struct stat* buf) {
    CTX->log()->trace("{}() called with path '{}'", __func__, path);
    std::string rel_path;
    if (CTX->relativize_path(path, rel_path)) {
    if (CTX->relativize_path(path, rel_path, false)) {
        return with_errno(adafs_stat(rel_path, buf));
    }
    return syscall_no_intercept(SYS_lstat, rel_path.c_str(), buf);
@@ -442,7 +442,7 @@ int hook_readlinkat(int dirfd, const char * cpath, char * buf, int bufsiz) {
                      __func__, cpath, dirfd, bufsiz);

    std::string resolved;
    auto rstatus = CTX->relativize_fd_path(dirfd, cpath, resolved);
    auto rstatus = CTX->relativize_fd_path(dirfd, cpath, resolved, false);
    switch(rstatus) {
        case RelativizeStatus::fd_unknown:
            return syscall_no_intercept(SYS_readlinkat, dirfd, cpath, buf, bufsiz);
+5 −4
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@ const std::string& PreloadContext::cwd() const {

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

    // Relativize path should be called only after the library constructor has been executed
    assert(initialized_);
@@ -81,13 +82,13 @@ RelativizeStatus PreloadContext::relativize_fd_path(int dirfd,
        path = raw_path;
    }

    if (resolve_path(path, relative_path)) {
    if (resolve_path(path, relative_path, resolve_last_link)) {
        return RelativizeStatus::internal;
    }
    return RelativizeStatus::external;
}

bool PreloadContext::relativize_path(const char * raw_path, std::string& relative_path) const {
bool PreloadContext::relativize_path(const char * raw_path, std::string& relative_path, bool resolve_last_link) const {
    // Relativize path should be called only after the library constructor has been executed
    assert(initialized_);
    // If we run the constructor we also already setup the mountdir
@@ -106,7 +107,7 @@ bool PreloadContext::relativize_path(const char * raw_path, std::string& relativ
    } else {
        path = raw_path;
    }
    return resolve_path(path, relative_path);
    return resolve_path(path, relative_path, resolve_last_link);
}

const std::shared_ptr<OpenFileMap>& PreloadContext::file_map() const {
+4 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ unsigned int path_match_components(const std::string& path, unsigned int &path_c
    return matched;
}

bool resolve_path (const std::string& path, std::string& resolved) {
bool resolve_path (const std::string& path, std::string& resolved, bool resolve_last_link) {
    CTX->log()->debug("{}() path: '{}'", __func__, path);

    struct stat st;
@@ -108,6 +108,9 @@ bool resolve_path (const std::string& path, std::string& resolved) {
                return false;
            }
            if (S_ISLNK(st.st_mode)) {
                if (!resolve_last_link && end == path.size()) {
                    continue;
                }
                char link_resolved[PATH_MAX_LEN];
                if (realpath(resolved.c_str(), link_resolved) == nullptr) {
                    CTX->log()->error("{}() Failed to get realpath for link '{}'. Error: {}", __func__, resolved, strerror(errno));