asmlinkage

本文详细解释了asmlinkage宏在Linux源代码中的作用,它用于指示函数不应从寄存器接收参数,而应从堆栈接收参数。文章深入探讨了asmlinkage宏的定义、用法及其在不同场景下的应用,如system_call函数和sys_nice函数。此外,还介绍了80x86架构下传递参数的两种方法:寄存器方法和堆栈方法,以及asmlinkage宏如何确保系统调用遵循堆栈参数传递模式。

什么是 "asmlinkage"?


相信大家在看linux的source code的时候,都会注意到asmlinkage这个宏,它是用来做什么的呢?

The asmlinkage tag is one other thing that we should observe about this simple function. This is a #define for some gcc magic that tells the compiler that the function should

not expect to find any of its arguments in registers (a common optimization), but only on the CPU's stack. Recall our earlier assertion that system_call consumes its first

argument, the system call number, and allows up to four more arguments that are passed along to the real system call. system_call achieves this feat simply by leaving its

other arguments (which were passed to it in registers) on the stack. All system calls are marked with the asmlinkage tag, so they all look to the stack for arguments. Of

course, in sys_ni_syscall's case, this doesn't make any difference, because sys_ni_syscall doesn't take any arguments, but it's an issue for most other system calls.

看一下/usr/include/asm/linkage.h里面的定义:
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
__attribute__是关键字,是gcc的C语言扩展,regparm(0)表示不从寄存器传递参数

如果是__attribute__((regparm(3))),那么调用函数的时候参数不是通过栈传递,而是直接放到寄存器里,被调用函数直接从寄存器取参数

还有一种是:

#define fastcall __attribute__((regparm(3)))
#define asmlinkage __attribute__((regparm(0)))
函数定义前加宏asmlinkage ,表示这些函数通过堆栈而不是通过寄存器传递参数。
gcc编译器在汇编过程中调用c语言函数时传递参数有两种方法:一种是通过堆栈,另一种是通过寄存器。缺省时采用寄存器,假如你要在你的汇编过程中调用c语言函数,并且想通过堆栈传递参数,你定义的c函数时要在函数前加上宏asmlinkage

asmlinkage long sys_nice(int increment)
"asmlinkage" 是在 i386 system call 实作中相当重要的一个 gcc 标签(tag)。
当 system call handler 要调用相对应的 system call routine 时,便将一般用途缓存器的值 push 到 stack 里,因此 system call routine 就要由 stack 来读取 system call handler 传递的

参数。这就是 asmlinkage 标签的用意。
system call handler 是 assembly code,system call routine(例如:sys_nice)是 C code,当 assembly code 调用 C function,并且是以 stack 方式传参数(parameter)时,在 C

function 的 prototype 前面就要加上 "asmlinkage"。
加上 "asmlinkage" 后,C function 就会由 stack 取参数,而不是从 register 取参数(可能发生在程序代码最佳化后)。
更进一步的说明...
80x86 的 assembly 有 2 种传递参数的方法:
1. register method
2. stack method
Register method 大多使用一般用途(general-purpose)缓存器来传递参数,这种方法的好处是简单且快速。另外一种传递参数的做法是使用 stack(堆栈),assembly code 的模式如下:
push number1
push number2
push number3
call sum
在 'sum' procedure 里取值的方法,最简单的做法是:
pop ax
pop ax
pop bx
pop cx
Stack Top 是放 IP,我们传给 sum procedure 的参数由 stack 的后一个 entry 开始读取。
其它有关 asmlinkage
1. asmlinkage 是一个定义
2. "asmlinkage" 被定义在 /usr/include/linux/linkage.h
3. 如果您看了 linkage.h,会发现 "__attribute__" 这个语法,这是 gcc 用来定义 function attribute 的语法

