Unknown symbol security_hook_heads (err 0)
/* * A LSM modules which implements role based access control. */ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/security.h> #include <linux/xattr.h> #include <linux/capability.h> #include <linux/unistd.h> #include <linux/mm.h> #include <linux/mman.h> #include <linux/slab.h> #include <linux/pagemap.h> #include <linux/swap.h> #include <linux/uaccess.h> #include <linux/spinlock.h> #include <linux/syscalls.h> #include <linux/file.h> #include <linux/namei.h> #include <linux/mount.h> #include <linux/ext2_fs.h> #include <linux/proc_fs.h> #include <linux/kd.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv6.h> #include <linux/tty.h> #include <net/icmp.h> #include <net/ip.h> /* for sysctl_local_port_range[] */ #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ #include <asm/uaccess.h> #include <asm/ioctls.h> #include <linux/bitops.h> #include <linux/interrupt.h> #include <linux/netdevice.h> /* for network interface checks */ #include <linux/netlink.h> #include <linux/tcp.h> #include <linux/udp.h> #include <linux/quota.h> #include <linux/un.h> /* for Unix socket types */ #include <net/af_unix.h> /* for Unix socket types */ #include <linux/parser.h> #include <linux/nfs_mount.h> #include <net/ipv6.h> #include <linux/hugetlb.h> #include <linux/personality.h> #include <linux/sysctl.h> #include <linux/audit.h> #include <linux/string.h> #include <linux/unistd.h> #include <linux/lsm_hooks.h> #include <linux/syscalls.h> #include <linux/kallsyms.h> #include <linux/sched.h> #include <asm/uaccess.h> #include <asm/unistd.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/syscalls.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/fcntl.h> #include <linux/version.h> #include <linux/syscalls.h> //定义将要hook的系统调用 #define SYSCALL_CONNECT 0x01 #define SYSCALL_SOCKET 0x02 #define SYSCALL_MKDIR 0x04 #define SYSCALL_RMDIR 0x08 #define SYSCALL_TASK_CREATE 0x10 //定义四种角色 #define ROLE_RECYCLER_NAME "recycler" #define ROLE_OPERATOR_NAME "operator" #define ROLE_NETMANAGER_NAME "netmanager" #define ROLE_ADMIN_NAME "admin" #define ROLE_RECYCLER 1 #define ROLE_OPERATOR 2 #define ROLE_NETMANAGER 3 #define ROLE_ADMIN 4 //定义几个配置文件的路径,此处是硬编码的 #define ROLE_CONFIG "/etc/rbos/role_config" #define USER_CONFIG "/etc/rbos/user_config" //最多支持16种角色,128个用户的分配 #define SAMPLE_MAX_ROLE 16 #define SAMPLE_MAX_USER 128 #define SAMPLE_MAX_BUF 1024 //角色结构 typedef struct __role__ { unsigned int roleid; unsigned int right; }_ROLE_STRUCT; _ROLE_STRUCT all_roles[SAMPLE_MAX_ROLE]={{0,0},}; unsigned int all_roles_cnt=0; //用户结构 typedef struct __user__ { unsigned int userid; unsigned int right; }_USER_STRUCT; _USER_STRUCT all_users[SAMPLE_MAX_USER]={{0,SYSCALL_CONNECT | SYSCALL_SOCKET | SYSCALL_MKDIR |SYSCALL_RMDIR | SYSCALL_TASK_CREATE},}; unsigned int all_users_cnt=1; typedef union { struct _socket_info{ int domain; int type; int protocol; }; struct _connect_info { struct socket *sock; struct sockaddr *address; int addrlen; }connect_info; struct _mkdir_info { struct inode *dir; struct dentry *dentry; int mask; }mkdir_info; struct _rmdir_info { struct inode *dir; struct dentry *dentry; }rmdir_info; struct _taskcreate_info{ unsigned long clone_flags; }; }perm_info_t; unsigned int sample_asc2int(char * str,int len) //将整形字符串转换为整数 { unsigned int rst =0; int i; for(i =0;i<len;i++) { rst=rst * 10 + str[i]-'0'; } printk(KERN_WARNING "asc2int::%d,len:%d str:%s.\n",rst,len,str); return rst; } int check_connect_perm(perm_info_t *info,unsigned int right) { printk(KERN_WARNING "___Check connect permission___:: %s\n", __FUNCTION__); if(right & SYSCALL_CONNECT) { return 0; } else { return -EINVAL; } } int check_socket_perm(perm_info_t *info,unsigned int right) { printk(KERN_WARNING "___Check socket create permission___:: %s\n", __FUNCTION__); if(right&SYSCALL_SOCKET) { return 0; } else { return -EINVAL; } } int check_taskcreate_perm(perm_info_t *info,unsigned int right) { printk(KERN_WARNING "___Check task_create permission___:: %s\n", __FUNCTION__); if(right & SYSCALL_TASK_CREATE) { return 0; } else { return -EINVAL; } } int check_mkdir_perm(perm_info_t *info,unsigned int right) { printk(KERN_WARNING "___Check mkdir permission___:: %s\n", __FUNCTION__); if(right & SYSCALL_MKDIR) { return 0; } else { return -EINVAL; } } int check_rmdir_perm(perm_info_t *info,unsigned int right) { printk(KERN_WARNING "___Check rmdir permission___:: %s\n", __FUNCTION__); if(right & SYSCALL_RMDIR) { return 0; } else { return -EINVAL; } } static int check_perm(int syscall_type, perm_info_t *perm_info) { int ret=0; struct cred * new; unsigned int uid=0; unsigned int right=0; //获取用户实际uid,并且得到用户的权限,默认用户都拥有SYSCALL_TASK_CREATE的权限 //注意并没有使用有效用户id;因为有效用户id会通过setuid位升权限 new=prepare_creds(); uid =(unsigned int)(new->uid).val; int i; for( i=0;i<all_users_cnt;i++) { if(all_users[i].userid == uid) { right |= all_users[i].right; break; } } if(right==0) //非测试用户,打开所有权限 { right=SYSCALL_CONNECT | SYSCALL_SOCKET | SYSCALL_MKDIR |SYSCALL_RMDIR | SYSCALL_TASK_CREATE; } printk(KERN_WARNING "____Check Permission___::%s, real uid :: %d.\n", __FUNCTION__,uid); switch (syscall_type) { case SYSCALL_CONNECT: ret = check_connect_perm(perm_info,right); break; case SYSCALL_SOCKET: ret = check_socket_perm(perm_info,right); break; case SYSCALL_TASK_CREATE: ret = check_taskcreate_perm(perm_info,right); break; case SYSCALL_MKDIR: ret = check_mkdir_perm(perm_info,right); break; case SYSCALL_RMDIR: ret = check_rmdir_perm(perm_info,right); break; } return ret; } static int sample_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) { perm_info_t perm_info; return check_perm(SYSCALL_CONNECT, &perm_info); } static int sample_socket(int domain,int type,int protocol,int kern) //TODO 完善参数列表 { perm_info_t perm_info; return check_perm(SYSCALL_SOCKET,&perm_info); } static int sample_task_create(unsigned long clone_flags) { perm_info_t perm_info; return check_perm(SYSCALL_TASK_CREATE,&perm_info); } static int sample_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) { perm_info_t perm_info; return check_perm(SYSCALL_MKDIR, &perm_info); } static int sample_inode_rmdir(struct inode *dir, struct dentry *dentry) { perm_info_t perm_info; return check_perm(SYSCALL_RMDIR, &perm_info); } static void get_role_config(void) { char buf[SAMPLE_MAX_BUF]={0}; struct file * f=NULL; const char * filename =ROLE_CONFIG; char * p; int i=0; char * line_start; char * token_start; printk(KERN_INFO "get role config from %s.\n",filename); mm_segment_t oldfs; f =filp_open(filename,O_RDONLY,0); if( IS_ERR(f) || (f==NULL)) { printk(KERN_WARNING "get role config error.\n"); return ; } p=buf; line_start = buf; token_start=buf; int role_index =0; oldfs =get_fs(); //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); set_fs(get_ds()); //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); while(vfs_read(f,buf+i,1,&f->f_pos)==1) { //printk(KERN_INFO "%s::%d.THE SRC:%s\n",__FUNCTION__,__LINE__,buf); if(i==SAMPLE_MAX_BUF) //读满缓存区 { break; } if(buf[i]==':') //读到角色 { //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); buf[i]=0;//把":"截断 printk(KERN_INFO "read a role of :%s.\n",line_start); all_roles_cnt++; if(role_index != 0) { printk(KERN_INFO "last role right:%x.\n",all_roles[role_index].right); } if(strcmp((const char *)line_start,ROLE_ADMIN_NAME)==0) { role_index = ROLE_ADMIN; } //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(strcmp((const char *)line_start,ROLE_NETMANAGER_NAME)==0) { role_index = ROLE_NETMANAGER; } //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(strcmp((const char *)line_start,ROLE_OPERATOR_NAME)==0) { role_index =ROLE_OPERATOR; } //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(strcmp((const char *)line_start,ROLE_RECYCLER_NAME)==0) { role_index=ROLE_RECYCLER; } token_start = buf+i+1; } if(buf[i]=='\n') //遇到换行符了 { line_start = buf +i +1; } //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(buf[i]==',' || buf[i]==';') //到了一个token的终点 { //[token_start,buf+i)是一个token buf[i]=0; if((buf+i-token_start)<4) //明显不是一个token { ; } else { //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(strcmp((const char *)token_start,"SYSCALL_CONNECT")==0) //具有SYSCALL_CONNECT权限 { all_roles[role_index].right |=SYSCALL_CONNECT; } //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(strcmp((const char *)token_start,"SYSCALL_SOCKET")==0) { all_roles[role_index].right |= SYSCALL_SOCKET; } //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(strcmp((const char *)token_start,"SYSCALL_MKDIR")==0) { all_roles[role_index].right |=SYSCALL_MKDIR; } //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(strcmp((const char *)token_start,"SYSCALL_RMDIR")==0) { all_roles[role_index].right |=SYSCALL_RMDIR; } //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(strcmp((const char *)token_start,"SYSCALL_TASK_CREATE")==0) { all_roles[role_index].right |= SYSCALL_TASK_CREATE; } } token_start=buf+i+1; } i++; } set_fs(oldfs); filp_close(f,0); printk(KERN_INFO "load %d roles.\n",all_roles_cnt); } static void get_user_config(void) { char buf[SAMPLE_MAX_BUF]={0}; struct file * f=NULL; const char * filename =USER_CONFIG; char * p; int i=0; char * line_start; char * token_start; printk(KERN_INFO "get user config from %s.\n",filename); mm_segment_t oldfs; f =filp_open(filename,O_RDONLY,0); if( IS_ERR(f) || (f==NULL)) { printk(KERN_WARNING "get user config error.\n"); return ; } p=buf; line_start = buf; token_start=buf; int user_index =0; oldfs =get_fs(); //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); set_fs(KERNEL_DS); //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); while(vfs_read(f,buf+i,1,&f->f_pos)==1) { //printk(KERN_INFO "%s::%d.\n",__FUNCTION__,__LINE__); if(i==SAMPLE_MAX_BUF) //读满缓存区 { break; } if(buf[i]==':') //读到用户了 { unsigned int userid = sample_asc2int(line_start,buf+i-line_start); printk(KERN_INFO "read userid of %d.\n",userid); if(all_users_cnt) { printk(KERN_INFO "last user ::%d,right:%x.\n",all_users[all_users_cnt-1].userid,all_users[all_users_cnt-1].right); } all_users[all_users_cnt++].userid =userid; user_index = all_users_cnt-1; token_start = buf+i+1; } //TODO if(buf[i]=='\n') //遇到换行符了 { line_start = buf +i +1; } if(buf[i]==',' || buf[i]==';') //到了一个token的终点 { //[token_start,buf+i)是一个token buf[i]=0; if((buf+i-token_start)<5) //明显不是一个token,这有可能为空 { ; } else { if(strcmp((const char *)token_start,ROLE_ADMIN_NAME)==0) { all_users[user_index].right |=all_roles[ROLE_ADMIN].right; } if(strcmp((const char *)token_start,ROLE_OPERATOR_NAME)==0) { all_users[user_index].right |=all_roles[ROLE_OPERATOR].right; } if(strcmp((const char *)token_start,ROLE_RECYCLER_NAME)==0) { all_users[user_index].right |=all_roles[ROLE_RECYCLER].right; } if(strcmp((const char *)token_start,ROLE_NETMANAGER_NAME)==0) { all_users[user_index].right |=all_roles[ROLE_NETMANAGER].right; } } token_start=buf+i+1; } i++; } set_fs(oldfs); filp_close(f,0); printk(KERN_INFO "load %d user.\n",all_users_cnt); } static struct security_hook_list demo_hooks[]= { LSM_HOOK_INIT(socket_connect,sample_socket_connect), LSM_HOOK_INIT(socket_create,sample_socket), LSM_HOOK_INIT(task_create,sample_task_create), // LSM_HOOK_INIT(inode_mkdir,sample_inode_mkdir), LSM_HOOK_INIT(inode_rmdir,sample_inode_rmdir) }; static int sample_init(void) { printk(KERN_INFO "ADD LSM SAMPLE.\n"); printk(KERN_INFO "LOAD ROLE CONFIG.\n");//载入role config; get_role_config(); printk(KERN_INFO "LOAD USER CONFIG.\n");//载入user config; get_user_config(); security_add_hooks(demo_hooks,ARRAY_SIZE(demo_hooks)); printk(KERN_INFO "Sample: Initializing.\n"); return 0; } static void sample_exit(void) { printk(KERN_INFO "Sample: Exiting.\n"); } module_init(sample_init); module_exit(sample_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("JMH"); MODULE_DESCRIPTION("A LSM Driver implements RBAC");
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2020-04-09 Linux获得mac地址
2020-04-09 校对:思路
2020-04-09 拒绝手机浏览器短视频
2020-04-09 问题:每秒的问题
2020-04-09 黑马校对软件
2018-04-09 oepnni安装