linux selinux基础

https://www.redhat.com/zh/topics/linux/what-is-selinux

  • 背景:

    安全增强型 Linux(Security-Enhanced Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。

    SELinux 主要由美国国家安全局开发。2.6 及以上版本的 Linux 内核都已经集成了 SELinux 模块。

    SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。

    设想一下,如果一个以 root 身份运行的网络服务存在 0day 漏洞,黑客就可以利用这个漏洞,以 root 的身份在您的服务器上为所欲为了。是不是很可怕?

    SELinux 就是来解决这个问题的。

  • 自主访问控制(DAC)

    在没有使用 SELinux 的操作系统中,决定一个资源是否能被访问的因素是:某个资源是否拥有对应用户的权限(读、写、执行)。

    只要访问这个资源的进程符合以上的条件就可以被访问。

    而最致命问题是,root 用户不受任何管制,系统上任何资源都可以无限制地访问。

    这种权限管理机制的主体是用户,也称为自主访问控制(DAC)。

  • 强制访问控制(MAC)

    在使用了 SELinux 的操作系统中,决定一个资源是否能被访问的因素除了上述因素之外,还需要判断每一类进程是否拥有对某一类资源的访问权限。

    这样一来,即使进程是以 root 身份运行的,也需要判断这个进程的类型以及允许访问的资源类型才能决定是否允许访问某个资源。进程的活动空间也可以被压缩到最小。

    即使是以 root 身份运行的服务进程,一般也只能访问到它所需要的资源。即使程序出了漏洞,影响范围也只有在其允许访问的资源范围内。安全性大大增加。

    这种权限管理机制的主体是进程,也称为强制访问控制(MAC)。

    而 MAC 又细分为了两种方式,一种叫类别安全(MCS)模式,另一种叫多级安全(MLS)模式。

    下文中的操作均为 MCS 模式。

    在 DAC 模式下,只要相应目录有相应用户的权限,就可以被访问。而在 MAC 模式下,还要受进程允许访问目录范围的限制。

SELinux由这几部分组成:

主体(Subject)

SELinux中需要管理(限制)的主体是进程或线程。

目标(Object)

目标就是文件系统上的资源,比如文件、目录、端口等。

策略(Policy)

由于操作系统中存在大量的进程和文件,无法一一管理,所以SELinux通过设定一些策略来进行统一管理,由策略决定哪些进程需要管理,以及如何管理。一个策略中会有多条规则,每条规则可以关闭或开启。策略通过这些规则来详细规定某个服务是否对某些资源具有相关权限。

规则是模块化和可扩展的,新安装的程序可以通过添加新模块的方式添加新的规则。同样的,用户也可以手动添加或删除规则。

在CentOS7中,默认提供三个策略:
```
targeted:默认使用的策略,针对网络服务限制较多,对于本地服务限制较少。
minimum:以targeted为基础,仅针对选定的网络服务进行限制。
mls:多级安全保护,会对所有进程进行限制。是最严格最完整的SELinux规则,安全度最高,但不易使用。
```

安全上下文(Security Context)

安全上下文分为两部分:主体的和目标的,只有主体和目标的安全上下文对应上,才能具有相应的操作权限。安全上下文是 SELinux 的核心。

安全上下文的结构及含义

安全上下文有四个字段,分别用冒号隔开。形如:system_u:object_r:admin_home_t:s0。
  • 使用命令ls -Z可以查看文件和目录的安全上下文:
[icexmoon@xyz ~]$ ls -Z
drwxrwxr-x. icexmoon icexmoon unconfined_u:object_r:home_bin_t:s0 bin
drwxrwxr-x. icexmoon icexmoon unconfined_u:object_r:user_home_t:s0 shell_scripts
  • 进程的安全上下文

类似的,我们也可以查看进程的安全上下文字段:

[icexmoon@xyz ~]$ ps -eZ
LABEL                              PID TTY          TIME CMD
system_u:system_r:init_t:s0          1 ?        00:00:04 systemd
system_u:system_r:kernel_t:s0        2 ?        00:00:00 kthreadd
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2316 ? 00:00:00 sshd
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2317 pts/0 00:00:00 bash
system_u:system_r:abrt_t:s0-s0:c0.c1023 2339 ?  00:00:00 abrt-dbus
system_u:system_r:ksmtuned_t:s0   2388 ?        00:00:00 sleep
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2389 pts/0 00:00:00 ps

其中unconfined_u:object_r:home_bin_t:s0就是SELinux中目标的上下文,字段以:分隔,含义为:

user(用户):

主要分为两类:system_u为系统服务创建的文件,unconflined_u为用户进程创建的文件。

role(角色):

均为object_r表示一个文件

type(类型):

这是在targeted模式下唯一需要关注的字段,只有主体的类型和目标的类型对应上,才会认为安全上下文匹配上了,进而赋予权限。

可以使用crond这个服务进程进行说明:

[icexmoon@xyz ~]$ ps -eZ | grep cron
system_u:system_r:crond_t:s0-s0:c0.c1023 1257 ? 00:00:01 crond
system_u:system_r:crond_t:s0-s0:c0.c1023 1259 ? 00:00:00 atd
[icexmoon@xyz ~]$ ll -dZ /usr/sbin/crond /etc/crontab /etc/cron.d /var/spool/cron
drwxr-xr-x. root root system_u:object_r:system_cron_spool_t:s0 /etc/cron.d
-rw-r--r--. root root system_u:object_r:system_cron_spool_t:s0 /etc/crontab
-rwxr-xr-x. root root system_u:object_r:crond_exec_t:s0 /usr/sbin/crond
drwx------. root root system_u:object_r:user_cron_spool_t:s0 /var/spool/cron

可以看到,crond的type是crond_t,而理论上crond会操作的相关文件(/etc/crontab)等的相关type是system_cron_spool_t和crond_exec_t,所以在SELinux中必然有相关规则可以让crond_t这个类型对应到system_cron_spool_t和crond_exec_t这两个类型上

  • 上下文的描述文件(*_contexts)

    可以在上下文的描述文件中为需要的对象指定标签

    • file_contexts:

    用于为文件分配标签,并且可供多种用户空间组件使用。在创建新政策时,需创建或更新该文件,以便为文件分配新标签。如需应用新的file_contexts,需重新构建文件系统映像,或对要重新添加标签的文件运行restorecon(比如重新加载权限restorecon -R /(对应权限目录))。在升级时,对file_contexts所做的更改会在升级过程中自动应用于系统和用户数据分区。此外,还可以通过以下方式使这些更改在升级过程中自动应用于其他分区:在以允许读写的方式装载相应分区后,将restorecon_recursive(重载权限)调用添加到init.board.rc文件中

    • property_contexts:

    用于为Android系统属性分配标签,以便控制哪些进程可以设置这些属性。在启动期间,init进程会读取此配置

    • service_contexts:

    用于为Android Binder服务分配标签,以便控制哪些进程可以为相应服务添加(注册)和查找(查询)Binder引用。在启动期间,servicemanager进程会读取此配置

    • genfs_contexts:

    用于为不支持扩展属性的文件系统(例如,proc或vfat)分配标签。此配置会作为内核政策的一部分进行加载,但更改可能对内核inode无效。要全面应用更改,需要重新启动设备,或卸载并重新装载文件系统。此外,通过使用context=mount选项,还可以为装载的特定系统文件(例如vfat)分配特定标签

    • seapp_contexts:

    用于为应用进程和/data/data目录分配标签。在每次应用启动时,zygote进程都会读取此配置;在启动期间,installd会读取此配置

    • mac_permissions.xml:

    用于根据应用签名和应用软件包名称(后者可选)为应用分配seinfo标记。随后,分配的seinfo标记可在seapp_contexts文件中用作密钥,以便为带有该seinfo标记的所有应用分配特定标签。在启动期间,system_server会读取此配置

简单来说:

file_contexts //系统中所有file_contexts安全上下文
seapp_contexts //app安全上下文
property_contexts //属性的安全上下文
service_contexts    //service文件安全上下文
genfs_contexts //虚拟文件系统安全上下文
SELinux 有三种工作模式,分别是:
  1. enforcing:强制模式。违反 SELinux 规则的行为将被阻止并记录到日志中。

  2. permissive:宽容模式。违反 SELinux 规则的行为只会记录到日志中。一般为调试用。

  3. disabled:关闭 SELinux。

SELinux 工作模式可以在 /etc/selinux/config 中设定。

如果想从 disabled 切换到 enforcing 或者 permissive 的话,需要重启系统。反过来也一样。

enforcing 和 permissive 模式可以通过 setenforce 1|0 命令快速切换

  • 在sepolicy中添加相应权限

MTK的权限文件有如下两个目录

Android N及之前:
路径一:device/mediatek/common/sepolicy
路径二:system/sepolicy/

Android O、P:

路径一:device/mediatek/sepolicy
路径二:system/sepolicy/

selinux调试及常见问题解决

当我们添加权限之后,编译是有可能会碰到neverallow的问题,此时会编译报错,原因是因为新添加的sepolicy项目违反了domain.te 中规定的的总策略原则。如果这时直接修改neverallow规则,可以通过编译,但是可能会导致CTS测试失败,所以这时就要想办法绕过neverallow规则。

SeLinux的log:

avc: denied { add_name } for name=“22_X_50_Y_20_OK_36666.bmp” scontext=u:r:hal_fingerprint_default:s0 tcontext=u:object_r:oxi_hal_image_file:s0 tclass=dir permissive=0
avc: denied { 操作权限 } scontext=u:r:源类型:s0 tcontext=u:r:目标类型:s0 tclass=访问类别 permissive=0

以在AndroidP上工程模式闪光灯测试项问题为例,讲述此方法的一个流程。
闪光灯测试项以对闪光灯节点进行置1和置0来打开和关闭闪光灯。
闪光灯节点路径:sys/devices/virtual/flashlight_core/flashlight/flashlight_contrl

其SeLinux类型为:

查看某一文件的SeLinux类型的命令如下:
ls -alZ
-rwxrwxrwx 1 system radio u:object_r:sysfs:s0 4096 2018-11-12 02:56 flashlight_contrl

按照此前介绍的方法,我们需要在em_svr.te和radio.te文件中分别加入如下权限:

allow em_svr sysfs:file { open read write };
allow radio sysfs:file { open read write };

但是编译时就会发现,sysfs类型的文件是不允许em_svr、radio类型的进程对其进行write的操作的。

解决方法如下:
(1)在file.te中增加一种类型
type sysfs_hct_file, fs_type, sysfs_type;
(2) 在file_context中重新定义闪光灯节点的文件类型
/sys/devices/virtual/flashlight_core/flashlight/flashlight_contrl u:object_r:sysfs_hct_file:s0
(3) 在em_svr.te和radio.te文件分别加入权限
allow em_svr sysfs_hct_file:file { open read write };
allow radio sysfs_hct_file:file { open read write };

按上述流程之后,查看闪光灯节点的文件类型如下:

-rwxrwxrwx 1 system radio u:object_r:sysfs_hct_file:s0 4096 2018-11-13 14:49 flashlight_contrl

其类型已变为我们定义的类型。

vendor/file_contexts 中声明执行权限;
vendor/hal_camera_default.te 声明 hal_camera_default,绑定初始化父服务并申请相关权限;
prebuilts/api/26.0/nonplat_sepolicy.cil 声明引用关系。

  • dmesg 中涉及缺失的权限

dmesg | grep “u:r:hal_camera”

[   72.120184] type=1400 audit(1668749846.926:144): avc: denied { read } for comm="HwBinder:273_1" name="u:object_r:default_prop:s0" dev="tmpfs" ino=18930 scontext=u:r:hal_camera_default:s0 

b) 日志中提示具体权限对应关系

