blob: 5607bc72289e6cdc554a4e873fe7e305aa09e275 [file] [log] [blame]
Stephen Smalleyf0740362012-01-04 12:30:47 -05001#include <sys/types.h>
2#include <unistd.h>
3#include <string.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <ctype.h>
7#include <errno.h>
8#include <pwd.h>
9#include <grp.h>
rpcraigf1724a32012-08-01 15:35:37 -040010#include <sys/mman.h>
11#include <sys/mount.h>
Stephen Smalleyf0740362012-01-04 12:30:47 -050012#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <selinux/selinux.h>
16#include <selinux/context.h>
17#include <selinux/android.h>
Stephen Smalley0ca91b32012-03-19 10:25:53 -040018#include <selinux/label.h>
Stephen Smalleye8b0fd82012-07-31 09:12:53 -040019#include <selinux/avc.h>
Stephen Smalley895b4462012-09-19 16:27:36 -040020#include <private/android_filesystem_config.h>
Stephen Smalleyd10c3432012-11-05 11:49:35 -050021#include "policy.h"
Stephen Smalleyf0740362012-01-04 12:30:47 -050022#include "callbacks.h"
23#include "selinux_internal.h"
24
25/*
26 * XXX Where should this configuration file be located?
27 * Needs to be accessible by zygote and installd when
28 * setting credentials for app processes and setting permissions
29 * on app data directories.
30 */
Stephen Smalley7446c912012-03-19 10:37:05 -040031static char const * const seapp_contexts_file[] = {
William Roberts77e151b2013-01-23 14:01:14 -080032 "/data/security/seapp_contexts",
Stephen Smalley7446c912012-03-19 10:37:05 -040033 "/seapp_contexts",
34 0 };
Stephen Smalleyf0740362012-01-04 12:30:47 -050035
Stephen Smalley32ebfe82012-03-20 13:05:37 -040036static const struct selinux_opt seopts[] = {
William Roberts77e151b2013-01-23 14:01:14 -080037 { SELABEL_OPT_PATH, "/data/security/file_contexts" },
Stephen Smalley32ebfe82012-03-20 13:05:37 -040038 { SELABEL_OPT_PATH, "/file_contexts" },
39 { 0, NULL } };
Stephen Smalley7446c912012-03-19 10:37:05 -040040
Stephen Smalley4a655ec2012-09-18 15:08:32 -040041static const char *const sepolicy_file[] = {
William Roberts77e151b2013-01-23 14:01:14 -080042 "/data/security/sepolicy",
rpcraigf1724a32012-08-01 15:35:37 -040043 "/sepolicy",
44 0 };
45
Stephen Smalleya8795982012-11-28 10:42:46 -050046enum levelFrom {
47 LEVELFROM_NONE,
48 LEVELFROM_APP,
49 LEVELFROM_USER,
50 LEVELFROM_ALL
51};
52
53#if DEBUG
54static char const * const levelFromName[] = {
55 "none",
56 "app",
57 "user",
58 "all"
59};
60#endif
61
Stephen Smalleyf0740362012-01-04 12:30:47 -050062struct seapp_context {
63 /* input selectors */
64 char isSystemServer;
65 char *user;
66 size_t len;
67 char prefix;
68 char *seinfo;
69 char *name;
70 /* outputs */
71 char *domain;
72 char *type;
73 char *level;
William Roberts1b36ad02012-07-27 13:52:33 -070074 char *sebool;
Stephen Smalleya8795982012-11-28 10:42:46 -050075 enum levelFrom levelFrom;
Stephen Smalleyf0740362012-01-04 12:30:47 -050076};
77
78static int seapp_context_cmp(const void *A, const void *B)
79{
Stephen Smalleyd23b9e02012-09-21 10:45:39 -040080 const struct seapp_context *const *sp1 = A, *const *sp2 = B;
Stephen Smalleyf0740362012-01-04 12:30:47 -050081 const struct seapp_context *s1 = *sp1, *s2 = *sp2;
82
83 /* Give precedence to isSystemServer=true. */
84 if (s1->isSystemServer != s2->isSystemServer)
85 return (s1->isSystemServer ? -1 : 1);
86
87 /* Give precedence to a specified user= over an unspecified user=. */
88 if (s1->user && !s2->user)
89 return -1;
90 if (!s1->user && s2->user)
91 return 1;
92
93 if (s1->user) {
94 /* Give precedence to a fixed user= string over a prefix. */
95 if (s1->prefix != s2->prefix)
96 return (s2->prefix ? -1 : 1);
97
98 /* Give precedence to a longer prefix over a shorter prefix. */
99 if (s1->prefix && s1->len != s2->len)
100 return (s1->len > s2->len) ? -1 : 1;
101 }
102
103 /* Give precedence to a specified seinfo= over an unspecified seinfo=. */
104 if (s1->seinfo && !s2->seinfo)
105 return -1;
106 if (!s1->seinfo && s2->seinfo)
107 return 1;
108
109 /* Give precedence to a specified name= over an unspecified name=. */
110 if (s1->name && !s2->name)
111 return -1;
112 if (!s1->name && s2->name)
113 return 1;
114
William Roberts1b36ad02012-07-27 13:52:33 -0700115 /* Give precedence to a specified sebool= over an unspecified sebool=. */
116 if (s1->sebool && !s2->sebool)
117 return -1;
118 if (!s1->sebool && s2->sebool)
119 return 1;
120
Stephen Smalleyf0740362012-01-04 12:30:47 -0500121 /* Anything else has equal precedence. */
122 return 0;
123}
124
125static struct seapp_context **seapp_contexts = NULL;
126static int nspec = 0;
127
Stephen Smalley7446c912012-03-19 10:37:05 -0400128int selinux_android_seapp_context_reload(void)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500129{
Stephen Smalley7446c912012-03-19 10:37:05 -0400130 FILE *fp = NULL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500131 char line_buf[BUFSIZ];
Stephen Smalleyf0740362012-01-04 12:30:47 -0500132 char *token;
133 unsigned lineno;
134 struct seapp_context *cur;
135 char *p, *name = NULL, *value = NULL, *saveptr;
136 size_t len;
Stephen Smalley7446c912012-03-19 10:37:05 -0400137 int i = 0, ret;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500138
Stephen Smalley7446c912012-03-19 10:37:05 -0400139 while ((fp==NULL) && seapp_contexts_file[i])
140 fp = fopen(seapp_contexts_file[i++], "r");
141
Stephen Smalleyf0740362012-01-04 12:30:47 -0500142 if (!fp) {
Stephen Smalley7446c912012-03-19 10:37:05 -0400143 selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__);
144 return -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500145 }
146
147 nspec = 0;
148 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
149 p = line_buf;
150 while (isspace(*p))
151 p++;
152 if (*p == '#' || *p == 0)
153 continue;
154 nspec++;
155 }
156
157 seapp_contexts = calloc(nspec, sizeof(struct seapp_context *));
158 if (!seapp_contexts)
159 goto oom;
160
161 rewind(fp);
162 nspec = 0;
163 lineno = 1;
164 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
165 len = strlen(line_buf);
166 if (line_buf[len - 1] == '\n')
167 line_buf[len - 1] = 0;
168 p = line_buf;
169 while (isspace(*p))
170 p++;
171 if (*p == '#' || *p == 0)
172 continue;
173
174 cur = calloc(1, sizeof(struct seapp_context));
175 if (!cur)
176 goto oom;
177
178 token = strtok_r(p, " \t", &saveptr);
179 if (!token)
180 goto err;
181
182 while (1) {
183 name = token;
184 value = strchr(name, '=');
185 if (!value)
186 goto err;
187 *value++ = 0;
188
189 if (!strcasecmp(name, "isSystemServer")) {
190 if (!strcasecmp(value, "true"))
191 cur->isSystemServer = 1;
192 else if (!strcasecmp(value, "false"))
193 cur->isSystemServer = 0;
194 else {
195 goto err;
196 }
197 } else if (!strcasecmp(name, "user")) {
198 cur->user = strdup(value);
199 if (!cur->user)
200 goto oom;
201 cur->len = strlen(cur->user);
202 if (cur->user[cur->len-1] == '*')
203 cur->prefix = 1;
204 } else if (!strcasecmp(name, "seinfo")) {
205 cur->seinfo = strdup(value);
206 if (!cur->seinfo)
207 goto oom;
208 } else if (!strcasecmp(name, "name")) {
209 cur->name = strdup(value);
210 if (!cur->name)
211 goto oom;
212 } else if (!strcasecmp(name, "domain")) {
213 cur->domain = strdup(value);
214 if (!cur->domain)
215 goto oom;
216 } else if (!strcasecmp(name, "type")) {
217 cur->type = strdup(value);
218 if (!cur->type)
219 goto oom;
220 } else if (!strcasecmp(name, "levelFromUid")) {
221 if (!strcasecmp(value, "true"))
Stephen Smalleya8795982012-11-28 10:42:46 -0500222 cur->levelFrom = LEVELFROM_APP;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500223 else if (!strcasecmp(value, "false"))
Stephen Smalleya8795982012-11-28 10:42:46 -0500224 cur->levelFrom = LEVELFROM_NONE;
225 else {
226 goto err;
227 }
228 } else if (!strcasecmp(name, "levelFrom")) {
229 if (!strcasecmp(value, "none"))
230 cur->levelFrom = LEVELFROM_NONE;
231 else if (!strcasecmp(value, "app"))
232 cur->levelFrom = LEVELFROM_APP;
233 else if (!strcasecmp(value, "user"))
234 cur->levelFrom = LEVELFROM_USER;
235 else if (!strcasecmp(value, "all"))
236 cur->levelFrom = LEVELFROM_ALL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500237 else {
238 goto err;
239 }
240 } else if (!strcasecmp(name, "level")) {
241 cur->level = strdup(value);
242 if (!cur->level)
243 goto oom;
William Roberts1b36ad02012-07-27 13:52:33 -0700244 } else if (!strcasecmp(name, "sebool")) {
245 cur->sebool = strdup(value);
246 if (!cur->sebool)
247 goto oom;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500248 } else
249 goto err;
250
251 token = strtok_r(NULL, " \t", &saveptr);
252 if (!token)
253 break;
254 }
255
256 seapp_contexts[nspec] = cur;
257 nspec++;
258 lineno++;
259 }
260
261 qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
262 seapp_context_cmp);
263
264#if DEBUG
265 {
266 int i;
267 for (i = 0; i < nspec; i++) {
268 cur = seapp_contexts[i];
Stephen Smalleya8795982012-11-28 10:42:46 -0500269 selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFrom=%s",
William Roberts1b36ad02012-07-27 13:52:33 -0700270 __FUNCTION__,
271 cur->isSystemServer ? "true" : "false", cur->user,
272 cur->seinfo, cur->name, cur->sebool, cur->domain,
273 cur->type, cur->level,
Stephen Smalleya8795982012-11-28 10:42:46 -0500274 levelFromName[cur->levelFrom]);
Stephen Smalleyf0740362012-01-04 12:30:47 -0500275 }
276 }
277#endif
278
Stephen Smalley7446c912012-03-19 10:37:05 -0400279 ret = 0;
280
Stephen Smalleyf0740362012-01-04 12:30:47 -0500281out:
282 fclose(fp);
Stephen Smalley7446c912012-03-19 10:37:05 -0400283 return ret;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500284
285err:
286 selinux_log(SELINUX_ERROR, "%s: Error reading %s, line %u, name %s, value %s\n",
Stephen Smalley7446c912012-03-19 10:37:05 -0400287 __FUNCTION__, seapp_contexts_file[i - 1], lineno, name, value);
288 ret = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500289 goto out;
290oom:
291 selinux_log(SELINUX_ERROR,
292 "%s: Out of memory\n", __FUNCTION__);
Stephen Smalley7446c912012-03-19 10:37:05 -0400293 ret = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500294 goto out;
295}
296
Stephen Smalley7446c912012-03-19 10:37:05 -0400297
298static void seapp_context_init(void)
299{
300 selinux_android_seapp_context_reload();
301}
302
Stephen Smalleyf0740362012-01-04 12:30:47 -0500303static pthread_once_t once = PTHREAD_ONCE_INIT;
304
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400305/*
Stephen Smalleya8795982012-11-28 10:42:46 -0500306 * Max id that can be mapped to category set uniquely
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400307 * using the current scheme.
308 */
Stephen Smalleya8795982012-11-28 10:42:46 -0500309#define CAT_MAPPING_MAX_ID (0x1<<16)
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400310
311enum seapp_kind {
312 SEAPP_TYPE,
313 SEAPP_DOMAIN
314};
315
316static int seapp_context_lookup(enum seapp_kind kind,
Stephen Smalley895b4462012-09-19 16:27:36 -0400317 uid_t uid,
318 int isSystemServer,
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400319 const char *seinfo,
Stephen Smalley895b4462012-09-19 16:27:36 -0400320 const char *pkgname,
321 context_t ctx)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500322{
Stephen Smalley895b4462012-09-19 16:27:36 -0400323 const char *username = NULL;
324 char *end = NULL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500325 struct passwd *pw;
326 struct seapp_context *cur;
Stephen Smalley895b4462012-09-19 16:27:36 -0400327 int i;
328 size_t n;
Stephen Smalleya8795982012-11-28 10:42:46 -0500329 uid_t userid;
330 uid_t appid;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500331
Stephen Smalleya8795982012-11-28 10:42:46 -0500332 userid = uid / AID_USER;
Stephen Smalley895b4462012-09-19 16:27:36 -0400333 appid = uid % AID_USER;
334 if (appid < AID_APP) {
335 for (n = 0; n < android_id_count; n++) {
336 if (android_ids[n].aid == appid) {
337 username = android_ids[n].name;
338 break;
339 }
Stephen Smalleyce4e2e62012-08-23 12:20:42 -0400340 }
Stephen Smalley895b4462012-09-19 16:27:36 -0400341 if (!username)
342 goto err;
343 } else if (appid < AID_ISOLATED_START) {
Stephen Smalley525a2242012-09-24 10:22:45 -0400344 username = "_app";
Stephen Smalley895b4462012-09-19 16:27:36 -0400345 appid -= AID_APP;
346 } else {
Stephen Smalley525a2242012-09-24 10:22:45 -0400347 username = "_isolated";
Stephen Smalley895b4462012-09-19 16:27:36 -0400348 appid -= AID_ISOLATED_START;
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400349 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500350
Stephen Smalleya8795982012-11-28 10:42:46 -0500351 if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
Stephen Smalley895b4462012-09-19 16:27:36 -0400352 goto err;
353
Stephen Smalleyf0740362012-01-04 12:30:47 -0500354 for (i = 0; i < nspec; i++) {
355 cur = seapp_contexts[i];
356
Stephen Smalley895b4462012-09-19 16:27:36 -0400357 if (cur->isSystemServer != isSystemServer)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500358 continue;
359
360 if (cur->user) {
361 if (cur->prefix) {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400362 if (strncasecmp(username, cur->user, cur->len-1))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500363 continue;
364 } else {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400365 if (strcasecmp(username, cur->user))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500366 continue;
367 }
368 }
369
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400370 if (cur->seinfo) {
371 if (!seinfo || strcasecmp(seinfo, cur->seinfo))
372 continue;
373 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500374
375 if (cur->name) {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400376 if (!pkgname || strcasecmp(pkgname, cur->name))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500377 continue;
378 }
379
Stephen Smalley895b4462012-09-19 16:27:36 -0400380 if (kind == SEAPP_TYPE && !cur->type)
381 continue;
382 else if (kind == SEAPP_DOMAIN && !cur->domain)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500383 continue;
384
William Roberts1b36ad02012-07-27 13:52:33 -0700385 if (cur->sebool) {
386 int value = security_get_boolean_active(cur->sebool);
387 if (value == 0)
388 continue;
389 else if (value == -1) {
390 selinux_log(SELINUX_ERROR, \
391 "Could not find boolean: %s ", cur->sebool);
392 goto err;
393 }
394 }
395
Stephen Smalley895b4462012-09-19 16:27:36 -0400396 if (kind == SEAPP_TYPE) {
397 if (context_type_set(ctx, cur->type))
398 goto oom;
399 } else if (kind == SEAPP_DOMAIN) {
400 if (context_type_set(ctx, cur->domain))
401 goto oom;
402 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500403
Stephen Smalleya8795982012-11-28 10:42:46 -0500404 if (cur->levelFrom != LEVELFROM_NONE) {
Stephen Smalleyf0740362012-01-04 12:30:47 -0500405 char level[255];
Stephen Smalleya8795982012-11-28 10:42:46 -0500406 switch (cur->levelFrom) {
407 case LEVELFROM_APP:
408 snprintf(level, sizeof level, "%s:c%u,c%u",
409 context_range_get(ctx), appid & 0xff,
410 256 + (appid>>8 & 0xff));
411 break;
412 case LEVELFROM_USER:
413 snprintf(level, sizeof level, "%s:c%u,c%u",
414 context_range_get(ctx),
415 512 + (userid & 0xff),
416 768 + (userid>>8 & 0xff));
417 break;
418 case LEVELFROM_ALL:
419 snprintf(level, sizeof level, "%s:c%u,c%u,c%u,c%u",
420 context_range_get(ctx), appid & 0xff,
421 256 + (appid>>8 & 0xff),
422 512 + (userid & 0xff),
423 768 + (userid>>8 & 0xff));
424 break;
425 default:
426 goto err;
427 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500428 if (context_range_set(ctx, level))
429 goto oom;
430 } else if (cur->level) {
431 if (context_range_set(ctx, cur->level))
432 goto oom;
433 }
William Roberts1b36ad02012-07-27 13:52:33 -0700434
Stephen Smalleyf0740362012-01-04 12:30:47 -0500435 break;
436 }
437
Stephen Smalley895b4462012-09-19 16:27:36 -0400438 if (kind == SEAPP_DOMAIN && i == nspec) {
439 /*
440 * No match.
441 * Fail to prevent staying in the zygote's context.
442 */
443 selinux_log(SELINUX_ERROR,
444 "%s: No match for app with uid %d, seinfo %s, name %s\n",
445 __FUNCTION__, uid, seinfo, pkgname);
446
447 if (security_getenforce() == 1)
448 goto err;
449 }
450
451 return 0;
452err:
453 return -1;
454oom:
455 return -2;
456}
457
458int selinux_android_setfilecon2(const char *pkgdir,
459 const char *pkgname,
460 const char *seinfo,
461 uid_t uid)
462{
463 char *orig_ctx_str = NULL, *ctx_str;
464 context_t ctx = NULL;
465 int rc;
466
467 if (is_selinux_enabled() <= 0)
468 return 0;
469
470 __selinux_once(once, seapp_context_init);
471
472 rc = getfilecon(pkgdir, &ctx_str);
473 if (rc < 0)
474 goto err;
475
476 ctx = context_new(ctx_str);
477 orig_ctx_str = ctx_str;
478 if (!ctx)
479 goto oom;
480
481 rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx);
482 if (rc == -1)
483 goto err;
484 else if (rc == -2)
485 goto oom;
486
Stephen Smalleyf0740362012-01-04 12:30:47 -0500487 ctx_str = context_str(ctx);
488 if (!ctx_str)
489 goto oom;
490
491 rc = security_check_context(ctx_str);
492 if (rc < 0)
493 goto err;
494
495 if (strcmp(ctx_str, orig_ctx_str)) {
496 rc = setfilecon(pkgdir, ctx_str);
497 if (rc < 0)
498 goto err;
499 }
500
501 rc = 0;
502out:
503 freecon(orig_ctx_str);
504 context_free(ctx);
505 return rc;
506err:
507 selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n",
508 __FUNCTION__, pkgdir, uid, strerror(errno));
509 rc = -1;
510 goto out;
511oom:
512 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
513 rc = -1;
514 goto out;
515}
516
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400517int selinux_android_setfilecon(const char *pkgdir,
518 const char *pkgname,
519 uid_t uid)
520{
521 return selinux_android_setfilecon2(pkgdir, pkgname, NULL, uid);
522}
523
Stephen Smalleyf0740362012-01-04 12:30:47 -0500524int selinux_android_setcontext(uid_t uid,
525 int isSystemServer,
526 const char *seinfo,
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400527 const char *pkgname)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500528{
Stephen Smalley895b4462012-09-19 16:27:36 -0400529 char *orig_ctx_str = NULL, *ctx_str;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500530 context_t ctx = NULL;
Stephen Smalley895b4462012-09-19 16:27:36 -0400531 int rc;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500532
533 if (is_selinux_enabled() <= 0)
534 return 0;
535
536 __selinux_once(once, seapp_context_init);
537
538 rc = getcon(&ctx_str);
539 if (rc)
540 goto err;
541
542 ctx = context_new(ctx_str);
543 orig_ctx_str = ctx_str;
544 if (!ctx)
545 goto oom;
546
Stephen Smalley895b4462012-09-19 16:27:36 -0400547 rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
548 if (rc == -1)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500549 goto err;
Stephen Smalley895b4462012-09-19 16:27:36 -0400550 else if (rc == -2)
551 goto oom;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500552
553 ctx_str = context_str(ctx);
554 if (!ctx_str)
555 goto oom;
556
557 rc = security_check_context(ctx_str);
558 if (rc < 0)
559 goto err;
560
561 if (strcmp(ctx_str, orig_ctx_str)) {
562 rc = setcon(ctx_str);
563 if (rc < 0)
564 goto err;
565 }
566
567 rc = 0;
568out:
569 freecon(orig_ctx_str);
570 context_free(ctx);
Stephen Smalleye8b0fd82012-07-31 09:12:53 -0400571 avc_netlink_close();
Stephen Smalleyf0740362012-01-04 12:30:47 -0500572 return rc;
573err:
574 if (isSystemServer)
575 selinux_log(SELINUX_ERROR,
576 "%s: Error setting context for system server: %s\n",
577 __FUNCTION__, strerror(errno));
578 else
579 selinux_log(SELINUX_ERROR,
580 "%s: Error setting context for app with uid %d, seinfo %s: %s\n",
581 __FUNCTION__, uid, seinfo, strerror(errno));
582
Stephen Smalleyf77e60d2012-07-27 15:41:10 -0400583 rc = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500584 goto out;
585oom:
586 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
587 rc = -1;
588 goto out;
589}
590
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400591static struct selabel_handle *sehandle = NULL;
592
Stephen Smalley906742d2012-08-23 16:04:59 -0400593static struct selabel_handle *file_context_open(void)
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400594{
Stephen Smalley906742d2012-08-23 16:04:59 -0400595 struct selabel_handle *h;
Stephen Smalley32ebfe82012-03-20 13:05:37 -0400596 int i = 0;
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400597
Stephen Smalley906742d2012-08-23 16:04:59 -0400598 h = NULL;
599 while ((h == NULL) && seopts[i].value) {
600 h = selabel_open(SELABEL_CTX_FILE, &seopts[i], 1);
Stephen Smalley32ebfe82012-03-20 13:05:37 -0400601 i++;
602 }
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400603
Stephen Smalley906742d2012-08-23 16:04:59 -0400604 if (!h)
rpcraigf1724a32012-08-01 15:35:37 -0400605 selinux_log(SELINUX_ERROR, "%s: Error getting sehandle label (%s)\n",
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400606 __FUNCTION__, strerror(errno));
Stephen Smalley906742d2012-08-23 16:04:59 -0400607 return h;
608}
609
610static void file_context_init(void)
611{
612 sehandle = file_context_open();
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400613}
614
615static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
616
617int selinux_android_restorecon(const char *pathname)
618{
619
Kenny Root20f62f32012-10-22 17:09:23 -0700620 if (is_selinux_enabled() <= 0)
621 return 0;
622
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400623 __selinux_once(fc_once, file_context_init);
624
625 int ret;
626
627 if (!sehandle)
628 goto bail;
629
630 struct stat sb;
631
632 if (lstat(pathname, &sb) < 0)
633 goto err;
634
635 char *oldcontext, *newcontext;
636
637 if (lgetfilecon(pathname, &oldcontext) < 0)
638 goto err;
639
640 if (selabel_lookup(sehandle, &newcontext, pathname, sb.st_mode) < 0)
641 goto err;
642
643 if (strcmp(newcontext, "<<none>>") && strcmp(oldcontext, newcontext))
644 if (lsetfilecon(pathname, newcontext) < 0)
645 goto err;
646
647 ret = 0;
648out:
649 if (oldcontext)
650 freecon(oldcontext);
651 if (newcontext)
652 freecon(newcontext);
653
654 return ret;
655
656err:
657 selinux_log(SELINUX_ERROR,
658 "%s: Error restoring context for %s (%s)\n",
659 __FUNCTION__, pathname, strerror(errno));
660
661bail:
662 ret = -1;
663 goto out;
664}
rpcraig9b100832012-07-27 06:36:59 -0400665
666
rpcraigf1724a32012-08-01 15:35:37 -0400667struct selabel_handle* selinux_android_file_context_handle(void)
668{
Stephen Smalley906742d2012-08-23 16:04:59 -0400669 return file_context_open();
rpcraigf1724a32012-08-01 15:35:37 -0400670}
rpcraig9b100832012-07-27 06:36:59 -0400671
rpcraigf1724a32012-08-01 15:35:37 -0400672int selinux_android_reload_policy(void)
673{
674 char path[PATH_MAX];
Stephen Smalley4a655ec2012-09-18 15:08:32 -0400675 int fd = -1, rc;
rpcraigf1724a32012-08-01 15:35:37 -0400676 struct stat sb;
677 void *map = NULL;
678 int i = 0;
679
Stephen Smalley4a655ec2012-09-18 15:08:32 -0400680 while (fd < 0 && sepolicy_file[i]) {
681 snprintf(path, sizeof(path), "%s",
682 sepolicy_file[i]);
rpcraigf1724a32012-08-01 15:35:37 -0400683 fd = open(path, O_RDONLY);
rpcraigf1724a32012-08-01 15:35:37 -0400684 i++;
685 }
686 if (fd < 0) {
687 selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
688 strerror(errno));
689 return -1;
690 }
691 if (fstat(fd, &sb) < 0) {
692 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
693 path, strerror(errno));
694 close(fd);
695 return -1;
696 }
697 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
698 if (map == MAP_FAILED) {
699 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
700 path, strerror(errno));
701 close(fd);
702 return -1;
703 }
704
705 rc = security_load_policy(map, sb.st_size);
706 if (rc < 0) {
707 selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n",
708 strerror(errno));
709 munmap(map, sb.st_size);
710 close(fd);
711 return -1;
712 }
713
714 munmap(map, sb.st_size);
715 close(fd);
716 selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", path);
717
718 return 0;
719}
720
721int selinux_android_load_policy(void)
722{
Stephen Smalleyd10c3432012-11-05 11:49:35 -0500723 char *mnt = SELINUXMNT;
724 int rc;
725 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
726 if (rc < 0) {
rpcraigf1724a32012-08-01 15:35:37 -0400727 if (errno == ENODEV) {
728 /* SELinux not enabled in kernel */
729 return -1;
730 }
Stephen Smalleyd10c3432012-11-05 11:49:35 -0500731 if (errno == ENOENT) {
732 /* Fall back to legacy mountpoint. */
733 mnt = OLDSELINUXMNT;
Alice Chud2302ca2013-01-04 16:02:46 -0800734 rc = mkdir(mnt, 0755);
735 if (rc == -1 && errno != EEXIST) {
736 selinux_log(SELINUX_ERROR,"SELinux: Could not mkdir: %s\n",
737 strerror(errno));
738 return -1;
739 }
Stephen Smalleyd10c3432012-11-05 11:49:35 -0500740 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
741 }
742 }
743 if (rc < 0) {
rpcraigf1724a32012-08-01 15:35:37 -0400744 selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n",
745 strerror(errno));
746 return -1;
747 }
Stephen Smalleyd10c3432012-11-05 11:49:35 -0500748 set_selinuxmnt(mnt);
rpcraigf1724a32012-08-01 15:35:37 -0400749
750 return selinux_android_reload_policy();
rpcraig9b100832012-07-27 06:36:59 -0400751}