由于近期在做的一个linux项目要上selinux功能,驱动上倒是问题不多,但是在配置权限时真的是各种难搞的问题,现在经过公司cybersecurity专家的不懈努力,总算是有所进展,做个记录。
简单说selinux就是安全增强型Linux(Security-Enhanced Linux),linux本身已经集成了这个功能,所以它就是一个内核模块,是一个安全子系统。
最大限度减小系统中服务进程可访问的资源,简单说就是最小权限原则,系统中的进程只拥有它所需要的访问权限。
主体:进程
对象:被主体访问的文件、目录、设备节点等
政策和规则:系统中有大量的文件和进程,为了节省时间和开销,通常我们只是选择性的对某些进程进行管制。
安全上下文:进程和文件都有自己的安全上下文,比如: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需要在启动参数中打开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=yCONFIG_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=32768CONFIG_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主要是配置进程与文件目录的安全上下文以及规则
其中有三类文件和规则的配置密切相关
########################################
##
## Set the attributes for generic
## character device files.
##
##
##
## Domain allowed access.
##
##
#
interface(`dev_setattr_generic_chr_files',`gen_require(`type device_t;')allow $1 device_t:chr_file setattr;
')
/opt/bt_proc -- gen_context(system_u:object_r:btproc_exec_t,s0)
allow btproc_t bin_t:dir { search remove_name create read write open getattr lock };
其他还有几个文件对于配置规则来说是比较有帮助的,在te文件中添加规则时,结合这几个文件看,可以提高效率,以及代码的简洁
#
# 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;
')
#
# 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 }')
以这个报错实例来说明
报错实例: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的约束规则就会限制主体对这种类型的客体的访问。
所以有两种解决思路
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 属性)才能不受这个约束限制了。
摘录自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模式的状态,看设备能不能正常起来。以上