scontext=u:r:hal_camera_default:s0 --> hal_camera_default.te
tcontext=u:object_r:default_prop:s0 --> default_prop
tclass=file --> file
denied { read } --> read

串联后书写为:hal_camera_default.te 中增加

allow hal_camera_default default_prop:file read;

此时确定为缺少 get_prop 权限允许,可以改为

get_prop(hal_camera_default, default_prop);

c) 将缺失的权限补齐到对应 xxx.te
system/sepolicy/vendor/hal_camera_default.te

--- a/vendor/hal_camera_default.te
+++ b/vendor/hal_camera_default.te
@@ -9,3 +9,4 @@ allow hal_camera_default fwk_sensor_hwservice:hwservice_manager find;
 # For collecting bugreports.
 allow hal_camera_default dumpstate:fd use;
 allow hal_camera_default dumpstate:fifo_file write;
+get_prop(hal_camera_default, default_prop);
\ No newline at end of file
  • 通过selinux增加设备节点的权限
device.te 添加
type test_dev_device, dev_type;

file_contexts 添加
/dev/xxx_spi[0-9]+  u:object_r:test_dev_device:s0

test_bin.te 添加
allow test_bin test_dev_device:chr_file {rw_file_perms};

  • 无法读取属性问题

当在.mk文件中,新增一个prop定义的时候,例如 PRODUCT_PROPERTY_OVERRIDES += vendor.xxx.sys.test=1

