Generalize levelFromUid support.
Generalize levelFromUid support to support per-app, per-user,
or per-combination level assignment. Adds a new levelFrom=none|app|user|all
syntax for specifying the desired behavior in seapp_contexts.
levelFromUid=true|false is still supported but translated to
levelFrom=app|none.
No change in existing behavior for existing seapp_contexts configurations.
Change-Id: I0e9c18ecf3113fa7079d2101899c92a241ef80a0
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/src/android.c b/src/android.c
index 4ea908c..d299ade 100644
--- a/src/android.c
+++ b/src/android.c
@@ -43,6 +43,22 @@
"/sepolicy",
0 };
+enum levelFrom {
+ LEVELFROM_NONE,
+ LEVELFROM_APP,
+ LEVELFROM_USER,
+ LEVELFROM_ALL
+};
+
+#if DEBUG
+static char const * const levelFromName[] = {
+ "none",
+ "app",
+ "user",
+ "all"
+};
+#endif
+
struct seapp_context {
/* input selectors */
char isSystemServer;
@@ -56,7 +72,7 @@
char *type;
char *level;
char *sebool;
- char levelFromUid;
+ enum levelFrom levelFrom;
};
static int seapp_context_cmp(const void *A, const void *B)
@@ -203,9 +219,21 @@
goto oom;
} else if (!strcasecmp(name, "levelFromUid")) {
if (!strcasecmp(value, "true"))
- cur->levelFromUid = 1;
+ cur->levelFrom = LEVELFROM_APP;
else if (!strcasecmp(value, "false"))
- cur->levelFromUid = 0;
+ cur->levelFrom = LEVELFROM_NONE;
+ else {
+ goto err;
+ }
+ } else if (!strcasecmp(name, "levelFrom")) {
+ if (!strcasecmp(value, "none"))
+ cur->levelFrom = LEVELFROM_NONE;
+ else if (!strcasecmp(value, "app"))
+ cur->levelFrom = LEVELFROM_APP;
+ else if (!strcasecmp(value, "user"))
+ cur->levelFrom = LEVELFROM_USER;
+ else if (!strcasecmp(value, "all"))
+ cur->levelFrom = LEVELFROM_ALL;
else {
goto err;
}
@@ -238,12 +266,12 @@
int i;
for (i = 0; i < nspec; i++) {
cur = seapp_contexts[i];
- selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFromUid=%s",
+ selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFrom=%s",
__FUNCTION__,
cur->isSystemServer ? "true" : "false", cur->user,
cur->seinfo, cur->name, cur->sebool, cur->domain,
cur->type, cur->level,
- cur->levelFromUid ? "true" : "false");
+ levelFromName[cur->levelFrom]);
}
}
#endif
@@ -275,10 +303,10 @@
static pthread_once_t once = PTHREAD_ONCE_INIT;
/*
- * Max appid (uid - AID_APP) that can be mapped to category set uniquely
+ * Max id that can be mapped to category set uniquely
* using the current scheme.
*/
-#define CAT_MAPPING_MAX_APPID (0x1<<16)
+#define CAT_MAPPING_MAX_ID (0x1<<16)
enum seapp_kind {
SEAPP_TYPE,
@@ -298,8 +326,10 @@
struct seapp_context *cur;
int i;
size_t n;
- uid_t appid = 0;
+ uid_t userid;
+ uid_t appid;
+ userid = uid / AID_USER;
appid = uid % AID_USER;
if (appid < AID_APP) {
for (n = 0; n < android_id_count; n++) {
@@ -318,7 +348,7 @@
appid -= AID_ISOLATED_START;
}
- if (appid >= CAT_MAPPING_MAX_APPID)
+ if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
goto err;
for (i = 0; i < nspec; i++) {
@@ -371,11 +401,30 @@
goto oom;
}
- if (cur->levelFromUid) {
+ if (cur->levelFrom != LEVELFROM_NONE) {
char level[255];
- snprintf(level, sizeof level, "%s:c%u,c%u",
- context_range_get(ctx), appid & 0xff,
- 256 + (appid>>8 & 0xff));
+ switch (cur->levelFrom) {
+ case LEVELFROM_APP:
+ snprintf(level, sizeof level, "%s:c%u,c%u",
+ context_range_get(ctx), appid & 0xff,
+ 256 + (appid>>8 & 0xff));
+ break;
+ case LEVELFROM_USER:
+ snprintf(level, sizeof level, "%s:c%u,c%u",
+ context_range_get(ctx),
+ 512 + (userid & 0xff),
+ 768 + (userid>>8 & 0xff));
+ break;
+ case LEVELFROM_ALL:
+ snprintf(level, sizeof level, "%s:c%u,c%u,c%u,c%u",
+ context_range_get(ctx), appid & 0xff,
+ 256 + (appid>>8 & 0xff),
+ 512 + (userid & 0xff),
+ 768 + (userid>>8 & 0xff));
+ break;
+ default:
+ goto err;
+ }
if (context_range_set(ctx, level))
goto oom;
} else if (cur->level) {