赞
踩
系统:Android10.0
设备: FireFly RK3399 (ROC-RK3399-PC-PLUS)
上一节介绍了如何属性编程, 参考:
Android系统10 RK3399 init进程启动(三十七) 属性代码编程_旗浩QH的博客-CSDN博客
但是安卓对属性有selinux权限控制的, 本文重点介绍如何在selinux的不同模式下, 如permissive和enforceing模式下进行selinux规则编程。
将prop_test放在/vendor/bin中, 普通用户+permissive模式, 运行prop_test, 此时正常运行(adb重启了):
qh100_rk3399:/ $ getprop | grep adb.tcp
[service.adb.tcp.port]: [15000]
qh100_rk3399:/ $ getprop | grep ctl #结果为空
qh100_rk3399:/ $ getprop | grep new[new.prop.test.name]: [qh100]
同时查看可执行程序和各个属性的安全上下文:
console:/ $ ps -elZ | grep prop_test
u:r:shell:s0 0 R 2000 15297 15289 87 19 0 64 8433 0 pts/0 00:00:02 prop_test
console:/ $ ls -Z /vendor/bin/prop_test
u:object_r:vendor_file:s0 /vendor/bin/prop_test
属性的安全安全上下文:
qh100_rk3399:/ $ getprop -Z service.adb.tcp.port
[service.adb.tcp.port]: [u:object_r:shell_prop:s0]
qh100_rk3399:/ $ getprop -Z vendor.new.prop.test.name
[vendor.new.prop.test.name]: [u:object_r:default_prop:s0]
qh100_rk3399:/ $ getprop -Z ctl.start
u:object_r:ctl_default_prop:s0
qh100_rk3399:/ $ getprop -Z ctl.stop
u:object_r:ctl_default_prop:s0
qh100_rk3399:/ $ getprop -Z ctl.restart
u:object_r:ctl_default_prop:s0
在selinux为permissve模式下不修改任何selinux规则, 以上代码正常,但是设置成enforce模式下:
qh100_rk3399:/ $ su
qh100_rk3399::/ # setenforce 1
qh100_rk3399::/ # exit
运行prop_test,日志显示:
qh100_rk3399:/ $ prop_test
/system/bin/sh: /vendor/bin/prop_test: Permission denied
在串口上查看属性自然无效:
console:/ $ getprop | grep new
说明此时属性因为selinux权限管控,无法任意修改属性。所以此时需要定制selinux规则。
需要配置的selinux规则文件如下所示:
prop_test作为vendor,分区去修改shell_prop类型的属性service.adb.tcp.port, 可能修改到system分区的selinux的规则, 所以暂时将主程序改成如下, 负责重启服务:vendor.gnss_service
- int main(int argc, char *argv[])
- {
- print_android_version();
- CplusTestPropString();
-
- property_set("vendor.new.prop.test.name", "qh100");
-
- #if 0
- set_adbd_tcp_port(0);
- property_set("ctl.stop", "adbd");
- property_set("ctl.start", "adbd");
- #else
- property_set("ctl.restart", "vendor.gnss_service");
- #endif
-
- while(1);
-
- return 0;
- }