#include "sc_hook.h" #include <linux/kthread.h> MODULE_AUTHOR("xfliu"); MODULE_DESCRIPTION("Syscall hook"); MODULE_VERSION("0.01"); static sys_call_ptr_t* sys_call_table; sys_call_ptr_t old_sys_table[MAX_SC_IDX]; int hook_sys_table[sc_end_type]; char hook_sys_name[sc_end_type][16]; atomic_t sc_ref_table[sc_end_type]; char* cur_module = NULL; #define SC_FUNC_PART #ifdef SC_FUNC_PART int num=0; static struct task_struct *kthread = NULL; //此逻辑与架构无关 static int sc_hook_process(int sc_map_idx, int sc_table_idx, const char* file_name) { int name_len = 0; int ret = 0; if (!task_ctx) { return 0; } if (file_name) { SC_DEBUG(sc_debug, KERN_INFO "open file :%s\n", file_name); if (IsFileIgnore(file_name)) { return 0; } name_len = strlen(task_ctx->sc_task[sc_table_idx].filename); // no file_name : hook action if (0 == name_len) ret = 0; // have file_name name but current name not equals file_name : pass else if (0 != strcmp(file_name, task_ctx->sc_task[sc_table_idx].filename)) ret = 1; // have file_name name and current name not equals file_name : hook // actions else ret = 0; } if (1 == ret) return 0; // check fault rate and decide whether hook action or not if (task_ctx->sc_task[sc_table_idx].sc_para[sc_map_idx].drop_rate > 0) { ret = process_drop(&task_ctx->sc_task[sc_table_idx].sc_para[sc_map_idx]); if (NF_ACCEPT == ret) { SC_DEBUG(sc_debug, KERN_INFO "systemcall miss this time:%d\n", sc_table_idx); return 0; } } else { SC_DEBUG(sc_debug, KERN_INFO "systemcall null:%d\n", sc_table_idx); return 0; } SC_DEBUG( sc_debug, KERN_INFO "systemcall match this time:%d\n", sc_table_idx); if (task_ctx->sc_task[sc_table_idx].sc_para[sc_map_idx].err_code) { SC_DEBUG(sc_debug, KERN_INFO "systemcall err_code[%d]:%d\n", task_ctx->sc_task[sc_table_idx].sc_para[sc_map_idx].err_code, sc_table_idx); return -task_ctx->sc_task[sc_table_idx].sc_para[sc_map_idx].err_code; } if (task_ctx->sc_task[sc_table_idx].sc_para[sc_map_idx].delay_time) { SC_DEBUG(sc_debug, KERN_INFO "systemcall sleep[%d]:%d\n", task_ctx->sc_task[sc_table_idx].sc_para[sc_map_idx].delay_time, sc_table_idx); msleep(task_ctx->sc_task[sc_table_idx].sc_para[sc_map_idx].delay_time); } SC_DEBUG(sc_debug, KERN_INFO "systemcall do nothing:%d\n", sc_table_idx); return 0; } # ifdef PTREGS_SYSCALL_STUBS static long ref_sys_process(const struct pt_regs* regs, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = (old_sys_table[sc_idx])(regs); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_open(const struct pt_regs* regs) { char filetemp[256] = {0}; if (copy_from_user(filetemp, (char*)regs->regs[1], sizeof(filetemp))) { return ref_sys_process(regs, __NR_openat, sc_open_type); } int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_openat, sc_open_type); //__NR_open ret = check_if_hook(sc_open_type); if (ret < 0) return ref_sys_process(regs, __NR_openat, sc_open_type); return sc_hook_process(sc_open_type, ret, filetemp); } static asmlinkage long hook_write(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_write, sc_write_type); ret = check_if_hook(sc_write_type); if (ret < 0) return ref_sys_process(regs, __NR_write, sc_write_type); return sc_hook_process(sc_write_type, ret, NULL); } static asmlinkage long hook_read(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_read, sc_read_type); ret = check_if_hook(sc_read_type); if (ret < 0) return ref_sys_process(regs, __NR_read, sc_read_type); return sc_hook_process(sc_read_type, ret, NULL); } static asmlinkage long hook_accept(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_accept, sc_accept_type); ret = check_if_hook(sc_accept_type); if (ret < 0) return ref_sys_process(regs, __NR_accept, sc_accept_type); return sc_hook_process(sc_accept_type, ret, NULL); } static asmlinkage long hook_connect(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_connect, sc_connect_type); ret = check_if_hook(sc_connect_type); if (ret < 0) return ref_sys_process(regs, __NR_connect, sc_connect_type); return sc_hook_process(sc_connect_type, ret, NULL); } static asmlinkage long hook_sendto(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_sendto, sc_send_type); ret = check_if_hook(sc_send_type); if (ret < 0) return ref_sys_process(regs, __NR_sendto, sc_send_type); return sc_hook_process(sc_send_type, ret, NULL); } static asmlinkage long hook_recvfrom(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_recvfrom, sc_recv_type); ret = check_if_hook(sc_recv_type); if (ret < 0) return ref_sys_process(regs, __NR_recvfrom, sc_recv_type); return sc_hook_process(sc_recv_type, ret, NULL); } static asmlinkage long hook_lseek(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_lseek, sc_lseek_type); ret = check_if_hook(sc_lseek_type); if (ret < 0) return ref_sys_process(regs, __NR_lseek, sc_lseek_type); return sc_hook_process(sc_lseek_type, ret, NULL); } static asmlinkage long hook_fsync(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_fsync, sc_fsync_type); ret = check_if_hook(sc_fsync_type); if (ret < 0) return ref_sys_process(regs, __NR_fsync, sc_fsync_type); return sc_hook_process(sc_fsync_type, ret, NULL); } static asmlinkage long hook_socket(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_socket, sc_socket_type); ret = check_if_hook(sc_socket_type); if (ret < 0) return ref_sys_process(regs, __NR_socket, sc_socket_type); return sc_hook_process(sc_socket_type, ret, NULL); } static long asmlinkage hook_bind(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_bind, sc_bind_type); ret = check_if_hook(sc_bind_type); if (ret < 0) return ref_sys_process(regs, __NR_bind, sc_bind_type); return sc_hook_process(sc_bind_type, ret, NULL); } static asmlinkage long hook_listen(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_listen, sc_listen_type); ret = check_if_hook(sc_listen_type); if (ret < 0) return ref_sys_process(regs, __NR_listen, sc_listen_type); return sc_hook_process(sc_listen_type, ret, NULL); } static asmlinkage long hook_mount(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_mount, sc_mount_type); ret = check_if_hook(sc_mount_type); if (ret < 0) return ref_sys_process(regs, __NR_mount, sc_mount_type); return sc_hook_process(sc_mount_type, ret, NULL); } static asmlinkage long hook_umount(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_umount2, sc_umount2_type); ret = check_if_hook(sc_umount2_type); if (ret < 0) return ref_sys_process(regs, __NR_umount2, sc_umount2_type); return sc_hook_process(sc_umount2_type, ret, NULL); } static asmlinkage long hook_ioctl(const struct pt_regs* regs) { int ret = 0; if (!task_ctx) return ref_sys_process(regs, __NR_ioctl, sc_ioctl_type); ret = check_if_hook(sc_ioctl_type); if (ret < 0) return ref_sys_process(regs, __NR_ioctl, sc_ioctl_type); return sc_hook_process(sc_ioctl_type, ret, NULL); } # else typedef long (*open_sys)(const char __user* filename, int flags, int mode); static long ref_open_process(const char __user* filename, int flags, int mode, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((open_sys) old_sys_table[sc_idx])(filename, flags, mode); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_open(const char __user* filename, int flags, int mode) { char filetemp[256] = {0}; int ret = 0; if (copy_from_user(filetemp, filename, sizeof(filetemp))) { return ref_open_process(filename, flags, mode, __NR_open, sc_open_type); } if (!task_ctx) return ref_open_process(filename, flags, mode, __NR_open, sc_open_type); ret = check_if_hook(sc_open_type); if (ret < 0) return ref_open_process(filename, flags, mode, __NR_open, sc_open_type); return sc_hook_process(sc_open_type, ret, filetemp); } typedef long (*fs_sys)(unsigned int fd, const char __user* buf, size_t count); static long ref_fs_process(unsigned int fd, const char __user* buf, size_t count, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((fs_sys) old_sys_table[sc_idx])(fd, buf, count); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_read(unsigned int fd, char __user* buf, size_t count) { int ret = 0; if (!task_ctx) return ref_fs_process(fd, buf, count, __NR_read, sc_read_type); ret = check_if_hook(sc_read_type); if (ret < 0) return ref_fs_process(fd, buf, count, __NR_read, sc_read_type); return sc_hook_process(sc_read_type, ret, NULL); } static asmlinkage long hook_write(unsigned int fd, const char __user* buf, size_t count) { int ret = 0; if (!task_ctx || fd <= 2) return ref_fs_process(fd, buf, count, __NR_write, sc_write_type); ret = check_if_hook(sc_write_type); if (ret < 0) return ref_fs_process(fd, buf, count, __NR_write, sc_write_type); return sc_hook_process(sc_write_type, ret, NULL); } typedef long (*socket_sys)(int family, int type, int protocol); static long ref_socket_process(int family, int type, int protocol, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((socket_sys) old_sys_table[sc_idx])(family, type, protocol); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_socket(int family, int type, int protocol) { int ret = 0; if (!task_ctx) return ref_socket_process(family, type, protocol, __NR_socket, sc_socket_type); ret = check_if_hook(sc_socket_type); if (ret < 0) return ref_socket_process(family, type, protocol, __NR_socket, sc_socket_type); return sc_hook_process(sc_socket_type, ret, NULL); } typedef long (*bind_sys)(int fd, struct sockaddr __user *umyaddr, int addrlen); static long ref_bind_process(int fd, struct sockaddr __user *umyaddr, int addrlen, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((bind_sys) old_sys_table[sc_idx])(fd, umyaddr, addrlen); atomic_dec(&sc_ref_table[sc_type]); return ret; } static long asmlinkage hook_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) { int ret = 0; if (!task_ctx) return ref_bind_process(fd, umyaddr, addrlen, __NR_bind, sc_bind_type); ret = check_if_hook(sc_bind_type); if (ret < 0) return ref_bind_process(fd, umyaddr, addrlen, __NR_bind, sc_bind_type); return sc_hook_process(sc_bind_type, ret, NULL); } typedef long (*listen_sys)(int fd, int backlog); static long ref_listen_process(int fd, int backlog, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((listen_sys) old_sys_table[sc_idx])(fd, backlog); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_listen(int fd, int backlog) { int ret = 0; if (!task_ctx) return ref_listen_process(fd, backlog, __NR_listen, sc_listen_type); ret = check_if_hook(sc_listen_type); if (ret < 0) return ref_listen_process(fd, backlog, __NR_listen, sc_listen_type); return sc_hook_process(sc_listen_type, ret, NULL); } typedef long (*netp_sys)(int, struct sockaddr __user*, int __user*); static long ref_netp_process(int fd, struct sockaddr __user* user, int __user* id, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((netp_sys) old_sys_table[sc_idx])(fd, user, id); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_accept(int fd, struct sockaddr __user* user, int __user* id) { int ret = 0; if (!task_ctx) return ref_netp_process(fd, user, id, __NR_accept, sc_accept_type); ret = check_if_hook(sc_accept_type); if (ret < 0) return ref_netp_process(fd, user, id, __NR_accept, sc_accept_type); return sc_hook_process(sc_accept_type, ret, NULL); } typedef long (*neti_sys)(int, struct sockaddr __user*, int); static long ref_neti_process(int fd, struct sockaddr __user* user, int id, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((neti_sys) old_sys_table[sc_idx])(fd, user, id); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_connect(int fd, struct sockaddr __user* user, int id) { int ret = 0; if (!task_ctx) return ref_neti_process(fd, user, id, __NR_connect, sc_connect_type); ret = check_if_hook(sc_connect_type); if (ret < 0) return ref_neti_process(fd, user, id, __NR_connect, sc_connect_type); return sc_hook_process(sc_connect_type, ret, NULL); } typedef long (*netli_sys)(int, void __user*, size_t, unsigned, struct sockaddr __user*, int); static long ref_netli_process(int fd, void __user* user, size_t len, unsigned id, struct sockaddr __user* addr, int l_len, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((netli_sys) old_sys_table[sc_idx])(fd, user, len, id, addr, l_len); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_sendto(int fd, void __user* user, size_t len, unsigned id, struct sockaddr __user* addr, int l_len) { int ret = 0; if (!task_ctx) return ref_netli_process(fd, user, len, id, addr, l_len, __NR_sendto, sc_send_type); ret = check_if_hook(sc_send_type); if (ret < 0) return ref_netli_process(fd, user, len, id, addr, l_len, __NR_sendto, sc_send_type); return sc_hook_process(sc_send_type, ret, NULL); } typedef long (*netlp_sys)(int, void __user*, size_t, unsigned, struct sockaddr __user*, int __user*); static long ref_netlp_process(int fd, void __user* user, size_t len, unsigned id, struct sockaddr __user* addr, int __user* l_len, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((netlp_sys) old_sys_table[sc_idx])(fd, user, len, id, addr, l_len); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_recvfrom(int fd, void __user* user, size_t len, unsigned id, struct sockaddr __user* addr, int __user* l_len) { int ret = 0; if (!task_ctx) return ref_netlp_process(fd, user, len, id, addr, l_len, __NR_recvfrom, sc_recv_type); ret = check_if_hook(sc_recv_type); if (ret < 0) return ref_netlp_process(fd, user, len, id, addr, l_len, __NR_recvfrom, sc_recv_type); return sc_hook_process(sc_recv_type, ret, NULL); } typedef long (*mount_sys)(char __user *dev_name, char __user *dir_name, char __user *type, unsigned long flags, void __user *data); static long ref_mount_process(char __user *dev_name, char __user *dir_name, char __user *type, unsigned long flags, void __user *data, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((mount_sys) old_sys_table[sc_idx])(dev_name, dir_name, type, flags, data); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_mount(char __user *dev_name, char __user *dir_name, char __user *type, unsigned long flags, void __user *data) { int ret = 0; if (!task_ctx) return ref_mount_process(dev_name, dir_name, type, flags, data, __NR_mount, sc_mount_type); ret = check_if_hook(sc_mount_type); if (ret < 0) return ref_mount_process(dev_name, dir_name, type, flags, data, __NR_mount, sc_mount_type); return sc_hook_process(sc_mount_type, ret, NULL); } typedef long (*umount_sys)(char __user *name, int flags); static long ref_umount_process(char __user *name, int flags, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((umount_sys) old_sys_table[sc_idx])(name, flags); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_umount(char __user *name, int flags) { int ret = 0; if (!task_ctx) return ref_umount_process(name, flags, __NR_umount2, sc_umount2_type); ret = check_if_hook(sc_umount2_type); if (ret < 0) return ref_umount_process(name, flags, __NR_umount2, sc_umount2_type); return sc_hook_process(sc_umount2_type, ret, NULL); } typedef long (*ioctl_sys)(unsigned int fd, unsigned int cmd, unsigned long arg); static long ref_ioctl_process(unsigned int fd, unsigned int cmd, unsigned long arg, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((ioctl_sys) old_sys_table[sc_idx])(fd, cmd, arg); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { int ret = 0; if (!task_ctx) return ref_ioctl_process(fd, cmd, arg, __NR_ioctl, sc_ioctl_type); ret = check_if_hook(sc_ioctl_type); if (ret < 0) return ref_ioctl_process(fd, cmd, arg, __NR_ioctl, sc_ioctl_type); return sc_hook_process(sc_ioctl_type, ret, NULL); } typedef long (*lseek_sys)(unsigned int fd, off_t offset, unsigned int whence); static long ref_lseek_process(unsigned int fd, off_t offset, unsigned int whence, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((lseek_sys) old_sys_table[sc_idx])(fd, offset, whence); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_lseek(unsigned int fd, off_t offset, unsigned int whence) { int ret = 0; if (!task_ctx) return ref_lseek_process(fd, offset, whence, __NR_lseek, sc_lseek_type); ret = check_if_hook(sc_lseek_type); if (ret < 0) return ref_lseek_process(fd, offset, whence, __NR_lseek, sc_lseek_type); return sc_hook_process(sc_lseek_type, ret, NULL); } typedef long (*fsync_sys)(unsigned int fd); static long ref_fsync_process(unsigned int fd, int sc_idx, int sc_type) { int ret = 0; atomic_inc(&sc_ref_table[sc_type]); ret = ((fsync_sys) old_sys_table[sc_idx])(fd); atomic_dec(&sc_ref_table[sc_type]); return ret; } static asmlinkage long hook_fsync(unsigned int fd) { int ret = 0; if (!task_ctx) return ref_fsync_process(fd, __NR_fsync, sc_fsync_type); ret = check_if_hook(sc_fsync_type); if (ret < 0) return ref_fsync_process(fd, __NR_fsync, sc_fsync_type); return sc_hook_process(sc_fsync_type, ret, NULL); } # endif // end for PTREGS_SYSCALL_STUBS #endif // end for SC_FUNC_PART #define LOCAL_FUNC #ifdef LOCAL_FUNC #if 1 //初版 static int sysm_info_mgr(sys_call_ptr_t hook_fn, int sc_idx, int sc_type) { hook_sys_table[sc_type] = sc_idx; printk("sysm_info_mgr sc_type:%d,index:%d \n", sc_type, sc_idx); strcpy(hook_sys_name[sc_type], cur_module); old_sys_table[sc_idx] = sys_call_table[sc_idx]; printk("sysm_info_mgr sc_type,index999999999999999999\n"); printk("准备读写入内核操作\n"); disable_write_protect(); sys_call_table[sc_idx] = hook_fn; enable_write_protect(); printk("准备读写入内核操作完成9999999\n"); return 0; } #endif #if 0 //初版 static void release_sc(void) { int i = 0; int timer = 0; bool bFInd = true; long long timecount = 0; disable_write_protect(); for (; i < sc_end_type; i++) { sys_call_table[hook_sys_table[i]] = old_sys_table[hook_sys_table[i]]; printk("system-call:%dindex:%d \n", i, hook_sys_table[i]); } enable_write_protect(); /* unload system-call is tough trouble, i will explain it for you as the * followings as we all know, system-call may in a blocked state. * something horrible may happen when we do release_sc while a process * stuck in a blocked state by system-call. cus the code segment was * freed once we rmmod the ko. however, when blocked systerm-call wake * up, it returns to the disappreared code segment. and this case may * panic kernel. * * to prevent this happen, i have tryed a lot ways but not found a * perfect one till now. a sc-reference protected by lock may work, but * i give it up for the perfomance, use a atomic value instead! anyway, * this is a dangerous function. remember to FIXME when you got an * better idea */ while (1) { //如果某个系统调用被频繁使用,引用计数可能永远不会降为0,导致无限等待,会不会出现这种情况呢。 // every 1s tells users that where we stuck in if (timer / 1000 >= 1) { timer = 0; for (i = 0; i < sc_end_type; i++) { if (atomic_read(&sc_ref_table[i]) > 0) { bFInd = false; printk("system-call:%s is in use(%d) now, wait it to " "exit\n", hook_sys_name[i], atomic_read(&sc_ref_table[i])); } } if (bFInd) { printk("module-sc-%s removed.\n", hook_sys_name[i]); break; } } msleep(ms_nap); timer += ms_nap; timecount += ms_nap; if (timecount > 10 * 1000) { printk("module-sc-%s removed.\n", hook_sys_name[i]); break; } } } #endif #if 1 //rmmod卸载问题修改 static void release_sc(void) { int i = 0; int wait_count = 0; const int MAX_WAIT = 300; // 最大等待30秒 (300 * 100ms) // 1. 首先解除所有钩子 disable_write_protect(); for (i = 0; i < sc_end_type; i++) { if (hook_sys_table[i] > 0) { sys_call_table[hook_sys_table[i]] = old_sys_table[hook_sys_table[i]]; printk("unhook system-call:%d, index:%d\n", i, hook_sys_table[i]); } } enable_write_protect(); // 2. 等待引用计数归零,但有超时机制 for (wait_count = 0; wait_count < MAX_WAIT; wait_count++) { bool all_zero = true; for (i = 0; i < sc_end_type; i++) { int ref_count = atomic_read(&sc_ref_table[i]); if (ref_count > 0) { all_zero = false; if (wait_count % 10 == 0) { // 每1秒打印一次 printk("waiting for %s, refcount: %d\n", hook_sys_name[i], ref_count); } break; } } if (all_zero) { printk("all system calls released successfully\n"); break; } msleep(100); // 等待100ms } if (wait_count >= MAX_WAIT) { printk("warning: forced unload after timeout, some syscalls may still be in use\n"); } // 3. 清理状态 for (i = 0; i < sc_end_type; i++) { hook_sys_table[i] = 0; hook_sys_name[i][0] = '\0'; } } #endif #endif #if 1 //初版 //挂钩子崩溃 static int sc_reg(void) { int i = 0; int ret = 0; for (; i < sc_end_type; i++) { atomic_set(&sc_ref_table[i], 0); } // hook open cur_module = "open"; # ifdef PTREGS_SYSCALL_STUBS ret = sysm_info_mgr(hook_open, __NR_openat, sc_open_type); # else ret = sysm_info_mgr((sys_call_ptr_t) hook_open, __NR_open, sc_open_type); # endif if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_open_type]); } // hook read cur_module = "read"; ret = sysm_info_mgr((sys_call_ptr_t) hook_read, __NR_read, sc_read_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_read_type]); } // hook write cur_module = "write"; ret = sysm_info_mgr((sys_call_ptr_t) hook_write, __NR_write, sc_write_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_write_type]); } // hook lseek cur_module = "hook_lseek"; ret = sysm_info_mgr((sys_call_ptr_t) hook_lseek, __NR_lseek, sc_lseek_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_lseek_type]); } // hook fsync cur_module = "hook_fsync"; ret = sysm_info_mgr((sys_call_ptr_t) hook_fsync, __NR_fsync, sc_fsync_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_fsync_type]); } // hook socket cur_module = "socket"; ret = sysm_info_mgr((sys_call_ptr_t) hook_socket, __NR_socket, sc_socket_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_socket_type]); } //hook bind cur_module = "bind"; ret = sysm_info_mgr((sys_call_ptr_t) hook_bind, __NR_bind, sc_bind_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_bind_type]); } //hook listen cur_module = "listen"; ret = sysm_info_mgr((sys_call_ptr_t) hook_listen, __NR_listen, sc_listen_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_listen_type]); } // hook accept cur_module = "accept"; ret = sysm_info_mgr( (sys_call_ptr_t) hook_accept, __NR_accept, sc_accept_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_accept_type]); } // hook connect cur_module = "connect"; ret = sysm_info_mgr((sys_call_ptr_t) hook_connect, __NR_connect, sc_connect_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_connect_type]); } // hook send/sendto cur_module = "sendto-send"; ret = sysm_info_mgr((sys_call_ptr_t) hook_sendto, __NR_sendto, sc_send_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_send_type]); } // hook recv/recvfrom cur_module = "recvfrom-recv"; ret = sysm_info_mgr( (sys_call_ptr_t) hook_recvfrom, __NR_recvfrom, sc_recv_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_recv_type]); } // hook mount cur_module = "mount"; ret = sysm_info_mgr((sys_call_ptr_t) hook_mount, __NR_mount, sc_mount_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_mount_type]); } // hook umount cur_module = "umount"; ret = sysm_info_mgr((sys_call_ptr_t) hook_umount, __NR_umount2, sc_umount2_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_umount2_type]); } // hook ioctl cur_module = "hook_ioctl"; ret = sysm_info_mgr((sys_call_ptr_t) hook_ioctl, __NR_ioctl, sc_ioctl_type); if (0 != ret) { printk("ERROR: hook %s failed\n", cur_module); return 1; } else { printk("module-sc-%s inserted.\n", hook_sys_name[sc_ioctl_type]); } // FIXME TODO HERE return 0; } #endif static int reader_thread(void *data) { while (!kthread_should_stop()) { // printk(KERN_INFO "test content: %s\n", test); // printk(KERN_INFO "buffer content: %s\n", buffer); printk(KERN_INFO "process: %s\n", task_ctx->sc_task[1].process); printk(KERN_INFO "pid: %s\n", task_ctx->sc_task[1].pid); printk(KERN_INFO "start_time: %d\n", task_ctx->sc_task[1].start_time); msleep(1000); // Sleep for 1 second } return 0; } static int __init scm_init(void) { // get sys_call_table sys_call_table = get_sysm_name();//内核,获取系统调用表 if (!sys_call_table) { printk("%s-%s insert error, no sys_call_table\n", MODULE_NAME, __func__); return 1; } if (0 != sc_reg()) goto release_resource; printk(KERN_INFO "不挂钩子正常获取到了内核table1111111111111111"); // netfiletr mode init if (nf) { if (0 != nf_reg()) { printk("netfilter-%s insert error,失败99999999999, register failed\n", __func__); goto release_resource; } printk("%s-%s inserted with nf,成功999999999999999999999999\n", MODULE_NAME, __func__); } else { printk("%s-%s inserted without nf\n", MODULE_NAME, __func__); } // shm module init if (insert_dev) { // shm_size = sizeof(chaosRunTaskCtlTabInline); printk("shm初始化成功91111111111111111\n"); printk("dev_reg-------------------\n"); if (0 != dev_reg()) { printk("%s-%s insert error, dev register failed\n",MODULE_NAME,__func__); goto release_resource; } printk("%s-%s inserted with dev\n", MODULE_NAME, __func__); } else { printk("%s-%s inserted without dev\n", MODULE_NAME, __func__); } // kthread = kthread_run(reader_thread, NULL, "sc_hook"); printk("task_ctx is %p, shm_size is %d(%lu)-----------------\n", task_ctx, shm_size, sizeof(chaosRunTaskCtlTabInline)); if(task_ctx) { printk("task_ctx init\n"); } else { printk("task_ctx init error\n"); } return 0; release_resource: release_sc(); nf_unreg(); return 1; } #if 0 //初版 static void __exit scm_exit(void) { if (insert_dev) dev_unreg(); printk("release nf\n"); if (nf) nf_unreg(); release_sc(); printk("%s-%s removed.\n", MODULE_NAME, __func__); // wait for a while for safety printk("wait netfilter exit(%dms)\n", NF_TIMEOUT); msleep(NF_TIMEOUT); printk("release shm dev:%s\n", MODULE_NAME); } #endif //rmmod卸载问题 static void __exit scm_exit(void) { printk("starting module unload...\n"); // 2. 释放系统调用钩子 printk("releasing system call hooks...\n"); release_sc(); // 3. 释放netfilter printk("releasing netfilter...\n"); if (nf) nf_unreg(); // 4. 最后释放设备 printk("releasing device...\n"); if (insert_dev) dev_unreg(); printk("%s-%s removed successfully.\n", MODULE_NAME, __func__); } module_init(scm_init); module_exit(scm_exit);在调用钩子函数时disable_write_protect总是崩溃,我想知道在arm架构下的读写还可以怎么实现
最新发布
10-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值