1f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/types.h> 2f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <unistd.h> 3f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <string.h> 4f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdio.h> 5f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdlib.h> 6f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <ctype.h> 7f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <errno.h> 8f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <pwd.h> 9f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <grp.h> 10f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig#include <sys/mman.h> 11f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig#include <sys/mount.h> 12f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/types.h> 13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/stat.h> 14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <fcntl.h> 15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/selinux.h> 16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/context.h> 17f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/android.h> 180ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley#include <selinux/label.h> 19e8b0fd8c21a68fd0a7fcf656a7b6eae10e61c8e5Stephen Smalley#include <selinux/avc.h> 20895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley#include <private/android_filesystem_config.h> 21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "callbacks.h" 22f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "selinux_internal.h" 23f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 24f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 25f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * XXX Where should this configuration file be located? 26f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Needs to be accessible by zygote and installd when 27f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * setting credentials for app processes and setting permissions 28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * on app data directories. 29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 307446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalleystatic char const * const seapp_contexts_file[] = { 317446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley "/data/system/seapp_contexts", 327446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley "/seapp_contexts", 337446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley 0 }; 34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 3532ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalleystatic const struct selinux_opt seopts[] = { 3632ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley { SELABEL_OPT_PATH, "/data/system/file_contexts" }, 3732ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley { SELABEL_OPT_PATH, "/file_contexts" }, 3832ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley { 0, NULL } }; 397446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley 404a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalleystatic const char *const sepolicy_file[] = { 41f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig "/data/system/sepolicy", 42f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig "/sepolicy", 43f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig 0 }; 44f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig 45f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct seapp_context { 46f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* input selectors */ 47f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char isSystemServer; 48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *user; 49f074036424618c130dacb3464465a8b40bffef5Stephen Smalley size_t len; 50f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char prefix; 51f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *seinfo; 52f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *name; 53f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* outputs */ 54f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *domain; 55f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *type; 56f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *level; 571b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts char *sebool; 58f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char levelFromUid; 59f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}; 60f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 61f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int seapp_context_cmp(const void *A, const void *B) 62f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 63f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const struct seapp_context **sp1 = A, **sp2 = B; 64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const struct seapp_context *s1 = *sp1, *s2 = *sp2; 65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 66f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Give precedence to isSystemServer=true. */ 67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (s1->isSystemServer != s2->isSystemServer) 68f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return (s1->isSystemServer ? -1 : 1); 69f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Give precedence to a specified user= over an unspecified user=. */ 71f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (s1->user && !s2->user) 72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!s1->user && s2->user) 74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 1; 75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (s1->user) { 77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Give precedence to a fixed user= string over a prefix. */ 78f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (s1->prefix != s2->prefix) 79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return (s2->prefix ? -1 : 1); 80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Give precedence to a longer prefix over a shorter prefix. */ 82f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (s1->prefix && s1->len != s2->len) 83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return (s1->len > s2->len) ? -1 : 1; 84f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 85f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Give precedence to a specified seinfo= over an unspecified seinfo=. */ 87f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (s1->seinfo && !s2->seinfo) 88f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 89f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!s1->seinfo && s2->seinfo) 90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 1; 91f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 92f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Give precedence to a specified name= over an unspecified name=. */ 93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (s1->name && !s2->name) 94f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 95f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!s1->name && s2->name) 96f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 1; 97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 981b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts /* Give precedence to a specified sebool= over an unspecified sebool=. */ 991b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts if (s1->sebool && !s2->sebool) 1001b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts return -1; 1011b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts if (!s1->sebool && s2->sebool) 1021b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts return 1; 1031b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts 104f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Anything else has equal precedence. */ 105f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 106f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 107f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 108f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct seapp_context **seapp_contexts = NULL; 109f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int nspec = 0; 110f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 1117446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalleyint selinux_android_seapp_context_reload(void) 112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 1137446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley FILE *fp = NULL; 114f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char line_buf[BUFSIZ]; 115f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *token; 116f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned lineno; 117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct seapp_context *cur; 118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *p, *name = NULL, *value = NULL, *saveptr; 119f074036424618c130dacb3464465a8b40bffef5Stephen Smalley size_t len; 1207446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley int i = 0, ret; 1217446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley 1227446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley while ((fp==NULL) && seapp_contexts_file[i]) 1237446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley fp = fopen(seapp_contexts_file[i++], "r"); 124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!fp) { 1267446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__); 1277446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley return -1; 128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 129f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 130f074036424618c130dacb3464465a8b40bffef5Stephen Smalley nspec = 0; 131f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (fgets(line_buf, sizeof line_buf - 1, fp)) { 132f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p = line_buf; 133f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (isspace(*p)) 134f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p++; 135f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (*p == '#' || *p == 0) 136f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley nspec++; 138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley seapp_contexts = calloc(nspec, sizeof(struct seapp_context *)); 141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!seapp_contexts) 142f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 143f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rewind(fp); 145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley nspec = 0; 146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley lineno = 1; 147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (fgets(line_buf, sizeof line_buf - 1, fp)) { 148f074036424618c130dacb3464465a8b40bffef5Stephen Smalley len = strlen(line_buf); 149f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (line_buf[len - 1] == '\n') 150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley line_buf[len - 1] = 0; 151f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p = line_buf; 152f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (isspace(*p)) 153f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p++; 154f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (*p == '#' || *p == 0) 155f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 156f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 157f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur = calloc(1, sizeof(struct seapp_context)); 158f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!cur) 159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 160f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 161f074036424618c130dacb3464465a8b40bffef5Stephen Smalley token = strtok_r(p, " \t", &saveptr); 162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!token) 163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (1) { 166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley name = token; 167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley value = strchr(name, '='); 168f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!value) 169f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *value++ = 0; 171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!strcasecmp(name, "isSystemServer")) { 173f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!strcasecmp(value, "true")) 174f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->isSystemServer = 1; 175f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else if (!strcasecmp(value, "false")) 176f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->isSystemServer = 0; 177f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else { 178f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 179f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (!strcasecmp(name, "user")) { 181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->user = strdup(value); 182f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!cur->user) 183f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 184f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->len = strlen(cur->user); 185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (cur->user[cur->len-1] == '*') 186f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->prefix = 1; 187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (!strcasecmp(name, "seinfo")) { 188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->seinfo = strdup(value); 189f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!cur->seinfo) 190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (!strcasecmp(name, "name")) { 192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->name = strdup(value); 193f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!cur->name) 194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (!strcasecmp(name, "domain")) { 196f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->domain = strdup(value); 197f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!cur->domain) 198f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 199f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (!strcasecmp(name, "type")) { 200f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->type = strdup(value); 201f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!cur->type) 202f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 203f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (!strcasecmp(name, "levelFromUid")) { 204f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!strcasecmp(value, "true")) 205f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->levelFromUid = 1; 206f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else if (!strcasecmp(value, "false")) 207f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->levelFromUid = 0; 208f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else { 209f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 210f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 211f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (!strcasecmp(name, "level")) { 212f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur->level = strdup(value); 213f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!cur->level) 214f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 2151b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts } else if (!strcasecmp(name, "sebool")) { 2161b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts cur->sebool = strdup(value); 2171b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts if (!cur->sebool) 2181b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts goto oom; 219f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else 220f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 221f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 222f074036424618c130dacb3464465a8b40bffef5Stephen Smalley token = strtok_r(NULL, " \t", &saveptr); 223f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!token) 224f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 225f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 226f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 227f074036424618c130dacb3464465a8b40bffef5Stephen Smalley seapp_contexts[nspec] = cur; 228f074036424618c130dacb3464465a8b40bffef5Stephen Smalley nspec++; 229f074036424618c130dacb3464465a8b40bffef5Stephen Smalley lineno++; 230f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 231f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 232f074036424618c130dacb3464465a8b40bffef5Stephen Smalley qsort(seapp_contexts, nspec, sizeof(struct seapp_context *), 233f074036424618c130dacb3464465a8b40bffef5Stephen Smalley seapp_context_cmp); 234f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 235f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#if DEBUG 236f074036424618c130dacb3464465a8b40bffef5Stephen Smalley { 237f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int i; 238f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < nspec; i++) { 239f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur = seapp_contexts[i]; 2401b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFromUid=%s", 2411b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts __FUNCTION__, 2421b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts cur->isSystemServer ? "true" : "false", cur->user, 2431b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts cur->seinfo, cur->name, cur->sebool, cur->domain, 2441b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts cur->type, cur->level, 2451b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts cur->levelFromUid ? "true" : "false"); 246f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 247f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 248f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#endif 249f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 2507446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley ret = 0; 2517446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley 252f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyout: 253f074036424618c130dacb3464465a8b40bffef5Stephen Smalley fclose(fp); 2547446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley return ret; 255f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 256f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr: 257f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_ERROR, "%s: Error reading %s, line %u, name %s, value %s\n", 2587446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley __FUNCTION__, seapp_contexts_file[i - 1], lineno, name, value); 2597446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley ret = -1; 260f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 261f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyoom: 262f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_ERROR, 263f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: Out of memory\n", __FUNCTION__); 2647446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley ret = -1; 265f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 266f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 267f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 2687446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley 2697446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalleystatic void seapp_context_init(void) 2707446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley{ 2717446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley selinux_android_seapp_context_reload(); 2727446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley} 2737446c917148c778315e511ad5c990492d3c8cdb8Stephen Smalley 274f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic pthread_once_t once = PTHREAD_ONCE_INIT; 275f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 276895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley#define SEAPP_TYPE 1 277895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley#define SEAPP_DOMAIN 2 278895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalleystatic int seapp_context_lookup(int kind, 279895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley uid_t uid, 280895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley int isSystemServer, 281edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley const char *seinfo, 282895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley const char *pkgname, 283895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley context_t ctx) 284f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 285895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley const char *username = NULL; 286895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley char *end = NULL; 287f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct passwd *pw; 288f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct seapp_context *cur; 289895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley int i; 290895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley size_t n; 291895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley uid_t appid = 0; 292895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 293895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley appid = uid % AID_USER; 294895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (appid < AID_APP) { 295895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley for (n = 0; n < android_id_count; n++) { 296895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (android_ids[n].aid == appid) { 297895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley username = android_ids[n].name; 298895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley break; 299895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley } 300ce4e2e6a0819b0a23d80fa137b5ee0e351aff855Stephen Smalley } 301895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (!username) 302895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto err; 303895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley } else if (appid < AID_ISOLATED_START) { 304895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley username = "app_"; 305895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley appid -= AID_APP; 306895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley } else { 307895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley username = "isolated"; 308895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley appid -= AID_ISOLATED_START; 309ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley } 310f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 311895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (appid >= MLS_CATS) 312895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto err; 313895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 314f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < nspec; i++) { 315f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cur = seapp_contexts[i]; 316f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 317895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (cur->isSystemServer != isSystemServer) 318f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 319f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 320f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (cur->user) { 321f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (cur->prefix) { 322ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley if (strncasecmp(username, cur->user, cur->len-1)) 323f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 324f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else { 325ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley if (strcasecmp(username, cur->user)) 326f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 327f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 328f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 329f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 330edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley if (cur->seinfo) { 331edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley if (!seinfo || strcasecmp(seinfo, cur->seinfo)) 332edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley continue; 333edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley } 334f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 335f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (cur->name) { 336ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley if (!pkgname || strcasecmp(pkgname, cur->name)) 337f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 338f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 339f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 340895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (kind == SEAPP_TYPE && !cur->type) 341895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley continue; 342895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley else if (kind == SEAPP_DOMAIN && !cur->domain) 343f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 344f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 3451b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts if (cur->sebool) { 3461b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts int value = security_get_boolean_active(cur->sebool); 3471b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts if (value == 0) 3481b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts continue; 3491b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts else if (value == -1) { 3501b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts selinux_log(SELINUX_ERROR, \ 3511b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts "Could not find boolean: %s ", cur->sebool); 3521b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts goto err; 3531b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts } 3541b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts } 3551b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts 356895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (kind == SEAPP_TYPE) { 357895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (context_type_set(ctx, cur->type)) 358895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto oom; 359895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley } else if (kind == SEAPP_DOMAIN) { 360895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (context_type_set(ctx, cur->domain)) 361895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto oom; 362895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley } 363f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 364c9726aba339f3d935ff14c0734edf13116af3cbfStephen Smalley if (cur->levelFromUid) { 365f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char level[255]; 366f074036424618c130dacb3464465a8b40bffef5Stephen Smalley snprintf(level, sizeof level, "%s:c%lu", 367895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley context_range_get(ctx), appid); 368f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (context_range_set(ctx, level)) 369f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 370f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (cur->level) { 371f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (context_range_set(ctx, cur->level)) 372f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 373f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 3741b36ad00bfbea16ad4456a9fd715e594d57f2fd6William Roberts 375f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 376f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 377f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 378895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (kind == SEAPP_DOMAIN && i == nspec) { 379895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley /* 380895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley * No match. 381895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley * Fail to prevent staying in the zygote's context. 382895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley */ 383895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley selinux_log(SELINUX_ERROR, 384895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley "%s: No match for app with uid %d, seinfo %s, name %s\n", 385895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley __FUNCTION__, uid, seinfo, pkgname); 386895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 387895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (security_getenforce() == 1) 388895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto err; 389895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley } 390895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 391895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley return 0; 392895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalleyerr: 393895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley return -1; 394895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalleyoom: 395895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley return -2; 396895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley} 397895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 398895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalleyint selinux_android_setfilecon2(const char *pkgdir, 399895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley const char *pkgname, 400895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley const char *seinfo, 401895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley uid_t uid) 402895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley{ 403895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley char *orig_ctx_str = NULL, *ctx_str; 404895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley context_t ctx = NULL; 405895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley int rc; 406895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 407895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (is_selinux_enabled() <= 0) 408895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley return 0; 409895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 410895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley __selinux_once(once, seapp_context_init); 411895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 412895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley rc = getfilecon(pkgdir, &ctx_str); 413895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (rc < 0) 414895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto err; 415895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 416895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley ctx = context_new(ctx_str); 417895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley orig_ctx_str = ctx_str; 418895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (!ctx) 419895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto oom; 420895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 421895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx); 422895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (rc == -1) 423895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto err; 424895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley else if (rc == -2) 425895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto oom; 426895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley 427f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ctx_str = context_str(ctx); 428f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!ctx_str) 429f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 430f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 431f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = security_check_context(ctx_str); 432f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc < 0) 433f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 434f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 435f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (strcmp(ctx_str, orig_ctx_str)) { 436f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = setfilecon(pkgdir, ctx_str); 437f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc < 0) 438f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 439f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 440f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 441f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = 0; 442f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyout: 443f074036424618c130dacb3464465a8b40bffef5Stephen Smalley freecon(orig_ctx_str); 444f074036424618c130dacb3464465a8b40bffef5Stephen Smalley context_free(ctx); 445f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 446f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr: 447f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n", 448f074036424618c130dacb3464465a8b40bffef5Stephen Smalley __FUNCTION__, pkgdir, uid, strerror(errno)); 449f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 450f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 451f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyoom: 452f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 453f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 454f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 455f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 456f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 457edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalleyint selinux_android_setfilecon(const char *pkgdir, 458edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley const char *pkgname, 459edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley uid_t uid) 460edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley{ 461edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley return selinux_android_setfilecon2(pkgdir, pkgname, NULL, uid); 462edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley} 463edfaad87e34e7a5bb691d45fd6df3e0b5ad0bb1aStephen Smalley 464f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint selinux_android_setcontext(uid_t uid, 465f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int isSystemServer, 466f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *seinfo, 467ba70ee4c5ab8026e97fce5c2452dfe588dfaac3eStephen Smalley const char *pkgname) 468f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 469895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley char *orig_ctx_str = NULL, *ctx_str; 470f074036424618c130dacb3464465a8b40bffef5Stephen Smalley context_t ctx = NULL; 471895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley int rc; 472f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 473f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (is_selinux_enabled() <= 0) 474f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 475f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 476f074036424618c130dacb3464465a8b40bffef5Stephen Smalley __selinux_once(once, seapp_context_init); 477f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 478f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = getcon(&ctx_str); 479f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc) 480f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 481f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 482f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ctx = context_new(ctx_str); 483f074036424618c130dacb3464465a8b40bffef5Stephen Smalley orig_ctx_str = ctx_str; 484f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!ctx) 485f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 486f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 487895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx); 488895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley if (rc == -1) 489f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 490895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley else if (rc == -2) 491895b446e8b4844f2da7354e74d5d96cc7f4418f3Stephen Smalley goto oom; 492f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 493f074036424618c130dacb3464465a8b40bffef5Stephen Smalley ctx_str = context_str(ctx); 494f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!ctx_str) 495f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto oom; 496f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 497f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = security_check_context(ctx_str); 498f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc < 0) 499f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 500f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 501f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (strcmp(ctx_str, orig_ctx_str)) { 502f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = setcon(ctx_str); 503f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc < 0) 504f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 505f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 506f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 507f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = 0; 508f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyout: 509f074036424618c130dacb3464465a8b40bffef5Stephen Smalley freecon(orig_ctx_str); 510f074036424618c130dacb3464465a8b40bffef5Stephen Smalley context_free(ctx); 511e8b0fd8c21a68fd0a7fcf656a7b6eae10e61c8e5Stephen Smalley avc_netlink_close(); 512f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 513f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr: 514f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (isSystemServer) 515f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_ERROR, 516f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: Error setting context for system server: %s\n", 517f074036424618c130dacb3464465a8b40bffef5Stephen Smalley __FUNCTION__, strerror(errno)); 518f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else 519f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_ERROR, 520f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: Error setting context for app with uid %d, seinfo %s: %s\n", 521f074036424618c130dacb3464465a8b40bffef5Stephen Smalley __FUNCTION__, uid, seinfo, strerror(errno)); 522f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 523f77e60de67dbc84d06aa77adef6bdf80455ee9f5Stephen Smalley rc = -1; 524f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 525f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyoom: 526f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 527f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 528f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto out; 529f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 530f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 5310ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleystatic struct selabel_handle *sehandle = NULL; 5320ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 533906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalleystatic struct selabel_handle *file_context_open(void) 5340ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley{ 535906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley struct selabel_handle *h; 53632ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley int i = 0; 5370ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 538906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley h = NULL; 539906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley while ((h == NULL) && seopts[i].value) { 540906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley h = selabel_open(SELABEL_CTX_FILE, &seopts[i], 1); 54132ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley i++; 54232ebfe869edfc32633cf4f2ee2b56b7d8ce97a19Stephen Smalley } 5430ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 544906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley if (!h) 545f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig selinux_log(SELINUX_ERROR, "%s: Error getting sehandle label (%s)\n", 5460ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley __FUNCTION__, strerror(errno)); 547906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley return h; 548906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley} 549906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley 550906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalleystatic void file_context_init(void) 551906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley{ 552906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley sehandle = file_context_open(); 5530ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley} 5540ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5550ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleystatic pthread_once_t fc_once = PTHREAD_ONCE_INIT; 5560ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5570ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleyint selinux_android_restorecon(const char *pathname) 5580ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley{ 5590ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5600ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley __selinux_once(fc_once, file_context_init); 5610ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5620ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley int ret; 5630ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5640ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley if (!sehandle) 5650ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley goto bail; 5660ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5670ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley struct stat sb; 5680ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5690ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley if (lstat(pathname, &sb) < 0) 5700ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley goto err; 5710ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5720ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley char *oldcontext, *newcontext; 5730ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5740ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley if (lgetfilecon(pathname, &oldcontext) < 0) 5750ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley goto err; 5760ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5770ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley if (selabel_lookup(sehandle, &newcontext, pathname, sb.st_mode) < 0) 5780ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley goto err; 5790ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5800ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley if (strcmp(newcontext, "<<none>>") && strcmp(oldcontext, newcontext)) 5810ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley if (lsetfilecon(pathname, newcontext) < 0) 5820ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley goto err; 5830ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5840ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley ret = 0; 5850ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleyout: 5860ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley if (oldcontext) 5870ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley freecon(oldcontext); 5880ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley if (newcontext) 5890ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley freecon(newcontext); 5900ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5910ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley return ret; 5920ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5930ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleyerr: 5940ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley selinux_log(SELINUX_ERROR, 5950ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley "%s: Error restoring context for %s (%s)\n", 5960ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley __FUNCTION__, pathname, strerror(errno)); 5970ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley 5980ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalleybail: 5990ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley ret = -1; 6000ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley goto out; 6010ca91b300c711079816fa67b4148cac3cd1eef8cStephen Smalley} 6029b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig 6039b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig 604f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraigstruct selabel_handle* selinux_android_file_context_handle(void) 605f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig{ 606906742dfd76bf9f21bddbddc43966c2cc9b0da0eStephen Smalley return file_context_open(); 607f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig} 608f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig 609f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraigint selinux_android_reload_policy(void) 610f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig{ 611f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig char path[PATH_MAX]; 6124a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalley int fd = -1, rc; 613f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig struct stat sb; 614f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig void *map = NULL; 615f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig int i = 0; 616f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig 6174a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalley while (fd < 0 && sepolicy_file[i]) { 6184a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalley snprintf(path, sizeof(path), "%s", 6194a655eca75a79149c25616c4a5a44f5b8d26b28fStephen Smalley sepolicy_file[i]); 620f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig fd = open(path, O_RDONLY); 621f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig i++; 622f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig } 623f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig if (fd < 0) { 624f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n", 625f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig strerror(errno)); 626f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig return -1; 627f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig } 628f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig if (fstat(fd, &sb) < 0) { 629f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n", 630f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig path, strerror(errno)); 631f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig close(fd); 632f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig return -1; 633f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig } 634f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 635f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig if (map == MAP_FAILED) { 636f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n", 637f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig path, strerror(errno)); 638f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig close(fd); 639f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig return -1; 640f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig } 641f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig 642f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig rc = security_load_policy(map, sb.st_size); 643f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig if (rc < 0) { 644f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n", 645f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig strerror(errno)); 646f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig munmap(map, sb.st_size); 647f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig close(fd); 648f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig return -1; 649f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig } 650f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig 651f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig munmap(map, sb.st_size); 652f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig close(fd); 653f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", path); 654f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig 655f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig return 0; 656f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig} 6579b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig 658f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraigint selinux_android_load_policy(void) 659f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig{ 660f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig mkdir(SELINUXMNT, 0755); 661f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, NULL)) { 662f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig if (errno == ENODEV) { 663f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig /* SELinux not enabled in kernel */ 664f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig return -1; 665f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig } 666f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n", 667f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig strerror(errno)); 668f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig return -1; 669f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig } 670f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig set_selinuxmnt(SELINUXMNT); 6719b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig 672f1724a371be1678ebf79474ab9a390dd6a5c96c7rpcraig return selinux_android_reload_policy(); 6739b10083ab40e78cce8cc2b940ce22db6d1095fc5rpcraig} 674