android 开机启动流程分析(05)SE Android 的解读

该系列文章总纲链接:专题分纲目录 android 开机启动流程分析


本章关键点总结 & 说明:

说明:思维导图是基于之前文章不断迭代的,本章内容我们关注➕android SELinux 部分即可

init中SELinux的源码分析,Android平台中,SEAndroid的初始化由进程的祖先init的main函数完成,相关代码如下所示:

int main(int argc, char **argv)
{
	...
	//说明:init中对SElinux的控制主要依赖于使用了libselinux库(android的SEAndroid库)
	//向SELinux设置两个回调函数,主要是打印log
	union selinux_callback cb;
	cb.func_log = log_callback;
	selinux_set_callback(SELINUX_CB_LOG, cb);
	cb.func_audit = audit_callback;	
	selinux_set_callback(SELINUX_CB_AUDIT, cb);
	selinux_initialize();	//SELinux初始化
	
    //restore context:就是根据XXX_contexts中的内容给一些目录做labeling{打SELinux标签}。
	restorecon("/dev");
	restorecon("/dev/socket");
	restorecon("/dev/__properties__");
	restorecon_recursive("/sys");
	...
}

1 selinux_initialize实现如下:

static void selinux_initialize(void)
{
	/**判断selinux功能是否启用。方法是:
	  /sys/fs/selinux 是否存在。或者ro.boot.selinux 属性不为disabled
	 */
    if (selinux_is_disabled()) {
        return;
    }
    if (selinux_android_load_policy() < 0) {//加载sepolicy文件
        ERROR("SELinux: Failed to load policy; rebooting into recovery mode\n");
        android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
        while (1) { pause(); }  // never reached
    }
	//初始化file_context,seapp_context及property_context相关内容
    selinux_init_all_handles();
	/**
	  selinux有两种工作模式,
      “permissive”:所有操作都被允许(即没有MAC),但是如果有违反权限的话,会记录日志
      “enforcing”:所有操作都会进行权限检查
     */
    bool is_enforcing = selinux_is_enforcing();
	//设置SELinux的模式,向"/sys/fs/selinux"/enforce文件中写入is_enforcing值
    security_setenforce(is_enforcing);
}

这里关注核心的2个方法,selinux_android_load_policy和selinux_init_all_handles

1.1 selinux_android_load_policy的实现

int selinux_android_load_policy(void)
{
	const char *mnt = SELINUXMNT;
	int rc;
	//挂载/sys/fs/selinux,SELINUXFS值为"selinuxfs"
	rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
	...//rc<0容错处理
	/**
	  说明:/sys/fs/selinux为userpace和kernel中的SELinux模块交互的通道
	 */
	set_selinuxmnt(mnt);
    return selinux_android_load_policy_helper(false);
}

继续分析selinux_android_load_policy_helper的实现,如下: 

static int selinux_android_load_policy_helper(bool reload)
{
	int fd = -1, rc;
	struct stat sb;
	void *map = NULL;
	...//根据文件存在与否确定policy_index的值
	//根据policy_index的不同0/1来确定,注意sepolicy文件的位置:
		/data/security/current/sepolicy:自定义的策略文件一般放在这里,init优先使用它。
		/sepolicy:root根目录下的sepolicy:如果data目录下没有sepolicy,则使用系统默认的sepolicy。
	fd = open(sepolicy_file[policy_index], O_RDONLY | O_NOFOLLOW);
	...
	fstat(fd, &sb);
	...
	map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); //这里通过mmap的方式,将sepolicy文件映射到map中
	...
	//该函数由selinux.h定义,它将此map、即sepolicy文件加载到内核中
	rc = security_load_policy(map, sb.st_size);
	...
	munmap(map, sb.st_size);
	close(fd);
	return 0;
}

特殊说明:

libselinux库通过操作/sys/fs/selinux下的文件来完成和Kernel中SELinux模块的交互。
同时将sepolicy文件传递给Kernel,这样Kernel就有了安全策略配置文件,后续的MAC才能开展起来。

1.2 selinux_init_all_handles的实现如下:

/**
  创建两个handler,主要为后续做labeling{打SELinux的系统标签}控制
  通过调用libselinux的函数来打开前面分析file_contexts和property_contexts文件
  以便可以用来查询系统文件和系统属性的安全上下文。
 */
void selinux_init_all_handles(void)
{
    sehandle = selinux_android_file_context_handle();//文件上下文handle
    selinux_android_set_sehandle(sehandle);
    sehandle_prop = selinux_android_prop_context_handle();//属性上下文handle
}

 restorecon分析如下:

static int selinux_android_restorecon_common(...){											 
	if (is_selinux_enabled() <= 0)
        return 0;
	...
        return restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid);
		//->最后会调用lsetfilecon->核心就是调用lsetxattr来设置文件系统属性
    }
}

2 property权限检查的分析

 /**
  在init的handle_property_set_fd中获取property_set发送的消息
  处理时会执行check_perms或check_control_mac_perms,2个方法最后都会调用check_mac_perms
  因此属性服务设置的SELinux权限检测是在init中,方法check_mac_perms的实现如下:
 */
static int check_mac_perms(const char *name, char *sctx)
{
    if (is_selinux_enabled() <= 0)
        return 1;
    ...//容错处理
	//检查property_context中是否定义了目标SContext,即tctx。
    if (selabel_lookup(sehandle_prop, &tctx, name, 1) != 0)
        goto err;
	/**
	 将源SContext和目标SContext进行比较,判断是否有相关权限。
	 name是属性的名字
     源SContext是调用setprop进程的SContext。调用setprop的进程的SContext
	 目标SContext是property_context文件中定义的SContext。不同的属性有不同的SContext
	 操作名称(perm,由access vector定义。对Property这种Object class而言,其唯一需要做权限检查的操作就是set。
	 要检查的Object class(系统所支持的类在external/sepolicy/security_classes文件中定义,
		参考external/sepolicy/access_vectors这个文件)。
	具体的哪一个属性(name参数指定,就是具体指明哪一文件)。
	 */
    if (selinux_check_access(sctx, tctx, class, perm, (void*) name) == 0)
        result = 1;
    freecon(tctx);
 err:
    return result;
}

 说明:这里仅仅是从init中的代码来分析SELinux的机制,实际上SElinux也要专门开一个专题来讲才会清楚。目前这里仅作简介

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值