SEAndroid安全机制中的进程安全上下文关联分析模板_第1页
SEAndroid安全机制中的进程安全上下文关联分析模板_第2页
SEAndroid安全机制中的进程安全上下文关联分析模板_第3页
SEAndroid安全机制中的进程安全上下文关联分析模板_第4页
SEAndroid安全机制中的进程安全上下文关联分析模板_第5页
已阅读5页,还剩13页未读, 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、SEAndroid安全机制中的进程安全上下文关联分析前面一篇文章分析了文件安全上下文关联过程。但是在SEAndroid中,除了要给文件关联安全上下文外,还需要给进程关联安全上下文, 因为只有当进程和文件都关联安全上下文之后, SEAndroid安全策略才能发挥作用。也就是说,当一个进程试图访问一个文件时,SEAndroid会将进程和文件的安全上下文提取出来,根据安全策略规则,决定是否允许访问。本文就详细分析SEAndroid的进程安全上下文的关联过程。在传统的Linux系统中,每一个应用程序都对应有一个可执行文件。在这种情况下,我们就 可以在安全策略中设定一个规则:当一个可执行文件加载到一个进

2、程中执行时,该进程的安全上下文就设置为指定的值。也就是说,我们可以在安全策略中静态地为进程设置安全上下 文。然而,这种进程安全上下文设置方式不适合于An droid系统中的应用程序进程。从前面和这两篇文章可以知道,An droid系统中的应用程序进程都是由Zygote进程fork出来。这些应用程序进程被 Zygote进程fork出来之后,不像传统 Linux的应用程序进程一样,会通 过exec系统调用将对应的可执行文件加载起来执行。这样就会使得Zygote进程及其创建的所有应用程序进程对应的可执行文件均为/system/bin/app_process。由于我们却需要给不同的应用程序设置不同的安

3、全上下文,以便给它们赋予不同的安全权限,因此我们需要在应用程序进程创建出来之后动态地设置它的安全上下文。根据上面的描述,我们就总结出,在SEAndroid安全机制中,进程的安全上下文设 置分为静态和动态两种方式,如图1所示:叶MteC Stt fo*图1 SEAndroid安全机制中的进程安全上下丈关联方式接下来,我们就分别描述这两种进程安全上下文设置方式。1.为独立进程静态地设置安全上下文An droid系统的第一个进程是init,其它所有的进程都是由init进程直接或者间接fork 出来的。我们在前面一篇文章提到,一个新创建的文件的安全上下文在默认情况下来自于其 父目录。与此类似,一个新创

4、建的进程的安全上下文在默认情况下来自于其父进程。因此, 我们就先看看系统中的第一个进程init的安全上下文是如何设置的。查看in it进程的启动脚本system/core/rootdir/i ni t.rc,可以看到以下的内容:plain view plain copy 在CODE上查看代码片派生到我的代码片 on early-i nit# Set the security context for the init process.# This should occur before anything else (e.g. ueve ntd) is started. setc on u:r:i

5、 nit:sO这段脚本的意思是in it进程启动之后就马上调用函数setco n将自己的安全上下文设置为u:r:init:sO ”,即将init进程的domain指定为init。接下来我们再看看 in it这个domai n的定义,在 external/sepolicy/i nit.te文件中:plain view plain copy 在 CODE 上查看代码片派生到我的代码片# init switches to init domain (via init.rc). type init, domain;permissive init;# init is unconfined. unconfi

6、ned_domain(init) tmpfs_domain(init)# add a rule to handle unlabelled mounts allow init unlabeled:filesystem mount;第一个type语句将domai n设置为in it的属性,这意味着init是用来描述进程的安全 上下文的。第二个permissive语句指定当doma in为in it的进程违反 SEA ndroid安全策略访问资 源时,只进行日志输出,而不是拒绝执行。由于这里列出来的内容是来自An droid 4.3的,而An droid 4.3开启的是 Permissive的SEA

7、 ndroid模式,因此这里会看到这样的一个permissive语句。第三个 unconfined_domain 语句是一个宏,定义在 external/sepolicy/te_macros 文件中, 用来指定in it是一个不受限制的doma in,即它可以访问系统中的大部分资源。它的定义如下所示:plain view plain copy 在 CODE 上查看代码片派生到我的代码片II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II I

8、I IIa a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a# unconfin ed_doma in( doma in)# Allow the specified doma in to do any thi ng.#defi ne( unconfin ed_doma in typeattribute $1 mlstrustedsubject;typeattribute $1 unconfin eddoma in;)第四个tmpfs_domain语句也是定义在 external/sepolicy/te

