Android系统10 RK3399 init进程启动(三十八) 属性Selinux实战编程

配套系列教学视频链接:

      安卓系列教程之ROM系统开发-百问100ask

说明

系统:Android10.0

设备: FireFly RK3399 (ROC-RK3399-PC-PLUS)

前言

上一节介绍了如何属性编程, 参考:

Android系统10 RK3399 init进程启动(三十七) 属性代码编程_旗浩QH的博客-CSDN博客

但是安卓对属性有selinux权限控制的, 本文重点介绍如何在selinux的不同模式下, 如permissive和enforceing模式下进行selinux规则编程。


一, 不配置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基本规则

需要配置的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规则:

  1. 设置自定义属性new.prop.test.name的安全上下文, 同时定义prop_test文件的安全上下文
  2. prop_test特定的进程域.
  3. 定义进程于的规则

 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规则已经有了, 但是设置属性的规则还是没有的。

三, 增加属性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的规则有深刻理解。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旗浩QH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值