asmlinkage

说明这是系统调用
它是GCC对C程序的一种扩展, #define asmlinkage __attribute__((regparm(0)))
表示用0个寄存器传递函数参数,这样,所有的函数参数强迫从栈中提取。
这个asmlinkage大都用在系统调用中,系统调用需要在entry.s文件中用汇编语言调用,所以必须要保证它符合C语言的参数传递规则,才能用汇编语言正确调用它。
这也是为何使用asmlinkage的原因吧!这是我的理解。

 

 

有網友來信問到,kernel 裡的 system call 實作函數中(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 的語法。

--jollen

相信大家在看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))),那么调用函数的时候参数不是通过栈传递,而是直接放到寄存器里,被调用函数直接从寄存器取参数。

 

#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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值