9、_macros文件中的一个宏, 用来指定当domain为init的进程在type为tmpfs的目录中创建文件时,将新创建的文件的 type设置为in it_tmpfs,并且允许doma in为in it的进程对它们进行读和执行。它的定义如下 所示:plain view plain copy 在CODE上查看代码片派生到我的代码片II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II IIa a a a a a a a a a a a a

10、 a a a a a a a a a a a a a a a a a a a a a a a a# tmpfs_domai n(domai n)# Define and allow access to a unique type for# this doma in whe n creati ng tmpfs / shmem / ashmem files.defi ne(tmpfs_doma intype $1_tmpfs, file_type;type_tra nsiti on $1 tmpfs:file $1_tmpfs;# Map with PROT_EXEC.allow $1 $1_tm

11、pfs:file read execute execmod ;)第5个allow语句允许domai n为in it的进程mou nt未指定安全上下文的文件系统时, 将其安全上下文设置为un labeled。上面列出的脚本就指明了in it进程的安全上下文,以及它所具有的 SEA ndroid权限。接下来我们就再来看看负责创建应用程序进程的Zygote进程的安全上下文的设置过程。Zygote进程是由in it进程创建的,它的启动命令定义在文件system/core/rootdir/i ni t.rc中,如下所示:plain view plain copy 在 CODE 上查看代码片派生到我的代码

12、片service zygote /system/b in/app_process -Xzygote /system/b in -zygote -start-system-server class mainsocket zygote stream 660 root systemon restart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netd这意味着Zygote进程对应的可执行文件为/system

13、/bin/app_process。通过检查 exter nal/sepolicy/file_c on texts,我们可以发现文件 /system/b in/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/zygo

14、te.te 文件中,定义了一个名称为zygote 的 domain,以及名称为 zygote_exec的type,如下所示: plain view plain copy 在 CODE 上查看代码片派生到我的代码片# zygotetype zygote, doma in;type zygote_exec, exec_type, file_type;permissive zygote;in it_daem on _domai n(zygote)unconfin ed_doma in( zygote)第一个type语句将domain设置为zygote的属性,表明zygote是用来描述进程的安 全上下

15、文的。第二个 type语句将 exec_type和file_type 设置为 zygote_exec的属性,表明 zygote_exec是用来描述可执行文件的安全上下文的。第三个permissive语句同样是表明当 domain为zygote的进程违反 SEAndroid安全 策略访问资源时,只进行日志输出,而不是拒绝执行。第四个 init_daemon_domain 语句是一个宏,定义在文件external/sepolicy/te_macros中,用来设置zygote这个domain的权限,它的定义如下所示:plain view plain copy 在CODE上查看代码片派生到我的代码片I

16、I II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II IIa a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a# in it_daem on _domai n(domai n)# Set up a tran siti on from in it to the daem on doma in# upon executi ng its bin ar

