From c94394b08cfef0c24fad80a2f5fb9f559ade5c63 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 11 Apr 2026 10:51:47 +0100 Subject: [PATCH 1/2] Added renameat and renameat2 handler support --- capio/posix/handlers/chdir.hpp | 3 ++- capio/posix/handlers/rename.hpp | 48 +++++++++++++++++++++++++++++++-- capio/posix/libcapio_posix.cpp | 6 +++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/capio/posix/handlers/chdir.hpp b/capio/posix/handlers/chdir.hpp index 179beb196..f8139a314 100644 --- a/capio/posix/handlers/chdir.hpp +++ b/capio/posix/handlers/chdir.hpp @@ -33,7 +33,8 @@ int chdir_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long ar if (is_capio_path(path)) { set_current_dir(path); - errno = 0; + errno = 0; + *result = 0; return CAPIO_POSIX_SYSCALL_SUCCESS; } diff --git a/capio/posix/handlers/rename.hpp b/capio/posix/handlers/rename.hpp index 8bdaa4941..1f87dbbb9 100644 --- a/capio/posix/handlers/rename.hpp +++ b/capio/posix/handlers/rename.hpp @@ -1,10 +1,10 @@ #ifndef CAPIO_POSIX_HANDLERS_RENAME_HPP #define CAPIO_POSIX_HANDLERS_RENAME_HPP -#if defined(SYS_rename) - #include "utils/filesystem.hpp" +#if defined(SYS_rename) + int rename_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long *result) { const std::filesystem::path oldpath(reinterpret_cast(arg0)); const std::filesystem::path newpath(reinterpret_cast(arg1)); @@ -37,4 +37,48 @@ int rename_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long a } #endif // SYS_rename + +#if defined(SYS_renameat) + +int renameat_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, + long *result) { + const auto old_dirfd = arg0, new_dirfd = arg2; + const std::filesystem::path oldpath(reinterpret_cast(arg1)); + const std::filesystem::path newpath(reinterpret_cast(arg3)); + long tid = syscall_no_intercept(SYS_gettid); + + START_LOG(tid, "call(oldpath=%s, newpath=%s)", oldpath.c_str(), newpath.c_str()); + + if (old_dirfd != AT_FDCWD || new_dirfd != AT_FDCWD) { + LOG("Rename with dirfd different from current working directory not yet supported"); + return CAPIO_POSIX_SYSCALL_SKIP; + } + + auto oldpath_abs = capio_absolute(oldpath); + auto newpath_abs = capio_absolute(newpath); + + if (is_prefix(oldpath_abs, newpath_abs)) { // TODO: The check is more complex + errno = EINVAL; + *result = -errno; + return CAPIO_POSIX_SYSCALL_SUCCESS; + } + + if (is_capio_path(oldpath_abs)) { + rename_capio_path(oldpath_abs, newpath_abs); + auto res = rename_request(tid, oldpath_abs, newpath_abs); + *result = (res < 0 ? -errno : res); + return CAPIO_POSIX_SYSCALL_SUCCESS; + } else { + if (is_capio_path(newpath_abs)) { + std::filesystem::copy(oldpath_abs, newpath_abs); + *result = -errno; + return CAPIO_POSIX_SYSCALL_SUCCESS; + } else { + return CAPIO_POSIX_SYSCALL_SKIP; + } + } +} + +#endif + #endif // CAPIO_POSIX_HANDLERS_RENAME_HPP diff --git a/capio/posix/libcapio_posix.cpp b/capio/posix/libcapio_posix.cpp index 9382c05a9..8e174ff3d 100644 --- a/capio/posix/libcapio_posix.cpp +++ b/capio/posix/libcapio_posix.cpp @@ -293,6 +293,12 @@ static constexpr std::array build_syscall_table( #ifdef SYS_rename _syscallTable[SYS_rename] = rename_handler; #endif +#ifdef SYS_renameat + _syscallTable[SYS_renameat] = renameat_handler; +#endif +#ifdef SYS_renameat2 + _syscallTable[SYS_renameat2] = renameat_handler; +#endif #ifdef SYS_rmdir _syscallTable[SYS_rmdir] = rmdir_handler; #endif From 538d36c220db54352b92ea3699b2e4f7338f860b Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 11 Apr 2026 12:48:33 +0100 Subject: [PATCH 2/2] Improved handlers --- capio/posix/handlers/rename.hpp | 92 ++++++++++++-------------------- capio/posix/libcapio_posix.cpp | 2 +- capio/posix/utils/filesystem.hpp | 5 ++ 3 files changed, 41 insertions(+), 58 deletions(-) diff --git a/capio/posix/handlers/rename.hpp b/capio/posix/handlers/rename.hpp index 1f87dbbb9..d62fcb970 100644 --- a/capio/posix/handlers/rename.hpp +++ b/capio/posix/handlers/rename.hpp @@ -3,31 +3,43 @@ #include "utils/filesystem.hpp" -#if defined(SYS_rename) - -int rename_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long *result) { - const std::filesystem::path oldpath(reinterpret_cast(arg0)); - const std::filesystem::path newpath(reinterpret_cast(arg1)); - long tid = syscall_no_intercept(SYS_gettid); - START_LOG(tid, "call(oldpath=%s, newpath=%s)", oldpath.c_str(), newpath.c_str()); - - auto oldpath_abs = capio_absolute(oldpath); - auto newpath_abs = capio_absolute(newpath); - - if (is_prefix(oldpath_abs, newpath_abs)) { // TODO: The check is more complex +int renameat2_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, + long *result) { + const auto flags = arg4; + const std::filesystem::path old_dir_fd_path = get_dir_path(static_cast(arg0)); + const std::filesystem::path old_path(reinterpret_cast(arg1)); + const std::filesystem::path new_dir_fd_path = get_dir_path(static_cast(arg2)); + const std::filesystem::path new_path(reinterpret_cast(arg3)); + const long tid = syscall_no_intercept(SYS_gettid); + + // TODO: implement handling of FLAGS + + START_LOG(tid, + "call(old_dir_fd_path=%s, old_path=%s, new_dir_fd_path=%s, newpath=%s, flags=%d)", + old_dir_fd_path.c_str(), old_path.c_str(), new_dir_fd_path.c_str(), new_path.c_str(), + flags); + + // Resolve paths relative to path of dir_fd ONLY if input path is not absolute + const auto old_path_abs = + old_path.is_absolute() ? old_path : capio_absolute(old_dir_fd_path / old_path); + + const auto new_path_abs = + new_path.is_absolute() ? new_path : capio_absolute(new_dir_fd_path / new_path); + + if (is_prefix(old_path_abs, new_path_abs)) { // TODO: The check is more complex errno = EINVAL; *result = -errno; return CAPIO_POSIX_SYSCALL_SUCCESS; } - if (is_capio_path(oldpath_abs)) { - rename_capio_path(oldpath_abs, newpath_abs); - auto res = rename_request(tid, oldpath_abs, newpath_abs); + if (is_capio_path(old_path_abs)) { + rename_capio_path(old_path_abs, new_path_abs); + auto res = rename_request(tid, old_path_abs, new_path_abs); *result = (res < 0 ? -errno : res); return CAPIO_POSIX_SYSCALL_SUCCESS; } else { - if (is_capio_path(newpath_abs)) { - std::filesystem::copy(oldpath_abs, newpath_abs); + if (is_capio_path(new_path_abs)) { + std::filesystem::copy(old_path_abs, new_path_abs); *result = -errno; return CAPIO_POSIX_SYSCALL_SUCCESS; } else { @@ -36,49 +48,15 @@ int rename_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long a } } -#endif // SYS_rename - -#if defined(SYS_renameat) +int rename_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long *result) { + // Force flags to zero to ensure that spurious data is being passed to handler + return renameat2_handler(AT_FDCWD, arg0, AT_FDCWD, arg1, 0, 0, result); +} int renameat_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long *result) { - const auto old_dirfd = arg0, new_dirfd = arg2; - const std::filesystem::path oldpath(reinterpret_cast(arg1)); - const std::filesystem::path newpath(reinterpret_cast(arg3)); - long tid = syscall_no_intercept(SYS_gettid); - - START_LOG(tid, "call(oldpath=%s, newpath=%s)", oldpath.c_str(), newpath.c_str()); - - if (old_dirfd != AT_FDCWD || new_dirfd != AT_FDCWD) { - LOG("Rename with dirfd different from current working directory not yet supported"); - return CAPIO_POSIX_SYSCALL_SKIP; - } - - auto oldpath_abs = capio_absolute(oldpath); - auto newpath_abs = capio_absolute(newpath); - - if (is_prefix(oldpath_abs, newpath_abs)) { // TODO: The check is more complex - errno = EINVAL; - *result = -errno; - return CAPIO_POSIX_SYSCALL_SUCCESS; - } - - if (is_capio_path(oldpath_abs)) { - rename_capio_path(oldpath_abs, newpath_abs); - auto res = rename_request(tid, oldpath_abs, newpath_abs); - *result = (res < 0 ? -errno : res); - return CAPIO_POSIX_SYSCALL_SUCCESS; - } else { - if (is_capio_path(newpath_abs)) { - std::filesystem::copy(oldpath_abs, newpath_abs); - *result = -errno; - return CAPIO_POSIX_SYSCALL_SUCCESS; - } else { - return CAPIO_POSIX_SYSCALL_SKIP; - } - } + // Force flags to zero to ensure that spurious data is being passed to handler + return renameat2_handler(arg0, arg1, arg2, arg3, 0, arg5, result); } -#endif - #endif // CAPIO_POSIX_HANDLERS_RENAME_HPP diff --git a/capio/posix/libcapio_posix.cpp b/capio/posix/libcapio_posix.cpp index 8e174ff3d..3aedd1a46 100644 --- a/capio/posix/libcapio_posix.cpp +++ b/capio/posix/libcapio_posix.cpp @@ -297,7 +297,7 @@ static constexpr std::array build_syscall_table( _syscallTable[SYS_renameat] = renameat_handler; #endif #ifdef SYS_renameat2 - _syscallTable[SYS_renameat2] = renameat_handler; + _syscallTable[SYS_renameat2] = renameat2_handler; #endif #ifdef SYS_rmdir _syscallTable[SYS_rmdir] = rmdir_handler; diff --git a/capio/posix/utils/filesystem.hpp b/capio/posix/utils/filesystem.hpp index cc6c22d09..04f13dff2 100644 --- a/capio/posix/utils/filesystem.hpp +++ b/capio/posix/utils/filesystem.hpp @@ -229,6 +229,11 @@ inline std::vector get_capio_fds() { std::filesystem::path get_dir_path(int dirfd) { START_LOG(syscall_no_intercept(SYS_gettid), "call(dirfd=%d)", dirfd); + if (dirfd == AT_FDCWD) { + LOG("Returning current CWD"); + return get_current_dir(); + } + auto it = capio_files_descriptors->find(dirfd); if (it != capio_files_descriptors->end()) { LOG("dirfd %d points to path %s", dirfd, it->second.c_str());