当前位置首页 > 百科> 正文

Linux安全模组

2019-03-15 19:38:38 百科
Linux安全模组

Linux安全模组

Linux安全模组(Linux Secrity Module,简称LSM)是一种轻量级通用访问控制框架,适合于多种访问控制模型在它上面以核心可载入模组的形实现。用户可以根据自己的需求选择合适的安全模组载入到核心上实现。

基本介绍

  • 中文名:Linux安全模组
  • 外文名:Linux Security Modules
  • 学科:计算机科学
  • 机制:安全域、hook函式等
  • 定义:轻量级通用访问控制框架
  • 套用:Linux系统

基本原理

LSM的产生是具有其历史原因的。随着分散式信息系统的发展和套用业务的日益複杂,信息系统的安全需求也趋于多样化。现有的安全策略往往是针对特定的安全需求而设计的,因此单一的安全策略越来越难以满足信息系统安全需求。在这种情况下,允许各种安全策略同时存在于系统内并发挥安全作用的安全框架成为研究重点。GFAC、Flask等安全框架由于出现较早,且有专门的研究机构对其进行研究,目前已有如RSBAC、SELinux等较为成熟的套用。但由于二者对核心影响相对较大,且未形成统一标準,因此并未融入主流作业系统。
2001年,在Linux核心2.5高峰会议上,Linux创始人Linus Torvalds提出Linux核心需要自己的通用访问框架,并建议以核心模组的方式来实施各种安全策略。回响Linus号召Chris Wright等人完成了LSM的设计开发工作,并与2002年4月28日以程式补丁的形式对外公布。2003年,LSM正式成为核心组成部分,随核心2.6发行。LSM作为轻量级、通用的访问控制框架,具有以下特点:
  1. 真正通用,使得採用不同的安全模型仅仅是载入不同的核心模组;
  2. 概念简单、高效,而且对核心冲击较小;
  3. 支持现有的POSIX.1e的capabilities逻辑,将其作为一种可选安全模组。
作为通用访问控制框架,LSM本身并不提供任何的安全策略,而是为各种安全策略提供了通用的框架。安全策略以安全模组的形式实现,并加通过LSM载入进入系统,为系统提供安全保障。为此保证此目的,LSM对系统核心做了如下修改:
  1. 为核心关键数据结构增加安全域栏位,用以关联安全信息;
  2. 在关键系统调用之前插入hook函式,对访问进行判断;
  3. 提供模组注册与卸载函式,用于安全模组的载入与卸载;
  4. 提供通用的安全系统调用接口,用以安全系统调用的扩展;
  5. 部分分离capabilities机制,将其作为独立的安全模组。
安全模组通过模组注册函式载入进入LSM,对核心关键资源设定安全信息,并将自己的安全策略函式与LSM的hook函式进行关联。用户进程提出系统资源访问访问请求,转入核心空间,并做传统的Linux系统DAC(Discretionary Access Control)判断。之后,LSM调用hook函式,该hook函式以指针的形式与特定安全模组的安全策略函式关联,用以判断对该对象的访问是否符合安全策略,从而进行访问控制。LSM基本原理如图所示。
Linux安全模组

实现机制

安全域

LSM在核心关键数据结构添加了安全域栏位。该栏位由具体的安全模组设定管理,存储着核心关键数据结构的安全信息。安全信息是系统资源的标识,是多数访问控制策略实现其安全机制的重要信息。不同的安全策略,所针对的安全问题不同,其关注的客体安全信息也不同。因此,LSM没有在核心中添加特定的安全信息,而是为核心添加了透明安全域(Opaque Security Fields),以保证其通用性。
安全域栏位是一个空类型的指针,特定安全模组载入后,该指针所指向的数据空间存储着核心数据结构的安全信息。该安全信息是由具体的安全模组设定和管理的,不受LSM框架的影响。如此,便可以保证LSM对多种安全模组的通用性。但是,安全域栏位无法同时指向两个及两个以上安全模组对核心设定的安全信息,这也正是本课题拟解决的问题之一。
LSM为安全模组提供了设定和管理核心数据结构安全域栏位的hook函式接口。安全模组只需要实现这些函式,便可以灵活对核心数据结构的安全信息进行设定和管理。例如,LSM提供了alloc_security和frce_security函式用于申请和释放安全信息空间,提供了post_lookup函式用于对inode查询之后修改安全信息。
以SELinux的file结构为例,LSM为核心数据结构file增添了透明的安全域栏位,该栏位指向SELinux对file结构设定的安全信息。修改后的file结构如下:
struct file{……    void* f-security;/*空类型指针f-security*/    ……};
SELinux对file结构设定的安全信息如下:
struct file_security_struct{    u32 sid;    u32 fown—sid;    u32 isid;    u32 pseqno;};
SELinux设定file结构的安全信息,并file安全域关联:
static int filc_alloc_security(struct file *file){……    struct file_security_struct *fsec;    fsec=kzalloc(sizeof(struct1File_security_struct),GFP_KERNEL);    if(!fSec)    return -NNOMEM;    file->f_security=fSec;/*将指针f-security与安全数据fcsc关联*/……}
SELinux撤销file结构的安全信息,一般发生在SELinux模组从LSM卸载时:
static void file_free_security(struct file *file){    struct file_security_struct *fsec=file->f_security;    file一>f_security=NULL;    kfree(fSec);}
可见,对核心安全域栏位的定义及管理都是由具体的安全模组实现,这便保证了LSM框架的高通用性。LSM为核心的9个关键数据结添加了安全域栏位,如表所示。
Linux安全模组

hook函式调用

LSM在执行对核心关键资源访问之前,插入对hook函式的调用。这些hook函式从功能上讲,大致可分成两类:
  • 用于管理核心对象安全域的hook函式
  • 用以执行访问控制的hook函式。