17、y.defi ne( ini t_daem on _doma in, doma in _auto_tra ns(i nit, $1_exec, $1)tmpfs_doma in ($1)宏 init_daemon_domain 由另外两个宏 tmpfs_domain 禾口 domain_auto_trans 组成。宏 tmpfs_domain的作用在前面已经分析过了,接下来我们重点关注宏domain_auto_trans的定义,也是在文件 external/sepolicy/te_macros中,如下所示:plain view plain copy 在 CODE 上查看代码片派生到我的代码片I

18、I II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II IIa a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a# domain_auto_tra ns(olddoma in, type, n ewdoma in)# Automatically tran siti on from olddoma in to n ewdoma in# upon e

19、xecuti ng a file labeled with type.#defi ne(doma in _auto_tra ns, # Allow the n ecessary permissi ons.domain_tra ns($1,$2,$3)# Make the tran siti on occur by default.type_tra nsition $1 $2:process $3;)第二个type_tra nsiti on语句指定当一个 domain为in it的进程创建一个子进程执行一 个type为zygote_exec的文件时,将该子进程的 domain设置为zygote,

20、而不是继承父进程 的 domain。第一个 domain_trans 语句是一个宏,也是定义在external/sepolicy/te_macros 中,用来允许进程的domai n从in it修改为zygote,它的定义如下所示:plain view plain copy 在CODE上查看代码片派生到我的代码片II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II IIa a a a a a a a a a a a a a a a a

21、 a a a a a a a a a a a a a a a a a a a a# domain_tra ns(olddoma in, type, n ewdoma in)# Allow a tran siti on from olddoma in to n ewdoma in# upon executi ng a file labeled with type.# This only allows the tran siti on; it does not# cause it to occur automatically - use doma in _auto_tra ns# if that

22、is what you want.#defi ne(doma in_tran s, # Old doma in may exec the file and tran siti on to the new doma in.allow $1 $2:file getattr ope n read execute ;allow $1 $3:process tran siti on;# New doma in is en tered by execut ing the file. allow $3 $2:file en trypo int read execute ;# New domai n can

23、se nd SIGCHLD to its caller.allow $3 $1:process sigchld;# En able AT_SECURE, i.e. libc secure mode.don taudit $1 $3:process no atsecure;# XXX don taudit can didate but requires further study.allow $1 $3:process sigi nh rlimit inh ;)其中,最重要的是以下两个 allow语句:plain view plain copy 在 CODE 上查看代码片派生到我的代码片allo

24、w $1 $3:process tran siti on;allow $3 $2:file en trypo int read execute ;第一个allow语句允许doma in为in it的进程将 doma in修改为zygote。第二个 allow 语句允许type为zygote_exec的可执行文件作为进入zygote这个domain 的入口点。概括来说,在 external/sepolicy/zygote.te 文件中,通过 init_daemon_domain 指明了 Zygote进程的domain为zygote。我们可以从 Zygote进程的创建过程来理解这些安全策略。 首先

25、, Zygote进程是由init进程fork出来的。在 fork出来的时候,Zygote进程的domain 来自于父进程in it的doma in,即此时Zygote进程的doma in为in it。接下来,刚刚fork出来 的Zygote进程会通过系统接口exec将文件/system/bin/app_process加载进来执行。由于上面提到的allow和type_transition规则的存在,使得文件 /system/bin/app_process被exec到刚刚 fork出来的Zygote进程的时候,它的 domain自动地从init转换为zygote。这样我们就可以 给init进程和Z

26、ygote进程设置不同的 domain,以便可以给它们赋予不同的SEAndroid安全权限。回至U external/sepolicy/zygote.te 文件中,最后一个 unconfined_domain 语句同样是将zygote这个domain设置为一个不受限的 domain,以便它可以访问系统中的大部分资源。这样,我们就以init和Zygote进程的安全上下文设置过程为例,说明了那些对应这些进程的安全上下文的设置方式与 接下来我们就再来分析An droid系有不同可执行文件的进程的安全上下文的关联过程了。 传统的Linux系统的应用程序进程的设置方式是一致的。 统的应用程序进程的安全上

27、下文的关联过程。2.为应用程序进程设置安全上下文从前面一篇文章可以知道,应用程序进程是由ActivityManagerService请求Zygote进程创建的。ActivityManagerService在请求Zygote进程创建应用程序进程的时候,会传递 很多参数,例如应用程序在安装时分配到的uid和gid。增加了 SEAndroid安全机制之后,ActivityManagerService 传递给Zygote进程的参数包含了一个seinfo。这个seinfo与我们在前面一文中介绍的seinfo是一样的,不过它的作用是用来设置应用程序进程的安全上下文,而不是设置应用程序数据文件的安全上下文。

28、接下来我们就分析应用程序进程的安全上下文设置过程。从前面一文的Step 1可以知道,当ActivityMangerService需要创建应用程序进程的 时候,就会调用 ActivityMangerService 类的成员函数 startProcessLocked,它的实现如下所示:java view plain copy 在CODE上查看代码片派生到我的代码片 public final class ActivityManagerService extends ActivityManagerNativeimpleme nts Watchdog.M on itor, BatteryStatsImp

29、l.BatteryCallback private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) try / Start the process. It will either succeed and retur n a result containing / the PID of the new process, or else throw a Run timeExcepti on. Process.ProcessStartResultstartResul

30、tProcess.start(a ndroid.app.ActivityThread,cessName, uid, uid, gids, debugFlags, moun tExter nal, app.i nfo.targetSdkVers ion, app.i nfo.se info, n ull); catch (RuntimeException e) 这个函数定义在文件frameworks/base/services/java/com/a ndroid/server/am/ActivityMa nagerService.java 中。参数app指向的是一个 Process

31、Record对象,用来描述正在创建的应用程序进程。 其中,它的成员变量 info指向的是一个 Applicationlnfo对象。从前面一文可以知道,这个 Applicationlnfo对象有一个类型为String的成员变量seinfo,是在应用程序安装的时候通过解析文件 mac_permissions.xml获得的。ActivityManagerService 类的成员函数 startProcessLocked 通过调用 Process类的静态 成员函数start来创建应用程序进程,其中就包含了要创建的应用程序进程的各种参数。从 前面一篇文章可以知道,这些参数会通过Socket IPC传递给

