diff --git a/src/common/capio/filesystem.hpp b/src/common/capio/filesystem.hpp index 14bf1bb22..57f4ff2ab 100644 --- a/src/common/capio/filesystem.hpp +++ b/src/common/capio/filesystem.hpp @@ -115,4 +115,57 @@ inline bool is_capio_path(const std::filesystem::path &path_to_check) { return std::regex(computed); } +/** + * Resolve a possible symbolic link to the absolute path that it points to + * @param input_path + * @return + */ +[[nodiscard]] static std::string resolve_possible_symlink(const std::filesystem::path &input_path) { + START_LOG(capio_syscall(SYS_gettid), "call(path=%s)", input_path.c_str()); + + LOG("Absolute path = %s", input_path.c_str()); + +#ifdef __CAPIO_POSIX + syscall_no_intercept_flag = true; +#endif + + auto input_abs_path = std::filesystem::absolute(input_path); + + std::filesystem::path resolved; + + for (const auto &part : input_abs_path) { + resolved /= part; + + if (part == "." || part.empty()) { + continue; + } + if (part == "..") { + resolved = resolved.parent_path(); + continue; + } + if (std::filesystem::is_symlink(resolved)) { + char buf[PATH_MAX]{0}; + if (capio_syscall(SYS_readlink, resolved.c_str(), buf, sizeof(buf) - 1) == -1) { + LOG("File might not exist. path was %s and Error is %s", resolved.c_str(), + strerror(errno)); + continue; + } + + if (std::filesystem::path target(buf); target.is_relative()) { + resolved = resolved.parent_path() / target; + } else { + resolved = target; + } + + resolved = std::filesystem::absolute(resolved); + } + } + auto return_value = std::filesystem::absolute(input_path); +#ifdef __CAPIO_POSIX + syscall_no_intercept_flag = false; +#endif + + return return_value; +} + #endif // CAPIO_COMMON_FILESYSTEM_HPP diff --git a/src/posix/handlers/open.hpp b/src/posix/handlers/open.hpp index f62d7cf6c..b782cc181 100644 --- a/src/posix/handlers/open.hpp +++ b/src/posix/handlers/open.hpp @@ -74,32 +74,27 @@ int open_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg auto tid = static_cast(syscall_no_intercept(SYS_gettid)); START_LOG(tid, "call(path=%s, flags=%d, mode=%d)", pathname.data(), flags, mode); - if (is_forbidden_path(pathname)) { - LOG("Path %s is forbidden: skip", pathname.data()); + std::string path = compute_abs_path(pathname.data(), -1); + + if (is_forbidden_path(pathname) || !is_capio_path(path)) { + LOG("Path %s is not a capio path: skip", pathname.data()); return CAPIO_POSIX_SYSCALL_REQUEST_SKIP; } - std::string path = compute_abs_path(pathname.data(), -1); - - if (is_capio_path(path)) { - if ((flags & O_CREAT) == O_CREAT) { - LOG("O_CREAT"); - create_request(-1, path.data(), tid); - } else { - LOG("not O_CREAT"); - open_request(-1, path.data(), tid); - } + std::string resolved_path = resolve_possible_symlink(path); + if ((flags & O_CREAT) == O_CREAT) { + LOG("O_CREAT"); + create_request(-1, path.data(), tid); } else { - LOG("Not a CAPIO path. skipping..."); - return CAPIO_POSIX_SYSCALL_REQUEST_SKIP; + LOG("not O_CREAT"); + open_request(-1, resolved_path.data(), tid); } int fd = static_cast(syscall_no_intercept(SYS_open, arg0, arg1, arg2, arg3, arg4, arg5)); - if (is_capio_path(path) && fd >= 0) { - LOG("Adding capio path"); - add_capio_fd(tid, path, fd, 0, (flags & O_CLOEXEC) == O_CLOEXEC); - } + LOG("Adding capio path"); + add_capio_fd(tid, resolved_path, fd, 0, (flags & O_CLOEXEC) == O_CLOEXEC); + LOG("fd=%d", fd); *result = fd; return CAPIO_POSIX_SYSCALL_SUCCESS; @@ -116,33 +111,27 @@ int openat_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long a START_LOG(tid, "call(dirfd=%ld, path=%s, flags=%d, mode=%d)", dirfd, pathname.data(), flags, mode); - if (is_forbidden_path(pathname)) { - LOG("Path %s is forbidden: skip", pathname.data()); + std::string path = compute_abs_path(pathname.data(), dirfd); + if (is_forbidden_path(pathname) || !is_capio_path(path)) { + LOG("Path %s is not a capio path: skip", pathname.data()); return CAPIO_POSIX_SYSCALL_REQUEST_SKIP; } - std::string path = compute_abs_path(pathname.data(), dirfd); + std::string resolved_path = resolve_possible_symlink(path); - if (is_capio_path(path)) { - if ((flags & O_CREAT) == O_CREAT) { - LOG("O_CREAT"); - create_request(-1, path.data(), tid); - } else { - LOG("not O_CREAT"); - open_request(-1, path.data(), tid); - } + if ((flags & O_CREAT) == O_CREAT) { + LOG("O_CREAT"); + create_request(-1, path.data(), tid); } else { - LOG("Not a CAPIO path. skipping..."); - return CAPIO_POSIX_SYSCALL_REQUEST_SKIP; + LOG("not O_CREAT"); + open_request(-1, resolved_path.data(), tid); } int fd = static_cast(syscall_no_intercept(SYS_openat, arg0, arg1, arg2, arg3, arg4, arg5)); LOG("fd=%d", fd); - if (is_capio_path(path) && fd >= 0) { - LOG("Adding capio path"); - add_capio_fd(tid, path, fd, 0, (flags & O_CLOEXEC) == O_CLOEXEC); - } + LOG("Adding resolved capio path (%s)", resolved_path.c_str()); + add_capio_fd(tid, resolved_path, fd, 0, (flags & O_CLOEXEC) == O_CLOEXEC); *result = fd; return CAPIO_POSIX_SYSCALL_SUCCESS; diff --git a/src/posix/utils/cache/consent_request_cache.hpp b/src/posix/utils/cache/consent_request_cache.hpp index 9727d37f9..753e5ac11 100644 --- a/src/posix/utils/cache/consent_request_cache.hpp +++ b/src/posix/utils/cache/consent_request_cache.hpp @@ -38,11 +38,12 @@ class ConsentRequestCache { * If entry is not present in cache, then proceed to perform request. othrewise if present, * there is no need to perform request to server and can proceed */ - if (available_consent->find(path) == available_consent->end()) { + if (const auto resolved_path = resolve_possible_symlink(path); + available_consent->find(resolved_path) == available_consent->end()) { LOG("File not present in cache. performing request"); - auto res = ConsentRequestCache::_consent_to_proceed_request(path, tid, source_func); + auto res = _consent_to_proceed_request(resolved_path, tid, source_func); LOG("Registering new file for consent to proceed"); - available_consent->emplace(path, res); + available_consent->emplace(resolved_path, res); } LOG("Unlocking thread"); } diff --git a/tests/unit/server/src/main.cpp b/tests/unit/server/src/main.cpp index 9efd16c12..d1e53045d 100644 --- a/tests/unit/server/src/main.cpp +++ b/tests/unit/server/src/main.cpp @@ -1,6 +1,8 @@ #include #include +#define syscall_no_intercept syscall + std::string workflow_name = CAPIO_DEFAULT_WORKFLOW_NAME; std::string node_name;