[static FL]part3: type

本文详细介绍了几种基本的数据结构类型,包括pair、tuple、record、list和option类型,并解释了它们的特点及使用方式。
pair type: (e1, e2)
     typing: t1*t2, t1,t2分别是e1和e2的值
     取值:#1, #2
     可以nest,但是只能有两项

tuple type:(e1, e2...)
     类似pair,本质是record
     和record(by name)比,是by position, 顺序是有意义的
     语法糖:其实也是{1= e1, 2 = e2},类型t1*t2... 也是 {1:t1, 2:t2...}, #1的意义也是key的意义

record type: {C1=e1, C2=e2...}
     typing: {C1:t1, C2:t2...}
     each-of type
     通过#C1访问
语法糖:对于each-of type(record, tuple)也能使用case expression
     只有一个分支的case r of ({C1 = x1, C2 = x2}) =>e
     可以进一步在variable binding里加入pattern matching, 写成let val {C1 = x1, C2 = x2} = r in e end
     可以进一步将pattern写在函数参数中。实际上函数只接收一个参数,只是通过语法糖,将这个参数通过pattern matching取得内容
          =>无需提供参数类型信息了,因为已经在pattern中。type checker会根据xi的用法推断出类型,对于没有推断出的类型使用多态类型'a 'b 'c表示
     无参函数实际上是对传入的unit值()进行匹配

list type:[e1, e2...]
     typing: 必须类型都是t,表示为t list
     []:空列表,type是任何值的列表,表示为'a list(alpha list)
     e1::list: 在列表中加值。1::[] => [1]
     null: 检查是否为空
     hd: head element of list
     tl: tail list of list

option type: None|Some e
     typing:None: 'a option; Some e:t
     isSome: 是否是Some类型
     valOf: 取得e
