SEAndroid安全机制中的进程安全上下文关联分析模板
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
SEAndroid安全机制中的进程安全上下
文关联分析
前面一篇文章分析了文件安全上下文关联过程。但是在SEAndroid中,除了要给文件关联安全上下文外,还需要给进程关联安全上下文,因为只有当进程和文件都关联安全上下文之后,SEAndroid安全策略才能发挥作用。也就是说,当一个进程试图访问一个文件时,SEAndroid 会将进程和文件的安全上下文提取出来,根据安全策略规则,决定是否允许访问。本文就详细分析SEAndroid的进程安全上下文的关联过程。
在传统的Linux系统中,每一个应用程序都对应有一个可执行文件。在这种情况下,我们就可以在安全策略中设定一个规则:当一个可执行文件加载到一个进程中执行时,该进程的安全上下文就设置为指定的值。也就是说,我们可以在安全策略中静态地为进程设置安全上下文。然而,这种进程安全上下文设置方式不适合于Android系统中的应用程序进程。从前面和这两篇文章可以知道,Android系统中的应用程序进程都是由Zygote进程fork出来。这些应用程序进程被Zygote进程fork出来之后,不像传统Linux的应用程序进程一样,会通过exec系统调用将对应的可执行文件加载起来执行。这样就会使得Zygote进程及其创建的所有应用程序进程对应的可执行文件均为/system/bin/app_process。由于我们却需要给不同的应用程序设置不同的安全上下文,以便给它们赋予不同的安全权限,因此我们需要在应用程序进程创建出来之后动态地设置它的安全上下文。
根据上面的描述,我们就总结出,在SEAndroid安全机制中,进程的安全上下文设置分为静态和动态两种方式,如图1所示:
接下来,我们就分别描述这两种进程安全上下文设置方式。
1. 为独立进程静态地设置安全上下文
Android系统的第一个进程是init,其它所有的进程都是由init进程直接或者间接fork 出来的。我们在前面一篇文章提到,一个新创建的文件的安全上下文在默认情况下来自于其父目录。与此类似,一个新创建的进程的安全上下文在默认情况下来自于其父进程。因此,我们就先看看系统中的第一个进程init的安全上下文是如何设置的。
查看init进程的启动脚本system/core/rootdir/init.rc,可以看到以下的内容:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
on early-init
......
# Set the security context for the init process.
# This should occur before anything else (e.g. ueventd) is started.
setcon u:r:init:s0
......
这段脚本的意思是init进程启动之后就马上调用函数setcon将自己的安全上下文设置为“u:r:init:s0”,即将init进程的domain指定为init。
接下来我们再看看init这个domain的定义,在external/sepolicy/init.te文件中:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
# init switches to init domain (via init.rc).
type init, domain;
permissive init;
# init is unconfined.
unconfined_domain(init)
tmpfs_domain(init)
# add a rule to handle unlabelled mounts
allow init unlabeled:filesystem mount;
第一个type语句将domain设置为init的属性,这意味着init是用来描述进程的安全上下文的。
第二个permissive语句指定当domain为init的进程违反SEAndroid安全策略访问资源时,只进行日志输出,而不是拒绝执行。由于这里列出来的内容是来自Android 4.3的,而Android 4.3开启的是Permissive的SEAndroid模式,因此这里会看到这样的一个permissive 语句。
第三个unconfined_domain语句是一个宏,定义在external/sepolicy/te_macros文件中,用来指定init是一个不受限制的domain,即它可以访问系统中的大部分资源。它的定义如下所示:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
#####################################
# unconfined_domain(domain)
# Allow the specified domain to do anything.
#
define(`unconfined_domain', `
typeattribute $1 mlstrustedsubject;
typeattribute $1 unconfineddomain;
')
第四个tmpfs_domain语句也是定义在external/sepolicy/te_macros文件中的一个宏,用来指定当domain为init的进程在type为tmpfs的目录中创建文件时,将新创建的文件的type设置为init_tmpfs,并且允许domain为init的进程对它们进行读和执行。它的定义如下所示:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
#####################################
# tmpfs_domain(domain)
# Define and allow access to a unique type for
# this domain when creating tmpfs / shmem / ashmem files.
define(`tmpfs_domain', `
type $1_tmpfs, file_type;
type_transition $1 tmpfs:file $1_tmpfs;
# Map with PROT_EXEC.
allow $1 $1_tmpfs:file { read execute execmod };
')
第5个allow语句允许domain为init的进程mount未指定安全上下文的文件系统时,将其安全上下文设置为unlabeled。
上面列出的脚本就指明了init进程的安全上下文,以及它所具有的SEAndroid权限。接下来我们就再来看看负责创建应用程序进程的Zygote进程的安全上下文的设置过程。
Zygote进程是由init进程创建的,它的启动命令定义在文件system/core/rootdir/init.rc 中,如下所示:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
这意味着Zygote进程对应的可执行文件为/system/bin/app_process。
通过检查external/sepolicy/file_contexts,我们可以发现文件/system/bin/app_process 的安全上下文为“u:object_r:zygote_exec:s0”,如下所示:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
/system/bin/app_process u:object_r:zygote_exec:s0
也就是说,文件/system/bin/app_process的type为zygote_exec。
在external/sepolicy/zygote.te文件中,定义了一个名称为zygote的domain,以及名称为zygote_exec的type,如下所示:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
# zygote