这是一个介绍 Android 特点体系的系列文章:
- Android 特点体系入门
- 特点文件生成进程剖析
- 如何增加体系特点
- 特点与 Selinux (本文)
- 特点体系全体结构与启动进程剖析
- 特点读写进程源码剖析
Android O 以后,特点的 Selinux 的规矩变得复杂起来了,今日咱们先看一个简单的比如,做根本的了解。在Hal与硬件服务
的 treble 章节咱们还会持续来学习特点相关的 Selinux 装备。
读写特点的示例代码
首先咱们在 device/jelly/rice14
目录下创立如下的目录:
PropTest/
├── Android.bp
└── prop_test.cpp
其间 prop_test.cpp
具体内容如下:
#include <string>
#include <cutils/properties.h>
#define LOG_TAG "prop_test"
#include <log/log.h>
#include <android-base/properties.h>
using namespace std;
int main(int argc, char *argv[])
{
// 打印版别信息
char android_version[PROPERTY_VALUE_MAX];
property_get("ro.build.version.release", android_version, "");
ALOGD("android version : %s", android_version);
// 写入自定义特点
property_set("vendor.my.prop.test", "xxx");
// 读自定义特点
char prop_test[PROPERTY_VALUE_MAX];
property_get("vendor.my.prop.test", prop_test, "");
ALOGD("prop test : %s", prop_test);
while(1) {
}
return 0;
}
配套的编译文件 Android.bp
如下:
cc_binary {
name: "prop_test",
srcs: [ "prop_test.cpp" ],
vendor: true,
shared_libs: [
"libbase",
"liblog",
"libcutils",
"libutils"
],
}
至此,整个示例程序就完成了,最终修正咱们自定义 Product 的装备文件 device/jelly/rice14/rice14.mk
:
PRODUCT_PACKAGES +=
# ......
prop_test
Selinux 的装备
接着需求装备 SeLinux:
在 device/jelly/rice14
目录下创立如下的文件与目录:
sepolicy/
├── file_contexts
├── property_contexts
├── property.te
└── prop_te
不要忘了装备自定义 sepolicy 目录,在 device/jelly/rice14/rice14.mk
中增加如下内容:
BOARD_SEPOLICY_DIRS +=
device/jelly/rice14/sepolicy
首先在 property.te
中定义特点类型
type vendor_mytest_prop, property_type;
接着在 property_contexts
中装备好咱们自定义特点 vendor.my.prop.test
的安全上下文:
vendor.my.prop.test u:object_r:vendor_mytest_prop:s0
接着在 prop_test.te
中装备好可履行文件和对应进程的类型和域转换规矩以及特点的读写权限:
# 可履行文件对应进程类型
type myprop_test_dt, domain;
# 可履行文件类型
type myprop_test_dt_exec, exec_type, vendor_file_type, file_type;
# 域转换规矩
init_daemon_domain(myprop_test_dt)
domain_auto_trans(shell, myprop_test_dt_exec, myprop_test_dt)
# 特点读写规矩
set_prop(myprop_test_dt, vendor_mytest_prop);
get_prop(myprop_test_dt, vendor_mytest_prop);
get_prop(myprop_test_dt, exported2_default_prop);
在特点读写规矩中,咱们增加了对 exported2_default_prop
类型特点的读取规矩,exported2_default_prop
是源码中 ro.build.version.release
特点对应的 type,我是通过如下的查找命令查找到的:
find . -name "property_contexts" | xargs grep ro.build.version.release
./system/sepolicy/public/property_contexts:ro.build.version.release u:object_r:exported2_default_prop:s0 exact string
./system/sepolicy/prebuilts/api/29.0/public/property_contexts:ro.build.version.release u:object_r:exported2_default_prop:s0 exact string
./system/sepolicy/prebuilts/api/28.0/public/property_contexts:ro.build.version.release u:object_r:exported2_default_prop:s0 exact string
最终咱们需求再 file_contexts
中装备可履行文件的安全上下文:
/vendor/bin/prop_test u:object_r:myprop_test_dt_exec:s0
接着咱们就可以履行在虚拟机的 shell 中履行 prop_test 可履行文件了:
# 启动虚拟机
emulator
# 重开一个终端,进入虚拟机 shell 环境
adb shell
# root
su
# selinux 装备为 Permissive 模式
setenforce 0
# 退出 root
exit
prop_test
接着咱们查看 log:
logcat | grep prop_test
10-23 10:25:42.420 2959 2959 W prop_test: type=1400 audit(0.0:27): avc: denied { read } for name="u:object_r:vendor_mytest_prop:s0" dev="tmpfs" ino=6750 scontext=u:r:shell:s0 tcontext=u:object_r:vendor_mytest_prop:s0 tclass=file permissive=0
10-23 10:25:42.424 2959 2959 D prop_test: android version : 10
10-23 10:25:42.428 2959 2959 D prop_test: prop test :
10-23 10:29:41.930 3704 3704 W prop_test: type=1400 audit(0.0:58): avc: denied { use } for path="/dev/pts/0" dev="devpts" ino=3 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=0
10-23 10:29:41.930 3704 3704 W prop_test: type=1400 audit(0.0:60): avc: denied { use } for path="/dev/pts/0" dev="devpts" ino=3 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=0
10-23 10:29:41.930 3704 3704 W prop_test: type=1400 audit(0.0:61): avc: denied { use } for path="/dev/goldfish_pipe" dev="tmpfs" ino=7279 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=0
10-23 10:29:41.930 3704 3704 W prop_test: type=1400 audit(0.0:62): avc: denied { use } for path="/dev/goldfish_pipe" dev="tmpfs" ino=7279 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=0
10-23 10:31:17.980 3919 3919 I prop_test: type=1400 audit(0.0:87): avc: denied { use } for path="/dev/pts/0" dev="devpts" ino=3 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=1
10-23 10:31:17.980 3919 3919 I prop_test: type=1400 audit(0.0:88): avc: denied { read write } for path="/dev/pts/0" dev="devpts" ino=3 scontext=u:r:myprop_test_dt:s0 tcontext=u:object_r:devpts:s0 tclass=chr_file permissive=1
10-23 10:31:17.980 3919 3919 I prop_test: type=1400 audit(0.0:89): avc: denied { read write } for path="socket:[9765]" dev="sockfs" ino=9765 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=unix_stream_socket permissive=1
10-23 10:31:17.980 3919 3919 I prop_test: type=1400 audit(0.0:90): avc: denied { use } for path="/vendor/bin/prop_test" dev="dm-1" ino=158 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:shell:s0 tclass=fd permissive=1
10-23 10:31:18.000 3919 3919 D prop_test: android version : 10
10-23 10:31:18.002 3919 3919 D prop_test: prop test : xxx
发现咱们的程序任然缺少一些权限,咱们把权限相关的 log 拷贝下来,在源码根目录下新建一个 avc_log.txt 文件,把缺少权限相关的 log 拷贝进去:
# avc_log.txt
10-23 10:38:05.670 2910 2910 W prop_test: type=1400 audit(0.0:28): avc: denied { use } for path="/dev/pts/0" dev="devpts" ino=3 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=0
10-23 10:38:05.670 2910 2910 W prop_test: type=1400 audit(0.0:30): avc: denied { use } for path="/dev/pts/0" dev="devpts" ino=3 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=0
10-23 10:38:05.670 2910 2910 W prop_test: type=1400 audit(0.0:31): avc: denied { use } for path="socket:[10955]" dev="sockfs" ino=10955 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=0
10-23 10:38:05.670 2910 2910 W prop_test: type=1400 audit(0.0:32): avc: denied { use } for path="/dev/goldfish_pipe" dev="tmpfs" ino=7343 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=0
10-23 10:38:57.400 3034 3034 I prop_test: type=1400 audit(0.0:39): avc: denied { use } for path="/dev/pts/0" dev="devpts" ino=3 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=fd permissive=1
10-23 10:38:57.400 3034 3034 I prop_test: type=1400 audit(0.0:40): avc: denied { read write } for path="/dev/pts/0" dev="devpts" ino=3 scontext=u:r:myprop_test_dt:s0 tcontext=u:object_r:devpts:s0 tclass=chr_file permissive=1
10-23 10:38:57.400 3034 3034 I prop_test: type=1400 audit(0.0:41): avc: denied { read write } for path="socket:[10955]" dev="sockfs" ino=10955 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:adbd:s0 tclass=unix_stream_socket permissive=1
10-23 10:38:57.410 3034 3034 I prop_test: type=1400 audit(0.0:42): avc: denied { use } for path="/vendor/bin/prop_test" dev="dm-1" ino=158 scontext=u:r:myprop_test_dt:s0 tcontext=u:r:shell:s0 tclass=fd permissive=1
接着履行命令 audit2allow -i avc_log.txt
生成缺失的权限装备:
allow myprop_test_dt adbd:fd use;
allow myprop_test_dt adbd:unix_stream_socket { read write };
allow myprop_test_dt devpts:chr_file { read write };
allow myprop_test_dt shell:fd use;
把这些权限装备加入到 prop_test.te
后,重新编译体系,启动虚拟机,程序即可正常运转。