32、Zygote进程。最后,Zygote进程会通过调用ZygoteConnection类的成员函数runOnce来执行创建应用程序进程的工作。ZygoteConnection类的成员函数runOnce的实现如下所示:java view plain copy 在CODE上查看代码片派生到我的代码片 class ZygoteConnection boolea n runOnce() throws ZygoteI nit.MethodA ndArgsCaller try args = readArgumentList(); catch (IOExcepti on ex) try parsedArgs =

33、 new Arguments(args);pid = Zygote.forkA ndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits,parsedArgs.mountExternal,parsedArgs.seInfo,parsedArgs.niceName); catch (IOExcepti on ex) catch (ErrnoException ex) catch (IllegalArgume ntExcepti on ex) catch (ZygoteS

34、ecurityExcepti on ex) 这个函数定义在文件frameworks/base/core/java/com/android/internal/os/ZygoteConnection .java中。ZygoteConnection类的成员函数 runOnce首先是通过调用另外一个成员函数 readArgumentList读取ActivityManagerService 发送过来的应用程序进程创建参数args,接着再创建一个Arguments对象来解析该参数。解析后得到的参数传递给Zygote类的静态成员函数forkAndSpecialize,以便后者可以执行创建应用程序进程的工作。

35、Zygote类的静态成员函数 forkAndSpecialize的实现如下所示:java view plain copy 在CODE上查看代码片派生到我的代码片 public class Zygote public static int forkAndSpecialize(int uid, int gid, int gids, int debugFlags, in t rlimits, int moun tExter nal. String selnfo. String ni ceName) preFork();int pid = nativeForkAndSpecialize(uid, gi

36、d, gids, debugFlags, rlimits, moun tExter nal, selnfo, ni ceName); postFork();return pid;native public static int nativeForkAndSpecialize(int uid, int gid, int gids, int debugFlags, in t rlimits, int moun tExter nal, String selnfo, String ni ceName);这个函数定义在文件libcore/dalvik/src/ma in /java/dalvik/sys

37、tem/Zygote.java中。Zygote类的静态成员函数 forkAndSpecialize的实现很简单,它通过调用另外一个JNI函数nativeForkAndSpecialize来执行创建应用程序进程的工作。Zygote 类的 JNI 函数nativeForkAndSpecialize的由 C+ 层的函数Dalvik_dalvik_system_Zygote_forkA ndSpecialize来实现,如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片static void Dalvik_dalvik_system_Zygote_forkA ndS

38、pecialize(c on st u4* args, JValue* pResult)pid_t pid;pid = forkAndSpecializeCommon(args, false);RETURN_INT(pid);这个函数定义在文件dalvik/vm/native/dalvik_system_Zygote.cpp 中。注意,Zygote类的JNI函数nativeForkAndSpecialize在调用的过程中,传递进来的 参数都被保存在函数 Dalvik_dalvik_system_Zygote_forkAndSpecialize 的参数 args指向的一块 内存中。函数 Dalv

39、ik_dalvik_system_Zygote_forkAndSpecialize通过调用 另外一个函数forkAndSpecializeCommon来执行创建应用程序进程的工作,它的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)pid_t pid;uid_t uid = (uid_t) args0;gid_t gid = (gid_t) args1;char *seInfo = NULL;char *n

40、iceName = NULL;if (isSystemServer) else Stri ngObject* seI nfoObj = (Stri ngObject*)args6;if (seI nfoObj) selnfo = dvmCreateCstrFromStri ng(sel nfoObj);Stri ngObject* niceNameObj = (Stri ngObject*)args7;if (n iceNawww.sha nxiwa ng. netmeObj) ni ceName = dvmCreateCstrFromStri ng( ni ceNameObj);pid =

41、fork();if (pid = 0) err = setSELi nuxCon text(uid, isSystemServer, selnfo, niceName);return pid;这个函数定义在文件dalvik/vm/native/dalvik_system_Zygote.cpp 中。参数isSystemServer表示当前创建的是 System Server进程还是应用程序进程。 在我 们这个场景中,它的值等于 false,表示要创建的是应用程序进程。从参数 args指向的内存 可以获得各种各样的参数,例如 uid、gid、seinfo和nice name等。获得了要创建的进程的

