selinux移植调试记录

前言

由于近期在做的一个linux项目要上selinux功能,驱动上倒是问题不多,但是在配置权限时真的是各种难搞的问题,现在经过公司cybersecurity专家的不懈努力,总算是有所进展,做个记录。

什么是selinux

简单说selinux就是安全增强型Linux(Security-Enhanced Linux),linux本身已经集成了这个功能,所以它就是一个内核模块,是一个安全子系统。

主要作用

最大限度减小系统中服务进程可访问的资源,简单说就是最小权限原则,系统中的进程只拥有它所需要的访问权限。

selinux的组成

主体:进程
对象:被主体访问的文件、目录、设备节点等
政策和规则:系统中有大量的文件和进程,为了节省时间和开销,通常我们只是选择性的对某些进程进行管制。
安全上下文:进程和文件都有自己的安全上下文,比如:root:sysadm_r:sysadm_systemd_t,只有两边的上下文和策略文件中制定的规则对上了,进程才能进行相应的操作,而这个上下文主要有创建文件的位置和进程所决定。

工作模式

可以在/etc/selinux/config中设定

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.	//强制模式。违反selinux规则的行为都会被阻止并记录到日志中
# permissive - SELinux prints warnings instead of enforcing.		//宽容模式。调试用,不会阻止违反selinux规则的行为,但会记录日志
# disabled - No SELinux policy is loaded.	//关闭selinux
SELINUX=enforcing
#SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
# default - equivalent to the old strict and targeted policies
# mls     - Multi-Level Security (for military and educational use)
# src     - Custom policy built from source
SELINUXTYPE=crs3_0

# SETLOCALDEFS= Check local definition changes
SETLOCALDEFS=0

改完后需要重启系统
ps:enforcing和permissive模式切换可通过setenforce 1|0指令进行修改。

工作流程

当一个主体要去访问一个对象时,首先检测当前的selinux模式状态,如果是disable模式,那直接检查对象的rwx权限是否允许主体的访问操作;如果是permissive或者enforcing模式,则会对当前的policy文件中制定的规则进行比对阶段,通过比较主体于客体的安全上下文以及对应的动作是否有在规则文件中被允许声明,如果有,则允许主体继续下一步的操作;如果没有,则会报错阻止主体的访问并记录日志,但是在permissive下不会阻止,主体还是能够继续下一步对客体的访问。

查看当前的文件或进程的安全上下文

查询文件或目录上下文
ls -Z 路径

-r--r--r--    1 root     root     system_u:object_r:system_map_t           0 Feb  1 00:00 kallsyms

查询进程的安全上下文
ps -auxZ | grep 进程名

system_u:system_r:infra_t       root       259  0.0  0.1   5368  1156 ?        Sl   00:00   0:00 vmf

uboot和kernel中的配置

uboot需要在启动参数中打开selinux

-        "bootargs_set=setenv bootargs console=" CONFIG_CONSOLE_DEV "," BAUDRATE " ${rootfs} rootwait ro uboot_version=" PLAIN_VERSION " maxcpus=" USE_CPUS " lpj=" DEF_LPJ " loglevel=" LOG_LEVEL " " CONFIG_MFG_NAND_PARTITION "\0" \
+        "bootargs_set=setenv bootargs console=" CONFIG_CONSOLE_DEV "," BAUDRATE " ${rootfs} rootwait ro uboot_version=" PLAIN_VERSION " maxcpus=" USE_CPUS " lpj=" DEF_LPJ " loglevel=" LOG_LEVEL " security=selinux selinux=1 enforcing=1 " CONFIG_MFG_NAND_PARTITION "\0" \

kernel在menuconfig中打开selinux相关配置

-# CONFIG_AUDIT is not set
+CONFIG_AUDIT=y
 CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_WATCH=y
+CONFIG_AUDIT_TREE=y
-# CONFIG_SECURITY is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITY_WRITABLE_HOOKS=y
 # CONFIG_SECURITYFS is not set
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_PATH is not set
+CONFIG_LSM_MMAP_MIN_ADDR=32768
 CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
 # CONFIG_HARDENED_USERCOPY is not set
 # CONFIG_STATIC_USERMODEHELPER is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0
+# CONFIG_SECURITY_SMACK is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_SECURITY_LOADPIN is not set
+# CONFIG_SECURITY_YAMA is not set
+CONFIG_INTEGRITY=y
+# CONFIG_INTEGRITY_SIGNATURE is not set
+CONFIG_INTEGRITY_AUDIT=y
+# CONFIG_IMA is not set
+# CONFIG_EVM is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+CONFIG_AUDIT_GENERIC=y

refpolicy文件内容介绍

