Re: clean up in android.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2012-09-18 at 09:40 -0400, Stephen Smalley wrote:
> I think the setcon and setfilecon2 code could be further unified so that
> the entire logic for matching an entry is encapsulated in a single
> helper function that takes a bool argument indicating whether it is
> looking for a domain or type entry.

So the attached patch does the first part above - unify the seapp
context lookup logic from setcon and setfilecon2, without making any
changes to how the username mapping is performed.

> We might also want to reconsider how we map the app usernames to a
> string for seapp_contexts.  I just remapped the new format to the app_
> prefix so that there would be no breakage going from ICS to JB, but it
> is a bit misleading.
> 
> I also think we might want to revisit how we compute the level.
> Rather than only setting a single category, we might want to compute a
> category pair based on the UID to increase the number of possible unique
> levels and avoid any risk that we will run out of unique levels for a
> large number of installed apps.  For comparison, libvirt assigns a
> randomly selected category pair for virtual machines and I heard
> recently that OpenShift is mapping UIDs to category pairs.  
> 

-- 
Stephen Smalley
National Security Agency
diff --git a/src/android.c b/src/android.c
index af6c79c..3c9cb6e 100644
--- a/src/android.c
+++ b/src/android.c
@@ -272,33 +272,22 @@ static void seapp_context_init(void)
 
 static pthread_once_t once = PTHREAD_ONCE_INIT;
 
