如果想要了解selinux
的介绍可以戳AOSP安全策略SElinux_android以及问题排查思路,有助于更深的理解和应用。
1 添加⼀个系统框架服务,例redmine:179485
// ⽤于针对java的binder service,如果需要调⽤到框架的某些接⼝,或是给app提供某些特殊接⼝,可能
// 需要增加java binder服务:
@Override
public void onStart() {
publishBinderService("ccc_service", new BinderService());
publishLocalService(CCCServiceInternal.class, new LocalService());
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
# 执⾏命令:'get_build_var BOARD_PLAT_PRIVATE_SEPOLICY_DIR' 后对应的⽬录修改,如:
# 修改 device/rockchip/common/sepolicy/private/service.te
# 在最后⼀⾏添加(关联上下⽂)
type ccc_service, system_api_service, system_server_service,
service_manager_type;
# 然后修改同⽬录下device/rockchip/common/sepolicy/private/service_contexts ⽂件(给服
# 务打上标签,可以在service_context⽬录进⾏)
# 中间插⼊⼀⾏
ccc u:object_r:ccc_service:s0
2 添加⼀个开机⾃启动⼆进制服务 - Android 7.1
- 增加某个⼆进制程序或某个脚本,想要开机⾃动执⾏,如 rockchip.sample.nougat.sh
#! /system/bin/sh
echo "starting service..."
# 注:如果是脚本,务必保持⾸⾏有shell的路径,如上所⽰,且中!后有空格本节所有要修改的⽂件都位于:get_build_var BOARD_SEPOLICY_DIRS执⾏结果列出的⽂件夹中。
- 声明服务 在init.rc(任意会加载执⾏到的rc⽂件,或⾃⼰声明⼀个新的rc⽂件)中声明服务
service rockchip-sample-nougat-sh /system/bin/rockchip.sample.nougat.sh
#格式: service service_name service_path, 注意,脚本务必要可执⾏,服务名后接的直接就是可执⾏程序,
#这个可执⾏程序必须在file_context中指定标签,脚本程序不能写成 /system/bin/sh xxx.sh,这样就代表服务的主体是sh/shell,⽽不是你的脚本!!!
class main #class代表启动阶段,具体需求请⾃⾏搜索修改
user root
group root wifi
oneshot #只启动⼀次就退出;如果不是⾃启动,需要触发需要加 disable 参数,通过start servic_name即可启动服务
- 错误脚本服务⽰例:
service rockchip-sample-nougat-sh /system/bin/sh /system/bin/rockchip.sample.nougat.sh
class main
user root
group root wifi
oneshot
- 声明运⾏域
sepolicy⽬录下新建 rockchip_sample_nougat.te
type rockchip_sample_nougat, domain;
type rockchip_sample_nougat_exec, exec_type, file_type;
init_daemon_domain(rockchip_sample_nougat)
- 给⼆进制程序打标签,绑定到te⽂件
在sepolicy⽬录下的file_contexts⽂件添加:
/system/bin/rockchip\.sample\.nougat\.sh
u:object_r:rockchip_sample_nougat_exec:s0 # 格式: service_path
u:object_r:te_type_name_exec:s0 # 要和上⾯声明的te⽂件相对应,注意转移字符 \
3 添加⼀个开机⾃启动⼆进制服务 - Android 8.0及以上
# 注:本节所有要修改的⽂件都位于:get_build_var BOARD_SEPOLICY_DIRS执⾏结果列出的⽂件夹中。
# 以xxxservice为例。与Android 7.1没有很⼤区别,注意程序或脚本要放在vendor/bin/下:
# 1. init.rc或其他rc
service xxxservice /vendor/bin/xxxservice
class main
oneshot
# 2. xxxservice.te,与Android 7.1没有很⼤区别,注声明exec type的时候要同时关联
vendor_file_type:
type xxxservice, domain;
type xxxservice_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(xxxservice)
# 3. file_contexts,与Android 7.1⼀致
# 添加⼀条
/vendor/bin/xxxservice u:object_r:xxxservice_exec:s0
4.添加开机启动服务完整实例(以全志R818为例):
1.推送执行文件:
通过peony_perf1.mk ,将执行文件拷贝到/system/bin目录中
# /device/softwinner/peony-perf1/peony_perf1.mk
# 添加如下
#tld filelist
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/auto_shell.sh:system/auto_shell.sh \
2.在init.rc下添加对应服务。推荐在对应方案的.rc下新增服务init.device.rc
:
# /device/softwinner/peony-perf1/init.device.rc
# 在末尾添加
service auto_shell /system/bin/auto_shell.sh
class core
critical # 重要服务, 一般与 oneshot 不同时存在
oneshot # 执行一次
disabled # 不自己执行,需要被动调用
seclabel u:r:auto_shell:s0
shutdown critical
# 或者提前一些执行
service auto_shell_init /system/bin/auto_shell_init.sh
class core
critical # 重要服务, 一般与 oneshot 不同时存在
oneshot
seclabel u:r:auto_shell_init:s0
shutdown critical
# 再或者
service myshell /system/bin/auto_shell.sh
user root
group root
disabled
seclabel u:r:shell:s0 #使用这个就不需要下一步的自定义.te了
oneshot
on property:sys.boot_completed=1 # 在引导结束后执行
start auto_shell # myshell auto_shell_init
3.添加所需要的权限:
3.1在这/device/softwinner/common/sepolicy/private/ 下创建对应脚本名称的.te文件`auto_shell.te`
# 路径:/device/softwinner/common/sepolicy/vendor/auto_shell_init.te
# set_alarm seclabel is specified in init.<board>.rc
type auto_shell, domain, coredomain;
type auto_shell_exec, system_file_type, exec_type, file_type;
init_daemon_domain(auto_shell);
3.2修改文件file_contexts,增加权限:
# 路径:/device/softwinner/common/sepolicy/vendor/file_contexts
# 末尾添加:auto_shell
/system/bin/auto_shell.sh u:object_r:auto_shell_exec:s0
3.3需要额外修改:
---- system/core/init/selinux.cpp
++++ system/core/init/selinux.cpp
bool IsEnforcing() {
+ return false;
if (ALLOW_PERMISSIVE_SELINUX) {
return StatusFromProperty() == SELINUX_ENFORCING;
}
return true;
}
权限可通过命令查看:ls -Z filePath
# 命令
ls -Z /system/bin/auto_shell.sh
# 结果
u:object_r:auto_shell_exec:s0 /system/bin/auto_shell.sh
也可以直接关闭selinux的权限校验!
5.修改系统规则以突破限制
注意:修改系统默认的安全规则(尽量不修改,需改要慎重)
问加你位置:
android/system/sepolicy/private/coredomain.te
android/system/sepolicy/prebuilts/api/29.0/private/coredomain.te
具体请自己查阅编译时所报的错误日志。
# coredomain.te 中/sys为例
# /sys
neverallow {
coredomain
-init
-auto_shell_init # this 这里添加是要解决csysfs:file限制的问题
-ueventd
-vold
} sysfs:file no_rw_file_perms;
# /dev
neverallow {
coredomain
-fsck
-init
-auto_shell_init # this 这里添加是要解决console_device:chr_file限制的问题
-ueventd
} device:{ blk_file file } no_rw_file_perms;
通过log查看auto_shell_init需要的权限:
console:/ # logcat | grep avc
// 或者 dmesg | grep avc
// 已经将节点和类型都列举出来了
// sysfs:file
cat : type=1400 audit(0.0:18): avc: denied { read } for name="usb_device" dev="sysfs" ino=22043 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
gpio_pin_contro: type=1400 audit(0.0:37): avc: denied { write } for name="export" dev="sysfs" ino=5998 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
gpio_pin_contro: type=1400 audit(0.0:38): avc: denied { open } for path="/sys/class/gpio/export" dev="sysfs" ino=5998 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
// shell_exec:file
auto_shell_init: type=1400 audit(0.0:7): avc: denied { read } for path="/system/bin/sh" dev="dm-0" ino=776 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:shell_exec:s0 tclass=file permissive=1
auto_shell_init: type=1400 audit(0.0:8): avc: denied { execute } for path="/system/bin/sh" dev="dm-0" ino=776 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:shell_exec:s0 tclass=file permissive=1
auto_shell_init: type=1400 audit(0.0:9): avc: denied { getattr } for path="/system/bin/sh" dev="dm-0" ino=776 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:shell_exec:s0 tclass=file permissive=1
auto_shell_init: type=1400 audit(0.0:27): avc: denied { read open } for path="/system/bin/sh" dev="dm-0" ino=776 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:shell_exec:s0 tclass=file permissive=1
// console_device:chr_file
auto_shell_init: type=1400 audit(0.0:10): avc: denied { write } for name="console" dev="tmpfs" ino=1259 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:console_device:s0 tclass=chr_file permissive=1
auto_shell_init: type=1400 audit(0.0:11): avc: denied { open } for path="/dev/console" dev="tmpfs" ino=1259 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:console_device:s0 tclass=chr_file permissive=1
// toolbox_exec:file
auto_shell_init: type=1400 audit(0.0:12): avc: denied { getattr } for path="/system/bin/toybox" dev="dm-0" ino=823 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:toolbox_exec:s0 tclass=file permissive=1
auto_shell_init: type=1400 audit(0.0:14): avc: denied { execute } for name="toybox" dev="dm-0" ino=823 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:toolbox_exec:s0 tclass=file permissive=1
auto_shell_init: type=1400 audit(0.0:15): avc: denied { read open } for path="/system/bin/toybox" dev="dm-0" ino=823 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:toolbox_exec:s0 tclass=file permissive=1
auto_shell_init: type=1400 audit(0.0:16): avc: denied { execute_no_trans } for path="/system/bin/toybox" dev="dm-0" ino=823 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:toolbox_exec:s0 tclass=file permissive=1
// system_file:file
gpio_pin_contro: type=1400 audit(0.0:29): avc: denied { execute_no_trans } for path="/system/bin/grep" dev="dm-0" ino=595 scontext=u:r:auto_shell_init:s0 tcontext=u:object_r:system_file:s0 tclass=file permissive=1
改进auto_shell_init的定义,我们看一下:
# set_alarm seclabel is specified in init.<board>.rc
type auto_shell_init, domain, coredomain;
type auto_shell_init_exec, system_file_type, exec_type, file_type;
init_daemon_domain(auto_shell_init)
# add this
allow auto_shell_init sysfs:file { read open write };
allow auto_shell_init shell_exec:file { read execute getattr open };
allow auto_shell_init console_device:chr_file { open write };
allow auto_shell_init toolbox_exec:file { read execute getattr open execute_no_trans };
allow auto_shell_init system_file:file { execute_no_trans };
再次提醒:官方不推荐修改系统原有规则,存在很大风险,这里只是拿来简单分享。