blob: fb1b439a5e1f9ac3bb89f734d6afdb15abd9093d [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 Smalleyf0740362012-01-04 12:30:47 -050021#include "callbacks.h"
22#include "selinux_internal.h"
23
24/*
25 * XXX Where should this configuration file be located?
26 * Needs to be accessible by zygote and installd when
27 * setting credentials for app processes and setting permissions
28 * on app data directories.
29 */
Stephen Smalley7446c912012-03-19 10:37:05 -040030static char const * const seapp_contexts_file[] = {
31 "/data/system/seapp_contexts",
32 "/seapp_contexts",
33 0 };
Stephen Smalleyf0740362012-01-04 12:30:47 -050034
Stephen Smalley32ebfe82012-03-20 13:05:37 -040035static const struct selinux_opt seopts[] = {
36 { SELABEL_OPT_PATH, "/data/system/file_contexts" },
37 { SELABEL_OPT_PATH, "/file_contexts" },
38 { 0, NULL } };
Stephen Smalley7446c912012-03-19 10:37:05 -040039
Stephen Smalley4a655ec2012-09-18 15:08:32 -040040static const char *const sepolicy_file[] = {
rpcraigf1724a32012-08-01 15:35:37 -040041 "/data/system/sepolicy",
42 "/sepolicy",
43 0 };
44
Stephen Smalleyf0740362012-01-04 12:30:47 -050045struct seapp_context {
46 /* input selectors */
47 char isSystemServer;
48 char *user;
49 size_t len;
50 char prefix;
51 char *seinfo;
52 char *name;
53 /* outputs */
54 char *domain;
55 char *type;
56 char *level;
William Roberts1b36ad02012-07-27 13:52:33 -070057 char *sebool;
Stephen Smalleyf0740362012-01-04 12:30:47 -050058 char levelFromUid;
59};
60
61static int seapp_context_cmp(const void *A, const void *B)
62{
Stephen Smalleyd23b9e02012-09-21 10:45:39 -040063 const struct seapp_context *const *sp1 = A, *const *sp2 = B;
Stephen Smalleyf0740362012-01-04 12:30:47 -050064 const struct seapp_context *s1 = *sp1, *s2 = *sp2;
65
66 /* Give precedence to isSystemServer=true. */
67 if (s1->isSystemServer != s2->isSystemServer)
68 return (s1->isSystemServer ? -1 : 1);
69
70 /* Give precedence to a specified user= over an unspecified user=. */
71 if (s1->user && !s2->user)
72 return -1;
73 if (!s1->user && s2->user)
74 return 1;
75
76 if (s1->user) {
77 /* Give precedence to a fixed user= string over a prefix. */
78 if (s1->prefix != s2->prefix)
79 return (s2->prefix ? -1 : 1);
80
81 /* Give precedence to a longer prefix over a shorter prefix. */
82 if (s1->prefix && s1->len != s2->len)
83 return (s1->len > s2->len) ? -1 : 1;
84 }
85
86 /* Give precedence to a specified seinfo= over an unspecified seinfo=. */
87 if (s1->seinfo && !s2->seinfo)
88 return -1;
89 if (!s1->seinfo && s2->seinfo)
90 return 1;
91
92 /* Give precedence to a specified name= over an unspecified name=. */
93 if (s1->name && !s2->name)
94 return -1;
95 if (!s1->name && s2->name)
96 return 1;
97
William Roberts1b36ad02012-07-27 13:52:33 -070098 /* Give precedence to a specified sebool= over an unspecified sebool=. */
99 if (s1->sebool && !s2->sebool)
100 return -1;
101 if (!s1->sebool && s2->sebool)
102 return 1;
103
Stephen Smalleyf0740362012-01-04 12:30:47 -0500104 /* Anything else has equal precedence. */
105 return 0;
106}
107
108static struct seapp_context **seapp_contexts = NULL;
109static int nspec = 0;
110
Stephen Smalley7446c912012-03-19 10:37:05 -0400111int selinux_android_seapp_context_reload(void)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500112{
Stephen Smalley7446c912012-03-19 10:37:05 -0400113 FILE *fp = NULL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500114 char line_buf[BUFSIZ];
Stephen Smalleyf0740362012-01-04 12:30:47 -0500115 char *token;
116 unsigned lineno;
117 struct seapp_context *cur;
118 char *p, *name = NULL, *value = NULL, *saveptr;
119 size_t len;
Stephen Smalley7446c912012-03-19 10:37:05 -0400120 int i = 0, ret;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500121
Stephen Smalley7446c912012-03-19 10:37:05 -0400122 while ((fp==NULL) && seapp_contexts_file[i])
123 fp = fopen(seapp_contexts_file[i++], "r");
124
Stephen Smalleyf0740362012-01-04 12:30:47 -0500125 if (!fp) {
Stephen Smalley7446c912012-03-19 10:37:05 -0400126 selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__);
127 return -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500128 }
129
130 nspec = 0;
131 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
132 p = line_buf;
133 while (isspace(*p))
134 p++;
135 if (*p == '#' || *p == 0)
136 continue;
137 nspec++;
138 }
139
140 seapp_contexts = calloc(nspec, sizeof(struct seapp_context *));
141 if (!seapp_contexts)
142 goto oom;
143
144 rewind(fp);
145 nspec = 0;
146 lineno = 1;
147 while (fgets(line_buf, sizeof line_buf - 1, fp)) {
148 len = strlen(line_buf);
149 if (line_buf[len - 1] == '\n')
150 line_buf[len - 1] = 0;
151 p = line_buf;
152 while (isspace(*p))
153 p++;
154 if (*p == '#' || *p == 0)
155 continue;
156
157 cur = calloc(1, sizeof(struct seapp_context));
158 if (!cur)
159 goto oom;
160
161 token = strtok_r(p, " \t", &saveptr);
162 if (!token)
163 goto err;
164
165 while (1) {
166 name = token;
167 value = strchr(name, '=');
168 if (!value)
169 goto err;
170 *value++ = 0;
171
172 if (!strcasecmp(name, "isSystemServer")) {
173 if (!strcasecmp(value, "true"))
174 cur->isSystemServer = 1;
175 else if (!strcasecmp(value, "false"))
176 cur->isSystemServer = 0;
177 else {
178 goto err;
179 }
180 } else if (!strcasecmp(name, "user")) {
181 cur->user = strdup(value);
182 if (!cur->user)
183 goto oom;
184 cur->len = strlen(cur->user);
185 if (cur->user[cur->len-1] == '*')
186 cur->prefix = 1;
187 } else if (!strcasecmp(name, "seinfo")) {
188 cur->seinfo = strdup(value);
189 if (!cur->seinfo)
190 goto oom;
191 } else if (!strcasecmp(name, "name")) {
192 cur->name = strdup(value);
193 if (!cur->name)
194 goto oom;
195 } else if (!strcasecmp(name, "domain")) {
196 cur->domain = strdup(value);
197 if (!cur->domain)
198 goto oom;
199 } else if (!strcasecmp(name, "type")) {
200 cur->type = strdup(value);
201 if (!cur->type)
202 goto oom;
203 } else if (!strcasecmp(name, "levelFromUid")) {
204 if (!strcasecmp(value, "true"))
205 cur->levelFromUid = 1;
206 else if (!strcasecmp(value, "false"))
207 cur->levelFromUid = 0;
208 else {
209 goto err;
210 }
211 } else if (!strcasecmp(name, "level")) {
212 cur->level = strdup(value);
213 if (!cur->level)
214 goto oom;
William Roberts1b36ad02012-07-27 13:52:33 -0700215 } else if (!strcasecmp(name, "sebool")) {
216 cur->sebool = strdup(value);
217 if (!cur->sebool)
218 goto oom;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500219 } else
220 goto err;
221
222 token = strtok_r(NULL, " \t", &saveptr);
223 if (!token)
224 break;
225 }
226
227 seapp_contexts[nspec] = cur;
228 nspec++;
229 lineno++;
230 }
231
232 qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
233 seapp_context_cmp);
234
235#if DEBUG
236 {
237 int i;
238 for (i = 0; i < nspec; i++) {
239 cur = seapp_contexts[i];
William Roberts1b36ad02012-07-27 13:52:33 -0700240 selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFromUid=%s",
241 __FUNCTION__,
242 cur->isSystemServer ? "true" : "false", cur->user,
243 cur->seinfo, cur->name, cur->sebool, cur->domain,
244 cur->type, cur->level,
245 cur->levelFromUid ? "true" : "false");
Stephen Smalleyf0740362012-01-04 12:30:47 -0500246 }
247 }
248#endif
249
Stephen Smalley7446c912012-03-19 10:37:05 -0400250 ret = 0;
251
Stephen Smalleyf0740362012-01-04 12:30:47 -0500252out:
253 fclose(fp);
Stephen Smalley7446c912012-03-19 10:37:05 -0400254 return ret;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500255
256err:
257 selinux_log(SELINUX_ERROR, "%s: Error reading %s, line %u, name %s, value %s\n",
Stephen Smalley7446c912012-03-19 10:37:05 -0400258 __FUNCTION__, seapp_contexts_file[i - 1], lineno, name, value);
259 ret = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500260 goto out;
261oom:
262 selinux_log(SELINUX_ERROR,
263 "%s: Out of memory\n", __FUNCTION__);
Stephen Smalley7446c912012-03-19 10:37:05 -0400264 ret = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500265 goto out;
266}
267
Stephen Smalley7446c912012-03-19 10:37:05 -0400268
269static void seapp_context_init(void)
270{
271 selinux_android_seapp_context_reload();
272}
273
Stephen Smalleyf0740362012-01-04 12:30:47 -0500274static pthread_once_t once = PTHREAD_ONCE_INIT;
275
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400276/*
277 * Max appid (uid - AID_APP) that can be mapped to category set uniquely
278 * using the current scheme.
279 */
280#define CAT_MAPPING_MAX_APPID (0x1<<16)
281
282enum seapp_kind {
283 SEAPP_TYPE,
284 SEAPP_DOMAIN
285};
286
287static int seapp_context_lookup(enum seapp_kind kind,
Stephen Smalley895b4462012-09-19 16:27:36 -0400288 uid_t uid,
289 int isSystemServer,
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400290 const char *seinfo,
Stephen Smalley895b4462012-09-19 16:27:36 -0400291 const char *pkgname,
292 context_t ctx)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500293{
Stephen Smalley895b4462012-09-19 16:27:36 -0400294 const char *username = NULL;
295 char *end = NULL;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500296 struct passwd *pw;
297 struct seapp_context *cur;
Stephen Smalley895b4462012-09-19 16:27:36 -0400298 int i;
299 size_t n;
300 uid_t appid = 0;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500301
Stephen Smalley895b4462012-09-19 16:27:36 -0400302 appid = uid % AID_USER;
303 if (appid < AID_APP) {
304 for (n = 0; n < android_id_count; n++) {
305 if (android_ids[n].aid == appid) {
306 username = android_ids[n].name;
307 break;
308 }
Stephen Smalleyce4e2e62012-08-23 12:20:42 -0400309 }
Stephen Smalley895b4462012-09-19 16:27:36 -0400310 if (!username)
311 goto err;
312 } else if (appid < AID_ISOLATED_START) {
Stephen Smalley525a2242012-09-24 10:22:45 -0400313 username = "_app";
Stephen Smalley895b4462012-09-19 16:27:36 -0400314 appid -= AID_APP;
315 } else {
Stephen Smalley525a2242012-09-24 10:22:45 -0400316 username = "_isolated";
Stephen Smalley895b4462012-09-19 16:27:36 -0400317 appid -= AID_ISOLATED_START;
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400318 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500319
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400320 if (appid >= CAT_MAPPING_MAX_APPID)
Stephen Smalley895b4462012-09-19 16:27:36 -0400321 goto err;
322
Stephen Smalleyf0740362012-01-04 12:30:47 -0500323 for (i = 0; i < nspec; i++) {
324 cur = seapp_contexts[i];
325
Stephen Smalley895b4462012-09-19 16:27:36 -0400326 if (cur->isSystemServer != isSystemServer)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500327 continue;
328
329 if (cur->user) {
330 if (cur->prefix) {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400331 if (strncasecmp(username, cur->user, cur->len-1))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500332 continue;
333 } else {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400334 if (strcasecmp(username, cur->user))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500335 continue;
336 }
337 }
338
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400339 if (cur->seinfo) {
340 if (!seinfo || strcasecmp(seinfo, cur->seinfo))
341 continue;
342 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500343
344 if (cur->name) {
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400345 if (!pkgname || strcasecmp(pkgname, cur->name))
Stephen Smalleyf0740362012-01-04 12:30:47 -0500346 continue;
347 }
348
Stephen Smalley895b4462012-09-19 16:27:36 -0400349 if (kind == SEAPP_TYPE && !cur->type)
350 continue;
351 else if (kind == SEAPP_DOMAIN && !cur->domain)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500352 continue;
353
William Roberts1b36ad02012-07-27 13:52:33 -0700354 if (cur->sebool) {
355 int value = security_get_boolean_active(cur->sebool);
356 if (value == 0)
357 continue;
358 else if (value == -1) {
359 selinux_log(SELINUX_ERROR, \
360 "Could not find boolean: %s ", cur->sebool);
361 goto err;
362 }
363 }
364
Stephen Smalley895b4462012-09-19 16:27:36 -0400365 if (kind == SEAPP_TYPE) {
366 if (context_type_set(ctx, cur->type))
367 goto oom;
368 } else if (kind == SEAPP_DOMAIN) {
369 if (context_type_set(ctx, cur->domain))
370 goto oom;
371 }
Stephen Smalleyf0740362012-01-04 12:30:47 -0500372
Stephen Smalleyc9726ab2012-07-11 16:10:13 -0400373 if (cur->levelFromUid) {
Stephen Smalleyf0740362012-01-04 12:30:47 -0500374 char level[255];
Stephen Smalleyd23b9e02012-09-21 10:45:39 -0400375 snprintf(level, sizeof level, "%s:c%u,c%u",
376 context_range_get(ctx), appid & 0xff,
377 256 + (appid>>8 & 0xff));
Stephen Smalleyf0740362012-01-04 12:30:47 -0500378 if (context_range_set(ctx, level))
379 goto oom;
380 } else if (cur->level) {
381 if (context_range_set(ctx, cur->level))
382 goto oom;
383 }
William Roberts1b36ad02012-07-27 13:52:33 -0700384
Stephen Smalleyf0740362012-01-04 12:30:47 -0500385 break;
386 }
387
Stephen Smalley895b4462012-09-19 16:27:36 -0400388 if (kind == SEAPP_DOMAIN && i == nspec) {
389 /*
390 * No match.
391 * Fail to prevent staying in the zygote's context.
392 */
393 selinux_log(SELINUX_ERROR,
394 "%s: No match for app with uid %d, seinfo %s, name %s\n",
395 __FUNCTION__, uid, seinfo, pkgname);
396
397 if (security_getenforce() == 1)
398 goto err;
399 }
400
401 return 0;
402err:
403 return -1;
404oom:
405 return -2;
406}
407
408int selinux_android_setfilecon2(const char *pkgdir,
409 const char *pkgname,
410 const char *seinfo,
411 uid_t uid)
412{
413 char *orig_ctx_str = NULL, *ctx_str;
414 context_t ctx = NULL;
415 int rc;
416
417 if (is_selinux_enabled() <= 0)
418 return 0;
419
420 __selinux_once(once, seapp_context_init);
421
422 rc = getfilecon(pkgdir, &ctx_str);
423 if (rc < 0)
424 goto err;
425
426 ctx = context_new(ctx_str);
427 orig_ctx_str = ctx_str;
428 if (!ctx)
429 goto oom;
430
431 rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx);
432 if (rc == -1)
433 goto err;
434 else if (rc == -2)
435 goto oom;
436
Stephen Smalleyf0740362012-01-04 12:30:47 -0500437 ctx_str = context_str(ctx);
438 if (!ctx_str)
439 goto oom;
440
441 rc = security_check_context(ctx_str);
442 if (rc < 0)
443 goto err;
444
445 if (strcmp(ctx_str, orig_ctx_str)) {
446 rc = setfilecon(pkgdir, ctx_str);
447 if (rc < 0)
448 goto err;
449 }
450
451 rc = 0;
452out:
453 freecon(orig_ctx_str);
454 context_free(ctx);
455 return rc;
456err:
457 selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n",
458 __FUNCTION__, pkgdir, uid, strerror(errno));
459 rc = -1;
460 goto out;
461oom:
462 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
463 rc = -1;
464 goto out;
465}
466
Stephen Smalleyedfaad82012-07-12 11:30:24 -0400467int selinux_android_setfilecon(const char *pkgdir,
468 const char *pkgname,
469 uid_t uid)
470{
471 return selinux_android_setfilecon2(pkgdir, pkgname, NULL, uid);
472}
473
Stephen Smalleyf0740362012-01-04 12:30:47 -0500474int selinux_android_setcontext(uid_t uid,
475 int isSystemServer,
476 const char *seinfo,
Stephen Smalleyba70ee42012-07-10 15:49:04 -0400477 const char *pkgname)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500478{
Stephen Smalley895b4462012-09-19 16:27:36 -0400479 char *orig_ctx_str = NULL, *ctx_str;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500480 context_t ctx = NULL;
Stephen Smalley895b4462012-09-19 16:27:36 -0400481 int rc;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500482
483 if (is_selinux_enabled() <= 0)
484 return 0;
485
486 __selinux_once(once, seapp_context_init);
487
488 rc = getcon(&ctx_str);
489 if (rc)
490 goto err;
491
492 ctx = context_new(ctx_str);
493 orig_ctx_str = ctx_str;
494 if (!ctx)
495 goto oom;
496
Stephen Smalley895b4462012-09-19 16:27:36 -0400497 rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
498 if (rc == -1)
Stephen Smalleyf0740362012-01-04 12:30:47 -0500499 goto err;
Stephen Smalley895b4462012-09-19 16:27:36 -0400500 else if (rc == -2)
501 goto oom;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500502
503 ctx_str = context_str(ctx);
504 if (!ctx_str)
505 goto oom;
506
507 rc = security_check_context(ctx_str);
508 if (rc < 0)
509 goto err;
510
511 if (strcmp(ctx_str, orig_ctx_str)) {
512 rc = setcon(ctx_str);
513 if (rc < 0)
514 goto err;
515 }
516
517 rc = 0;
518out:
519 freecon(orig_ctx_str);
520 context_free(ctx);
Stephen Smalleye8b0fd82012-07-31 09:12:53 -0400521 avc_netlink_close();
Stephen Smalleyf0740362012-01-04 12:30:47 -0500522 return rc;
523err:
524 if (isSystemServer)
525 selinux_log(SELINUX_ERROR,
526 "%s: Error setting context for system server: %s\n",
527 __FUNCTION__, strerror(errno));
528 else
529 selinux_log(SELINUX_ERROR,
530 "%s: Error setting context for app with uid %d, seinfo %s: %s\n",
531 __FUNCTION__, uid, seinfo, strerror(errno));
532
Stephen Smalleyf77e60d2012-07-27 15:41:10 -0400533 rc = -1;
Stephen Smalleyf0740362012-01-04 12:30:47 -0500534 goto out;
535oom:
536 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
537 rc = -1;
538 goto out;
539}
540
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400541static struct selabel_handle *sehandle = NULL;
542
Stephen Smalley906742d2012-08-23 16:04:59 -0400543static struct selabel_handle *file_context_open(void)
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400544{
Stephen Smalley906742d2012-08-23 16:04:59 -0400545 struct selabel_handle *h;
Stephen Smalley32ebfe82012-03-20 13:05:37 -0400546 int i = 0;
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400547
Stephen Smalley906742d2012-08-23 16:04:59 -0400548 h = NULL;
549 while ((h == NULL) && seopts[i].value) {
550 h = selabel_open(SELABEL_CTX_FILE, &seopts[i], 1);
Stephen Smalley32ebfe82012-03-20 13:05:37 -0400551 i++;
552 }
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400553
Stephen Smalley906742d2012-08-23 16:04:59 -0400554 if (!h)
rpcraigf1724a32012-08-01 15:35:37 -0400555 selinux_log(SELINUX_ERROR, "%s: Error getting sehandle label (%s)\n",
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400556 __FUNCTION__, strerror(errno));
Stephen Smalley906742d2012-08-23 16:04:59 -0400557 return h;
558}
559
560static void file_context_init(void)
561{
562 sehandle = file_context_open();
Stephen Smalley0ca91b32012-03-19 10:25:53 -0400563}
564
565static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
566
567int selinux_android_restorecon(const char *pathname)
568{
569
570 __selinux_once(fc_once, file_context_init);
571
572 int ret;
573
574 if (!sehandle)
575 goto bail;
576
577 struct stat sb;
578
579 if (lstat(pathname, &sb) < 0)
580 goto err;
581
582 char *oldcontext, *newcontext;
583
584 if (lgetfilecon(pathname, &oldcontext) < 0)
585 goto err;
586
587 if (selabel_lookup(sehandle, &newcontext, pathname, sb.st_mode) < 0)
588 goto err;
589
590 if (strcmp(newcontext, "<<none>>") && strcmp(oldcontext, newcontext))
591 if (lsetfilecon(pathname, newcontext) < 0)
592 goto err;
593
594 ret = 0;
595out:
596 if (oldcontext)
597 freecon(oldcontext);
598 if (newcontext)
599 freecon(newcontext);
600
601 return ret;
602
603err:
604 selinux_log(SELINUX_ERROR,
605 "%s: Error restoring context for %s (%s)\n",
606 __FUNCTION__, pathname, strerror(errno));
607
608bail:
609 ret = -1;
610 goto out;
611}
rpcraig9b100832012-07-27 06:36:59 -0400612
613
rpcraigf1724a32012-08-01 15:35:37 -0400614struct selabel_handle* selinux_android_file_context_handle(void)
615{
Stephen Smalley906742d2012-08-23 16:04:59 -0400616 return file_context_open();
rpcraigf1724a32012-08-01 15:35:37 -0400617}
rpcraig9b100832012-07-27 06:36:59 -0400618
rpcraigf1724a32012-08-01 15:35:37 -0400619int selinux_android_reload_policy(void)
620{
621 char path[PATH_MAX];
Stephen Smalley4a655ec2012-09-18 15:08:32 -0400622 int fd = -1, rc;
rpcraigf1724a32012-08-01 15:35:37 -0400623 struct stat sb;
624 void *map = NULL;
625 int i = 0;
626
Stephen Smalley4a655ec2012-09-18 15:08:32 -0400627 while (fd < 0 && sepolicy_file[i]) {
628 snprintf(path, sizeof(path), "%s",
629 sepolicy_file[i]);
rpcraigf1724a32012-08-01 15:35:37 -0400630 fd = open(path, O_RDONLY);
rpcraigf1724a32012-08-01 15:35:37 -0400631 i++;
632 }
633 if (fd < 0) {
634 selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
635 strerror(errno));
636 return -1;
637 }
638 if (fstat(fd, &sb) < 0) {
639 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
640 path, strerror(errno));
641 close(fd);
642 return -1;
643 }
644 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
645 if (map == MAP_FAILED) {
646 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
647 path, strerror(errno));
648 close(fd);
649 return -1;
650 }
651
652 rc = security_load_policy(map, sb.st_size);
653 if (rc < 0) {
654 selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n",
655 strerror(errno));
656 munmap(map, sb.st_size);
657 close(fd);
658 return -1;
659 }
660
661 munmap(map, sb.st_size);
662 close(fd);
663 selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", path);
664
665 return 0;
666}
667
668int selinux_android_load_policy(void)
669{
670 mkdir(SELINUXMNT, 0755);
671 if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, NULL)) {
672 if (errno == ENODEV) {
673 /* SELinux not enabled in kernel */
674 return -1;
675 }
676 selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n",
677 strerror(errno));
678 return -1;
679 }
680 set_selinuxmnt(SELINUXMNT);
681
682 return selinux_android_reload_policy();
rpcraig9b100832012-07-27 06:36:59 -0400683}