From 8550dd66b1cb10469ca235010d5c379f68ea1b8c Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Tue, 19 May 2026 00:34:26 -0400 Subject: [PATCH] fix(driver): read syscall args with unaligned-safe loads --- src/hooks/syscalls_hc.c | 21 +++++++-------------- src/hooks/syscalls_hc.h | 25 +++++++++++++++++++++++++ src/portal/portalcall_fastpath.c | 4 ++-- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/hooks/syscalls_hc.c b/src/hooks/syscalls_hc.c index 7ba5f74..7f8ce52 100644 --- a/src/hooks/syscalls_hc.c +++ b/src/hooks/syscalls_hc.c @@ -192,14 +192,7 @@ static inline void fill_handler(struct syscall_event *args, int argc, const unsi // Copy arguments safely - add proper NULL checks before dereferencing for (i = 0; i < IGLOO_SYSCALL_MAXARGS; i++){ if (i < argc && args_ptrs && args_ptrs[i]) { - // Safely copy argument value - verify valid pointer first - unsigned long arg_ptr = args_ptrs[i]; - if (arg_ptr && !IS_ERR_VALUE(arg_ptr)) { - args->args[i] = *(unsigned long*)arg_ptr; - } else { - args->args[i] = 0; - DBG_PRINTK("IGLOO: Invalid argument pointer at index %d\n", i); - } + args->args[i] = igloo_syscall_arg_value(args_ptrs, i); } else { args->args[i] = 0; // Initialize unused args to 0 } @@ -323,7 +316,7 @@ static inline bool hook_matches_syscall(struct kernel_syscall_hook *hook, if (argc > 0) { struct value_filter *f = &hook->hook.arg_filters[0]; if (f->enabled) { - long arg_val = *(long *)args[0]; + long arg_val = (long)igloo_syscall_arg_value(args, 0); if (f->type == SYSCALLS_HC_FILTER_EXACT) { if (arg_val != f->value) return false; } else { @@ -334,7 +327,7 @@ static inline bool hook_matches_syscall(struct kernel_syscall_hook *hook, if (argc > 1) { struct value_filter *f = &hook->hook.arg_filters[1]; if (f->enabled) { - long arg_val = *(long *)args[1]; + long arg_val = (long)igloo_syscall_arg_value(args, 1); if (f->type == SYSCALLS_HC_FILTER_EXACT) { if (arg_val != f->value) return false; } else { @@ -345,7 +338,7 @@ static inline bool hook_matches_syscall(struct kernel_syscall_hook *hook, if (argc > 2) { struct value_filter *f = &hook->hook.arg_filters[2]; if (f->enabled) { - long arg_val = *(long *)args[2]; + long arg_val = (long)igloo_syscall_arg_value(args, 2); if (f->type == SYSCALLS_HC_FILTER_EXACT) { if (arg_val != f->value) return false; } else { @@ -356,7 +349,7 @@ static inline bool hook_matches_syscall(struct kernel_syscall_hook *hook, if (argc > 3) { struct value_filter *f = &hook->hook.arg_filters[3]; if (f->enabled) { - long arg_val = *(long *)args[3]; + long arg_val = (long)igloo_syscall_arg_value(args, 3); if (f->type == SYSCALLS_HC_FILTER_EXACT) { if (arg_val != f->value) return false; } else { @@ -367,7 +360,7 @@ static inline bool hook_matches_syscall(struct kernel_syscall_hook *hook, if (argc > 4) { struct value_filter *f = &hook->hook.arg_filters[4]; if (f->enabled) { - long arg_val = *(long *)args[4]; + long arg_val = (long)igloo_syscall_arg_value(args, 4); if (f->type == SYSCALLS_HC_FILTER_EXACT) { if (arg_val != f->value) return false; } else { @@ -378,7 +371,7 @@ static inline bool hook_matches_syscall(struct kernel_syscall_hook *hook, if (argc > 5) { struct value_filter *f = &hook->hook.arg_filters[5]; if (f->enabled) { - long arg_val = *(long *)args[5]; + long arg_val = (long)igloo_syscall_arg_value(args, 5); if (f->type == SYSCALLS_HC_FILTER_EXACT) { if (arg_val != f->value) return false; } else { diff --git a/src/hooks/syscalls_hc.h b/src/hooks/syscalls_hc.h index 6e1523e..521c6c4 100644 --- a/src/hooks/syscalls_hc.h +++ b/src/hooks/syscalls_hc.h @@ -5,6 +5,14 @@ #include #include #include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) +#include +#else +#include +#endif #include "igloo_syscall_macros.h" @@ -100,6 +108,23 @@ bool portalcall_fastpath_should_skip(bool is_sendto, int argc, const unsigned long args[]); +static inline unsigned long igloo_syscall_arg_value(const unsigned long args[], + int index) +{ + unsigned long arg_slot; + + if (!args || index < 0 || index >= IGLOO_SYSCALL_MAXARGS) { + return 0; + } + + arg_slot = args[index]; + if (!arg_slot || IS_ERR_VALUE(arg_slot)) { + return 0; + } + + return get_unaligned((unsigned long *)arg_slot); +} + /* Unregister a syscall hook using its pointer */ int unregister_syscall_hook(struct kernel_syscall_hook *hook_ptr); diff --git a/src/portal/portalcall_fastpath.c b/src/portal/portalcall_fastpath.c index fcc6c7b..2623b83 100644 --- a/src/portal/portalcall_fastpath.c +++ b/src/portal/portalcall_fastpath.c @@ -81,12 +81,12 @@ bool portalcall_fastpath_should_skip(bool is_sendto, return false; } - magic = *(unsigned long *)args[0]; + magic = igloo_syscall_arg_value(args, 0); if ((magic & 0xffffffffUL) != PORTALCALL_SYSCALL_MAGIC) { return false; } - user_magic = *(unsigned long *)args[1]; + user_magic = igloo_syscall_arg_value(args, 1); return !portalcall_magic_is_registered((u32)user_magic); } EXPORT_SYMBOL(portalcall_fastpath_should_skip);