#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] = &#39;\0&#39;; } } #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
#ifndef _LINUX_MODULE_PARAMS_H #define _LINUX_MODULE_PARAMS_H /* (C) Copyright 2001, 2002 Rusty Russell IBM Corporation */ #include <linux/init.h> #include <linux/stringify.h> #include <linux/kernel.h> /* You can override this manually, but generally this should match the module name. */ #ifdef MODULE #define MODULE_PARAM_PREFIX /* empty */ #else #define MODULE_PARAM_PREFIX KBUILD_MODNAME "." #endif /* Chosen so that structs with an unsigned long line up. */ #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) /* This struct is here for syntactic coherency, it is not used */ #define __MODULE_INFO_DISABLED(name) \ struct __UNIQUE_ID(name) {} #ifdef CONFIG_MODULE_STRIPPED #define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name) #else #define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info) #endif #ifdef MODULE #define __MODULE_INFO(tag, name, info) \ static const char __UNIQUE_ID(name)[] \ __used __attribute__((section(".modinfo"), unused, aligned(1))) \ = __stringify(tag) "=" info #else /* !MODULE */ /* This struct is here for syntactic coherency, it is not used */ #define __MODULE_INFO(tag, name, info) __MODULE_INFO_DISABLED(name) #endif #define __MODULE_PARM_TYPE(name, _type) \ __MODULE_INFO(parmtype, name##type, #name ":" _type) /* One for each parameter, describing how to use it. Some files do multiple of these per line, so can&#39;t just use MODULE_INFO. */ #define MODULE_PARM_DESC(_parm, desc) \ __MODULE_INFO_STRIP(parm, _parm, #_parm ":" desc) struct kernel_param; /* * Flags available for kernel_param_ops * * NOARG - the parameter allows for no argument (foo instead of foo=1) */ enum { KERNEL_PARAM_OPS_FL_NOARG = (1 << 0) }; struct kernel_param_ops { /* How the ops should behave */ unsigned int flags; /* Returns 0, or -errno. arg is in kp->arg. */ int (*set)(const char *val, const struct kernel_param *kp); /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ int (*get)(char *buffer, const struct kernel_param *kp); /* Optional function to free kp->arg when module unloaded. */ void (*free)(void *arg); }; /* * Flags available for kernel_param * * UNSAFE - the parameter is dangerous and setting it will taint the kernel */ enum { KERNEL_PARAM_FL_UNSAFE = (1 << 0) }; struct kernel_param { const char *name; struct module *mod; const struct kernel_param_ops *ops; const u16 perm; s8 level; u8 flags; union { void *arg; const struct kparam_string *str; const struct kparam_array *arr; }; }; extern const struct kernel_param __start___param[], __stop___param[]; /* Special one for strings we want to copy into */ struct kparam_string { unsigned int maxlen; char *string; }; /* Special one for arrays */ struct kparam_array { unsigned int max; unsigned int elemsize; unsigned int *num; const struct kernel_param_ops *ops; void *elem; }; /** * module_param - typesafe helper for a module/cmdline parameter * @value: the variable to alter, and exposed parameter name. * @type: the type of the parameter * @perm: visibility in sysfs. * * @value becomes the module parameter, or (prefixed by KBUILD_MODNAME and a * ".") the kernel commandline parameter. Note that - is changed to _, so * the user can use "foo-bar=1" even for variable "foo_bar". * * @perm is 0 if the the variable is not to appear in sysfs, or 0444 * for world-readable, 0644 for root-writable, etc. Note that if it * is writable, you may need to use kernel_param_lock() around * accesses (esp. charp, which can be kfreed when it changes). * * The @type is simply pasted to refer to a param_ops_##type and a * param_check_##type: for convenience many standard types are provided but * you can create your own by defining those variables. * * Standard types are: * byte, short, ushort, int, uint, long, ulong * charp: a character pointer * bool: a bool, values 0/1, y/n, Y/N. * invbool: the above, only sense-reversed (N = true). */ #define module_param(name, type, perm) \ module_param_named(name, name, type, perm) /** * module_param_unsafe - same as module_param but taints kernel */ #define module_param_unsafe(name, type, perm) \ module_param_named_unsafe(name, name, type, perm) /** * module_param_named - typesafe helper for a renamed module/cmdline parameter * @name: a valid C identifier which is the parameter name. * @value: the actual lvalue to alter. * @type: the type of the parameter * @perm: visibility in sysfs. * * Usually it&#39;s a good idea to have variable names and user-exposed names the * same, but that&#39;s harder if the variable must be non-static or is inside a * structure. This allows exposure under a different name. */ #define module_param_named(name, value, type, perm) \ param_check_##type(name, &(value)); \ module_param_cb(name, &param_ops_##type, &value, perm); \ __MODULE_PARM_TYPE(name, #type) /** * module_param_named_unsafe - same as module_param_named but taints kernel */ #define module_param_named_unsafe(name, value, type, perm) \ param_check_##type(name, &(value)); \ module_param_cb_unsafe(name, &param_ops_##type, &value, perm); \ __MODULE_PARM_TYPE(name, #type) /** * module_param_cb - general callback for a module/cmdline parameter * @name: a valid C identifier which is the parameter name. * @ops: the set & get operations for this parameter. * @perm: visibility in sysfs. * * The ops can have NULL set or get functions. */ #define module_param_cb(name, ops, arg, perm) \ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0) #define module_param_cb_unsafe(name, ops, arg, perm) \ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, \ KERNEL_PARAM_FL_UNSAFE) /** * <level>_param_cb - general callback for a module/cmdline parameter * to be evaluated before certain initcall level * @name: a valid C identifier which is the parameter name. * @ops: the set & get operations for this parameter. * @perm: visibility in sysfs. * * The ops can have NULL set or get functions. */ #define __level_param_cb(name, ops, arg, perm, level) \ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level, 0) #define core_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 1) #define postcore_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 2) #define arch_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 3) #define subsys_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 4) #define fs_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 5) #define device_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 6) #define late_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 7) /* On alpha, ia64 and ppc64 relocations to global data cannot go into read-only sections (which is part of respective UNIX ABI on these platforms). So &#39;const&#39; makes no sense and even causes compile failures with some compilers. */ #if defined(CONFIG_ALPHA) || defined(CONFIG_IA64) || defined(CONFIG_PPC64) #define __moduleparam_const #else #define __moduleparam_const const #endif /* This is the fundamental function for registering boot/module parameters. */ #define __module_param_call(prefix, name, ops, arg, perm, level, flags) \ /* Default value instead of permissions? */ \ static const char __param_str_##name[] = prefix #name; \ static struct kernel_param __moduleparam_const __param_##name \ __used \ __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ = { __param_str_##name, THIS_MODULE, ops, \ VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } } /* Obsolete - use module_param_cb() */ #define module_param_call(name, set, get, arg, perm) \ static const struct kernel_param_ops __param_ops_##name = \ { .flags = 0, (void *)set, (void *)get }; \ __module_param_call(MODULE_PARAM_PREFIX, \ name, &__param_ops_##name, arg, \ (perm) + sizeof(__check_old_set_param(set))*0, -1, 0) /* We don&#39;t get oldget: it&#39;s often a new-style param_get_uint, etc. */ static inline int __check_old_set_param(int (*oldset)(const char *, struct kernel_param *)) { return 0; } #ifdef CONFIG_SYSFS extern void kernel_param_lock(struct module *mod); extern void kernel_param_unlock(struct module *mod); #else static inline void kernel_param_lock(struct module *mod) { } static inline void kernel_param_unlock(struct module *mod) { } #endif #ifndef MODULE /** * core_param - define a historical core kernel parameter. * @name: the name of the cmdline and sysfs parameter (often the same as var) * @var: the variable * @type: the type of the parameter * @perm: visibility in sysfs * * core_param is just like module_param(), but cannot be modular and * doesn&#39;t add a prefix (such as "printk."). This is for compatibility * with __setup(), and it makes sense as truly core parameters aren&#39;t * tied to the particular file they&#39;re in. */ #define core_param(name, var, type, perm) \ param_check_##type(name, &(var)); \ __module_param_call("", name, &param_ops_##type, &var, perm, -1, 0) /** * core_param_unsafe - same as core_param but taints kernel */ #define core_param_unsafe(name, var, type, perm) \ param_check_##type(name, &(var)); \ __module_param_call("", name, &param_ops_##type, &var, perm, \ -1, KERNEL_PARAM_FL_UNSAFE) #endif /* !MODULE */ /** * module_param_string - a char array parameter * @name: the name of the parameter * @string: the string variable * @len: the maximum length of the string, incl. terminator * @perm: visibility in sysfs. * * This actually copies the string when it&#39;s set (unlike type charp). * @len is usually just sizeof(string). */ #define module_param_string(name, string, len, perm) \ static const struct kparam_string __param_string_##name \ = { len, string }; \ __module_param_call(MODULE_PARAM_PREFIX, name, \ &param_ops_string, \ .str = &__param_string_##name, perm, -1, 0);\ __MODULE_PARM_TYPE(name, "string") /** * parameq - checks if two parameter names match * @name1: parameter name 1 * @name2: parameter name 2 * * Returns true if the two parameter names are equal. * Dashes (-) are considered equal to underscores (_). */ extern bool parameq(const char *name1, const char *name2); /** * parameqn - checks if two parameter names match * @name1: parameter name 1 * @name2: parameter name 2 * @n: the length to compare * * Similar to parameq(), except it compares @n characters. */ extern bool parameqn(const char *name1, const char *name2, size_t n); /* Called on module insert or kernel boot */ extern char *parse_args(const char *name, char *args, const struct kernel_param *params, unsigned num, s16 level_min, s16 level_max, void *arg, int (*unknown)(char *param, char *val, const char *doing, void *arg)); /* Called by module remove. */ #ifdef CONFIG_SYSFS extern void destroy_params(const struct kernel_param *params, unsigned num); #else static inline void destroy_params(const struct kernel_param *params, unsigned num) { } #endif /* !CONFIG_SYSFS */ /* All the helper functions */ /* The macros to do compile-time type checking stolen from Jakub Jelinek, who IIRC came up with this idea for the 2.4 module init code. */ #define __param_check(name, p, type) \ static inline type __always_unused *__check_##name(void) { return(p); } extern const struct kernel_param_ops param_ops_byte; extern int param_set_byte(const char *val, const struct kernel_param *kp); extern int param_get_byte(char *buffer, const struct kernel_param *kp); #define param_check_byte(name, p) __param_check(name, p, unsigned char) extern const struct kernel_param_ops param_ops_short; extern int param_set_short(const char *val, const struct kernel_param *kp); extern int param_get_short(char *buffer, const struct kernel_param *kp); #define param_check_short(name, p) __param_check(name, p, short) extern const struct kernel_param_ops param_ops_ushort; extern int param_set_ushort(const char *val, const struct kernel_param *kp); extern int param_get_ushort(char *buffer, const struct kernel_param *kp); #define param_check_ushort(name, p) __param_check(name, p, unsigned short) extern const struct kernel_param_ops param_ops_int; extern int param_set_int(const char *val, const struct kernel_param *kp); extern int param_get_int(char *buffer, const struct kernel_param *kp); #define param_check_int(name, p) __param_check(name, p, int) extern const struct kernel_param_ops param_ops_uint; extern int param_set_uint(const char *val, const struct kernel_param *kp); extern int param_get_uint(char *buffer, const struct kernel_param *kp); #define param_check_uint(name, p) __param_check(name, p, unsigned int) extern const struct kernel_param_ops param_ops_long; extern int param_set_long(const char *val, const struct kernel_param *kp); extern int param_get_long(char *buffer, const struct kernel_param *kp); #define param_check_long(name, p) __param_check(name, p, long) extern const struct kernel_param_ops param_ops_ulong; extern int param_set_ulong(const char *val, const struct kernel_param *kp); extern int param_get_ulong(char *buffer, const struct kernel_param *kp); #define param_check_ulong(name, p) __param_check(name, p, unsigned long) extern const struct kernel_param_ops param_ops_ullong; extern int param_set_ullong(const char *val, const struct kernel_param *kp); extern int param_get_ullong(char *buffer, const struct kernel_param *kp); #define param_check_ullong(name, p) __param_check(name, p, unsigned long long) extern const struct kernel_param_ops param_ops_charp; extern int param_set_charp(const char *val, const struct kernel_param *kp); extern int param_get_charp(char *buffer, const struct kernel_param *kp); extern void param_free_charp(void *arg); #define param_check_charp(name, p) __param_check(name, p, char *) /* We used to allow int as well as bool. We&#39;re taking that away! */ extern const struct kernel_param_ops param_ops_bool; extern int param_set_bool(const char *val, const struct kernel_param *kp); extern int param_get_bool(char *buffer, const struct kernel_param *kp); #define param_check_bool(name, p) __param_check(name, p, bool) extern const struct kernel_param_ops param_ops_bool_enable_only; extern int param_set_bool_enable_only(const char *val, const struct kernel_param *kp); /* getter is the same as for the regular bool */ #define param_check_bool_enable_only param_check_bool extern const struct kernel_param_ops param_ops_invbool; extern int param_set_invbool(const char *val, const struct kernel_param *kp); extern int param_get_invbool(char *buffer, const struct kernel_param *kp); #define param_check_invbool(name, p) __param_check(name, p, bool) /* An int, which can only be set like a bool (though it shows as an int). */ extern const struct kernel_param_ops param_ops_bint; extern int param_set_bint(const char *val, const struct kernel_param *kp); #define param_get_bint param_get_int #define param_check_bint param_check_int /** * module_param_array - a parameter which is an array of some type * @name: the name of the array variable * @type: the type, as per module_param() * @nump: optional pointer filled in with the number written * @perm: visibility in sysfs * * Input and output are as comma-separated values. Commas inside values * don&#39;t work properly (eg. an array of charp). * * ARRAY_SIZE(@name) is used to determine the number of elements in the * array, so the definition must be visible. */ #define module_param_array(name, type, nump, perm) \ module_param_array_named(name, name, type, nump, perm) /** * module_param_array_named - renamed parameter which is an array of some type * @name: a valid C identifier which is the parameter name * @array: the name of the array variable * @type: the type, as per module_param() * @nump: optional pointer filled in with the number written * @perm: visibility in sysfs * * This exposes a different name than the actual variable name. See * module_param_named() for why this might be necessary. */ #define module_param_array_named(name, array, type, nump, perm) \ param_check_##type(name, &(array)[0]); \ static const struct kparam_array __param_arr_##name \ = { .max = ARRAY_SIZE(array), .num = nump, \ .ops = &param_ops_##type, \ .elemsize = sizeof(array[0]), .elem = array }; \ __module_param_call(MODULE_PARAM_PREFIX, name, \ &param_array_ops, \ .arr = &__param_arr_##name, \ perm, -1, 0); \ __MODULE_PARM_TYPE(name, "array of " #type) extern const struct kernel_param_ops param_array_ops; extern const struct kernel_param_ops param_ops_string; extern int param_set_copystring(const char *val, const struct kernel_param *); extern int param_get_string(char *buffer, const struct kernel_param *kp); /* for exporting parameters in /sys/module/.../parameters */ struct module; #if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES) extern int module_param_sysfs_setup(struct module *mod, const struct kernel_param *kparam, unsigned int num_params); extern void module_param_sysfs_remove(struct module *mod); #else static inline int module_param_sysfs_setup(struct module *mod, const struct kernel_param *kparam, unsigned int num_params) { return 0; } static inline void module_param_sysfs_remove(struct module *mod) { } #endif #endif /* _LINUX_MODULE_PARAMS_H */ 这段代码中module_param的作用
12-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值