网站直播间怎么做,wordpress md风格,廊坊百度快速排名优化,天华建筑设计有限公司目录
Android系统属性
1.属性在哪里#xff1f;
2.属性长什么样#xff1f;
3.如何读写属性#xff1a;
4.属性的作用
属性文件生成过程
如何添加系统属性
1.添加系统属性到 /system/build.prop
2.添加系统属性到 /vendor/build.prop
3.添加系统属性到 /product/b…目录
Android系统属性
1.属性在哪里
2.属性长什么样
3.如何读写属性
4.属性的作用
属性文件生成过程
如何添加系统属性
1.添加系统属性到 /system/build.prop
2.添加系统属性到 /vendor/build.prop
3.添加系统属性到 /product/build.prop Android系统属性 属性文件生成过程分析如何添加系统属性属性与 Selinux属性系统整体框架与启动过程分析属性读写过程源码分析 在 Android 系统中为统一管理系统的属性设计了一个统一的属性系统每个属性都是一个 key-value 对。 我们可以通过 shell 命令Native 函数接口Java 函数接口的方式来读写这些 key-vaule 对。
1.属性在哪里
init 进程在启动会去加载后缀为 .prop 的属性文件 将属性文件中的属性加载到共享内存中 这样系统就有了默认的一些属性。
属性文件都在哪里呢
属性文件的后缀绝大部分都是 prop我们可以在 Android 模拟器的 shell 环境下搜索
find . -name *.prop/default.prop
/data/local.prop
/system/build.prop
/system/product/build.prop
/vendor/build.prop
/vendor/odm/etc/build.prop
/vendor/default.prop
/data/property/我们看看 /default.prop 属性文件的内容
cat /default.prop#
# ADDITIONAL_DEFAULT_PROPERTIES
#
ro.actionable_compatible_property.enabledtrue
ro.postinstall.fstab.prefix/system
ro.secure0
ro.allow.mock.location1
ro.debuggable1
debug.atrace.tags.enableflags0
dalvik.vm.image-dex2oat-Xms64m
dalvik.vm.image-dex2oat-Xmx64m
dalvik.vm.dex2oat-Xms64m
dalvik.vm.dex2oat-Xmx512m
dalvik.vm.usejittrue
dalvik.vm.usejitprofilestrue
dalvik.vm.dexopt.secondarytrue
dalvik.vm.appimageformatlz4
ro.dalvik.vm.native.bridge0
pm.dexopt.first-bootextract
pm.dexopt.bootextract
pm.dexopt.installspeed-profile
pm.dexopt.bg-dexoptspeed-profile
pm.dexopt.ab-otaspeed-profile
pm.dexopt.inactiveverify
pm.dexopt.sharedspeed
dalvik.vm.dex2oat-resolve-startup-stringstrue
dalvik.vm.dex2oat-max-image-block-size524288
dalvik.vm.minidebuginfotrue
dalvik.vm.dex2oat-minidebuginfotrue
ro.iorapd.enablefalse
tombstoned.max_tombstone_count50
persist.traced.enable1
ro.com.google.locationfeatures1
ro.setupwizard.modeDISABLED
persist.sys.usb.configadb可以看出属性确实是一些 key-value 对。
init 进程会调用 property_load_boot_defaults 函数来加载属性文件
void property_load_boot_defaults(bool load_debug_prop) {// TODO(b/117892318): merge prop.default and build.prop files into one// We read the properties and their values into a map, in order to always allow properties// loaded in the later property files to override the properties in loaded in the earlier// property files, regardless of if they are ro. properties or not.std::mapstd::string, std::string properties;if (!load_properties_from_file(/system/etc/prop.default, nullptr, properties)) {// Try recovery pathif (!load_properties_from_file(/prop.default, nullptr, properties)) {// Try legacy pathload_properties_from_file(/default.prop, nullptr, properties);}}load_properties_from_file(/system/build.prop, nullptr, properties);load_properties_from_file(/vendor/default.prop, nullptr, properties);load_properties_from_file(/vendor/build.prop, nullptr, properties);if (SelinuxGetVendorAndroidVersion() __ANDROID_API_Q__) {load_properties_from_file(/odm/etc/build.prop, nullptr, properties);} else {load_properties_from_file(/odm/default.prop, nullptr, properties);load_properties_from_file(/odm/build.prop, nullptr, properties);}load_properties_from_file(/product/build.prop, nullptr, properties);load_properties_from_file(/product_services/build.prop, nullptr, properties);load_properties_from_file(/factory/factory.prop, ro.*, properties);if (load_debug_prop) {LOG(INFO) Loading kDebugRamdiskProp;load_properties_from_file(kDebugRamdiskProp, nullptr, properties);}for (const auto [name, value] : properties) {std::string error;if (PropertySet(name, value, error) ! PROP_SUCCESS) {LOG(ERROR) Could not set name to value while loading .prop files error;}}property_initialize_ro_product_props();property_derive_build_fingerprint();update_sys_usb_config();
}从源码中我们也可以看到 init 进程加载了哪些属性文件以及加载的顺序。
2.属性长什么样
每一个属性是一个 key-value 对 ro.actionable_compatible_property.enabledtrue
ro.postinstall.fstab.prefix/system
ro.secure0
ro.allow.mock.location1
ro.debuggable1
debug.atrace.tags.enableflags0
dalvik.vm.image-dex2oat-Xms64m
dalvik.vm.image-dex2oat-Xmx64m等号左边是属性的名字等号右边是属性的值
属性的分类 一般属性普通的 key-value 对没有其他功能系统启动后如果修改了某个属性值(仅修改了内存中的值未写入到文件)再重启系统修改的值不会被保存下来读取到的仍是修改前的值特殊属性 属性名称以 ro 开头那么这个属性被视为只读属性。一旦设置属性值不能改变。net 开头的属性顾名思义就是与网络相关的属性net 属性中有一个特殊的属性net.change它记录了每一次最新设置和更新的 net 属性也就是每次设置和更新 net,属性时则会自动的更新 net.change 属性net.change 属性的 value 就是这个被设置或者更新的 net 属性的 name。例如我们更新了属性 net.bt.name 的值由于 net 有属性发生了变化那么属性服务就会自动更新 net.change将其值设置为 net.bt.name。以 persist 为开头的属性值当在系统中通过 setprop 命令设置这个属性时就会在 /data/property/ 目录下会保存一个副本。这样在系统重启后按照加载流程这些 persist 属性的值就不会消失了。属性 ctrl.start 和 ctrl.stop 是用来启动和停止服务。这里的服务是指定义在 rc 后缀文件中的服务。当我们向 ctrl.start 属性写入一个值时属性服务将使用该属性值作为服务名找到该服务启动该服务。这项服务的启动结果将会放入 init.svc.服务名 属性中可以通过查询这个属性值以确定服务是否已经启动。 3.如何读写属性
命令行 getprop wlan.driver.status
setprop wlan.driver.status timeoutNative 代码 char buf[20]qqqqqq;
char tempbuf[PROPERTY_VALUE_MAX];
property_set(type_value,buf);
property_get(type_value,tempbuf,0);Java 代码 String navBarOverride SystemProperties.get(qemu.hw.mainkeys);
SystemProperties.set(service.bootanim.exit, 0);4.属性的作用
常见的属性文件的作用如下
属性文件生成过程
运行的系统中有很多属性文件 /default.prop
/data/local.prop
/system/build.prop
/system/product/build.prop
/vendor/build.prop
/vendor/odm/etc/build.prop
/vendor/default.prop那么这些属性文件是从哪里来的呢
我们先看一下 /system/build.prop 文件的开头 # begin common build properties
# autogenerated by build/make/tools/buildinfo_common.sh
ro.system.build.dateFri Oct 13 17:23:40 CST 2023
# ......注释里面说当前文件由 build/make/tools/buildinfo_common.sh 自动生成我们去看一下这个 shell 脚本的具体内容 cat build/make/tools/buildinfo_common.sh#!/bin/bashpartition$1if [ $# -ne 1 ]; thenecho Usage: $0 partition 12exit 1
fiecho # begin common build properties
echo # autogenerated by $0echo ro.${partition}.build.date$DATE
echo ro.${partition}.build.date.utc$DATE %s
echo ro.${partition}.build.fingerprint$BUILD_FINGERPRINT
echo ro.${partition}.build.id$BUILD_ID
echo ro.${partition}.build.tags$BUILD_VERSION_TAGS
echo ro.${partition}.build.type$TARGET_BUILD_TYPE
echo ro.${partition}.build.version.incremental$BUILD_NUMBER
echo ro.${partition}.build.version.release$PLATFORM_VERSION
echo ro.${partition}.build.version.sdk$PLATFORM_SDK_VERSIONecho ro.product.${partition}.brand$PRODUCT_BRAND
echo ro.product.${partition}.device$PRODUCT_DEVICE
echo ro.product.${partition}.manufacturer$PRODUCT_MANUFACTURER
echo ro.product.${partition}.model$PRODUCT_MODEL
echo ro.product.${partition}.name$PRODUCT_NAMEecho # end common build properties 上述脚本中通过 echo 打印了许多信息。这些信息都进入了文件中那么调用过程中一定做了重定向操作。
我们在 build/make 中搜索 buildinfo_common.sh看看哪里使用了这个脚本 cd build/make
grep -R buildinfo_common.sh ../core/Makefile:BUILDINFO_COMMON_SH : build/make/tools/buildinfo_common.sh可以看到在 build/make/core/Makefile 文件中脚本的路径赋值给了 BUILDINFO_COMMON_SH 变量。
我们接着搜这个变量 # 还是在 build/make 目录下
grep -R BUILDINFO_COMMON_SH ../core/Makefile:BUILDINFO_COMMON_SH : build/make/tools/buildinfo_common.sh
./core/Makefile: bash $(BUILDINFO_COMMON_SH) $(1) $(2)
./core/Makefile:$(INSTALLED_DEFAULT_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(intermediate_system_build_prop)
./core/Makefile:$(intermediate_system_build_prop): $(BUILDINFO_SH) $(BUILDINFO_COMMON_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(API_FINGERPRINT)
./core/Makefile:$(INSTALLED_VENDOR_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(intermediate_system_build_prop)
./core/Makefile:$(INSTALLED_PRODUCT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(product_prop_files)
./core/Makefile:$(INSTALLED_ODM_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH)
./core/Makefile:$(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH)注意到第二行的输出 ./core/Makefile: bash $(BUILDINFO_COMMON_SH) $(1) $(2)这里调用了上面的 shell 脚本
打开文件看到它是函数 generate-common-build-props-with-product-vars-set 的一部分 define generate-common-build-props-with-product-vars-setBUILD_FINGERPRINT$(BUILD_FINGERPRINT_FROM_FILE) \BUILD_ID$(BUILD_ID) \BUILD_NUMBER$(BUILD_NUMBER_FROM_FILE) \BUILD_VERSION_TAGS$(BUILD_VERSION_TAGS) \DATE$(DATE_FROM_FILE) \PLATFORM_SDK_VERSION$(PLATFORM_SDK_VERSION) \PLATFORM_VERSION$(PLATFORM_VERSION) \TARGET_BUILD_TYPE$(TARGET_BUILD_VARIANT) \bash $(BUILDINFO_COMMON_SH) $(1) $(2)
endef这里用函数的参数做了从定向我们接着搜哪里使用这个函数: grep -R generate-common-build-props-with-product-vars-set ../core/Makefile: $(call generate-common-build-props-with-product-vars-set,$(1),$(2))
./core/Makefile:define generate-common-build-props-with-product-vars-set
./core/Makefile: $(call generate-common-build-props-with-product-vars-set,system,$)有两个地方调用了 generate-common-build-props-with-product-vars-set 函数
我们主要看第二个地方 # 定义 system_prop_file 变量的值
# system_prop_file 代表了一个 prop 属性文件
ifdef TARGET_SYSTEM_PROP
system_prop_file : $(TARGET_SYSTEM_PROP)
else
system_prop_file : $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
endif# 这里是一个 Makefile 规则
# intermediate_system_build_prop 的值类似于 out/target/product/xxx/obj/ETC/system_build_prop_intermediates/build.prop 是一个中间文件用于生成最终的 /system/build.prop
$(intermediate_system_build_prop): $(BUILDINFO_SH) $(BUILDINFO_COMMON_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(API_FINGERPRINT)echo Target buildinfo: $mkdir -p $(dir $)$(hide) echo $
ifneq ($(PRODUCT_OEM_PROPERTIES),)$(hide) echo # $; \echo # PRODUCT_OEM_PROPERTIES $; \echo # $;$(hide) $(foreach prop,$(PRODUCT_OEM_PROPERTIES), \echo import /oem/oem.prop $(prop) $;)
endif$(hide) PRODUCT_BRAND$(PRODUCT_SYSTEM_BRAND) \PRODUCT_MANUFACTURER$(PRODUCT_SYSTEM_MANUFACTURER) \PRODUCT_MODEL$(PRODUCT_SYSTEM_MODEL) \PRODUCT_NAME$(PRODUCT_SYSTEM_NAME) \PRODUCT_DEVICE$(PRODUCT_SYSTEM_DEVICE) \# 在这里调用 generate-common-build-props-with-product-vars-set 生成中间文件# out/target/product/xxx/obj/ETC/system_build_prop_intermediates/build.prop$(call generate-common-build-props-with-product-vars-set,system,$)$(hide) TARGET_BUILD_TYPE$(TARGET_BUILD_VARIANT) \TARGET_BUILD_FLAVOR$(TARGET_BUILD_FLAVOR) \TARGET_DEVICE$(TARGET_DEVICE) \PRODUCT_DEFAULT_LOCALE$(call get-default-product-locale,$(PRODUCT_LOCALES)) \PRODUCT_DEFAULT_WIFI_CHANNELS$(PRODUCT_DEFAULT_WIFI_CHANNELS) \PRIVATE_BUILD_DESC$(PRIVATE_BUILD_DESC) \BUILD_ID$(BUILD_ID) \BUILD_DISPLAY_ID$(BUILD_DISPLAY_ID) \DATE$(DATE_FROM_FILE) \BUILD_USERNAME$(BUILD_USERNAME) \BUILD_HOSTNAME$(BUILD_HOSTNAME) \BUILD_NUMBER$(BUILD_NUMBER_FROM_FILE) \BOARD_BUILD_SYSTEM_ROOT_IMAGE$(BOARD_BUILD_SYSTEM_ROOT_IMAGE) \AB_OTA_UPDATER$(AB_OTA_UPDATER) \PLATFORM_VERSION$(PLATFORM_VERSION) \PLATFORM_SECURITY_PATCH$(PLATFORM_SECURITY_PATCH) \PLATFORM_BASE_OS$(PLATFORM_BASE_OS) \PLATFORM_SDK_VERSION$(PLATFORM_SDK_VERSION) \PLATFORM_PREVIEW_SDK_VERSION$(PLATFORM_PREVIEW_SDK_VERSION) \PLATFORM_PREVIEW_SDK_FINGERPRINT$$(cat $(API_FINGERPRINT)) \PLATFORM_VERSION_CODENAME$(PLATFORM_VERSION_CODENAME) \PLATFORM_VERSION_ALL_CODENAMES$(PLATFORM_VERSION_ALL_CODENAMES) \PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION$(PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION) \BUILD_VERSION_TAGS$(BUILD_VERSION_TAGS) \$(if $(OEM_THUMBPRINT_PROPERTIES),BUILD_THUMBPRINT$(BUILD_THUMBPRINT_FROM_FILE)) \TARGET_CPU_ABI_LIST$(TARGET_CPU_ABI_LIST) \TARGET_CPU_ABI_LIST_32_BIT$(TARGET_CPU_ABI_LIST_32_BIT) \TARGET_CPU_ABI_LIST_64_BIT$(TARGET_CPU_ABI_LIST_64_BIT) \TARGET_CPU_ABI$(TARGET_CPU_ABI) \TARGET_CPU_ABI2$(TARGET_CPU_ABI2) \bash $(BUILDINFO_SH) $# 把 system_prop_file 中的内容写入中间文件$(hide) $(foreach file,$(system_prop_file), \if [ -f $(file) ]; then \echo Target buildinfo from: $(file); \echo $; \echo # $; \echo # from $(file) $; \echo # $; \cat $(file) $; \echo # end of $(file) $; \fi;)# FINAL_BUILD_PROPERTIES 的值来自 ADDITIONAL_BUILD_PROPERTIES# ADDITIONAL_BUILD_PROPERTIES 主要是 PRODUCT_PROPERTY_OVERRIDES 这个变量赋值 而这个变量就是我们开发时经常用于自定义属性的 一般在产品配置目录下定义# 这里把 FINAL_BUILD_PROPERTIES 中的属性写入中间文件$(if $(FINAL_BUILD_PROPERTIES), \$(hide) echo $; \echo # $; \echo # ADDITIONAL_BUILD_PROPERTIES $; \echo # $; )$(hide) $(foreach line,$(FINAL_BUILD_PROPERTIES), \echo $(line) $;)$(hide) build/make/tools/post_process_props.py $ $(PRODUCT_SYSTEM_PROPERTY_BLACKLIST)build_desc :ifeq (,$(filter true, $(TARGET_NO_KERNEL) $(TARGET_NO_RECOVERY)))
INSTALLED_RECOVERYIMAGE_TARGET : $(PRODUCT_OUT)/recovery.img
else
INSTALLED_RECOVERYIMAGE_TARGET :
endif# INSTALLED_BUILD_PROP_TARGET 的值为 out/target/product/xxx/system/build.prop
# 也就是我们最终要生成的文件
$(INSTALLED_BUILD_PROP_TARGET): $(intermediate_system_build_prop) $(INSTALLED_RECOVERYIMAGE_TARGET)echo Target build info: $# 这里把中间文件写入到最终文件中同时剔除 ro.product.first_api_level 相关的行$(hide) grep -v ro.product.first_api_level $(intermediate_system_build_prop) $以上代码总结一下
准备好一个中间文件 out/target/product/xxx/obj/ETC/system_build_prop_intermediates/build.prop调用 buildinfo_common.sh向中间文件写入数据把 system_prop_file 中的内容写入中间文件这里把用户自定义的的属性PRODUCT_PROPERTY_OVERRIDES写入中间文件这里把中间文件写入到最终文件out/target/product/xxx/system/build.pro中同时剔除 ro.product.first_api_level 相关的行
以上就是 /system/build.prop其他属性文件我们都可以依葫芦画瓢进行分析了。
如何添加系统属性
常见的自定义系统属性有三类 添加系统属性到 /system/build.prop添加系统属性到 /vendor/build.prop添加系统属性到 /product/build.prop 1.添加系统属性到 /system/build.prop
我们先看看生成 /system/build.prop 文件相关的部分源码 # build/make/core/Makefileifdef TARGET_SYSTEM_PROP
system_prop_file : $(TARGET_SYSTEM_PROP)
else
system_prop_file : $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
endif在上文我们分析过 system_prop_file 文件的内容最终会写入到 /system/build.prop 中/system/build.prop 的值又来自 TARGET_SYSTEM_PROP所以我们添加一个属性文件再修改 TARGET_SYSTEM_PROP 的值即可。
在我们的自定义 Product device/jelly/rice14 目录下添加一个 system.prop 文件文件的内容如下 ro.rice14.test2.0接着在 device/jelly/rice14/BoardConfig.mk 中添加 TARGET_SYSTEM_PROP device/jelly/rice14/system.prop然后重新编译系统启动模拟器 source build/envsetup.sh
lunch rice14-eng
make -j16
emulator启动虚拟机后我们可以进入虚拟机终端查看属性值 adb shellrice14:/ # getprop ro.rice14.test
2.0# end of device/jelly/rice14/system.prop这里查询到了我们刚添加的属性。
2.添加系统属性到 /vendor/build.prop
同样的我们先看看生成 /vendor/build.prop 文件相关的部分源码 ifdef property_overrides_split_enabled
FINAL_VENDOR_BUILD_PROPERTIES \$(call collapse-pairs, $(PRODUCT_PROPERTY_OVERRIDES))
FINAL_VENDOR_BUILD_PROPERTIES : $(call uniq-pairs-by-first-component, \$(FINAL_VENDOR_BUILD_PROPERTIES),)
endif # property_overrides_split_enabled这里会把 PRODUCT_PROPERTY_OVERRIDES 变量中的值赋值写入到 FINAL_VENDOR_BUILD_PROPERTIES从变量名字就可以看出这就是最终的 vendor 属性文件所以我们通过修改 PRODUCT_PROPERTY_OVERRIDES 变量的值即可添加属性 # device/jelly/rice14/rice14.mk
PRODUCT_PROPERTY_OVERRIDES \ro.vendor.xxxxxx \ro.vendor.yyyyyy3.添加系统属性到 /product/build.prop
同样的我们先看看生成 /product/build.prop 文件相关的部分源码 ifdef TARGET_PRODUCT_PROP
product_prop_files : $(TARGET_PRODUCT_PROP)
else
product_prop_files : $(wildcard $(TARGET_DEVICE_DIR)/product.prop)
endifFINAL_PRODUCT_PROPERTIES \$(call collapse-pairs, $(PRODUCT_PRODUCT_PROPERTIES) $(ADDITIONAL_PRODUCT_PROPERTIES))
FINAL_PRODUCT_PROPERTIES : $(call uniq-pairs-by-first-component, \$(FINAL_PRODUCT_PROPERTIES),)可以看到这里会把 product_prop_files 文件和 PRODUCT_PRODUCT_PROPERTIES 变量以及 ADDITIONAL_PRODUCT_PROPERTIES 变量中的值都会写入到最终的属性文件中。
所以上两节介绍的两种方式都可以这里我们演示先通过添加变量值的方式添加属性 # device/jelly/rice14/rice14.mk
PRODUCT_PRODUCT_PROPERTIES \ro.product.xxxxxx \ro.product.yyyyyy 属性与 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.husing 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 如下
至此整个示例程序就完成了最后修改我们自定义 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 可执行文件了:
# 重新编译源码
source build/envsetup.sh
lunch rice14-eng
make -j16
# 启动虚拟机
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: type1400 audit(0.0:27): avc: denied { read } for nameu:object_r:vendor_mytest_prop:s0 devtmpfs ino6750 scontextu:r:shell:s0 tcontextu:object_r:vendor_mytest_prop:s0 tclassfile permissive0
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: type1400 audit(0.0:58): avc: denied { use } for path/dev/pts/0 devdevpts ino3 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive0
10-23 10:29:41.930 3704 3704 W prop_test: type1400 audit(0.0:60): avc: denied { use } for path/dev/pts/0 devdevpts ino3 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive0
10-23 10:29:41.930 3704 3704 W prop_test: type1400 audit(0.0:61): avc: denied { use } for path/dev/goldfish_pipe devtmpfs ino7279 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive0
10-23 10:29:41.930 3704 3704 W prop_test: type1400 audit(0.0:62): avc: denied { use } for path/dev/goldfish_pipe devtmpfs ino7279 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive0
10-23 10:31:17.980 3919 3919 I prop_test: type1400 audit(0.0:87): avc: denied { use } for path/dev/pts/0 devdevpts ino3 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive1
10-23 10:31:17.980 3919 3919 I prop_test: type1400 audit(0.0:88): avc: denied { read write } for path/dev/pts/0 devdevpts ino3 scontextu:r:myprop_test_dt:s0 tcontextu:object_r:devpts:s0 tclasschr_file permissive1
10-23 10:31:17.980 3919 3919 I prop_test: type1400 audit(0.0:89): avc: denied { read write } for pathsocket:[9765] devsockfs ino9765 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassunix_stream_socket permissive1
10-23 10:31:17.980 3919 3919 I prop_test: type1400 audit(0.0:90): avc: denied { use } for path/vendor/bin/prop_test devdm-1 ino158 scontextu:r:myprop_test_dt:s0 tcontextu:r:shell:s0 tclassfd permissive1
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: type1400 audit(0.0:28): avc: denied { use } for path/dev/pts/0 devdevpts ino3 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive0
10-23 10:38:05.670 2910 2910 W prop_test: type1400 audit(0.0:30): avc: denied { use } for path/dev/pts/0 devdevpts ino3 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive0
10-23 10:38:05.670 2910 2910 W prop_test: type1400 audit(0.0:31): avc: denied { use } for pathsocket:[10955] devsockfs ino10955 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive0
10-23 10:38:05.670 2910 2910 W prop_test: type1400 audit(0.0:32): avc: denied { use } for path/dev/goldfish_pipe devtmpfs ino7343 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive0
10-23 10:38:57.400 3034 3034 I prop_test: type1400 audit(0.0:39): avc: denied { use } for path/dev/pts/0 devdevpts ino3 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassfd permissive1
10-23 10:38:57.400 3034 3034 I prop_test: type1400 audit(0.0:40): avc: denied { read write } for path/dev/pts/0 devdevpts ino3 scontextu:r:myprop_test_dt:s0 tcontextu:object_r:devpts:s0 tclasschr_file permissive1
10-23 10:38:57.400 3034 3034 I prop_test: type1400 audit(0.0:41): avc: denied { read write } for pathsocket:[10955] devsockfs ino10955 scontextu:r:myprop_test_dt:s0 tcontextu:r:adbd:s0 tclassunix_stream_socket permissive1
10-23 10:38:57.410 3034 3034 I prop_test: type1400 audit(0.0:42): avc: denied { use } for path/vendor/bin/prop_test devdm-1 ino158 scontextu:r:myprop_test_dt:s0 tcontextu:r:shell:s0 tclassfd permissive1接着执行命令 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 后重新编译系统启动虚拟机程序即可正常运行。