SeLinux 权限总结
SELinux 背景
- 在SELinux之前,Linux中使用的安全机制称为DAC,自主访问控制(Discretionary Access Control)。在自主访问控制下,主要根据文件所属的分组来限制对资源的访问。分组有3种,分别表示拥有者、同组用户和其他用户。DAC是一种很粗略的权限管理方法,只能控制对资源的读、写和执行,但是不能进行更精细的控制。
-
SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则).
简单理解: 服务进程需要什么权限,便
只给什么权限,没有用到的权限,就不给.
调试 SELinux 命令
命令列表
| 命令 | 含义 |
|---|---|
| getenforce | 获取当前seLinux状态 |
| setenforce 1 | 打开seLinux |
| setenforce 0 | 关闭seLinux |
getenforce 命令
# getenforce
Enforcing ===> 表示: SELinux 打开, 程序会受到 Selinux 权限限制
Permissive ===> 表示: SELinux 关闭, 程序 不会受到 Selinux 权限限制
setenforce 命令
# setenforce 0 ===> 关闭 SELinux
# setenforce 1 ===> 打开 SELinux
SELinux 常见问题 及 解决办法
获取 SELinux log
dmesg | grep denied
SELinux 标志 log
log:
`[ 53.024184] init: avc: denied { set } for property=SP3_Screen_state pid=2535 uid=1000 gid=1000 scontext=u:r:system_server:s0 tcontext=u:object_r:default_prop:s0 tclass=property_service permissive=0`
avc: denied { xx } xx permissive=0
log:
`[ 53.024184] init: avc: denied { set } for property=SP3_Screen_state pid=2535 uid=1000 gid=1000 scontext=u:r:system_server:s0 tcontext=u:object_r:default_prop:s0 tclass=property_service permissive=0`
- 解析其含义:
- 源类型 -> sourcecontext 指的是 scontext=u:r:system_server:s0 的 system_server
- 目标类型 -> stargetcontext 指的是 tcontext=u:object_r:default_prop:s0 中的 default_prop,
- 访问类型 -> sclass 指的是 tclass=property_service 中的 property_service
- 操作权限 -> s许可指的是 denied { set } 中的 set
-
找到 scontext 对应的 .te 文件. find device/qcom/sepolicy -name system_server.te
-
修改 .te 文件, 添加如下格式的一行语句:(结尾别忘了分号)
格式:allow 源类型 目标类型:访问类型 {操作权限};
eg:
allow system_server default_prop:property_service set;
编译 SELinux
编译 SELinux(正常模式)
编译 .rc 文件 , .te 文件:
编译:
make bootimage -j30
生成文件:
out/target/product/msm8909/obj/ETC/sepolicy_intermediates/policy.conf
reboot bootloader
fastboot flash boot boot.img
fastboot reboot
编译 SELinux(Recovery模式)
编译 Recovery SeLinux:
编译:
make recoveryimage -j30 --> 会编译 kernal , 和 recovery
烧录:
boot.img
编译:
make bootimage -j30
reboot bootloader
fastboot flash boot boot.img
fastboot reboot
recovery.img
代码目录:
bootable/recovery/
编译命令:
make recoveryimage -j30
生成文件:
out/target/product/msm8909/recovery.img
烧入到板子:
reboot bootloader
fastboot flash recovery recovery.img
fastboot reboot
selinux 编译时 neverallow 报错
`libsepol.report_failure: neverallow on line 344 of system/sepolicy/domain.te (or line 9216 of policy.conf) violated by allow system_server default_prop:property_service { set };
libsepol.check_assertions: 1 neverallow failures occurred`
按照 log 提示 找到对应的 .te:
system/sepolicy/domain.te
修改 .te
在 nerverallow 中用 {} 里用 -xx 排除某个
system/sepolicy/domain.te
-neverallow { domain -init -healthd } default_prop:property_service set;
+neverallow { domain -init -healthd -system_server } default_prop:property_service set;
- 类似这样的补丁.
自定义 SeLinux 安全策略(最高权限使用)
作用
解决: 类似这类问题
-
如果开机,需要自动安装 APK , 那么在启动脚本便需要执行
pm install命令来安装APK, 如果没有 自定义SElinux 安全策略,可能会遇到类似这种报错。[ 42.857882] init: cannot find 'pm' (No such file or directory), disabling 'exec 14 (pm)'- 而解决这中问题,需要在脚本中使用
/system/bin/sh /system/bin/pm install xx.apk - 但这种办法,我做为强迫症,觉得很麻烦,故我选择采用 自定义 SeLinux 安全策略(最高权限使用) 来解决这类问题.
- 仅仅需要在脚本执行
pm install xx.apk便可以安装 APK了. 而不需要添加上 一大堆前缀.
- 而解决这中问题,需要在脚本中使用
定义 nsc_elan_hr40 Selinux 安全策略:
参考 qti-testscripts.te
device/qcom/sepolicy/test/qti-testscripts.te
新建、编辑 nsc_elan_hr40.te
device/qcom/sepolicy/test/nsc_elan_hr40.te
# Copyright (c) 2015, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of The Linux Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
userdebug_or_eng(`
type nsc_elan_hr40, domain, domain_deprecated, mlstrustedsubject;
permissive nsc_elan_hr40;
domain_trans(init, shell_exec, nsc_elan_hr40)
#super_user - start
# Add nsc_elan_hr40 to various domains
net_domain(nsc_elan_hr40)
app_domain(nsc_elan_hr40)
dontaudit nsc_elan_hr40 self:capability_class_set *;
dontaudit nsc_elan_hr40 kernel:security *;
dontaudit nsc_elan_hr40 kernel:system *;
dontaudit nsc_elan_hr40 self:memprotect *;
dontaudit nsc_elan_hr40 domain:process *;
dontaudit nsc_elan_hr40 domain:fd *;
dontaudit nsc_elan_hr40 domain:dir *;
dontaudit nsc_elan_hr40 domain:lnk_file *;
dontaudit nsc_elan_hr40 domain:{ fifo_file file } *;
dontaudit nsc_elan_hr40 domain:socket_class_set *;
dontaudit nsc_elan_hr40 domain:ipc_class_set *;
dontaudit nsc_elan_hr40 domain:key *;
dontaudit nsc_elan_hr40 fs_type:filesystem *;
dontaudit nsc_elan_hr40 {fs_type dev_type file_type}:dir_file_class_set *;
dontaudit nsc_elan_hr40 node_type:node *;
dontaudit nsc_elan_hr40 node_type:{ tcp_socket udp_socket rawip_socket } *;
dontaudit nsc_elan_hr40 netif_type:netif *;
dontaudit nsc_elan_hr40 port_type:socket_class_set *;
dontaudit nsc_elan_hr40 port_type:{ tcp_socket dccp_socket } *;
dontaudit nsc_elan_hr40 domain:peer *;
dontaudit nsc_elan_hr40 domain:binder *;
dontaudit nsc_elan_hr40 property_type:property_service *;
dontaudit nsc_elan_hr40 service_manager_type:service_manager *;
dontaudit nsc_elan_hr40 keystore:keystore_key *;
dontaudit nsc_elan_hr40 domain:debuggerd *;
dontaudit nsc_elan_hr40 domain:drmservice *;
dontaudit nsc_elan_hr40 unlabeled:filesystem *;
#super_user - end
#Added below rule in same file to keep all debug policies
#under one common file.
# All domains can read proc enrty of nsc_elan_hr40
r_dir_file(domain, nsc_elan_hr40)
r_dir_file(nsc_elan_hr40, domain)
allow adbd nsc_elan_hr40:process dyntransition;
allow { domain -mediaextractor -mediacodec } nsc_elan_hr40:unix_stream_socket connectto;
allow domain nsc_elan_hr40:fd use;
allow { domain -mediaextractor -mediacodec } nsc_elan_hr40:unix_stream_socket { getattr getopt read write shutdown };
binder_call({ domain -init -netd }, nsc_elan_hr40)
allow domain nsc_elan_hr40:fifo_file { write getattr };
allow domain nsc_elan_hr40:process sigchld;
diag_use(radio)
')
-
device/qcom/sepolicy/Android.mk 会自动把 device/qcom/sepolicy/test/ 目录下的 所有的 .te 进行编译使用.
新建、编辑 init.nsc_elan_hr40.rc 服务文件
-
init.nsc_elan_hr40.rc# Copyright (C) 2012 The Android Open Source Project # # for NSC ELAN HR40 Project # service ElanHR40 /system/bin/sh /system/etc/ElanHR40.sh class late_start user root disabled oneshot seclabel u:r:nsc_elan_hr40:s0 # ----> 使用 nsc_elan_hr40 自定义 SELinux安全策略
新建、编辑 ElanHR40.sh 启动脚本
- /system/etc/ElanHR40.sh
#!/system/bin/sh
Tag="ELAN HR40: "
main()
{
log "$Tag just test customized Selinux."
sleep 1
log "$Tag done."
}
main
init.rc 导入 init.nsc_elan_hr40.rc
-
init.rc导入init.nsc_elan_hr40.rcimport /init.nsc_elan_hr40.rc
启动 ElanHR40 服务
-
init.qcom.rc-
在完全启动成功时,
on property:sys.boot_completed=1, 启动 ElanHR40 服务start ElanHR40
-
验证是否启动脚本成功
- 然后重启Android 板子, 看看 logcat 是否打印启动脚本对应的log , 来判断是否开机自启动脚本成功.
- 通过log , 可以看到开机自启动启动脚本成功。
Kernel 关闭 SELinux
修改kernel/arch/arm/configs/msm8909-1gb_defconfig文件(xxx一般为手机产品名),
去掉CONFIG_SECURITY_SELINUX=y 的配置项
NOTE: garen 还没有实践验证过.
Selinux 其他问题
does not have a SELinux domain defined.
-
/init.nsc_elan_hr40.rcon property:PowerUpIR=Enable exec /system/bin/gpioTest.sh 68 1 exec /system/bin/gpioTest.sh 69 1 exec /system/bin/gpioTest.sh 89 1 setprop PowerUpIR none -
执行
setprop PowerUpIR Enable- 报错
init: Service exec 8 (/system/bin/gpioTest.sh) does not have a SELinux domain defined.
- 报错
-
排查分析:
-
查询 security context: ls -lZ /system/bin/gpioTest.sh -rwxr-xr-x 1 root shell u:object_r:system_file:s0 430 2022-03-02 02:42 /system/bin/gpioTest.sh ---> 排查发现 gpioTest.sh 有 定义 SELinux domain的.
-
-
原因 :
system_file 属性 的 /system/bin/gpioTest.sh 不能直接被 exec ? -
解决:
添加 "/system/bin/sh"