属性与 SeLinux

这是一个介绍 Android 属性系统的系列文章:

  • Android 属性系统入门
  • 属性文件生成过程分析
  • 如何添加系统属性
  • 属性与 Selinux (本文)
  • 属性系统整体框架与启动过程分析
  • 属性读写过程源码分析

Android O 以后,属性的 Selinux 的规则变得复杂起来了,今天我们先看一个简单的例子,做基本的了解。在Hal与硬件服务的 treble 章节我们还会继续来学习属性相关的 Selinux 配置。

读写属性的示例代码

首先我们在 device/jelly/rice14 目录下创建如下的目录:

bash 复制代码
PropTest/
├── Android.bp
└── prop_test.cpp

其中 prop_test.cpp 具体内容如下:

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 如下:

json 复制代码
cc_binary {
    name: "prop_test",
    srcs: [ "prop_test.cpp" ],
    vendor: true,
    shared_libs: [
        "libbase",
        "liblog",
        "libcutils",
        "libutils"
    ],
}

至此,整个示例程序就完成了,最后修改我们自定义 Product 的配置文件 device/jelly/rice14/rice14.mk :

Makefile 复制代码
PRODUCT_PACKAGES += 
    # ......
    prop_test \

Selinux 的配置

接着需要配置 SeLinux:

device/jelly/rice14 目录下创建如下的文件与目录:

bash 复制代码
sepolicy/
├── file_contexts
├── property_contexts
├── property.te
└── prop_te

不要忘了配置自定义 sepolicy 目录,在 device/jelly/rice14/rice14.mk 中添加如下内容:

bash 复制代码
BOARD_SEPOLICY_DIRS += \
    device/jelly/rice14/sepolicy

首先在 property.te 中定义属性类型

bash 复制代码
type vendor_mytest_prop, property_type;

接着在 property_contexts 中配置好我们自定义属性 vendor.my.prop.test 的安全上下文:

bash 复制代码
vendor.my.prop.test u:object_r:vendor_mytest_prop:s0

接着在 prop_test.te 中配置好可执行文件和对应进程的类型和域转换规则以及属性的读写权限:

bash 复制代码
# 可执行文件对应进程类型
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,我是通过如下的搜索命令查找到的:

bash 复制代码
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 中配置可执行文件的安全上下文:

bash 复制代码
/vendor/bin/prop_test                   u:object_r:myprop_test_dt_exec:s0

接着我们就可以执行在虚拟机的 shell 中执行 prop_test 可执行文件了:

bash 复制代码
# 启动虚拟机
emulator
# 重开一个终端,进入虚拟机 shell 环境
adb shell
# root
su 
# selinux 配置为 Permissive 模式
setenforce 0
# 退出 root
exit
prop_test

接着我们查看 log:

bash 复制代码
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 拷贝进去:

bash 复制代码
# 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 生成缺失的权限配置:

bash 复制代码
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 后,重新编译系统,启动虚拟机,程序即可正常运行。

相关推荐
网络研究院1 小时前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术
凉亭下1 小时前
android navigation 用法详细使用
android
小比卡丘4 小时前
C语言进阶版第17课—自定义类型:联合和枚举
android·java·c语言
前行的小黑炭5 小时前
一篇搞定Android 实现扫码支付:如何对接海外的第三方支付;项目中的真实经验分享;如何高效对接,高效开发
android
落落落sss6 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
代码敲上天.7 小时前
数据库语句优化
android·数据库·adb
GEEKVIP9 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
model200511 小时前
android + tflite 分类APP开发-2
android·分类·tflite
彭于晏68911 小时前
Android广播
android·java·开发语言
与衫12 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql