SELinux,无semanage,Linux user到SELinux user的映射

前提:因为不用linux用户有不一样的权限,所以需要为不用Linux用户映射为不同权限的SELinux的用户权限。又基于平台不支持semanage等工具,因此需要把SELinux用户权限直接编译到固件种。

主要通过添加Linux用户与SELinux用户为相同名字,并为SELinux用户匹配不同的权限完成映射。


在SELinux模式下登录用户先进行linux用户名及密码的验证,然后再为Linux用户名匹配SELinux用户的安全上下问,最后对此安全上下文是否有相关policy去允许。Linux用户与SELinux用户匹配规则通过分析libselinux.so源码(即get_context_list.c中的get_ordered_context_list函数)得知。

int get_ordered_context_list(const char *user,
			     const char *fromcon,
			     char *** list)
{
	char **reachable = NULL;
	int rc = 0;
	unsigned nreachable = 0;
	char *backup_fromcon = NULL;
	FILE *fp;
	char *fname = NULL;
	size_t fname_len;
	const char *user_contexts_path = selinux_user_contexts_path();

	if (!fromcon) {
		/* Get the current context and use it for the starting context */
		rc = getcon(&backup_fromcon);
		if (rc < 0)
			return rc;
		fromcon = backup_fromcon;
	}

	/* Determine the ordering to apply from the optional per-user config
	   and from the global config. */
	fname_len = strlen(user_contexts_path) + strlen(user) + 2;
	fname = malloc(fname_len);
	if (!fname)
		goto failsafe;
	snprintf(fname, fname_len, "%s%s", user_contexts_path, user);
	fp = fopen(fname, "re");
	if (fp) {
		__fsetlocking(fp, FSETLOCKING_BYCALLER);
		rc = get_context_user(fp, fromcon, user, &reachable, &nreachable);

		fclose(fp);
		if (rc < 0 && errno != ENOENT) {
			fprintf(stderr,
				"%s:  error in processing configuration file %s\n",
				__FUNCTION__, fname);
			/* Fall through, try global config */
		}
	}
	free(fname);
	fp = fopen(selinux_default_context_path(), "re");
	if (fp) {
		__fsetlocking(fp, FSETLOCKING_BYCALLER);
		rc = get_context_user(fp, fromcon, user, &reachable, &nreachable);
		fclose(fp);
		if (rc < 0 && errno != ENOENT) {
			fprintf(stderr,
				"%s:  error in processing configuration file %s\n",
				__FUNCTION__, selinux_default_context_path());
			/* Fall through */
		}
	}

	if (!nreachable)
		goto failsafe;

      out:
	if (nreachable > 0) {
		*list = reachable;
		rc = nreachable;
	}
	else
		freeconary(reachable);

	freecon(backup_fromcon);

	return rc;

      failsafe:
	/* Unable to determine a reachable context list, try to fall back to
	   the "failsafe" context to at least permit root login
	   for emergency recovery if possible. */
	freeconary(reachable);
	reachable = malloc(2 * sizeof(char *));
	if (!reachable) {
		rc = -1;
		goto out;
	}
	reachable[0] = reachable[1] = 0;
	rc = get_failsafe_context(user, &reachable[0]);
	if (rc < 0) {
		freeconary(reachable);
		reachable = NULL;
		goto out;
	}
	nreachable = 1;			/* one context in the list */
	goto out;
}

首先通过user_contexts_path去获取SELinux的安全上下文,如果没有获取到会再通过selinux_default_context_path路径去获取安全上下文,最后如果两个地方都没有成功会直接使用get_failsafe_context中的安全上下文。

user_contexts_path对应的是/etc/selinux/targeted/contexts/users/,在这个目录下的查看与登录用户名相同的文件中去获取安全上下文。

 selinux_default_context_path对应的是/etc/selinux/targeted/contexts/default_contexts文件。

cget_failsafe_context对应的是/etc/selinux/targeted/contexts/failsafe_context文件。

 除failsafe_context文件文件外,文件内容有两部分,前面一部分匹配当前登录时系统使用的规则(rule)及类型(type)。

当匹配前面部分后,就为当前用户匹配为后面部分的规则(rule)及类型(type)。当前面两个文件中都没有匹配成功则直接使用failsafe_context文件中的规则(rule)及类型(type),因此failsafe_context文件中没有前面部分,只有后面部分的内容。匹配成功后会与policy.xx(不同的selinux版本xx的值不同)中的规则进行验证(如user root roles { system_r };),如果没有roles规则与之匹配则报错can't get SID for xxx,若有规则则登录成功。

注意,匹配SELinux安全上下文之前Linux用户密码输入错误时是另一个报错需要与之区分。

总结:1.在refpolicy-2.20200229/config/appconfig-standard/目录下新增XXX_default_contexts文件(XXX未新增的用户名),并在文件中配置需要的安全上下文权限(若已存在用户则直接修改或添加需要的安全上下文权限)。或在refpolicy-2.20200229/config/appconfig-standard/default_contexts文件中直接修改或添加需要的安全上下文权限。

2.在refpolicy-2.20200229/policy/users源码中添加对应的gen_user规则。

例如:添加用户名为ethan的安全上下文为ethan:system_r:kernel_t的SELinux用户

 修改并编译后登录验证:

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值