LSM是Linux Secrity Module的简称,即linux安全模块。其是一种轻量级通用访问控制框架,适合于多种访问控制模型在它上面以内核可加载模块的形实现。用户可以根据自己的需求选择合适的安全模块加载到内核上实现。
LSM设计思想:
LSM的设计思想:在最少改变内核代码的情况下,提供一个能够成功实现强制访问控制模块需要的结构或者接口。LSM避免了利用如在systrace系统调用中的出现过的系统调用干预,因为它不能扩展到多处理器内核,并且它受制于参数替换攻击。还有LSM在设计时做了两点考虑:对不使用的人来说尽量少引入麻烦,对使用的人来说要带来效率。以Linus Torvalds为代表的内核开发人员对Linux安全模块(LSM)提出了三点要求:
1、真正的通用,当使用一个不同的安全模型的时候,只需要加载一个不同的内核模块。
2、概念上简单,对Linux内核影响最小,高效,并且。
3、能够支持现存的POSIX.1e capabilities逻辑,作为一个可选的安全模块。
还有,针对linux上提出的各种不同的Linux安全增强系统对Linux安全模块(LSM)提出的要求是:能够允许他们以可加载内核模块的形式重新实现其安全功能,并且不会在安全性方面带来明显的损失,也不会带来额外的系统开销。
LSM框架结构:
LSM框架主要由五部分构成:
1、在特定的内核数据结构中加入安全域。
2、在内核源代码中不同的关键点插入对安全钩子函数的调用。
3、加入一个通用的安全系统调用。
4、提供了函数允许内核模块注册为安全模块或者注销。
5、5、将capabilities逻辑的大部分移植为一个可选的安全模块。
安全域是一个void*类型的指针,它使得安全模块把安全信息和内核内部对象联系起来。下面列出被修改加入了安全域的内核数据结构,以及各自所代表的内核内部对象:
-
task_struct结构:代表任务(进程)
-
linux_binprm结构:代表程序
-
super_block结构:代表文件系统
-
inode结构:代表管道,文件,或者Socket套接字
-
file结构:代表打开的文件
-
sk_buff结构:代表网络缓冲区(包)
-
net_device结构:代表网络设备
-
kern_ipc_perm结构:代表Semaphore信号,共享内存段,或者消息队列
-
msg_msg:代表单个的消息
Linux安全模块(LSM)提供了两类对安全钩子函数的调用:一类管理内核对象的安全域,另一类仲裁对这些内核对象的访问。对安全钩子函数的调用通过钩子来实现,钩子是全局表security_ops中的函数指针,这个全局表的类型是security_operations结构,这个结构定义在include/linux/security.h这个头文件中。
LSM接口的核心是security_ops,当系统启动时,他们被初始化为传统的DAC策略。传统DAC访问控制是指控制系统中的主体(如进程)对系统中的客体(如文件目录、文件)的访问(读、写和执行等)。自主访问控制DAC 是指主体(进程,用户)对客体(文件、目录、特殊设备文件、IPC等)的访问权限是由客体的属主或超级用户决定的,而且此权限一旦确定,将作为以后判断主体对客体是否有访问权限的依据。
在加载安全模块时,我们必需先对模块进行注册,我们可以使用register_security()函数向LSM注册一个安全模块。在我们的模块被加载成功后,就可以进行访问控制操作。如果此时还有一个安全模块要使用register_security()函数进行加载,则会出现错误,直到使用unregister_security()函数向框架注销后,下一个模块才可以载入。当然LSM还提供了mod_reg_security()函数和mod_unreg_security()函数,可以连续注册多个安全模块。如果有其他后来的模块需要载入,可以通过mod_reg_security()向第一个模块注册,形成支持不同策略的模块栈。
注:以上出现的函数均基于2.6.22以前的版本,对于后续的版本,出现了register_security()函数未被导出或者取消掉了unregister_security()函数。
LSM执行过程:
根据下图的执行步骤:用户在执行系统调用时,先通过原有的内核接口依次执行功能性的错误检查,接着进行传统的DAC检查,并在即将访问内核的内部对象之前,通过LSM钩子函数调用LSM。LSM再调用具体的访问控制策略来决定访问的合法性。图三显示了LSM钩子的调用:
图三:基于LSM的内核对象访问过程
Lilinux安全模块(LSM)主要支持"限制型"的访问控制决策:当Linux内核授予文件或目录访问权限时,Linux安全模块(LSM)可能会拒绝,而当 Linux内核拒绝访问时,可以跳过LSM。