-int selinux_android_setfilecon2(const char *pkgdir,
-				const char *pkgname,
+#define SEAPP_TYPE 1
+#define SEAPP_DOMAIN 2
+static int seapp_context_lookup(int kind,
+				uid_t uid,
+				int isSystemServer,
 				const char *seinfo,
-				uid_t uid)
+				const char *pkgname,
+				context_t ctx)
 {
 	const char *username;
-	char *orig_ctx_str = NULL, *ctx_str, *end = NULL;
-	context_t ctx = NULL;
+	char *end = NULL;
 	struct passwd *pw;
 	struct seapp_context *cur;
-	int i, rc;
+	int i;
 	unsigned long id = 0;
 
-	if (is_selinux_enabled() <= 0)
-		return 0;
-
-	__selinux_once(once, seapp_context_init);
-
-	rc = getfilecon(pkgdir, &ctx_str);
-	if (rc < 0)
-		goto err;
-
-	ctx = context_new(ctx_str);
-	orig_ctx_str = ctx_str;
-	if (!ctx)
-		goto oom;
-
 	pw = getpwuid(uid);
 	if (!pw)
 		goto err;
@@ -334,8 +323,7 @@ int selinux_android_setfilecon2(const char *pkgdir,
 	for (i = 0; i < nspec; i++) {
 		cur = seapp_contexts[i];
 
-		/* isSystemServer=true is only for app process labeling. */
-		if (cur->isSystemServer)
+		if (cur->isSystemServer != isSystemServer)
 			continue;
 
 		if (cur->user) {
@@ -358,7 +346,9 @@ int selinux_android_setfilecon2(const char *pkgdir,
 				continue;
 		}
 
-		if (!cur->type)
+		if (kind == SEAPP_TYPE && !cur->type)
+			continue;
+		else if (kind == SEAPP_DOMAIN && !cur->domain)
 			continue;
 
 		if (cur->sebool) {
@@ -372,8 +362,13 @@ int selinux_android_setfilecon2(const char *pkgdir,
 			}
 		}
 
-		if (context_type_set(ctx, cur->type))
-			goto oom;
+		if (kind == SEAPP_TYPE) {
+			if (context_type_set(ctx, cur->type))
+				goto oom;
+		} else if (kind == SEAPP_DOMAIN) {
+			if (context_type_set(ctx, cur->domain))
+				goto oom;
+		}
 
 		if (cur->levelFromUid) {
 			char level[255];
@@ -389,6 +384,55 @@ int selinux_android_setfilecon2(const char *pkgdir,
 		break;
 	}
 
+	if (kind == SEAPP_DOMAIN && i == nspec) {
+		/*
+		 * No match.
+		 * Fail to prevent staying in the zygote's context.
+		 */
+		selinux_log(SELINUX_ERROR,
+			    "%s:  No match for app with uid %d, seinfo %s, name %s\n",
+			    __FUNCTION__, uid, seinfo, pkgname);
+
+		if (security_getenforce() == 1)
+			goto err;
+	}
+
+	return 0;
+err:
+	return -1;
+oom:
+	return -2;
+}
+
+int selinux_android_setfilecon2(const char *pkgdir,
+				const char *pkgname,
+				const char *seinfo,
+				uid_t uid)
+{
+	char *orig_ctx_str = NULL, *ctx_str;
+	context_t ctx = NULL;
+	int rc;
+
+	if (is_selinux_enabled() <= 0)
+		return 0;
+
+	__selinux_once(once, seapp_context_init);
+
+	rc = getfilecon(pkgdir, &ctx_str);
+	if (rc < 0)
+		goto err;
+
+	ctx = context_new(ctx_str);
+	orig_ctx_str = ctx_str;
+	if (!ctx)
+		goto oom;
+
+	rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx);
+	if (rc == -1)
+		goto err;
+	else if (rc == -2)
+		goto oom;
+
 	ctx_str = context_str(ctx);
 	if (!ctx_str)
 		goto oom;
@@ -431,13 +475,9 @@ int selinux_android_setcontext(uid_t uid,
 			       const char *seinfo,
 			       const char *pkgname)
 {
-	const char *username;
-	char *orig_ctx_str = NULL, *ctx_str, *end = NULL;
+	char *orig_ctx_str = NULL, *ctx_str;
 	context_t ctx = NULL;
-	unsigned long id = 0;
-	struct passwd *pw;
-	struct seapp_context *cur;
-	int i, rc;
+	int rc;
 
 	if (is_selinux_enabled() <= 0)
 		return 0;
@@ -453,104 +493,11 @@ int selinux_android_setcontext(uid_t uid,
 	if (!ctx)
 		goto oom;
 
-	pw = getpwuid(uid);
-	if (!pw)
+	rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
+	if (rc == -1)
 		goto err;
-	username = pw->pw_name;
-
-	if (!strncmp(username, "app_", 4)) {
-		id = strtoul(username + 4, NULL, 10);
-		if (id >= MLS_CATS)
-			goto err;
-	} else if (username[0] == 'u' && isdigit(username[1])) {
-		unsigned long unused;
-		unused = strtoul(username+1, &end, 10);
-		if (end[0] != '_' || end[1] == 0)
-			goto err;
-		if (end[1] == 'a' && isdigit(end[2])) {
-			id = strtoul(end + 2, NULL, 10);
-			if (id >= MLS_CATS/2)
-				goto err;
-			/* regular app UID */
-			username = "app_";
-		} else if (end[1] == 'i' && isdigit(end[2])) {
-			id = strtoul(end + 2, NULL, 10);
-			if (id >= MLS_CATS/2)
-				goto err;
-			/* isolated service */
-			id += MLS_CATS/2;
-			username = "app_";
-		} else {
-			username = end + 1;
-		}
-	}
-
-	for (i = 0; i < nspec; i++) {
-		cur = seapp_contexts[i];
-
-		if (cur->isSystemServer != isSystemServer)
-			continue;
-		if (cur->user) {
-			if (cur->prefix) {
-				if (strncasecmp(username, cur->user, cur->len-1))
-					continue;
-			} else {
-				if (strcasecmp(username, cur->user))
-					continue;
-			}
-		}
-		if (cur->seinfo) {
-			if (!seinfo || strcasecmp(seinfo, cur->seinfo))
-				continue;
-		}
-		if (cur->name) {
-			if (!pkgname || strcasecmp(pkgname, cur->name))
-				continue;
-		}
-
-		if (!cur->domain)
-			continue;
-
-		if (cur->sebool) {
-			int value = security_get_boolean_active(cur->sebool);
-			if (value == 0)
-				continue;
-			else if (value == -1) {
-				selinux_log(SELINUX_ERROR, \
-				"Could not find boolean: %s ", cur->sebool);
-                                goto err;
-                        }
-                }
-
-		if (context_type_set(ctx, cur->domain))
-			goto oom;
-
-		if (cur->levelFromUid) {
-			char level[255];
-			snprintf(level, sizeof level, "%s:c%lu",
-				 context_range_get(ctx), id);
-			if (context_range_set(ctx, level))
-				goto oom;
-		} else if (cur->level) {
-			if (context_range_set(ctx, cur->level))
-				goto oom;
-		}
-
-		break;
-	}
-
-	if (i == nspec) {
-		/*
-		 * No match. 
-		 * Fail to prevent staying in the zygote's context.
-		 */
-		selinux_log(SELINUX_ERROR,
-			    "%s:  No match for app with uid %d, seinfo %s, name %s\n",
-			    __FUNCTION__, uid, seinfo, pkgname);
-
-		rc = (security_getenforce() == 0) ? 0 : -1;
-		goto out;
-	}
+	else if (rc == -2)
+		goto oom;
 
 	ctx_str = context_str(ctx);
 	if (!ctx_str)

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux