• [置顶] 强制访问控制内核模块Smack


    Smack(Simplified Mandatory Access Control Kernel)是Casey Schaufler[15]于2007年在LSM基础上实现的Linux强制访问控制安全模块,它以内核安全补丁的形式存在于Linux操作系统中,其设计思想是利用LSM安全域将Linux内核中所有主体与客体都打上安全标签,并规定安全策略,只有符合安全策略的访问方式才被容许。与SELinux和DTE相比,Smack安全策略要简单得多,但却能实现它们相似的强制访问控制功能,并且Smack对内核性能损耗比较低,因此,Smack也逐渐被业界看好和推广。

    2.4.1 Smack基本概念

    1. 主体

    Smack主体是指Linux内核进程。

    2. 客体

    Smack客体是指Linux内核客体对象,如文件、消息队列、套接字、共享内存、信号量等,客体也可以是Linux进程或者IPC。

    3. 安全标签

    Smack安全标签是C语言的字符串,但最多包含24个字符(包括‘/0’),Smack修改了进程task_struct安全域,在进程被初始创建时,其安全标签是“_”。同样,Smack修改了虚拟文件系统的inode和super_block安全域,使得文件系统被创建时所有文件的安全标签是“_”。

    4. 访问方式

    Smack最初版本的访问方式只有四种,即读(r或R)、写(w或W)、执行(x或X)、盲写(a或A)。其中,在进程之间通信中,一个进程发送消息或者数据包给另一个进程时,这样的操作属于写操作。

    5. 安全策略

    Smack的安全策略分为Smack内置的安全策略和用户可定制的安全策略。Smack内置的安全策略是指原本就已经被Smack访问控制代码所规定的,包括如下几条:

    (1)安全标签是“*”的进程发起的任何形式的访问都被拒绝;

    (2)安全标签是“^”的进程发起的读或执行的请求都被容许;

    (3)任何进程对安全标签是“_”的客体发起的读或执行的请求都被容许;

    (4)任何进程对安全标签是“*”的客体发起的任何形式的请求都被容许;

    (5)如果主体和客体的安全标签相同,那么该主体对该客体发起的任何形式的访问都被容许。

    除此之外,用户可以根据自己的安全需求,在主、客体安全标签都已经存在的前提下,通过“smackload”工具写入安全策略,例如:

    (1) abc    xyz     rwxarW

    (2) abc    xyz     rwr

    (3) abc    xyz    _

    smackload工具会自动配置访问方式的格式,(1)表示主体abc对客体xyz有读、写、执行、盲写的权限,(2)表示主体abc对客体xyz有读、写权限,(3)表示主体abc对客体xyz没有任何权限。当用户连续写入以上三条规则后,Smack会将相同主、客体的规则进行覆盖,最终,abc对xyz没有任何权限。

    2.4.2 Smack源码分析

    2007版本的smack源码[16]并不庞大,它被组织成了smack.h、smack_access.c、smack_lsm.c和smackfs.c四个源文件。下面本小节就针对这四个文件来分析Smack的实现原理。

    1. Smack的结构体

    由以上分析可以知道LSM的安全域是“void *security”,它可以指向任意类型的指针,正因为此,Smack定义了几个重要的结构体,使得内核对象的安全域指向它们,下表总结了LSM安全域和Smack结构体之间的对应关系:

    内核对象

    内核数据结构

    安全域

    Smack结构体

    文件系统

    super_block

    void *security

    superblock_smack

    管道、文件等

    inode

    void *security

    inode_smack

    进程

    task_struct

    void *security

    task_smack

    网络套接字

    sock

    void *sk_security

    sockect_smack

    除此之外,结构体smack_rule表示访问规则,它以内核链表的形式存在于内存中,用户通过“smackload”工具每写入一个规则,这个规则就被插入到Smack规则链表中,规则结构体只会被插入或者替换,而不会被删除。结构体smack_known包含了smack安全标签以及与之对应的smack安全级别和cipso结构体。smack_cipso包含了cipso的安全级别和安全分类,smk_netlbladdr包含了主机IP地址以及与之对应的Smack安全标签。

    2. Smack访问控制函数

    Smack访问控制函数smk_access定义如下所示:

    int smk_access(char *subject_label, char*object_label, int request);

    smk_access首先根据Smack默认的五条访问规则进行判断,然后在Smack内核规则链表中去查找和参数主客体标签一致的结点,判断此结点的权限是否包含请求的权限request。访问控制函数smk_curacc用于判断当前进程对目标客体是否有访问权限,smk_curacc_on_task用来判断当前进程对目标进程是否有访问权限,它们最终是调用smk_access来进行访问控制。需要指出的是,smk_curacc可以被特权进程绕过,正因为此,Smack不能阻止超级用户或特权进程的一切行为。

    3.Smack的LSM内核

    Smack是在LSM的基础上实现钩子函数以达到强制访问控制的目的,下表总结了Smack访问控制对象及其相应的钩子函数:

    主体

    客体

    控制行为

    钩子函数

    要求权限

    当前进程

    目标进程

    setpgid

    smack_task_setpgid

    当前进程

    目标进程

    getpgid

    smack_task_getpgid

    当前进程

    目标进程

    getsid

    smack_task_getsid

    当前进程

    目标进程

    setnice

    smack_task_setnice

    当前进程

    目标进程

    setioprio

    smack_task_setioprio

    当前进程

    目标进程

    getioprio

    smack_task_getioprio

    当前进程

    目标进程

    setscheduler

    smack_task_setscheduler

    当前进程

    目标进程

    getscheduler

    smack_task_getscheduler

    当前进程

    目标进程

    movememory

    smack_task_movememory

    当前进程

    目标进程

    kill

    smack_task_kill

    当前进程

    目标进程

    wait

    smack_task_wait


    主体

    客体

    控制行为

    钩子函数

    要求权限

    当前进程

    目标文件

    ioctl

    smack_file_ioctl

    根据请求方式

    当前进程

    目标文件

    lock

    smack_file_lock

    当前进程

    目标文件

    fcntl

    smack_file_fcntl

    根据请求方式

    当前文件

    目标进程

    send_sigiotask

    smack_file_send_sigiotask

    当前进程

    目标文件

    file_receive

    smack_file_receive

    根据请求方式

    源套接字

    目标套接字

    netlabel_send

    smack_netlabel_send

    源套接字

    目标套接字

    socket_connect

    smack_socket_connect

    当前进程

    共享内存

    shm_associate

    smack_shm_associate

    根据请求方式

    当前进程

    共享内存

    shm_shmctl

    smack_shm_shmctl

    根据请求方式

    当前进程

    共享内存

    shm_shmat

    smack_shm_shmat

    根据请求方式

    当前进程

    信号量

    sem_associate

    smack_sem_associate

    根据请求方式

    当前进程

    信号量

    sem_semctl

    smack_sem_semctl

    根据请求方式

    当前进程

    信号量

    sem_semop

    smack_sem_semop

    读和写

    当前进程

    消息队列

    msgctl

    smack_msg_queue_msgctl

    根据请求方式

    当前进程

    消息队列

    msgsnd

    smack_msg_queue_msgsnd

    根据请求方式

    当前进程

    IPC

    ipc_permission

    smack_ipc_permission

    根据请求方式

    源套接字

    目标套接字

    unix_stream_connect

    smack_unix_stream_connect

    读和写

    源套接字

    目标套接字

    unix_may_send

    smack_unix_may_send

    源套接字

    目标套接字

    socket_sendmsg

    smack_socket_sendmsg

    目标套接字

    源套接字

    sock_rcv_skb

    smack_socket_sock_rcv_skb

    正如上表所示,Smack是在LSM基础上实现了对进程、文件、套接字、共享内存、消息队列、信号量等的控制。Smack的访问控制非常简单,就是检查主体对客体有没有Smack访问方式,除此之外,Smack使用了钩子函数为进程和文件设置安全标签。当把Smack编译进Linux内核后,Linux操作系统上所有文件和进程默认的安全标签都是“_”。只有特权进程才能改变自身的安全标签,只有特权进程才能设置文件的安全标签。一个进程无法改变另一个进程的安全标签。当父进程创建子进程时,子进程的安全标签就是父进程的安全标签。当一个进程创建文件时,这些文件的安全标签就是进程的安全标签。当一个进程创建套接字时,套接字的安全标签就是该进程的安全标签。当两个进程要通过网络进行通信时,发送和接收IP包的进程必须对彼此都有写权限。

    4. Smack的虚拟文件系统

    smack_access.c和smack_lsm.c构成了Smack强制访问控制机制,但强制访问控制机制是需要安全策略数据库的支持,为此,Smack采取了虚拟文件系统作为其安全策略存储系统,这样Smack决策时间会很短,但这也就意味着,一旦计算机系统重新启动,需求人为得再次设定安全策略。Smack文件系统位于“/smack”目录下,包含了load、cipso、doi、direct、ambient、netlabel、onlycap和logging这几个虚拟文件,它们被组织成Linux内核链表形式,其中最常用到的是load、cipso和netlabel。load文件存放了Smack的安全策略,cipso存放cipso值,包括安全级别和安全分类,netlabel存放了主机的IP地址和其相关的Smack标签,cipso和netlabel用于Smack网络通信控制。Smack重写文件系统操作函数,并使用注册文件系统、挂载文件系统和初始化系统调用等内核API来实现虚拟文件系统。

    2.4.3 Android内核的Smack编译

    Smack内核代码除了上面介绍的四个文件外,还有makefile和Kconfig两个文件。makefile文件设定了Smack内核编译规则,而Kconfig文件指定了Smack的配置信息,其中就有一项是“bool simplified mandatoryaccess control kernel depend on NETLABEL & SECURITY_NETWORK”,从这条信息中可以看出,要想编译Smack,Android内核必须配置“NETLABEL”和“SECURITY_NETWORK”两项。

    本节以panda内核为例演示编译Smack内核的过程,首先从Google官网或pandaboard官网上下载panda内核,解压后会有panda/kernel-ics-chipsee-panda文件夹。

    1. 打开“shell”,输入指令“cdpanda/kernel-ics-chipsee-panda,cd arch/arm/configs”,找到目录下的缺省配置文件panda_chinese_def;

    2. 在终端上输入指令“vim panda_chinese_def”,打开此配置文件,经过查找,可以发现这个文件里没有配置“NETLABEL”和“SECURITY_NETWORK”两项,这也是Smack没有被编译进panda内核的原因;

    3. 用vim添加配置信息,如下所示:

    4. 保存退出后,输入如下指令:


    以上指令也同样适用于模拟器内核编译,需要强调的是,在编译Smack之前,要确保panda内核或模拟器内核已经配置了ext2或ext4或者支持扩展属性的yaffs2文件系统,否则Smack无法正常运行。为了验证Smack确实在Android系统上发挥了效果,本小节给出一个实验进行验证。

    1. 实验环境:

    软件环境为Ubuntu10.04,编译好的Android4.0源码和goldfish内核。

    2. 实验过程:

    (1)编写getsmk.c源码,getsmk.c输入是命令行参数,输出是文件的安全标签;

    (2)在Android源码目录下新建getsmk文件夹,并将getsmk.c拷贝到给文件夹下,编写Android.mk文件,让getsmk能够被交叉编译;

    (3)使用如下指令来启动模拟器:

    “emulator –sdcard/host/android4.0/sdcard.img –kernel/host/android4.0/kernel/goldfish/arch/arm/boot/zImage”

    (4)等待模拟器运行正常后,打开终端shell,使用“adb push”指令将可执行文件getsmk拷贝到“/data”目录下,随机选择文件,进行测试,测试结果如下:

    3. 实验结论:

    Smack会在系统初始化时使用钩子函数smack_d_instantiate将Linux系统所有文件和进程的安全标签都设置为“_”,因此,通过以上实验,smack确实在Android系统上生效了。



  • 相关阅读:
    Objective-C代码规范
    Http中Get/Post请求区别
    使用Vitamio打造自己的Android万能播放器
    Vitamio
    图片瀑布流
    TCP与UDP
    SQLite基本操作总结
    IOS文件操作的两种方式:NSFileManager操作和流操作
    JSON和XML
    一些iOS常用的第三方库和控件及第三方框架还有动画
  • 原文地址:https://www.cnblogs.com/pangblog/p/3265294.html
Copyright © 2020-2023  润新知