Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/common/capio/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
59 changes: 24 additions & 35 deletions src/posix/handlers/open.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,32 +74,27 @@ int open_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg
auto tid = static_cast<pid_t>(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<int>(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;
Expand All @@ -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<int>(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;
Expand Down
7 changes: 4 additions & 3 deletions src/posix/utils/cache/consent_request_cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/server/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <capio/constants.hpp>
#include <gtest/gtest.h>

#define syscall_no_intercept syscall

std::string workflow_name = CAPIO_DEFAULT_WORKFLOW_NAME;

std::string node_name;
Expand Down