Loading src/client/intercept.cpp +48 −25 Original line number Original line Diff line number Diff line Loading @@ -36,7 +36,7 @@ SPDX-License-Identifier: LGPL-3.0-or-later SPDX-License-Identifier: LGPL-3.0-or-later */ */ #include <pthread.h> #include <client/intercept.hpp> #include <client/intercept.hpp> #include <client/preload.hpp> #include <client/preload.hpp> #include <client/hooks.hpp> #include <client/hooks.hpp> Loading Loading @@ -74,7 +74,13 @@ void (*intercept_hook_point_post_kernel)(long syscall_number, long arg0, #endif #endif namespace { namespace { thread_local bool reentrance_guard_flag; static pthread_key_t reentrance_guard_key; static pthread_once_t key_once_control = PTHREAD_ONCE_INIT; static void make_key() { // This function will be called exactly once per process. pthread_key_create(&reentrance_guard_key, NULL); } thread_local gkfs::syscall::info saved_syscall_info; thread_local gkfs::syscall::info saved_syscall_info; constexpr void constexpr void Loading Loading @@ -533,7 +539,8 @@ hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, case SYS_execve: case SYS_execve: // If we do not set this to false, we are in trouble with vforks // If we do not set this to false, we are in trouble with vforks reentrance_guard_flag = false; pthread_once(&key_once_control, make_key); pthread_setspecific(reentrance_guard_key, NULL); *result = syscall_no_intercept_wrapper( *result = syscall_no_intercept_wrapper( syscall_number, reinterpret_cast<const char*>(arg0), syscall_number, reinterpret_cast<const char*>(arg0), reinterpret_cast<const char* const*>(arg1), reinterpret_cast<const char* const*>(arg1), Loading @@ -543,7 +550,8 @@ hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, #ifdef SYS_execveat #ifdef SYS_execveat case SYS_execveat: case SYS_execveat: // If we do not set this to false, we are in trouble with vforks // If we do not set this to false, we are in trouble with vforks reentrance_guard_flag = false; pthread_once(&key_once_control, make_key); pthread_setspecific(reentrance_guard_key, NULL); *result = syscall_no_intercept_wrapper( *result = syscall_no_intercept_wrapper( syscall_number, arg0, reinterpret_cast<const char*>(arg1), syscall_number, arg0, reinterpret_cast<const char*>(arg1), reinterpret_cast<const char* const*>(arg2), reinterpret_cast<const char* const*>(arg2), Loading Loading @@ -1011,12 +1019,19 @@ socketcall_wrapper(long syscall_number, long& arg0, long& arg1, long& arg2, } } #endif #endif void void hook_forwarded_syscall(long syscall_number, long arg0, long arg1, long arg2, hook_forwarded_syscall(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long result) { long arg3, long arg4, long arg5, long result) { pthread_once(&key_once_control, make_key); if (pthread_getspecific(reentrance_guard_key) != NULL) { return; } pthread_setspecific(reentrance_guard_key, (void*) 1); if(::get_current_syscall_info() == gkfs::syscall::no_info) { if(::get_current_syscall_info() == gkfs::syscall::no_info) { pthread_setspecific(reentrance_guard_key, NULL); return; return; } } Loading @@ -1029,6 +1044,8 @@ hook_forwarded_syscall(long syscall_number, long arg0, long arg1, long arg2, syscall_number, args, result); syscall_number, args, result); ::reset_current_syscall_info(); ::reset_current_syscall_info(); pthread_setspecific(reentrance_guard_key, NULL); } } void void Loading @@ -1042,12 +1059,13 @@ hook_clone_at_child(unsigned long flags, void* child_stack, int* ptid, static_cast<long>(newtls), 0}; static_cast<long>(newtls), 0}; #endif #endif reentrance_guard_flag = true; pthread_once(&key_once_control, make_key); pthread_setspecific(reentrance_guard_key, (void*) 1); LOG(SYSCALL, ::get_current_syscall_info() | gkfs::syscall::executed, LOG(SYSCALL, ::get_current_syscall_info() | gkfs::syscall::executed, SYS_clone, args, 0); SYS_clone, args, 0); reentrance_guard_flag = false; pthread_setspecific(reentrance_guard_key, NULL); } } void void Loading @@ -1061,18 +1079,20 @@ hook_clone_at_parent(unsigned long flags, void* child_stack, int* ptid, static_cast<long>(newtls), 0}; static_cast<long>(newtls), 0}; #endif #endif reentrance_guard_flag = true; pthread_once(&key_once_control, make_key); pthread_setspecific(reentrance_guard_key, (void*) 1); LOG(SYSCALL, ::get_current_syscall_info() | gkfs::syscall::executed, LOG(SYSCALL, ::get_current_syscall_info() | gkfs::syscall::executed, SYS_clone, args, returned_pid); SYS_clone, args, returned_pid); reentrance_guard_flag = false; pthread_setspecific(reentrance_guard_key, NULL); } } } // namespace } // namespace namespace gkfs::preload { namespace gkfs::preload { // This function is inside 'namespace gkfs::preload' int int internal_hook_guard_wrapper(long syscall_number, long arg0, long arg1, internal_hook_guard_wrapper(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg2, long arg3, long arg4, long arg5, Loading @@ -1085,7 +1105,8 @@ internal_hook_guard_wrapper(long syscall_number, long arg0, long arg1, arg3, arg4, arg5); arg3, arg4, arg5); #endif #endif if(reentrance_guard_flag) { pthread_once(&key_once_control, make_key); if (pthread_getspecific(reentrance_guard_key) != NULL) { ::save_current_syscall_info(gkfs::syscall::from_internal_code | ::save_current_syscall_info(gkfs::syscall::from_internal_code | gkfs::syscall::to_kernel | gkfs::syscall::to_kernel | gkfs::syscall::not_executed); gkfs::syscall::not_executed); Loading @@ -1094,15 +1115,14 @@ internal_hook_guard_wrapper(long syscall_number, long arg0, long arg1, int was_hooked = 0; int was_hooked = 0; reentrance_guard_flag = true; pthread_setspecific(reentrance_guard_key, (void*) 1); was_hooked = hook_internal(syscall_number, arg0, arg1, arg2, arg3, arg4, was_hooked = hook_internal(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, syscall_return_value); arg5, syscall_return_value); reentrance_guard_flag = false; pthread_setspecific(reentrance_guard_key, NULL); return was_hooked; return was_hooked; } } /* /* * hook_guard_wrapper -- a wrapper which can notice reentrance. * hook_guard_wrapper -- a wrapper which can notice reentrance. * * Loading @@ -1122,6 +1142,17 @@ hook_guard_wrapper(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg3, long arg4, long arg5, long* syscall_return_value) { long* syscall_return_value) { // --- START OF REVISED FIX for hook_guard_wrapper --- pthread_once(&key_once_control, make_key); // Ensure the key is created if (pthread_getspecific(reentrance_guard_key) != NULL) { // If the guard is set, forward the syscall to the kernel and return. return gkfs::syscall::forward_to_kernel; } // Set the guard to a non-NULL value. pthread_setspecific(reentrance_guard_key, (void*) 1); // --- END OF REVISED FIX for hook_guard_wrapper --- assert(CTX->interception_enabled()); assert(CTX->interception_enabled()); #ifdef SYS_socketcall #ifdef SYS_socketcall Loading @@ -1132,19 +1163,11 @@ hook_guard_wrapper(long syscall_number, long arg0, long arg1, long arg2, int was_hooked = 0; int was_hooked = 0; if(reentrance_guard_flag) { was_hooked = hook_internal(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, syscall_return_value); return was_hooked; } reentrance_guard_flag = true; was_hooked = ::hook(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, was_hooked = ::hook(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, syscall_return_value); syscall_return_value); reentrance_guard_flag = false; // Unset the guard before returning pthread_setspecific(reentrance_guard_key, NULL); return was_hooked; return was_hooked; } } Loading Loading
src/client/intercept.cpp +48 −25 Original line number Original line Diff line number Diff line Loading @@ -36,7 +36,7 @@ SPDX-License-Identifier: LGPL-3.0-or-later SPDX-License-Identifier: LGPL-3.0-or-later */ */ #include <pthread.h> #include <client/intercept.hpp> #include <client/intercept.hpp> #include <client/preload.hpp> #include <client/preload.hpp> #include <client/hooks.hpp> #include <client/hooks.hpp> Loading Loading @@ -74,7 +74,13 @@ void (*intercept_hook_point_post_kernel)(long syscall_number, long arg0, #endif #endif namespace { namespace { thread_local bool reentrance_guard_flag; static pthread_key_t reentrance_guard_key; static pthread_once_t key_once_control = PTHREAD_ONCE_INIT; static void make_key() { // This function will be called exactly once per process. pthread_key_create(&reentrance_guard_key, NULL); } thread_local gkfs::syscall::info saved_syscall_info; thread_local gkfs::syscall::info saved_syscall_info; constexpr void constexpr void Loading Loading @@ -533,7 +539,8 @@ hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, case SYS_execve: case SYS_execve: // If we do not set this to false, we are in trouble with vforks // If we do not set this to false, we are in trouble with vforks reentrance_guard_flag = false; pthread_once(&key_once_control, make_key); pthread_setspecific(reentrance_guard_key, NULL); *result = syscall_no_intercept_wrapper( *result = syscall_no_intercept_wrapper( syscall_number, reinterpret_cast<const char*>(arg0), syscall_number, reinterpret_cast<const char*>(arg0), reinterpret_cast<const char* const*>(arg1), reinterpret_cast<const char* const*>(arg1), Loading @@ -543,7 +550,8 @@ hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, #ifdef SYS_execveat #ifdef SYS_execveat case SYS_execveat: case SYS_execveat: // If we do not set this to false, we are in trouble with vforks // If we do not set this to false, we are in trouble with vforks reentrance_guard_flag = false; pthread_once(&key_once_control, make_key); pthread_setspecific(reentrance_guard_key, NULL); *result = syscall_no_intercept_wrapper( *result = syscall_no_intercept_wrapper( syscall_number, arg0, reinterpret_cast<const char*>(arg1), syscall_number, arg0, reinterpret_cast<const char*>(arg1), reinterpret_cast<const char* const*>(arg2), reinterpret_cast<const char* const*>(arg2), Loading Loading @@ -1011,12 +1019,19 @@ socketcall_wrapper(long syscall_number, long& arg0, long& arg1, long& arg2, } } #endif #endif void void hook_forwarded_syscall(long syscall_number, long arg0, long arg1, long arg2, hook_forwarded_syscall(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long result) { long arg3, long arg4, long arg5, long result) { pthread_once(&key_once_control, make_key); if (pthread_getspecific(reentrance_guard_key) != NULL) { return; } pthread_setspecific(reentrance_guard_key, (void*) 1); if(::get_current_syscall_info() == gkfs::syscall::no_info) { if(::get_current_syscall_info() == gkfs::syscall::no_info) { pthread_setspecific(reentrance_guard_key, NULL); return; return; } } Loading @@ -1029,6 +1044,8 @@ hook_forwarded_syscall(long syscall_number, long arg0, long arg1, long arg2, syscall_number, args, result); syscall_number, args, result); ::reset_current_syscall_info(); ::reset_current_syscall_info(); pthread_setspecific(reentrance_guard_key, NULL); } } void void Loading @@ -1042,12 +1059,13 @@ hook_clone_at_child(unsigned long flags, void* child_stack, int* ptid, static_cast<long>(newtls), 0}; static_cast<long>(newtls), 0}; #endif #endif reentrance_guard_flag = true; pthread_once(&key_once_control, make_key); pthread_setspecific(reentrance_guard_key, (void*) 1); LOG(SYSCALL, ::get_current_syscall_info() | gkfs::syscall::executed, LOG(SYSCALL, ::get_current_syscall_info() | gkfs::syscall::executed, SYS_clone, args, 0); SYS_clone, args, 0); reentrance_guard_flag = false; pthread_setspecific(reentrance_guard_key, NULL); } } void void Loading @@ -1061,18 +1079,20 @@ hook_clone_at_parent(unsigned long flags, void* child_stack, int* ptid, static_cast<long>(newtls), 0}; static_cast<long>(newtls), 0}; #endif #endif reentrance_guard_flag = true; pthread_once(&key_once_control, make_key); pthread_setspecific(reentrance_guard_key, (void*) 1); LOG(SYSCALL, ::get_current_syscall_info() | gkfs::syscall::executed, LOG(SYSCALL, ::get_current_syscall_info() | gkfs::syscall::executed, SYS_clone, args, returned_pid); SYS_clone, args, returned_pid); reentrance_guard_flag = false; pthread_setspecific(reentrance_guard_key, NULL); } } } // namespace } // namespace namespace gkfs::preload { namespace gkfs::preload { // This function is inside 'namespace gkfs::preload' int int internal_hook_guard_wrapper(long syscall_number, long arg0, long arg1, internal_hook_guard_wrapper(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg2, long arg3, long arg4, long arg5, Loading @@ -1085,7 +1105,8 @@ internal_hook_guard_wrapper(long syscall_number, long arg0, long arg1, arg3, arg4, arg5); arg3, arg4, arg5); #endif #endif if(reentrance_guard_flag) { pthread_once(&key_once_control, make_key); if (pthread_getspecific(reentrance_guard_key) != NULL) { ::save_current_syscall_info(gkfs::syscall::from_internal_code | ::save_current_syscall_info(gkfs::syscall::from_internal_code | gkfs::syscall::to_kernel | gkfs::syscall::to_kernel | gkfs::syscall::not_executed); gkfs::syscall::not_executed); Loading @@ -1094,15 +1115,14 @@ internal_hook_guard_wrapper(long syscall_number, long arg0, long arg1, int was_hooked = 0; int was_hooked = 0; reentrance_guard_flag = true; pthread_setspecific(reentrance_guard_key, (void*) 1); was_hooked = hook_internal(syscall_number, arg0, arg1, arg2, arg3, arg4, was_hooked = hook_internal(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, syscall_return_value); arg5, syscall_return_value); reentrance_guard_flag = false; pthread_setspecific(reentrance_guard_key, NULL); return was_hooked; return was_hooked; } } /* /* * hook_guard_wrapper -- a wrapper which can notice reentrance. * hook_guard_wrapper -- a wrapper which can notice reentrance. * * Loading @@ -1122,6 +1142,17 @@ hook_guard_wrapper(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg3, long arg4, long arg5, long* syscall_return_value) { long* syscall_return_value) { // --- START OF REVISED FIX for hook_guard_wrapper --- pthread_once(&key_once_control, make_key); // Ensure the key is created if (pthread_getspecific(reentrance_guard_key) != NULL) { // If the guard is set, forward the syscall to the kernel and return. return gkfs::syscall::forward_to_kernel; } // Set the guard to a non-NULL value. pthread_setspecific(reentrance_guard_key, (void*) 1); // --- END OF REVISED FIX for hook_guard_wrapper --- assert(CTX->interception_enabled()); assert(CTX->interception_enabled()); #ifdef SYS_socketcall #ifdef SYS_socketcall Loading @@ -1132,19 +1163,11 @@ hook_guard_wrapper(long syscall_number, long arg0, long arg1, long arg2, int was_hooked = 0; int was_hooked = 0; if(reentrance_guard_flag) { was_hooked = hook_internal(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, syscall_return_value); return was_hooked; } reentrance_guard_flag = true; was_hooked = ::hook(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, was_hooked = ::hook(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, syscall_return_value); syscall_return_value); reentrance_guard_flag = false; // Unset the guard before returning pthread_setspecific(reentrance_guard_key, NULL); return was_hooked; return was_hooked; } } Loading