需要定义如下selinux规则:
- 设置自定义属性new.prop.test.name的安全上下文, 同时定义prop_test文件的安全上下文
- prop_test特定的进程域.
- 定义进程于的规则
selinux规则文件结构:
device/rockchip/qh100_rk3399/test_se/
└── sepolicy
├── device.te
├── myse_test.te
├── file_contexts :定义prop_test可执行程序文件的安全上下文。
├── property_contexts : 定义属性对应的安全上下文。
└── prop_test.te: 定义prop_test进程对应的进程域和权限策略。
└── property.te : 定义属性对应的类型。
制定属性相关的selinux类型(vendor.new.prop.test.name):
vim device/rockchip/qh100_rk3399/test_se/sepolicy/property.te
type vendor_myprop_prop, property_type;
vim device/rockchip/qh100_rk3399/test_se/sepolicy/property_contexts
vendor.new.prop.test.name u:object_r:vendor_myprop_prop:s0
可执行程序文件prop_test对应的selinux格则:
vim device/rockchip/qh100_rk3399/test_se/sepolicy/prop_test.te
# subject context in proccess status
type myprop_test_dt, domain;
# object context as a file
type myprop_test_dt_exec, exec_type, vendor_file_type, file_type;
#grant perm as domain
init_daemon_domain(myprop_test_dt)
domain_auto_trans(shell, myprop_test_dt_exec, myprop_test_dt)
vim device/rockchip/qh100_rk3399/test_se/sepolicy/file_contexts
/vendor/bin/myse_test u:object_r:myse_test_dt_exec:s0
/vendor/bin/prop_test u:object_r:myprop_test_dt_exec:s0
/dev/myse_dev u:object_r:myse_testdev_t:s0
编译:
make selinux_policy -j16
得到:
out/target/product/qh100_rk3399/vendor/etc/selinux/
out/target/product/qh100_rk3399/odm/etc/selinux/
开发板更新selinux目标操作:
ProperyCode\selinux\binary\v1-onlyContext>adb push vendor\selinux /vendor/etc/
vendor\selinux\: 10 files pushed, 0 skipped. 15.2 MB/s (1023122 bytes in 0.064s)
ProperyCode\selinux\binary\v1-onlyContext>adb push odm\selinux /odm/etc/
odm\selinux\: 3 files pushed, 0 skipped. 14.5 MB/s (480980 bytes in 0.032s)
重启开发板, 执行验证, 注意此时可以在permissive模式下验证, 这样可以获取到更多的权限报错信息:
qh100_rk3399:/ $ ls -lZ /vendor/bin/prop_test
-rwxrwxrwx 1 root shell u:object_r:myprop_test_dt_exec:s0 11616 2022-08-25 12:28 /vendor/bin/prop_test
qh100_rk3399:/ $ prop_test
发现prop_test并没有报权限错误, 查看进程域, 发现进程域安全上下文发生了变化:
qh100_rk3399:/ $ ps -elfZ | grep prop_test
u:r:myprop_test_dt:s0 shell 1824 1710 94 12:41:04 pts/0 00:00:14 prop_test
u:r:shell:s0 shell 1842 1828 2 12:41:19 pts/1 00:00:00 grep prop_test
但是属性是否也被改变了呢?
qh100_rk3399:/ $ getprop | grep new
[vendor.new.prop.test.name]: [qh100]
qh100_rk3399:/ $ getprop -Z vendor.new.prop.test.name
u:object_r:vendor_myprop_prop:s0
自定义的属性也是按照规则文件来设置了安全上下文。
gnss服务在prop_test启动前后的pid有变化,说明程序代码没问题,selinux规则也生效了。
qh100_rk3399:/ $ ps -elf | grep gns
gps 2056 1 0 14:35:01 ? 00:00:00 android.hardware.gnss@1.0-service
shell 2190 2068 0 14:36:57 pts/1 00:00:00 grep gns
qh100_rk3399:/ $ ps -elf | grep gns
gps 2198 1 1 14:37:02 ? 00:00:00 android.hardware.gnss@1.0-service
shell 2208 2068 0 14:37:06 pts/1 00:00:00 grep gns
保存avc日志: logcat | grep avc
获取到权限: audit2allow -i avc_log.txt, 得到如下需要补充的权限格则:
#============= myprop_test_dt ==============
allow myprop_test_dt adbd:fd use;
allow myprop_test_dt devpts:chr_file { read write };
allow myprop_test_dt init:unix_stream_socket connectto;
allow myprop_test_dt property_socket:sock_file write;
allow myprop_test_dt shell:fd use;
切换到enforce模式:
qh100_rk3399:/ $ su
:/ # setenforce 1
:/ # getenforce
Enforcing
qh100_rk3399:/ $ prop_test
Segmentation fault
肯定是缺少权限,增加之前获取到的权限:
vim device/rockchip/qh100_rk3399/test_se/sepolicy/prop_test.te
#============= myprop_test_dt ==============
allow myprop_test_dt adbd:fd use;
allow myprop_test_dt devpts:chr_file { read write };
allow myprop_test_dt init:unix_stream_socket connectto;
allow myprop_test_dt property_socket:sock_file write;
allow myprop_test_dt shell:fd use;
编译之后,重新运行:一定要在enforce模式下,运行 prop_test,此时不会退出,
qh100_rk3399:/ $ getenforce
Enforcing
qh100_rk3399:/ $ prop_test
但是获取属性是没有的:
qh100_rk3399:/ $ su
:/ # getprop | grep new #即使切换到su用户,也无法获取到属性,因为设置不成功。
qh100_rk3399:/ $ ps -elf | grep gnss
gps 246 1 0 14:42:27 ? 00:00:00 android.hardware.gnss@1.0-service
shell 2046 2021 4 14:47:09 pts/1 00:00:00 grep gnss
第二次运行prop_test时:
qh100_rk3399:/ $ ps -elf | grep gnss
gps 246 1 0 14:42:27 ? 00:00:00 android.hardware.gnss@1.0-service
shell 2056 2021 0 14:47:16 pts/1 00:00:00 grep gnss
gnss服务没有重启成功, 同时自定义属性vendor.new.prop.test.name也没有设置成功, 也就是说selinux规则已经有了, 但是设置属性的规则还是没有的。
根据我们需要修改的属性的安全上下文, 我们配置对应的属性规则:
vim device/rockchip/qh100_rk3399/test_se/sepolicy/prop_test.te 后面添加:
set_prop(myprop_test_dt, vendor_myprop_prop);
#set_prop(myprop_test_dt, shell_prop);
set_prop(myprop_test_dt, ctl_default_prop);
注意, 上面注释的部分,打开之后,编译会报错, 大家可以自己试试,根据我们之前学习到的知识,自我分析一下。
编译之后,重新运行:一定要在enforce模式下验证,运行 prop_test:
qh100_rk3399:/ $ su
:/ # setenforce 1
:/ # exit
qh100_rk3399:/ $ getenforce
Enforcing
qh100_rk3399:/ $ prop_test
执行结果如下:
1|qh100_rk3399:/ $ ps -elf | grep gnss
gps 247 1 0 14:55:01 ? 00:00:00 android.hardware.gnss@1.0-service
shell 2207 2193 1 15:02:38 pts/1 00:00:00 grep gnss
第二次运行prop_test时:
qh100_rk3399:/ $ ps -elf | grep gnss
gps 2216 1 0 15:02:42 ? 00:00:00 android.hardware.gnss@1.0-service
shell 2235 2193 5 15:02:55 pts/1 00:00:00 grep gnss
说明在enforcing模式下,可以重启gnss服务。
获取自定义属性时:
qh100_rk3399:/ $ getprop | grep new
#此时没有结果,是因为在shell命令行执行getprop时, shell进程域没有权限获取vendor.new.prop.test.name ,
需要切换到root用户下才能看到:
qh100_rk3399:/ $ su
:/ # getprop | grep new
[vendor.new.prop.test.name]: [qh100]
一般在pemissive模式下, 修改属性时, 权限问题不是很突出, 但是一旦在enfocing模式,权限配置就非常重要, 甚至有些时候非常麻烦, 所以希望大家通过这几次实战selinux编程, 对selinux的规则有深刻理解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。