Loading src/client/gkfs_libc.cpp +127 −20 Original line number Diff line number Diff line Loading @@ -188,6 +188,8 @@ 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, fstat64, ( int fd,struct stat64* buf), ( fd, buf), "__fxstat64") DLSYM_WRAPPER(int, fxstatat, (int ver, int dfd, const char* path, struct stat* buf, int flags), (ver, dfd, path, buf, flags), "__fxstatat") Loading Loading @@ -329,7 +331,7 @@ resolve_gkfs_path(int dirfd, const char* path, std::string& resolved, auto res = std::mismatch(CTX->mountdir().begin(), CTX->mountdir().end(), std::string(path).begin()); if(res.first != CTX->mountdir().end()) { if(res.first != CTX->mountdir().end() and dirfd==AT_FDCWD) { return PathStatus::External; } Loading Loading @@ -433,6 +435,16 @@ open64(const char* path, int flags, ...) { GKFS_FALLBACK(open64, const_cast<char*>(path), flags, mode) } int open64(const char* path, int flags, mode_t mode) { initializeGekko(); GKFS_PATH_OPERATION(open, AT_FDCWD, path, mode, flags) GKFS_FALLBACK(open64, const_cast<char*>(path), flags, mode) } int openat(int dirfd, const char* path, int flags, ...) { Loading Loading @@ -465,24 +477,94 @@ close(int fd) { GKFS_FALLBACK(close, fd); } std::vector<int> get_open_fds() { std::vector<int> fds; const std::string fd_path = "/proc/self/fd"; DIR* dir = dlsym_opendir(fd_path.c_str()); if(!dir) { perror("opendir() failed"); return fds; } struct dirent* entry; while((entry = dlsym_readdir(dir))) { // Skip "." and ".." entries if(entry->d_type == DT_DIR) continue; try { int fd = std::stoi(entry->d_name); // Skip the directory FD itself if(fd != dirfd(dir)) { fds.push_back(fd); } } catch(const std::exception&) { // Ignore non-integer entries } } dlsym_closedir(dir); fds.erase(std::remove_if(fds.begin(), fds.end(), [](int fd) { return fcntl(fd, F_GETFD) < 0; }), fds.end()); return fds; } int close_range(unsigned low, unsigned high, int flags) { LOG(DEBUG, "close_range({}, {}, {})", low, high, flags); //return 0; auto fds = get_open_fds(); if(flags & CLOSE_RANGE_UNSHARE) { // Unshare the file descriptor table LOG(DEBUG, "close_range with CLOSE_RANGE_UNSHARE"); if(unshare(CLONE_FILES) == -1) { perror("unshare() failed"); return -1; } } if(flags & CLOSE_RANGE_CLOEXEC) { // Close all file descriptors in the range LOG(DEBUG, "close_range with CLOSE_RANGE_CLOEXEC"); } // Is fd from gekkofs ? initializeGekko(); if(CTX->interception_enabled()) { for(unsigned int i = low; i <= high; i++) { if(i > GKFS_MAX_OPEN_FDS) break; for(unsigned int i : fds) { if(i < low || i > high) continue; if(is_gkfs_fd(i)) { LOG_DEBUG("[GKFS] Closing fd {}", i); gkfs::syscall::gkfs_close(i); } else { LOG_DEBUG("[NONGKFS] Closing fd {}", i); close(i); } } // Fall back to close the original range (it may not be a good idea) return 0; } else { std::cout << "Not in gekko: close_range" << std::endl; for(unsigned int i : fds) { if(i < low || i > high) continue; std::cout << "Not in gekko: close_range " << i << std::endl; close(i); } GKFS_FALLBACK(close_range, low, high, flags); } // We are not in gekko just do it... // GKFS_FALLBACK(close_range, low, high, flags); return 0; } int creat(const char* path, mode_t mode) { Loading Loading @@ -752,7 +834,7 @@ stat64(const char* path, struct stat64* buf) { std::string resolved; switch(resolve_gkfs_path(AT_FDCWD, path, resolved)) { case PathStatus::Internal: { LOG(DEBUG, "[GKFS] {}", CTX->file_map()->get(fd)->path()); LOG(DEBUG, "[GKFS] {}", resolved); auto res = gkfs::syscall::gkfs_stat(resolved, &st); convert(&st, buf); return res; Loading Loading @@ -787,7 +869,7 @@ fstatat(int dfd, const char* path, struct stat* buf, int flags) { std::string resolved; switch(resolve_gkfs_path(dfd, path, resolved)) { case PathStatus::Internal: { LOG(DEBUG, "[GKFS] {}", CTX->file_map()->get(fd)->path()); LOG(DEBUG, "[GKFS] {}", resolved); auto res = gkfs::syscall::gkfs_stat(resolved, buf); return res; } Loading Loading @@ -866,13 +948,12 @@ fork(void) { int pipe(int pipefd[2]) { initializeGekko(); if(is_gkfs_fd(pipefd[0])) { LOG(DEBUG, "[GKFS] 0 {}", pipefd[0]); } if(is_gkfs_fd(pipefd[1])) { LOG(DEBUG, "[GKFS] 1 {}", pipefd[1]); } GKFS_FALLBACK(pipe, pipefd); auto res = dlsym_pipe(pipefd); LOG(DEBUG, "pipe {} <---> {}", pipefd[0], pipefd[1]); // GKFS_FALLBACK(pipe, pipefd); return res; } int Loading @@ -885,7 +966,20 @@ dup(int fd) { int dup2(int fd, int fd2) { initializeGekko(); GKFS_OPERATION(dup2, fd, fd2); if(is_gkfs_fd(fd) && is_gkfs_fd(fd2)) { LOG(DEBUG, "[GKFS] DUP2 G{} --> G{}", fd, fd2); return gkfs::syscall::gkfs_dup2(fd, fd2); }else if(is_gkfs_fd(fd2)) { LOG(DEBUG, "[GKFS-NON] DUP2 {} --> G{}", fd, fd2); return gkfs::syscall::gkfs_dup(fd); }else if(is_gkfs_fd(fd)) { LOG(DEBUG, "[GKFS-NON] DUP2 G{} --> {}", fd, fd2); return gkfs::syscall::gkfs_dup2(fd, fd2); } //GKFS_OPERATION(dup2, fd, fd2); GKFS_FALLBACK(dup2, fd, fd2); } Loading Loading @@ -1032,7 +1126,7 @@ realpath(const char* path, char* resolved_path) { return nullptr; case gkfs::preload::RelativizeStatus::internal: LOG(DEBUG, "[GKFS] {}", resolved); LOG(DEBUG, "[GKFS] {} --> {}", resolved, path); if(resolved_path == nullptr) { resolved_path = static_cast<char*>(malloc(resolved.size() + 1)); Loading Loading @@ -1287,8 +1381,21 @@ fdopen(int fd, const char* mode) { if(CTX->interception_enabled()) { if(is_gkfs_fd(fd)) { FILE* ret; ret = dlsym_fopen("/dev/null", mode); FILE* ret = static_cast<FILE*>(malloc(sizeof(FILE))); if(ret == NULL) { errno = ENOMEM; return NULL; } ret->_mode = 0666; ret->_flags = 0; if(strchr(mode, 'r') != NULL) ret->_flags |= O_RDONLY; if(strchr(mode, 'w')) ret->_flags = O_WRONLY | O_CREAT | O_TRUNC; if(strchr(mode, 'a')) ret->_flags = O_WRONLY | O_CREAT | O_APPEND; if(strchr(mode, '+')) ret->_flags = O_RDWR | O_CREAT; ret->_fileno = fd; return ret; } Loading Loading
src/client/gkfs_libc.cpp +127 −20 Original line number Diff line number Diff line Loading @@ -188,6 +188,8 @@ 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, fstat64, ( int fd,struct stat64* buf), ( fd, buf), "__fxstat64") DLSYM_WRAPPER(int, fxstatat, (int ver, int dfd, const char* path, struct stat* buf, int flags), (ver, dfd, path, buf, flags), "__fxstatat") Loading Loading @@ -329,7 +331,7 @@ resolve_gkfs_path(int dirfd, const char* path, std::string& resolved, auto res = std::mismatch(CTX->mountdir().begin(), CTX->mountdir().end(), std::string(path).begin()); if(res.first != CTX->mountdir().end()) { if(res.first != CTX->mountdir().end() and dirfd==AT_FDCWD) { return PathStatus::External; } Loading Loading @@ -433,6 +435,16 @@ open64(const char* path, int flags, ...) { GKFS_FALLBACK(open64, const_cast<char*>(path), flags, mode) } int open64(const char* path, int flags, mode_t mode) { initializeGekko(); GKFS_PATH_OPERATION(open, AT_FDCWD, path, mode, flags) GKFS_FALLBACK(open64, const_cast<char*>(path), flags, mode) } int openat(int dirfd, const char* path, int flags, ...) { Loading Loading @@ -465,24 +477,94 @@ close(int fd) { GKFS_FALLBACK(close, fd); } std::vector<int> get_open_fds() { std::vector<int> fds; const std::string fd_path = "/proc/self/fd"; DIR* dir = dlsym_opendir(fd_path.c_str()); if(!dir) { perror("opendir() failed"); return fds; } struct dirent* entry; while((entry = dlsym_readdir(dir))) { // Skip "." and ".." entries if(entry->d_type == DT_DIR) continue; try { int fd = std::stoi(entry->d_name); // Skip the directory FD itself if(fd != dirfd(dir)) { fds.push_back(fd); } } catch(const std::exception&) { // Ignore non-integer entries } } dlsym_closedir(dir); fds.erase(std::remove_if(fds.begin(), fds.end(), [](int fd) { return fcntl(fd, F_GETFD) < 0; }), fds.end()); return fds; } int close_range(unsigned low, unsigned high, int flags) { LOG(DEBUG, "close_range({}, {}, {})", low, high, flags); //return 0; auto fds = get_open_fds(); if(flags & CLOSE_RANGE_UNSHARE) { // Unshare the file descriptor table LOG(DEBUG, "close_range with CLOSE_RANGE_UNSHARE"); if(unshare(CLONE_FILES) == -1) { perror("unshare() failed"); return -1; } } if(flags & CLOSE_RANGE_CLOEXEC) { // Close all file descriptors in the range LOG(DEBUG, "close_range with CLOSE_RANGE_CLOEXEC"); } // Is fd from gekkofs ? initializeGekko(); if(CTX->interception_enabled()) { for(unsigned int i = low; i <= high; i++) { if(i > GKFS_MAX_OPEN_FDS) break; for(unsigned int i : fds) { if(i < low || i > high) continue; if(is_gkfs_fd(i)) { LOG_DEBUG("[GKFS] Closing fd {}", i); gkfs::syscall::gkfs_close(i); } else { LOG_DEBUG("[NONGKFS] Closing fd {}", i); close(i); } } // Fall back to close the original range (it may not be a good idea) return 0; } else { std::cout << "Not in gekko: close_range" << std::endl; for(unsigned int i : fds) { if(i < low || i > high) continue; std::cout << "Not in gekko: close_range " << i << std::endl; close(i); } GKFS_FALLBACK(close_range, low, high, flags); } // We are not in gekko just do it... // GKFS_FALLBACK(close_range, low, high, flags); return 0; } int creat(const char* path, mode_t mode) { Loading Loading @@ -752,7 +834,7 @@ stat64(const char* path, struct stat64* buf) { std::string resolved; switch(resolve_gkfs_path(AT_FDCWD, path, resolved)) { case PathStatus::Internal: { LOG(DEBUG, "[GKFS] {}", CTX->file_map()->get(fd)->path()); LOG(DEBUG, "[GKFS] {}", resolved); auto res = gkfs::syscall::gkfs_stat(resolved, &st); convert(&st, buf); return res; Loading Loading @@ -787,7 +869,7 @@ fstatat(int dfd, const char* path, struct stat* buf, int flags) { std::string resolved; switch(resolve_gkfs_path(dfd, path, resolved)) { case PathStatus::Internal: { LOG(DEBUG, "[GKFS] {}", CTX->file_map()->get(fd)->path()); LOG(DEBUG, "[GKFS] {}", resolved); auto res = gkfs::syscall::gkfs_stat(resolved, buf); return res; } Loading Loading @@ -866,13 +948,12 @@ fork(void) { int pipe(int pipefd[2]) { initializeGekko(); if(is_gkfs_fd(pipefd[0])) { LOG(DEBUG, "[GKFS] 0 {}", pipefd[0]); } if(is_gkfs_fd(pipefd[1])) { LOG(DEBUG, "[GKFS] 1 {}", pipefd[1]); } GKFS_FALLBACK(pipe, pipefd); auto res = dlsym_pipe(pipefd); LOG(DEBUG, "pipe {} <---> {}", pipefd[0], pipefd[1]); // GKFS_FALLBACK(pipe, pipefd); return res; } int Loading @@ -885,7 +966,20 @@ dup(int fd) { int dup2(int fd, int fd2) { initializeGekko(); GKFS_OPERATION(dup2, fd, fd2); if(is_gkfs_fd(fd) && is_gkfs_fd(fd2)) { LOG(DEBUG, "[GKFS] DUP2 G{} --> G{}", fd, fd2); return gkfs::syscall::gkfs_dup2(fd, fd2); }else if(is_gkfs_fd(fd2)) { LOG(DEBUG, "[GKFS-NON] DUP2 {} --> G{}", fd, fd2); return gkfs::syscall::gkfs_dup(fd); }else if(is_gkfs_fd(fd)) { LOG(DEBUG, "[GKFS-NON] DUP2 G{} --> {}", fd, fd2); return gkfs::syscall::gkfs_dup2(fd, fd2); } //GKFS_OPERATION(dup2, fd, fd2); GKFS_FALLBACK(dup2, fd, fd2); } Loading Loading @@ -1032,7 +1126,7 @@ realpath(const char* path, char* resolved_path) { return nullptr; case gkfs::preload::RelativizeStatus::internal: LOG(DEBUG, "[GKFS] {}", resolved); LOG(DEBUG, "[GKFS] {} --> {}", resolved, path); if(resolved_path == nullptr) { resolved_path = static_cast<char*>(malloc(resolved.size() + 1)); Loading Loading @@ -1287,8 +1381,21 @@ fdopen(int fd, const char* mode) { if(CTX->interception_enabled()) { if(is_gkfs_fd(fd)) { FILE* ret; ret = dlsym_fopen("/dev/null", mode); FILE* ret = static_cast<FILE*>(malloc(sizeof(FILE))); if(ret == NULL) { errno = ENOMEM; return NULL; } ret->_mode = 0666; ret->_flags = 0; if(strchr(mode, 'r') != NULL) ret->_flags |= O_RDONLY; if(strchr(mode, 'w')) ret->_flags = O_WRONLY | O_CREAT | O_TRUNC; if(strchr(mode, 'a')) ret->_flags = O_WRONLY | O_CREAT | O_APPEND; if(strchr(mode, '+')) ret->_flags = O_RDWR | O_CREAT; ret->_fileno = fd; return ret; } Loading