SELinux策略实例--type_transition(一)

来源:互联网 发布:淘宝商家怎么做活动 编辑:程序博客网 时间:2024/06/05 01:11

在上一篇博客http://blog.csdn.net/keheinash/article/details/68945914说明了如何在不重新编译整个SELinux源码的情况下,单独编译加载一个模块。这次在模块里增加一个type_transition的实例,并且编译加载,检查是否生效。

type_tansition的作用和语法

SELinux中,安全上下文(Security Context)的定义是User:Role:Type:MLS。在TE(Type Enforcement)策略中,Type(类型)是我们需要重点关注的。

type_transition是类型转换语句,允许主体或者客体在条件符合的情况下,将安全上下文中的type转移成为指定的类型。一般适用于两种场景:
1.进程创建新的客体时,新客体的类型来自type_transition的规定
2.进程执行execve系统调用后,进程的新类型来自type_transition的定义

type_transition的语法:

type_transition source_type target_type : class default_type;

策略编写

下面针对第二种场景,我们就在上一篇博客中使用的myapp模块加入type_transition策略:让一个source_type的进程,在执行target_type的可执行文件后,进程的类型变为default_type。并且加载编译加载myapp模块,并检查策略是否生效。

在这个场景下,我们先找到source_type是哪一种类型。如果当前目录下,有一个可执行文件a,那么当我执行./a的时候,进程就会去执行文件a的代码。那么这个启动a的进程是哪一个呢?当我们在命令行下执行./a时,当前所处的shell进程,会fork产生一个子进程,子进程是拷贝了父进程的代码的,那么为了执行a的代码,子进程会使用execve函数,这个函数用a文件的代码替换掉父进程的代码,这样我们a的代码就被执行起来了。而fork出来的子进程,继承了父进程的安全上下文,所以我们使用ps -Z查看当前shell的安全上下文,就可以知道子进程的type,也就是我们要找的source_type:
这里写图片描述
当前的shell类型是bash,type是sysadm_t,也就是我们要找的找的source_type。

接着我们指定target_type,为了便于验证,我指定一个自己定义的类型myapp_exec_t,因为不是系统默认定义的类型,为了可以使用这个类型,我们需要在myapp.te中定义:
这里写图片描述
在进程执行了myapp_exec_t的文件后,我们希望它变成某个我们指定的类型default_type,同样为了验证方便,我自定义一个myapp_t作为default_type,也在myapp.te中定义:
这里写图片描述

然后才可以在myapp.fc中,指定可执行文件的上下文,其实最主要的就是指定其type:
这里写图片描述

接下来是最重要的,在myapp.te中增加策略语句:

type_transition sysadm_t myapp_exec_t:process myapp_t;

为了让这这个转换可以顺利完成,我们还要加上一些allow规则:

allow sysadm_t myapp_exec_t:file execute;#允许sysadm_t类型的进程对myapp_exec_t类型的文件进行execute操作allow myapp_t myapp_exec_t:file entrypoint;#允许myapp_exec_t类型的文件可以“进入”myapp_exec_t域allow sysadm_t myapp_t:process transition;#允许进程从sysadm_t类型转换至myapp_exec_t类型

将以上语句写入到myapp.te:
这里写图片描述

策略编译与加载

然后编译,结果出错了:
这里写图片描述
提示找不到sysadm_t类型,这个类型我们没有定义过,但是ps -Z出来却发现当前的shell拥有这种类型,说明这个是SELinux内建的类型,所以我们在te文件中要显示的声明引用:
这里写图片描述
再次编译,通过后加载:
这里写图片描述

验证

接下来进行验证,由于在myapp.fc定义了这一句:
这里写图片描述
所以我们在/home/chenzx下编译一个可执行文件出来,为了便于观察,用c++写一段死循环代码,循环里进行一定时间的sleep:

#include <iostream>#include <unistd.h>int main(){        while(1){                std::cout << "selinux test!" << std::endl;                sleep(5);        }}

然后编译这段代码,生成可执行文件myapp,接着后台执行myapp,然后用ps -Z观察:
这里写图片描述
发现myapp进程仍然是sysadm_t进程,没有变成我们指定的myapp_t类型。

原因是因为我们刚创建的myapp文件,并不是myapp_exec_t类型,用ls -Z查看:
这里写图片描述
所以type_transition没有生效,可是我们明明在myapp.fc里定义了myapp文件的安全上下文的,这是因为当在一个目录下创建新的文件时,默认是会继承目录的安全上下文的,或者是SELinux的源码里定义了某些策略,让在特定类型目录下创建的文件成为指定类型。如果要让我们的定义生效,一般有两个方法:
1.使用restorecon命令,恢复文件的安全上下文
2.使用autorelabel,在系统重启的时候自动relabel整个系统

之后会专门写一篇博客讲这个问题,现在我们先用restorecon命令:
这里写图片描述

可以看到myapp的安全上下文已经和我们的定义一致,现在再次执行myapp,然后ps检查:
这里写图片描述
进程已经变成了myapp_t类型了,说明策略生效了

如果myapp不是二进制文件,而是脚本文件?

做完这个测试后,我想再试一下,如果myapp是一个脚本,策略是否也会生效?
于是我写了一个shell脚本,代码很简单,运行后,sleep一段时间,便于观察进程的上下文:

#!/bin/bashecho "test"sleep 120

同样地,使用restorecon命令,确保myapp上下文和我们定义的一致,然后执行bash myapp,ps查看结果:
这里写图片描述
进程居然没有转换成为myapp_t类型,再次用ls检查,发现myapp脚本文件确实已经是myapp_exec_t类型。

是不是和脚本有关,难道我们写的规则只适用于二进制文件?于是我把myapp变成一个python脚本,进行同样的测试,python代码如下:

#!/usr/bin/python

import time

while True:
time.sleep(5)
continue


restorecon后,后台执行该脚本,用ps命令查看进程安全上下文:
这里写图片描述
进程也没有变成我们期望的类型

难道真的是我们写的策略规则只适用于二进制可执行文件,如果真是这样,那如果有一天我们希望可执行文件是一个脚本也能达到这个效果时要怎么办呢?
这两个问题在下一篇博客讨论。

1 0
原创粉丝点击