会发生无法读写vendor.xxx.sys.test这个属性的问题, 因为存在SeLinux相关的问题。

这里以set prop权限为例去说明。

  • 定义type

    Type对应一个或者几个attribute,Type的定义格式:

    type type_name, attribute1, attribute2;

    在property.te文件中新增

    type mtk_xxx_sys_prop, property_type,extended_core_property_type;
    声明一个mtk_xxx_sys_prop的type,也可以说是标签。
    
  • 定义vendor.xxx.sys.test 的安全上下文

    定义其type为mtk_xxx_sys_prop。

    在property_contexts文件中新增

    vendor.xxx.sys.test u:object_r:mtk_xxx_sys_prop:s0
    
  • 定义allow规则

    允许system_app和system_server进程

    在system_app.te文件中新增

    set_prop(system_app, mtk_xxx_sys_prop)
    

    在system_server.te文件中新增

    set_prop(system_server,mtk_xxx_sys_prop)
    

    下面来看看set_prop函数。

     ````
     alps/system/sepolicy/public/te_macros
    
     305 #####################################
    
     306 # set_prop(sourcedomain, targetproperty)
    
     307 # Allows source domain to set the
    
     308 # targetproperty.
    
     309 #
    
     310 define(set_prop',
    
     311 unix_socket_connect($1, property, init)
    
     312 allow $1 $2:property_service set;
     ```
    

    所以根据这意思,完全可以拼凑出如下权限声明:

    allow system_app mtk_xxx_sys_prop:property_service set;
    

    允许 域为system_app的进程,对 标签 为mtk_xxx_sys_prop(其class属于property_service),执行set操作。

    而vendor.xxx.sys.test的安全上下文中 声明了

    type(标签)为mtk_xxx_sys_prop,
    

    因此,type(域)为 system_app 的进程 可以对vendor.xxx.sys.test 执行set操作。system_server同理。

https://blog.csdn.net/yanjun821126/article/details/80828908
https://blog.csdn.net/hy6533/article/details/120013316
https://blog.csdn.net/weixin_35723192/article/details/127921154

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值