42、各种参数之后,函数forkAndSpecializeCommon就通过系统调用fork创建出了一个子进程。注意,这时候函数forkAndSpecializeCommon 是在Zygote进程中执行的。因此,这里创建出来的子进程的安全上下文继承于Zygote进程。从前面的分析可以知道,这个安全上下文为u:r:zygote:s0。如果这时候我们什么也不做的话,那么创建出来的应用程序进程的安全上下文就会一直被设置为u:r:zygote:s0,这样会使得应用程序具有Zygote进程一样的SEAndroid安全权限。这是不允许的,因此,接下来需要通过调用函数setSELinuxContext来修改刚刚创

43、建出来的应用程序进程的安全上下文。函数setSELinuxContext的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片static int setSELinuxContext(uid_t uid, bool isSystemServer,const char *selnfo, const char *niceName)#ifdef HA VE_ANDROID_OSreturn seli nux_an droid_setc on text(uid, isSystemServer, seinfo, ni ceName);#elsereturn 0;#

44、en dif这个函数定义在文件dalvik/vm/native/dalvik_system_Zygote.cpp中。函数setSELinuxContext的实现很简单,它通 过调用libselinux 提供的函数 selinux_android_setcontext来设置刚刚创建出来的应用程序进程的安全上下文。函数seli nux_an droid_setc on text的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片int selinux_android_setcontext(uid_t uid,int isSystemServer,const

45、 char *seinfo,const char *pkgname)char *orig_ctx_str = NULL, *ctx_str;context_t ctx = NULL;int rc;if (is_seli nux_en abled() = 0)return 0;_selinux_once(once, seapp_context_init);rc = getcon(&ctx_str);ctx = context_new(ctx_str); orig_ctx_str = ctx_str;rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSy

46、stemServer, seinfo, pkgname, ctx);ctx_str = context_str(ctx);rc = security_check_context(ctx_str);if (strcmp(ctx_str, orig_ctx_str) rc = setcon(ctx_str);rc = 0;out:return rc;这个函数定义在文件 external/libselinux/src/android.c 中。参数isSystemServer表示当前创建的是 System Server进程还是应用程序进程。 在我 们这个场景中,它的值等于 false,表示要创建的是应

47、用程序进程。从参数 args指向的内存 可以获得各种各样的参数,例如uid、gid、seinfo和nice name等。获得了要创建的进程的各种参数之后,函数forkAndSpecializeCommon就通过系统调用fork创建出了一个子进程。注意,这时候函数forkAndSpecializeCommon 是在Zygote进程中执行的。因此,这里创建出来的子进程的安全上下文来继承于Zygote进程。从前面的分析可以知道,这个安全上下文为u:r:zygote:s0。如果这时候我们什么也不做的话,那么创建出来的应用程序进程的安全上下文就会一直被设置为u:r:zygote:s0,这样会使得应用程序

48、具有Zygote进程一样的SEAndroid安全权限。这是不允许的,因此,接下来需要通过调用函数setSELinuxContext来修改刚刚创建出来的应用程序进程的安全上下文。函数setSELinuxContext的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我的代码片 static int setSELinuxContext(uid_t uid, bool isSystemServer, const char *seInfo, const char *niceName)#ifdef HA VE_ANDROID_OSreturn selinux_andro

49、id_setcontext(uid, isSystemServer, seInfo, niceName);#elsereturn 0;#endif这个函数定义在文件 dalvik/vm/native/dalvik_system_Zygote.cpp 中。函数setSELinuxContext的实现很简单,它通 过调用libselinux 提供的函数 selinux_android_setcontext来设置刚刚创建出来的应用程序进程的安全上下文。函数seli nux_an droid_setc on text的实现如下所示:cpp view plain copy 在CODE上查看代码片派生到我

50、的代码片int selinux_android_setcontext(uid_t uid,int isSystemServer, const char *se info, const char *pkg name) char *orig_ctx_str = NULL, *ctx_str; con text_t ctx = NULL;int rc;if (is_seli nux_en abled() 0)rc = aspri ntf(&path, /proc/%d/attr/%s, pid, attr);else tid = gettid();rc = asprintf(&path, /proc

51、/self/task/%d/attr/%s, tid, attr);if (rc 0)return -1;fd = open(path, O_RDWR);free(path);if (fd 0)return -1;if (con text)do ret = write(fd, context, strlen(context) + 1); while (ret 0 & errno = EINTR);elsedo ret = write(fd, NULL, 0);/* clear */ while (ret 0 & errno = EINTR);errno_hold = errno;close(fd)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论