Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a59daa0 authored by Stephen Smalley's avatar Stephen Smalley Committed by James Morris
Browse files

SELinux: fix sleeping allocation in security_context_to_sid



Fix a sleeping function called from invalid context bug by moving allocation
to the callers prior to taking the policy rdlock.

Signed-off-by: default avatarStephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 12b29f34
Loading
Loading
Loading
Loading
+40 −30
Original line number Original line Diff line number Diff line
@@ -730,15 +730,16 @@ int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len)
	return security_sid_to_context_core(sid, scontext, scontext_len, 1);
	return security_sid_to_context_core(sid, scontext, scontext_len, 1);
}
}


/*
 * Caveat:  Mutates scontext.
 */
static int string_to_context_struct(struct policydb *pol,
static int string_to_context_struct(struct policydb *pol,
				    struct sidtab *sidtabp,
				    struct sidtab *sidtabp,
				    const char *scontext,
				    char *scontext,
				    u32 scontext_len,
				    u32 scontext_len,
				    struct context *ctx,
				    struct context *ctx,
				    u32 def_sid,
				    u32 def_sid)
				    gfp_t gfp_flags)
{
{
	char *scontext2 = NULL;
	struct role_datum *role;
	struct role_datum *role;
	struct type_datum *typdatum;
	struct type_datum *typdatum;
	struct user_datum *usrdatum;
	struct user_datum *usrdatum;
@@ -747,19 +748,10 @@ static int string_to_context_struct(struct policydb *pol,


	context_init(ctx);
	context_init(ctx);


	/* Copy the string so that we can modify the copy as we parse it. */
	scontext2 = kmalloc(scontext_len+1, gfp_flags);
	if (!scontext2) {
		rc = -ENOMEM;
		goto out;
	}
	memcpy(scontext2, scontext, scontext_len);
	scontext2[scontext_len] = 0;

	/* Parse the security context. */
	/* Parse the security context. */


	rc = -EINVAL;
	rc = -EINVAL;
	scontextp = (char *) scontext2;
	scontextp = (char *) scontext;


	/* Extract the user. */
	/* Extract the user. */
	p = scontextp;
	p = scontextp;
@@ -809,7 +801,7 @@ static int string_to_context_struct(struct policydb *pol,
	if (rc)
	if (rc)
		goto out;
		goto out;


	if ((p - scontext2) < scontext_len) {
	if ((p - scontext) < scontext_len) {
		rc = -EINVAL;
		rc = -EINVAL;
		goto out;
		goto out;
	}
	}
@@ -822,7 +814,6 @@ static int string_to_context_struct(struct policydb *pol,
	}
	}
	rc = 0;
	rc = 0;
out:
out:
	kfree(scontext2);
	return rc;
	return rc;
}
}


@@ -830,6 +821,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
					u32 *sid, u32 def_sid, gfp_t gfp_flags,
					u32 *sid, u32 def_sid, gfp_t gfp_flags,
					int force)
					int force)
{
{
	char *scontext2, *str = NULL;
	struct context context;
	struct context context;
	int rc = 0;
	int rc = 0;


@@ -839,27 +831,38 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
		for (i = 1; i < SECINITSID_NUM; i++) {
		for (i = 1; i < SECINITSID_NUM; i++) {
			if (!strcmp(initial_sid_to_string[i], scontext)) {
			if (!strcmp(initial_sid_to_string[i], scontext)) {
				*sid = i;
				*sid = i;
				goto out;
				return 0;
			}
			}
		}
		}
		*sid = SECINITSID_KERNEL;
		*sid = SECINITSID_KERNEL;
		goto out;
		return 0;
	}
	}
	*sid = SECSID_NULL;
	*sid = SECSID_NULL;


	/* Copy the string so that we can modify the copy as we parse it. */
	scontext2 = kmalloc(scontext_len+1, gfp_flags);
	if (!scontext2)
		return -ENOMEM;
	memcpy(scontext2, scontext, scontext_len);
	scontext2[scontext_len] = 0;

	if (force) {
		/* Save another copy for storing in uninterpreted form */
		str = kstrdup(scontext2, gfp_flags);
		if (!str) {
			kfree(scontext2);
			return -ENOMEM;
		}
	}

	POLICY_RDLOCK;
	POLICY_RDLOCK;
	rc = string_to_context_struct(&policydb, &sidtab,
	rc = string_to_context_struct(&policydb, &sidtab,
				      scontext, scontext_len,
				      scontext2, scontext_len,
				      &context, def_sid, gfp_flags);
				      &context, def_sid);
	if (rc == -EINVAL && force) {
	if (rc == -EINVAL && force) {
		context.str = kmalloc(scontext_len+1, gfp_flags);
		context.str = str;
		if (!context.str) {
			rc = -ENOMEM;
			goto out;
		}
		memcpy(context.str, scontext, scontext_len);
		context.str[scontext_len] = 0;
		context.len = scontext_len;
		context.len = scontext_len;
		str = NULL;
	} else if (rc)
	} else if (rc)
		goto out;
		goto out;
	rc = sidtab_context_to_sid(&sidtab, &context, sid);
	rc = sidtab_context_to_sid(&sidtab, &context, sid);
@@ -867,6 +870,8 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
		context_destroy(&context);
		context_destroy(&context);
out:
out:
	POLICY_RDUNLOCK;
	POLICY_RDUNLOCK;
	kfree(scontext2);
	kfree(str);
	return rc;
	return rc;
}
}


@@ -1339,9 +1344,14 @@ static int convert_context(u32 key,


	if (c->str) {
	if (c->str) {
		struct context ctx;
		struct context ctx;
		rc = string_to_context_struct(args->newp, NULL, c->str,
		s = kstrdup(c->str, GFP_KERNEL);
					      c->len, &ctx, SECSID_NULL,
		if (!s) {
					      GFP_KERNEL);
			rc = -ENOMEM;
			goto out;
		}
		rc = string_to_context_struct(args->newp, NULL, s,
					      c->len, &ctx, SECSID_NULL);
		kfree(s);
		if (!rc) {
		if (!rc) {
			printk(KERN_INFO
			printk(KERN_INFO
		       "SELinux:  Context %s became valid (mapped).\n",
		       "SELinux:  Context %s became valid (mapped).\n",