SELinux是安全增强型 Linux(Security-Enhanced Linux)简称 SELinux。它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。
相比其他强制性访问控制系统,SELinux 有如下优势:
SELinux for Android在架构和机制上与SELinux完全一样,考虑到移动设备的特点,所以移植到Android上的只是SELinux的一个子集。SELinux for Android的安全检查几乎覆盖了所有重要的系统资源,包括域转换,类型转换,进程、内核、文件、目录、设备,App,网络及IPC相关的操作。
Android分为宽容模式
(仅记录但不强制执行 SELinux 安全政策 )和强制模式
(强制执行并记录安全政策。如果失败,则显示为 EPERM 错误。 );在选择强制执行级别时只能二择其一。
您的选择将决定您的政策是采取操作,还是仅允许您收集潜在的失败事件。宽容模式在实现过程中尤其有用。
平台公有策略(platform public seoplicy)
平台共有策略全部定义在/system/sepolicy/public下,public下的type和attribute可以被non-platform中的策略所使用,也就是说,设备制造商的sepolicy作者在non-platform下可以对platform public sepolicy的策略进行扩展。
平台私有策略(platform private seoplicy)
与公有策略相反,被声明为私有策略的type或attribute对non-platform的策略作者是不可见的。
例如服务名为“com.abc” ServiceManager.addService("com.abc", xxx); 在priv-app 类系统应用com.zw.app 中添加系统服务
1. 定义服务名称和属性
/sepolicy/private/service_contexts.te 添加以下内容
com.abc u:object_r:abc_service:s0
2. /sepolicy/public/service.te 添加以下内容,
用于为 Android Binder 服务分配标签,以便控制哪些进程可以为相应服务添加(注册)和查找(查询)Binder 引用。在启动期间,ServieManager 进程会读取此配置。
app_api_service 允许普通app find 该服务
type abc_service, app_api_service, service_manager_type;
3. 在sepolicy/private/seapp_contexts 中定义com.zw.app 的域为zw_app
user=system seinfo=platform name=com.zw.app domain=zw_app type=system_app_data_file
4. 在sepolicy/public/中新建 zw_app.te, 写入以下内容
# Domain to run com.zw.app
type zw_app, domain, coredomain ;
5. sepolicy/public/中新建 zw_app.te,写入以下内容
允许zw_app 中调用添加ServiceManager.addService("com.abc", xxx); 添加abc_service
allow zw_app abc_service:service_manager add;
备注:
原生默认有很多限制,以下部分仅供参考
在 /system/sepolicy/private/untrusted_app_all.te 中允许普通app find app_api_service,
allow untrusted_app_all app_api_service:service_manager find;
在/system/sepolicy/private/app_neverallows.te 中,禁止不受信任的应用添加系统服务
neverallow all_untrusted_apps service_manager_type:service_manager add;
在/system/sepolicy/private/priv_app.te 中,禁止特权应用程序添加系统服务
neverallow priv_app service_manager_type:service_manager add;
异常Log
type=1400 audit(0.0:104avc: denied { search } for name="vendor" dev="tmpfs" ino=9241 scontext=u:r:dumpstate:s0 tcontext=u:object_r:mnt_vendor_file:s0 tclass=dir permissive=0
分析:
添加权限:
allow dumpstate mnt_vendor_file:dir search;
由于功能开发需要,现需要为system_server
进程添加对/sys/class/abc/phy0/index
节点读取的SELinux规则;
按照管理,我们先抓取日志,并过滤avc
字段; 经过筛选,可定位到如下这条日志:
12-31 16:06:44.566 946 946 W WifiStateMachin: type=1400 audit(0.0:77): avc: denied { read } for name="index" dev="sysfs" ino=34138 scontext=u:r:system_server:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
如果此时使用audit2allow
工具解析,会得到如下一行规则:
#============= system_server ==============
allow system_server sysfs:file read;
经验告诉我,system_server
是不能直接拥有对sysfs
的读文件权限的; 不信可以添加后编译,发现编译报错:
FAILED: out/target/product/xxxx/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows
/bin/bash -c "(rm -f out/target/product/xxxx/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows ) && (ASAN_OPTIONS=detect_leaks=0 out/host/linux-x86/bin/checkpolicy -M -c 30 -o out/target/product/xxxx/obj/ETC/sepolicy_neverallows_intermediates/sepolicy_neverallows out/target/product/xxxx/obj/ETC/sepolicy_neverallows_intermediates/policy.conf )"
libsepol.report_failure: neverallow on line 31 of system/sepolicy/private/domain.te (or line 26738 of policy.conf) violated by allow system_server sysfs:file { read };
libsepol.check_assertions: 1 neverallow failures occurred
Error while expanding policy
可见system/sepolicy/private/domain.te
第31行定义了一条neverallow
的规则:
# /sys
neverallow {
coredomain
-init
-ueventd
-vold
} sysfs:file no_rw_file_perms;
翻译过来即:所有主体为coredomain
(除了init
,ueventd
,vold
)的进程,均不能对sysfs
进行文件读写操作;
那么实际上,这里就同时遇到了上述的两条情况:
system_server
对sysfs
的文件读权限,显然太大了;system_server
对sysfs
的文件读权限,触犯了AOSP预设的neverallow
规则;通常情况下,这种问题可以通过细化/sys/class/abc/phy0/index
节点的标签,来缩小权限作用范围,同时避免触犯neverallow
规则; 具体操作如下:
/sys/class/abc/phy0/index
节点是否是一个实际存在的节点,使用readlink -f
获取真实路径; # readlink -f /sys/class/abc/phy0/index
/sys/devices/platform/soc/18800000.qcom,icnss/abc/phy0/index
/sys
,/proc
等路径下的节点是运行时生成的,而不是实际存在的文件,因此这类路径下的标签,不能使用file_contexts
来定义,而是使用genfs_contexts
定义,示例规则如下: genfscon sysfs /devices/platform/soc/18800000.qcom,icnss/abc/phy0/index u:object_r:sysfs_zw:s0
file.te
中添加sysfs_zw
标签的定义: type sysfs_zw, sysfs_type, fs_type;
system_server.te
文件中添加system_server
的规则: allow system_server sysfs_zw:file read;
由于新增了标签与规则,建议全编译后刷机验证(单推规则可能不生效) 开机后查看其标签类型:
xxxx:/ # ls -alZ /sys/class/abc/phy0/index
-r--r--r-- 1 root root u:object_r:sysfs_zw:s0 4096 2022-07-26 05:53 /sys/class/adc/phy0/index
整个过程比较简单,但是需要注意如下几点:
/sys
,/proc
等路径下运行时生成的路径)一定要使用readlink
命令来确认其真实路径,添加到软链接后的路径上是不生效的;procfs
,sysfs
),大概率会触犯neverallow
规则;sysfs_zw
),并继承自根标签(对应此例中sysfs
),这样再添加对此子标签的规则,则可以避免权限放大的问题;