SEandroid 安全机制—进程安全上下文

  • Post author:
  • Post category:其他


3进程安全上下文

前面一篇文章分析了文件安全上下文关联过程。但是在SEAndroid中,除了要给文件关联安全上下文外,

还需要给进程关联安全上下文,因为只有当进程和文件都关联安全上下文之后,SEAndroid安全策略才能发挥作用。

也就是说,当一个进程试图访问一个文件时,SEAndroid会将进程和文件的安全上下文提取出来,根据安全策略规则,决定是否允许访问。

在传统的Linux系统中,每一个应用程序都对应有一个可执行文件。在这种情况下,我们就可以在安全策略中设定一个规则:

当一个可执行文件加载到一个进程中执行时,该进程的安全上下文就设置为指定的值。也就是说,我们可以在安全策略中静态地

为进程设置安全上下文。然而,这种进程安全上下文设置方式不适合于Android系统中的应用程序进程。

同样的,android系统也有不同的进程,在此仅论述android上层的应用进程。

应用程序进程是由ActivityManagerService请求Zygote进程创建的。ActivityManagerService在请求Zygote进程创建

应用程序进程的时候,会传递很多参数,例如应用程序在安装时分配到的uid和gid。增加了SEAndroid安全机制之后,

ActivityManagerService传递给Zygote进程的参数包含了一个seinfo。不过它的作用是用来设置应用程序进程的安全上下文,

而不是设置应用程序数据文件的安全上下文。

当ActivityMangerService需要创建应用程序进程的时候,就会调用startProcessLocked方法,

Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);

其中就包含了要创建的应用程序进程的各种参数, 这些参数会通过socket传递给Zygote进程。

最后,Zygote进程会通过调用ZygoteConnection类的成员函数runOnce来执行创建应用程序进程的工作。

3.1 Java层创建进程

Zygote进程进行。

ZygoteConnection类的runOnce方法首先是调用readArgumentList方法读取ActivityManagerService发送

过来的应用程序进程创建参数args,接着再创建一个Arguments对象来解析该参数。

解析后得到的参数传递给Zygote类的forkAndSpecialize方法执行创建应用程序进程的工作。

Zygote的forkAndSpecialize方法如下,

int pid = nativeForkAndSpecialize(
                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                  instructionSet, appDataDir);

com_android_internal_os_Zygote.cpp对应的nativeForkAndSpecialize方法会调用ForkAndSpecializeCommon方法,

ForkAndSpecializeCommon首先创建一个进程,

pid_t pid = fork();

设置pid,uid等信息,

int rc = setresgid(gid, gid, gid);
rc = setresuid(uid, uid, uid);

设置进程安全上下文

if (java_se_info != NULL) {
        se_info = new ScopedUtfChars(env, java_se_info);
        se_info_c_str = se_info->c_str();
•••
rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);

如果不设置进程的安全上下文,那么创建出来的子进程的安全上下文继承于Zygote进程,也就是“u:r:zygote:s0”。

3.2 native层设置安全上下文

和文件的安全上下文一样, 设置进程的安全上下文也在libselinux.so库中进行。

android.c的selinux_android_setcontext方法如下,

int selinux_android_setcontext(uid_t uid,
			       bool isSystemServer,
			       const char *seinfo,
			       const char *pkgname)
{
	char *orig_ctx_str = NULL, *ctx_str;
	context_t ctx = NULL;
	int rc = -1;

	if (is_selinux_enabled() <= 0) //是否启用了SELinux
		return 0;

	rc = getcon(&ctx_str); // 获取原来已有的安全上下文
                     //进程在创建的时候,默认设置的是父进程的安全上下文
	if (rc)
		goto err;
// 创建一个新的安全上下文ctx,以便可以获得原来安全上下文的SELinux用户、角色和安全级别等信息。
	ctx = context_new(ctx_str);
	orig_ctx_str = ctx_str;
	if (!ctx)
		goto oom;
//根据传进来的参数seinfo在seapp_contexts文件中找到对应的Type,
//并且将其设置为新的安全上下文ctx的Type。
	rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx);
	if (rc == -1)
		goto err;
	else if (rc == -2)
		goto oom;
              //获取新创建的安全上下文的字符串
	ctx_str = context_str(ctx);
	if (!ctx_str)
		goto oom;
              //验证新创建的安全上下文的正确性
	rc = security_check_context(ctx_str);
	if (rc < 0)
		goto err;

	if (strcmp(ctx_str, orig_ctx_str)) {
                        // 设置新创建的安全上下文
		rc = setcon(ctx_str);
		if (rc < 0)
			goto err;
	}
•••

利用ps -Z指令可以看到进程的安全上下文,




至此,从Java层到native,最后到libselinux.so库,分析完了在SEAndroid安全机制中,进程安全上下文的设置过程了.



版权声明:本文为u012439416原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。