深入理解 Android 安全策略:属性标签与构建工具链
1. Android 属性标签概述
在 Android 系统中,属性标签是一项关键的安全机制,通过配置文件和 SELinux 策略,可以对应用私有数据目录及其运行时上下文进行恰当的标记。其主要目的在于限制属性的设置权限,防止经典的 DAC 根攻击意外更改属性值。以下是在这方面需要掌握的几个关键技能:
- 创建新属性
- 对新属性和现有属性进行标签设置
- 解读和处理属性拒绝访问的情况
- 了解特殊 Android 属性及其行为
2. 通过 property_contexts 文件进行属性标签设置
所有属性的标签设置都依赖于
property_contexts
文件,其语法与
file_contexts
类似。不同之处在于,
property_contexts
针对的是属性名称或属性键(在 Android 中,属性以键值对形式存储),属性键通常以句点(.)分隔,类似于
file_contexts
中的斜杠(/)。以下是一些示例:
ctl.ril-daemon u:object_r:ctl_rildaemon_prop:s0
ctl. u:object_r:ctl_default_prop:s0
从上述示例可以看出,所有以
ctl.
开头的属性都被标记为
ctl_default_prop
类型,但
ctl.ril-daemon
有其特定的类型标签
ctl_rildaemon_prop
。这展示了可以先进行通用标记,再根据需要设置更具体的标签。此外,对于未明确标记的属性,通过
property_contexts
中的 “匹配所有” 表达式,默认标签为
default_prop
:
# default property context
* u:object_r:default_prop:s0
3. 属性的权限设置
在系统中,可以使用命令行工具
getprop
和
setprop
查看当前属性并创建新属性,示例代码如下:
root@udoo:/ # getprop
...
[sys.usb.state]: [mtp,adb]
[wifi.interface]: [wlan0]
[wlan.driver.status]: [unloaded]
需要注意的是,虽然所有用户都可以读取属性(因为属性被映射到每个用户的地址空间),但并非所有用户都能设置(写入)属性。属性的 DAC 权限模型硬编码在
system/core/init/property_service.c
文件中:
/* White list of permissions for setting property services. */
struct {
const char *prefix;
unsigned int uid;
unsigned int gid;
} property_perms[] = {
{ "net.rmnet0.", AID_RADIO, 0 },
{ "net.gprs.", AID_RADIO, 0 },
{ "net.ppp", AID_RADIO, 0 },
...
{ "persist.service.bdroid.", AID_BLUETOOTH, 0 },
{ "selinux." , AID_SYSTEM, 0 },
{ "persist.audio.device", AID_SYSTEM, 0 },
{ NULL, 0, 0 }
只有当用户的 UID 或 GID 在
property_perms
数组中,且属性前缀匹配时,才能设置相应的属性。例如,要设置以
selinux.
开头的属性,用户必须是 UID 为
AID_SYSTEM
(uid 1000)或 root 用户。遗憾的是,目前没有类似
ls -Z
查看文件标签的
getprop -Z
命令来查看属性及其标签。
4. 重新标记现有属性
为了更好地掌握属性标签设置,以重新标记
wifi.interface
属性为例。首先,通过触发拒绝访问并查看拒绝日志来验证其当前上下文:
root@udoo:/ # setprop wifi.interface wlan0
avc: denied { set } for property=wifi.interface scontext=u:r:shell:s0
tcontext=u:object_r:default_prop:s0 tclass=property_service
从拒绝输出可知,该属性的类型标签为
default_prop
,接下来将其更改为
wifi_prop
。具体操作步骤如下:
1. 编辑
sepolicy
目录下的
property.te
文件,声明新的类型:
type wifi_prop, property_type;
-
修改
property_contexts文件,添加以下内容应用新标签:
# wifi properties
wifi. u:object_r:wifi_prop:s0
- 构建策略:
$ mmm external/sepolicy
-
推送新的
property_contexts文件:
$ adb push out/target/product/udoo/root/property_contexts
/data/security/current
- 触发动态重新加载:
$ adb shell setprop selinux.reload_policy 1
然而,首次尝试可能会失败,因为
property_contexts
文件的正确位置应该是
/data/security
,而不是
/data/security/current
。通过搜索相关文件可以发现这一问题:
$ grep -rn property_contexts *
init/init.c:745: { SELABEL_OPT_PATH, "/data/security/property_contexts" },
init/init.c:746: { SELABEL_OPT_PATH, "/property_contexts" },
init/init.c:760: ERROR("SELinux: Could not load property_contexts: %s\n",
将文件推送到正确位置并再次尝试:
$ adb push out/target/product/udoo/root/property_contexts /data/security
$ adb shell setprop selinux.reload_policy 1
但可能仍然失败,这是因为包含
wifi_prop
类型声明的
sepolicy
文件未被推送。需要将其推送并再次触发重新加载:
$ adb push out/target/product/udoo/root/sepolicy /data/security/current/
$ adb shell setprop selinux.reload_policy 1
此时会看到拒绝信息,但目标属性的标签已变为
u:object_r:wifi_prop:s0
。接下来,可以在
shell.te
文件中添加允许规则:
# wifi prop
allow shelldomain wifi_prop:property_service set;
编译策略,推送到设备并触发动态重新加载,再次尝试设置
wifi.interface
属性,将不再出现拒绝信息。
5. 创建和标记新属性
在系统中,所有属性都可以通过
setprop
调用或 C 语言(
bionic/libc/include/sys/system_properties.h
)和 Java(
android.os.SystemProperties
)中的等效函数调用动态创建。需要注意的是,Java 的
System.getProperty()
和
System.setProperty()
调用针对的是应用私有属性存储,与全局属性无关。对于非 root 用户创建或设置属性,需要修改
property_perms[]
数组。例如,要创建
udoo.name
和
udoo.owner
属性,并仅允许 root 用户和 shell 域访问:
root@udoo:/ # setprop udoo.name udoo
avc: denied { set } for property=udoo.name scontext=u:r:shell:s0
tcontext=u:object_r:default_prop:s0 tclass=property_service
root@udoo:/ # setprop udoo.owner William
从拒绝信息可知,这些属性的类型为
default_prop
,可按照重新标记现有属性的步骤进行修正。
6. 特殊属性
Android 中有一些具有特殊行为的属性,以下是几种常见的特殊属性:
| 属性类型 | 描述 | 示例命令 |
| ---- | ---- | ---- |
| 控制属性 | 以
ctl
开头,用于通过
init
控制服务 |
setprop ctl.start <servicename>
启动服务
setprop ctl.stop <servicename>
停止服务
setprop ctl.restart <servicename>
重启服务 |
| 持久属性 | 以
persist
开头,在重启后仍然保留,数据存储在
/data/property
目录下同名文件中 |
root@udoo:/ # ls /data/property/
persist.gps.oacmode
persist.service.bdroid.bdaddr
persist.sys.profiler_ms
persist.sys.usb.config
|
| SELinux 属性 |
selinux.reload_policy
属性用于触发动态重新加载事件 |
$ adb shell setprop selinux.reload_policy 1
|
7. Android 构建工具链概述
在深入了解 Android 安全策略的代码和策略之后,掌握构建工具链对于提高开发效率至关重要。以下是需要关注的几个方面:
- 构建特定目标
- 分析
sepolicy
的
Android.mk
文件
- 自定义构建策略配置
- 了解各种构建工具,如
check_seapp
、
insertkeys.py
、
checkpolicy
、
checkfc
、
sepolicy-check
和
sepolicy-analyze
8. 构建子组件 - 目标和项目
在 Android 开发中,我们使用过一些命令来构建项目,如
mm
、
mmm
和
make bootimage
。Google 在相关文档中对部分工具进行了描述,但仍有很多命令未详细列出。在 Android 构建系统中,“目标” 通常指特定的
make
目标,而非目标设备。可以通过指定目标来构建系统的特定部分,例如
make bootimage
用于构建
boot.img
文件,
make sepolicy
用于构建
sepolicy
文件。
要确定可以构建的目标名称,可以查看
Android.mk
文件中以
LOCAL_MODULE
开头的行。例如,在
external/sepolicy
的
Android.mk
文件中:
$ grep -w '^LOCAL_MODULE' Android.mk
LOCAL_MODULE := sepolicy
LOCAL_MODULE := file_contexts
LOCAL_MODULE := seapp_contexts
LOCAL_MODULE := property_contexts
LOCAL_MODULE := selinux-network.sh
LOCAL_MODULE := mac_permissions.xml
LOCAL_MODULE := eops.xml
Android 还提供了
mm
和
mmm
命令,它们的作用是构建
Android.mk
文件中指定的所有目标,但不构建其依赖项。
mm
命令使用当前工作目录,
mmm
命令需要指定路径。使用
-B
选项可以强制重新构建,这可以节省大量时间。
9. 剖析 sepolicy 的 Android.mk 文件
external/sepolicy
项目使用
Android.mk
文件来构建输出。下面详细分析构建
sepolicy
的过程:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A([开始]):::startend --> B(初始化 Android.mk 基本设置):::process
B --> C(声明中间目标文件 policy.conf):::process
C --> D(设置 MLS_SENS 和 MLS_CATS 变量):::process
D --> E(使用 build_policy 函数生成 policy.conf):::process
E --> F(使用 m4 处理 policy.conf):::process
F --> G(生成 .dontaudit 版本的 policy.conf):::process
G --> H(使用 checkpolicy 编译 sepolicy):::process
H --> I(设置 local 变量并清除 policy.conf):::process
I --> J([结束]):::startend
具体步骤如下:
-
初始化设置
:
include $(CLEAR_VARS)
LOCAL_MODULE := sepolicy
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
include $(BUILD_SYSTEM)/base_rules.mk…
- 声明中间目标文件 :
sepolicy_policy.conf := $(intermediates)/policy.conf
$(sepolicy_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(sepolicy_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(sepolicy_policy.conf) : $(call build_policy, security_classes
initial_sids access_vectors global_macros mls_macros mls
policy_capabilities te_macros attributes bools *.te roles users
initial_sid_contexts fs_use genfs_contexts port_contexts)
-
构建中间目标
policy.conf:
使用m4处理 SELinux 策略文件,将PRIVATE_MLS_SENS和PRIVATE_MLS_CATS作为宏定义传入,并生成.dontaudit版本:
@mkdir -p $(dir $@)
$(hide) m4 -D mls_num_sens=$(PRIVATE_MLS_SENS) -D
mls_num_cats=$(PRIVATE_MLS_CATS) -s $^ > $@
$(hide) sed '/dontaudit/d' $@ > $@.dontaudit…
-
构建最终目标
sepolicy:
使用checkpolicy将m4处理后的policy.conf和policy.conf.dontaudit编译成sepolicy和sepolicy.dontaudit:
$(LOCAL_BUILT_MODULE) : $(sepolicy_policy.conf)
$(HOST_OUT_EXECUTABLES)/checkpolicy
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $@ $<
$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $(dir
$<)/$(notdir $@).dontaudit $<.dontaudit…
- 清理和设置变量 :
built_sepolicy := $(LOCAL_BUILT_MODULE)
sepolicy_policy.conf :=
此外,构建
sepolicy
还依赖于
POLICYVERS
变量,如果未设置,默认值为 26。
通过深入理解 Android 属性标签和构建工具链,可以更好地进行 Android 安全策略的开发和管理,确保系统的安全性和稳定性。
深入理解 Android 安全策略:属性标签与构建工具链
10. 构建工具详解
在 Android 安全策略的构建过程中,有多个重要的构建工具发挥着关键作用,下面对这些工具进行详细介绍:
| 工具名称 | 功能描述 |
| ---- | ---- |
|
check_seapp
| 用于检查
seapp_contexts
文件的正确性,确保应用程序的上下文标签设置符合策略要求。它可以帮助开发者发现标签配置中的错误,避免因标签设置不当导致的安全漏洞。 |
|
insertkeys.py
| 该脚本主要用于在策略文件中插入密钥信息。在某些安全场景下,需要对策略进行加密或签名,
insertkeys.py
可以将相应的密钥插入到合适的位置,增强策略的安全性。 |
|
checkpolicy
| 核心的策略编译工具,将文本形式的 SELinux 策略转换为内核可以加载的二进制形式。它会对策略文件进行语法检查和语义分析,确保策略的合法性和一致性。在构建
sepolicy
文件时,
checkpolicy
会根据指定的策略版本号(如
POLICYVERS
)进行编译。 |
|
checkfc
| 用于检查文件上下文配置文件(如
file_contexts
)的正确性。它会验证文件路径和对应的标签是否符合策略规则,防止因文件上下文配置错误而导致的访问控制问题。 |
|
sepolicy-check
| 对 SELinux 策略文件进行全面的检查和验证,包括策略的完整性、兼容性和安全性等方面。通过
sepolicy-check
,可以提前发现策略中可能存在的问题,避免在系统运行时出现安全故障。 |
|
sepolicy-analyze
| 提供对 SELinux 策略的详细分析功能。它可以帮助开发者理解策略的结构和规则,分析策略对不同进程和对象的访问控制效果,从而进行策略的优化和调整。 |
11. 自定义构建策略配置
在实际开发中,可能需要根据特定的需求对构建策略进行自定义配置。以下是一些常见的自定义配置场景和操作步骤:
11.1 修改策略版本号
如果默认的策略版本号(如
POLICYVERS
的默认值 26)不满足需求,可以在构建脚本中手动指定新的版本号。例如,在
Android.mk
文件中添加如下代码:
POLICYVERS := 28
11.2 调整 MLS 敏感度和类别
MLS(多级安全)是 SELinux 中的一个重要特性,通过设置不同的敏感度和类别可以实现更精细的访问控制。在
sepolicy
的
Android.mk
文件中,可以修改
MLS_SENS
和
MLS_CATS
变量的值:
MLS_SENS := 5
MLS_CATS := 10
11.3 自定义策略文件路径
如果需要使用自定义的策略文件路径,可以在
Android.mk
文件中修改相关的路径配置。例如:
LOCAL_MODULE_PATH := $(TARGET_OUT)/custom/sepolicy
12. 构建过程中的常见问题及解决方法
在构建 Android 安全策略的过程中,可能会遇到各种问题,下面列举一些常见问题及相应的解决方法:
12.1 策略编译失败
-
问题描述
:使用
checkpolicy编译策略时出现错误信息,提示语法错误或语义错误。 -
解决方法
:检查策略文件中的语法错误,确保所有的规则和声明都符合 SELinux 策略的语法规范。可以使用
sepolicy-check工具进行更详细的检查,找出具体的错误位置。
12.2 文件上下文加载失败
-
问题描述
:系统无法正确加载文件上下文配置文件(如
property_contexts),导致属性标签设置无效。 -
解决方法
:检查文件路径是否正确,确保文件存在且具有正确的权限。可以通过搜索相关代码文件,如
init.c,找到文件加载的优先级位置,并将文件放置在正确的目录下。
12.3 动态重新加载策略失败
-
问题描述
:使用
setprop selinux.reload_policy 1触发动态重新加载策略时,没有生效或出现错误信息。 -
解决方法
:确保所有相关的策略文件(如
sepolicy和property_contexts)都已正确推送和更新。检查策略文件中是否存在未解决的依赖问题,确保所有的类型声明和规则都已正确定义。
13. 总结与展望
通过对 Android 属性标签和构建工具链的深入学习,我们了解了如何对 Android 系统中的属性进行标签设置,以及如何使用构建工具来生成和管理 SELinux 策略。属性标签的正确设置可以有效限制属性的访问权限,防止潜在的安全攻击;而掌握构建工具链则可以提高开发效率,确保策略的正确性和稳定性。
在未来的 Android 开发中,随着安全需求的不断提高,对 SELinux 策略的优化和定制将变得更加重要。开发者需要不断学习和掌握新的安全技术和工具,以应对日益复杂的安全挑战。同时,也需要关注 Android 系统的更新和变化,及时调整策略配置,确保系统的安全性和兼容性。
总之,深入理解 Android 安全策略的属性标签和构建工具链是保障 Android 系统安全的关键,希望本文的内容能够对开发者有所帮助。
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A([开始]):::startend --> B(选择自定义配置场景):::process
B --> C{是否修改策略版本号?}:::process
C -- 是 --> D(在 Android.mk 中指定新的 POLICYVERS):::process
C -- 否 --> E{是否调整 MLS 敏感度和类别?}:::process
E -- 是 --> F(修改 MLS_SENS 和 MLS_CATS 变量):::process
E -- 否 --> G{是否自定义策略文件路径?}:::process
G -- 是 --> H(修改 LOCAL_MODULE_PATH 变量):::process
D --> I(构建策略):::process
F --> I
H --> I
I --> J([结束]):::startend
以上流程图展示了自定义构建策略配置的基本流程,开发者可以根据具体需求选择不同的配置选项,然后进行策略的构建。
超级会员免费看
4833

被折叠的 条评论
为什么被折叠?



