模拟hook openat 系统调用,hook能够成功,但是调用原函数返回失败。主要错误码 -14/* Bad address /、-22/ Invalid argument */,有没有大神帮忙看看。
日志如下:

系统环境
root@jc-kvmvirtualmachine:~# cat /etc/kylin-build
Kylin-Desktop V10-SP1
Build 20220513
buildid: 31950
root@jc-kvmvirtualmachine:src# uname -a
Linux jc-kvmvirtualmachine 5.4.18-53-generic #42-KYLINOS SMP Fri Mar 4 06:09:02 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux
系统架构
root@jc-kvmvirtualmachine:~# lscpu
架构: aarch64
CPU 运行模式: 64-bit
字节序: Little Endian
CPU: 4
在线 CPU 列表: 0-3
每个核的线程数: 1
每个座的核数: 4
座: 1
NUMA 节点: 1
厂商 ID: 0x70
型号: 3
型号名称: Phytium,FT-2000/4
步进: 0x1
CPU 最大 MHz: 2100.0000
CPU 最小 MHz: 2100.0000
BogoMIPS: 100.00
NUMA 节点0 CPU: 0-3
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Vulnerable
Vulnerability Spec store bypass: Vulnerable
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Vulnerable
Vulnerability Tsx async abort: Not affected
标记: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
测试代码
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
#include <asm/ptrace.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ccc");
MODULE_VERSION("1.0");
void (*update_mapping_prot)(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot);
static unsigned long start_rodata = 0, end_rodata = 0;
void* sys_call_table_ptr[__NR_syscalls] = {0};
// 保存原始的openat函数指针
asmlinkage long (*orig_openat_func)(const struct pt_regs *) = NULL;
asmlinkage long my_stub_openat(const struct pt_regs *regs)
{
long fd = -1;
printk(KERN_INFO "=== HOOK OPENAT DEBUG START ===\n");
// 检查原始函数指针是否有效
if(!orig_openat_func){
printk(KERN_ERR "hook: orig_openat_func is NULL!\n");
return -ENOSYS;
}
printk(KERN_INFO "hook openat: calling original func %lx\n", (unsigned long)orig_openat_func);
fd = orig_openat_func(regs);
printk(KERN_INFO "hook openat: original func returned fd=%ld\n", fd);
printk(KERN_INFO "=== HOOK OPENAT DEBUG END ===\n");
return fd;
}
void free_new_sys_call_table(void *table) {
if(table){
vfree(table);
}
}
static void init_hook_func(int NR_call, unsigned long func) {
void* orig_table = (void*)kallsyms_lookup_name("sys_call_table");
if(!orig_table) {
printk(KERN_ERR "Failed to find sys_call_table symbol.\n");
return;
}
if(NR_call < 0 || NR_call >= __NR_syscalls) {
printk(KERN_ERR "Invalid syscall number: %d\n", NR_call);
return;
}
*((unsigned long *) (orig_table + (NR_call * sizeof(void *)))) = func;
printk(KERN_INFO "Hooked syscall number %d with function %lx\n", NR_call, func);
}
static int init_global_value(void){
void* orig_table = (void*)kallsyms_lookup_name("sys_call_table");
update_mapping_prot = (void *)kallsyms_lookup_name("update_mapping_prot");
start_rodata = (unsigned long)kallsyms_lookup_name("__start_rodata");
end_rodata= (unsigned long)kallsyms_lookup_name("__end_rodata");
if(!update_mapping_prot || !start_rodata || !end_rodata || !orig_table) {
printk(KERN_ERR "Failed to find required symbols.\n");
return -1;
}
memcpy(sys_call_table_ptr, orig_table, sizeof(void *) * __NR_syscalls);
orig_openat_func = (asmlinkage long (*)(const struct pt_regs *))sys_call_table_ptr[__NR_openat];
printk(KERN_INFO "myhook found symbols: update_mapping_prot: %lx, start_rodata: %lx, end_rodata: %lx, orig_table: %lx\n",
(unsigned long)update_mapping_prot, start_rodata, end_rodata, (unsigned long)orig_table);
printk(KERN_INFO "myhook saved orig_openat_func: %lx\n", (unsigned long)orig_openat_func);
return 0;
}
static void disable_write_protection(void)
{
update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, (end_rodata - start_rodata), PAGE_KERNEL);
return ;
}
static void enable_write_protection(void)
{
update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, (end_rodata - start_rodata), PAGE_KERNEL_RO);
return ;
}
static int __init patch_init(void) {
if(init_global_value() != 0){
printk(KERN_ERR "Failed to initialize global values.\n");
return -ENOSPC;
}
preempt_disable();
disable_write_protection();
init_hook_func(__NR_openat, (unsigned long)my_stub_openat);
enable_write_protection();
preempt_enable();
printk(KERN_INFO "Module loaded successfully.\n");
return 0;
}
static void __exit patch_cleanup(void)
{
preempt_disable();
disable_write_protection();
// 恢复原始的openat系统调用
if(orig_openat_func) {
init_hook_func(__NR_openat, (unsigned long)orig_openat_func);
printk(KERN_INFO "Restored original openat syscall: %lx\n", (unsigned long)orig_openat_func);
}
enable_write_protection();
preempt_enable();
printk(KERN_INFO "Module unloaded successfully.\n");
return ;
}
module_init(patch_init);
module_exit(patch_cleanup);