Android之动态修改system/etc目录下文件的一种实现方式-SELinux

时间:2022-04-10 12:27:18

在没有root的前提下,system分区为只读,若要动态修改该分区下的文件,可以按照下面流程实现:

1.写执行脚本,这里以修改system/etc/hosts文件为例,在/device/mediatek/mt67xx目录下创建名为modifyhosts.sh的文件,文件内容如下:

# 修改system分区为可读写
mount -o remount,rw /system

# 修改内容,可以执行拷贝、删除、写入等操作
echo 127.0.0.1 localhost > /etc/hosts

# 修改hosts文件权限
chmod 644 /etc/hosts

# 修改system分区为只读
mount -o remount,ro /system

2.配置脚本编译后的路径,在/device/mediatek/mt67xx/device.mk文件中配置脚本编译后的路径: 注意:脚本文件后缀可以不要

PRODUCT_COPY_FILES += $(LOCAL_PATH)/modifyhosts.sh:system/bin/modifyhosts.sh

3.配置启动脚本的服务,/system/core/rootdir/init.rc文件为系统启动初始化文件,最先加载,配置sh脚本启动服务:

service remount-sys /system/bin/modifyhosts.sh
# 这个服务不能通过启动一类服务来启动,只能单独以名字来启动
disabled
# 服务只运行一次,退出后不再重启
oneshot

4.定义主体的type,在/external/sepolicy目录下新建一个modifyhosts.te文件,在该文件中定义一个名为modifyhosts的domain以及名为modifyhosts_exec的type:

# 将domain设置为modifyhosts的属性,表明modifyhosts是用来描述进程的安全上下文的
type modifyhosts, domain;
# 调试时先加上下面这一句,它会打印出所有需要申请的权限,调试完成后删除该语句。
permissive modifyhosts;
# 将exec_type和file_type设置为modifyhosts_exec的属性,表明modifyhosts_exec是用来描述可执行文件的安全上下文的
type modifyhosts_exec, exec_type, file_type;
init_daemon_domain(modifyhosts)

5.定义客体的type,remount-sys进程对应的可执行文件是/system/bin/modifyhosts.sh,则在/external/sepolicy/file_contexts文件中添加/system/bin/modifyhosts.sh文件的安全上下文:

/system/bin/modifyhosts.sh u:object_r:modifyhosts_exec:s0

也就是说,客体/system/bin/modifyhosts.sh文件的type是modifyhosts_exec。

6.添加SELinux权限,由于不知道需要添加哪些权限,故按上面5个步骤操作完后,可以先编译版本刷机,之后在adb shell 下执行:

setprop ctl.start remount-sys
dmesg > /data/data/a.txt

导出执行log到指定目录下,根据log内容添加指定权限,dmesg是打印kernel层log的命令。

log内容如下:

[  659.805760] .(0)[269:logd.auditd]type=1400 audit(1481859095.080:77): avc: denied { remount } for pid=5080 comm="mount" scontext=u:r:modifyhosts:s0 tcontext=u:object_r:labeledfs:s0 tclass=filesystem permissive=1

从log可知,需要为modifyhosts.te文件添加权限,SELinux权限规则语句一般如下:

allow 主体的Type 客体的Type:操作 权限1;
或者:
allow 主体的Type 客体的Type:操作 { 权限1 权限2 };

可以从log中获取四个参数得出最后的规则:

allow modifyhosts labeledfs:filesystem { remount };

添加权限后再次编译版本,如果编译失败,且失败原因如下:

libsepol.report_failure: neverallow on line 284 of external/sepolicy/domain.te (or line 5613 of policy.conf) violated by allow modifyhosts labeledfs:filesystem { remount };
libsepol.check_assertions: 1 neverallow failures occurred

这是因为系统在domain.te文件中定义了全局的neverallow策略,与modifyhosts.te中allow的策略有冲突,此时请确认该权限是否是服务所必须的,如果是必须的可以在/external/sepolicy/domain.te文件中有冲突的neverallow语句中添加自己为例外:

neverallow { domain -kernel -init -recovery -vold -zygote
-modifyhosts # add by zhangyongfei
} { fs_type -sdcard_type }:filesystem { mount remount relabelfrom relabelto };

7.通过前面6步之后就调试好了,下面该在系统代码中添加真正调用该服务的代码了,这里可以在系统服务(AMS、PMS等)中调用下面方法启动该服务:

// remount-sys是在init.rc中自定义的服务名
SystemProperties.set("ctl.start","remount-sys");