前文所提到的alloc_security,free_security和post_lookup函式都属于第一类hook函式。而如控制创建和删除目录的inode_mkdir和inode_rmdir等hook函式则属于第二类。所有的hook函式都是由具体的安全模组根据其自身的安全策略实现的。安全模组载入后,LSM框架的钩子函式表security_ops将与安全模组实现的hook函式关联。在执行对系统关键资源访问之前,LSM将通过security_ops调用安全模组的hook函式对。访问行为进行安全控制,此时调用的hook函式一般属于第二类。第二类hook函式的返回值一般为整数,若为0,则表示安全模组允许对核心对象的访问;否则,表示拒绝访问。
security_ops是struct security_operations类型的结构体,该结构内的函式指针指向安全模组的hook函式。LSM通过secu“tyops.>functionname来实现对安全模组hook函式的调用。LSM在核心中插入了160个hook函式。根据所针对的核心对象不同,这些h00k函式可以分为七类:进程、程式载入、IPC、档案及档案系统、网路、Linux动态载入模组及一个系统hook函式类。这些hook函式通过security-ops结构组织起来并调用。security-ops的结构如下:
struct security_operations{        ……/*其它hook函式*/      int(*inode_create)(struct inode*dir,struct dentry*dentry,int mode);/*检验创建普通档案许可权*/    int(*task_create)(unsigned long clone_flags);/*检验创建子进程许可权*/    int(*socket_create)(int family'int type,int protocol,int kern);/*检验创建新socket许可权*/    int(*ipc_permission)(struct kern_ipc_pem*ipcp,short flag);/*检验访问IPC许可权*/ };
安全模组只需要对security-ops所引用的hook函式进行实现,便可以发挥访问控制功能。所针对的安全问题不同,不同的安全模组实现的hook函式的种类、数量和方式也可以不同。SELinux安全模组对几乎全部的hook函式做了实现,而LSM自带的默认的dummy安全模组对任何的hook函式只是简单的返回零值,不做任何安全检测。
综上,LSM框架可以通过hook函式调用安全模组对系统访问实施访问控制,同时,为安全模组提供了统一的函式接口,使安全模组的设计更加灵活和独立。

安全模组载入与卸载

安全模组需要先向LSM注册,通过后载入进入系统,其实现的钩子函式才能够被LSM调用,发挥安全作用。在系统核心引导时,LSM默认载入dummy安全模组。Dummy安全模组对全部的钩子函式不做任何实现,仅仅是返回允许系统访问的零值。
除dummy之外的安全模组载入卸载时,需要调用模组载入与卸载函式。LSM提供了两对函式以完成安全模组的载入和卸载:
int register_security(struct security_operations *security_ops)int unregister_security(struct security_operations *security_ops)int mod_reg_security(const char *name,struct security_operations *ops)int mod_unreg_security(const char *name,struct security_operations *ops)
其中,register_security/unregister_security用于主安全模组向LSM框架的载入与卸载,mod_reg_security/ mod_unreg_security用于其它安全模组向主安全模组注册。主安全模组是指除dummy模组之外首先载入进入LSM的安全模组,在主安全模组之后载入的安全模组都属于从安全模组。从安全模组无法直接向LSM注册,而需要通过向主安全模组注册,间接载入进入LSM,并且受主安全模组安全策略的管理。通过这种多安全模组栈式堆叠的机制,LSM提供了对多安全模组支持。但是,堆叠进入LSM的从安全模组并不能独立的发挥安全作用:从安全模组何时被调用、如何被调用,返回结果的决策,都受主安全模组的管理。如果主安全模组为提供对后继模组的载入管理的支持,LSM的栈式堆叠机制也就无法再起作用。这种机制实质上是LSM框架在多安全模组管理和决策结果处理方面对主安全模组的依赖。
以SELinux安全模组为例,模组在初始化的过程中,调用LSM的register_security函式,并将LSM的security_ops表指向自身的钩子函式表。关键代码如下
static _init int selinux_init(void){    ……    if(registcr_security(&selinux_ops);/*调用register_security函式*/    ……}
其中,selinux_ops为Selinux模组实现的hook函式表,其定义为:
extern struct security_operations *security_ops;
register_security函式由LSM提供,其过程为:
int _init register_security(struct_security_operations *ops){    ……    if(security_ops!=&default_security_ops)/*判断是否有已载入的主安全模组*/        return -EAGAIN;    security_ops=ops; }
模组载入过程中,若检测到已有主安全模组载入到LSM,则模组只能通过IIlod—reg—security函式向从安全模组注册。模组卸载时,将LSM的security-ops设定为默认的dummy模组的h00k函式表。mod—reg—security/moo—unreg—security函式由特定的主安全模组提供。由上述代码可见,安全模组载入的过程,实质上就是将LSM的hook函式表与安全模组实现的hook函式表相关联的过程。

安全系统调用

LSM在核心中添加了一个通用的安全系统调用,以提供对安全模组安全套用的支持。该调用的接口允许安全模组实施自己的系统调用,对已有的系统调用进行扩展,以保证安全策略的实施。LSM在核心中对安全模组提供的通用接口是sys_security,参数为unsigned int id,unsigned int call,unsigned long *args。一般说来,三个参数分别代表安全模组标识符,系统调用标识符以及调用的参数,但是安全模组可以根据其安全策略和函式的实现,对三个参数进行不同的解释。安全模组可以根据自身安全策略的需要选择对安全系统调用进行实现或者不实现,若不需要对此调用进行实现,仅需要令函式syssecurity返回.NOSYS值。

Capabilities机制

Capabilities机制的基本思想是分割超级用户许可权,防止超级许可权的误用和滥用,以实现最小特权原则。LSM的设计目标之一是把传统的分散在核心多处的capabilities机制分离出核心‘,形成一个独立的capabilities安全模组。Capabilities机制的分离,具有两方面的优势:首先,用户对capabilities机制的使用更加灵活,不需要该机制的用户只需将其从LSM卸载;其次,capabilities机制的分离,使得对capabilities的后继研究对Linux核心影响变得很小。
目前,LSM框架已把大部分的capabilities机制独立出核心,但仍有部分遗留在核心中。例如,标识进程capability使用一个位于taskstruct中的位向量表示,该位向量可以移到taskstruct的安全域中,但由于模组堆叠机制下的安全域共享问题,该位向量及相关逻辑仍保留在核心中。
声明:此文信息来源于网络,登载此文只为提供信息参考,并不用于任何商业目的。如有侵权,请及时联系我们:baisebaisebaise@yeah.net