refpolicy主要是配置进程与文件目录的安全上下文以及规则
其中有三类文件和规则的配置密切相关

  • xx.if 这个文件中的内容是一些接口,类似与代码中的函数,这个接口中会记录一部分规则,我们可以通过调用这些接口,来完成一些规则的配置,这个接口中可以一次增加多个规则,减少调试时间
########################################
## <summary>
##	Set the attributes for generic
##	character device files.
## </summary>
## <param name="domain">
##	<summary>
##	Domain allowed access.
##	</summary>
## </param>
#
interface(`dev_setattr_generic_chr_files',`
	gen_require(`
		type device_t;
	')

	allow $1 device_t:chr_file setattr;
')
  • xx.fc 这个文件配置的就是文件及进程安全上下文,配置权限域
/opt/bt_proc		--	gen_context(system_u:object_r:btproc_exec_t,s0)
  • xx.te 这个文件就是最重要的,我们会在里面声明权限域,以及允许这个权限域对其他的权限域的一些访问权限规则的声明
allow btproc_t bin_t:dir { search remove_name create read write open getattr lock };

其他还有几个文件对于配置规则来说是比较有帮助的,在te文件中添加规则时,结合这几个文件看,可以提高效率,以及代码的简洁

  • files_patterns.spt 这个文件中定义了一些权限宏,这些宏会在xx.if文件中被使用
#
# Directory patterns (dir)
#
# Parameters:
# 1. domain type
# 2. container (directory) type
# 3. directory type
#
define(`getattr_dirs_pattern',`
	allow $1 $2:dir search_dir_perms;
	allow $1 $3:dir getattr_dir_perms;
')
  • ogj_perm_sets.spt 这个文件中定义了各种类型对象的一些权限集合
#
# Directory (dir)
#
define(`getattr_dir_perms',`{ getattr }')
define(`setattr_dir_perms',`{ setattr }')
define(`search_dir_perms',`{ getattr search open }')
define(`list_dir_perms',`{ getattr search open read lock ioctl }')
define(`add_entry_dir_perms',`{ getattr search open lock ioctl write add_name }')
define(`del_entry_dir_perms',`{ getattr search open lock ioctl write remove_name }')
define(`rw_dir_perms', `{ open read getattr lock search ioctl add_name remove_name write }')
define(`create_dir_perms',`{ getattr create }')
define(`rename_dir_perms',`{ getattr rename }')
define(`delete_dir_perms',`{ getattr rmdir }')
define(`manage_dir_perms',`{ create open getattr setattr read write link unlink rename search add_name remove_name reparent rmdir lock ioctl }')
define(`relabelfrom_dir_perms',`{ getattr relabelfrom }')
define(`relabelto_dir_perms',`{ getattr relabelto }')
define(`relabel_dir_perms',`{ getattr relabelfrom relabelto }')

如何在te文件中增加规则

以这个报错实例来说明

报错实例:audit: type=1400 audit(1612137687.570:207): avc:  denied  { read } for  pid=3313 comm="sh" name="root" dev="ubifs" ino=24504 scontext=root:sysadm_r:sysadm_systemd_t tcontext=user_u:object_r:user_home_dir_t tclass=dir permissive=1

解析: { read } 表示当前主体缺少的权限,pid=3313 comm="sh"表示当前的主体进程,scontext=root:sysadm_r:sysadm_systemd_t即主体的安全上下文,sysadm_systemd_t即主体权限域,tcontext=user_u:object_r:user_home_dir_t即客体的安全上下文,user_home_dir_t即客体权限域,tclass=dir表示客体类型是dir目录
我们需要找到的关键点是{}、主体权限域、客体权限域、tclass
在te文件中增加规则的格式就是 allow 主体权限域 客体权限域:tclass {},所以就可以写成

allow sysadm_systemd_t user_home_dir_t:dir { read };

对于主体和客体域一致的情况下,可以把权限写进同一个{}中,减少行数

另外我们还要在te文件中声明主体域和客体域,一般我们都是在主体域的文件中增加规则,所以需要声明客体域,否则在编译规则文件的时候就会报错
格式type 客体域

#这里因为不是第一次声明这个域,所以要写在require{}里面
require{
type bin_t;
}

同样创建属性也是,attribute 属性

attribute mlsfilerelabel;
但还需要一下声明把infra_t域与mlsfilerelabel属性关联起来
typeattribute infra_t mlsfilerelabel;

问题

在增加规则的时候,不知道为什么总是有部分规则不管写成什么样都还是会报,没有生效
现在调查发现主要是当前的selinux type类型是mls,这个是一个selinux的多级安全的规则类型,可以对系统文件和进程进行分级,包括敏感度和组别。在满足某种条件的时候,mls的约束规则就会限制主体对这种类型的客体的访问。
所以有两种解决思路

  1. 原则上mls规则不要去改变,所以我们只能针对域进行修改,需要我们的域满足条件才能不被约束
mlsconstrain file { write create setattr relabelfrom append unlink link rename mounton }
( ( l1 domby l2 ) or
( t1 == mlsfilewritedown ) );
比如上面这句,表示的是主体域对客体域的file类型的{ write create setattr relabelfrom append unlink link rename mounton }权限将被约束,除非满足( ( l1 domby l2 ) or ( t1 == mlsfilewritedown ) )的条件
所以我们就给主体域增加一个类型(具有 mlsfilewritedown 属性)才能不受这个约束限制了。
  1. 修改selinux的type,不去使用mls,改用std,就可以跳过这个敏感度和组别的识别流程,修改build.conf文件应该就行

mls的介绍

摘录自selinux文档

多层安全(MLS)一般都是基于 Bell-LaPadula 模型[5],在 MLS 模型中,所有主体和客
体都标记有安全级别,在我们的例子中,我们有一个 PUBLIC 和 SECRET 安全级别,这两个级
别代表了数据的敏感程度(SECRET 的敏感度比 PUBLIC 的敏感度要高),在 MLS 中,主体总
是可以读写客体,除此之外,主体还可以读取底层客体(向下读取),写入高层客体(向上
写入),然而,主体可能永远不会读取高层客体(无向上读取),也不写入底层客体(无向
下写入),意思就是信息可以从底层流向高层,但不能反过来,因此要保护高层数据的机密
性。
MLS 是对访问控制最根本的改变,不再是数据所有者任意地决定谁可以访问客体,此外,
对大部分被认为不受信任的软件我们也有足够的安全措施,因为信息流规则阻止了不正当的
数据访问,在 MLS 中,通过固定的规则决定数据如何共享,而不管用户的请求(更重要的是
他们运行的程序),MLS 实现了大部分 MAC 机制,在目前流行的操作系统中普遍存在,MAC
机制与 MLS 类似,也是经过深思熟虑建立起来的,它实现了小部分固定的安全属性。
MLS 的主要弱点是它严格地,以不可改变的方式实现了单一安全目标(即保护政府文件
敏感数据的机密性),不是所有的操作系统安全业务都与数据机密性有关,大多数都对保密
政府文件(包括许多处理保密数据的政府系统)的强硬的简单的模型不肯顺从,为了在 MLS
中扩大这个目标,主体必须被授予安全策略特权(即违反无旁路的原则),并信任不会违反
策略的目的,这个不屈性和有限的焦点使 MLS 和类似的 MAC 机制实现了充足的要求。

有四个控制操作
符可以将两个 MLS 安全级别关联起来,如:
dom:如果 SL1 的敏感度大于或等于 SL2 的敏感度,则 SL1 dom(优于) SL2,SL1 的范
畴就是 SL2 范畴的一个超集。
domby:如果 SL1 的敏感度小于或等于 SL2 的敏感度,则 SL1 domby SL2,SL1 的范畴是
SL2 的子集。
eq:如果 SL1 的敏感度等于 SL2 的敏感度,则 SL1 eq SL2,SL1 和 SL2 的范畴也是相同
的。
incomp:如果SL1的范畴和SL2的范畴不能进行对比(即既不是子集也不是超集或其他),
那么 SL1 incomp(不可对比)SL2。

SELinux 中 MLS 的约束是附加在 TE 规则中的,如果启用了 MLS,要授予访问权两个检查
都必须通过

编译

refpolicy文件的编译一般开源库中都是有makefile的,主要就是增加一些库组件

sudo apt install policycoreutils
sudo apt install policycoreutils
sudo apt install semodule-utils
sudo apt install checkpolicy
sudo apt install libzstd-dev

然后我们怎么把生成的安全上下文(file_context)作为标签打进文件系统,直接打包?no no no,这里需要用到mkfs.ubifs工具,将rootfs.tar.bz2打包成rootfs.raw镜像,同时还要修改编译参数

tar -xvjf ./input/rootfs.tar.bz2 -C ./temp/rootfs > /dev/null && sync
$MKFS_UBIFS -m $M_IO -e $LEB_SIZE -c $ROOTFS_MAX_LEB -r ./temp/rootfs ./temp/rootfs.img -F -v && sync
写成
tar -xvjf ./input/rootfs.tar.bz2 -C ./temp/rootfs > /dev/null && sync
$MKFS_UBIFS -m $M_IO -e $LEB_SIZE -c $ROOTFS_MAX_LEB -r ./temp/rootfs ./temp/rootfs.img -F -v --selinux=./temp/rootfs/etc/selinux/$SELINUX_T/contexts/files/file_contexts && sync

结束

大概先记录这些,后面有时间再继续补充。另外,建议每修改一部分可以验证一下enforcing模式的状态,看设备能不能正常起来。以上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值