PageRenderTime 36ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/external/libselinux/src/android.c

https://gitlab.com/brian0218/rk3188_r-box_android4.2.2_sdk
C | 673 lines | 551 code | 101 blank | 21 comment | 185 complexity | 1ebaf24b3fcaa5164b1bcb504e71f8d9 MD5 | raw file
  1. #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>
  10. #include <sys/mman.h>
  11. #include <sys/mount.h>
  12. #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>
  18. #include <selinux/label.h>
  19. #include <selinux/avc.h>
  20. #include <private/android_filesystem_config.h>
  21. #include "callbacks.h"
  22. #include "selinux_internal.h"
  23. /*
  24. * XXX Where should this configuration file be located?
  25. * Needs to be accessible by zygote and installd when
  26. * setting credentials for app processes and setting permissions
  27. * on app data directories.
  28. */
  29. static char const * const seapp_contexts_file[] = {
  30. "/data/system/seapp_contexts",
  31. "/seapp_contexts",
  32. 0 };
  33. static const struct selinux_opt seopts[] = {
  34. { SELABEL_OPT_PATH, "/data/system/file_contexts" },
  35. { SELABEL_OPT_PATH, "/file_contexts" },
  36. { 0, NULL } };
  37. static const char *const sepolicy_file[] = {
  38. "/data/system/sepolicy",
  39. "/sepolicy",
  40. 0 };
  41. struct seapp_context {
  42. /* input selectors */
  43. char isSystemServer;
  44. char *user;
  45. size_t len;
  46. char prefix;
  47. char *seinfo;
  48. char *name;
  49. /* outputs */
  50. char *domain;
  51. char *type;
  52. char *level;
  53. char *sebool;
  54. char levelFromUid;
  55. };
  56. static int seapp_context_cmp(const void *A, const void *B)
  57. {
  58. const struct seapp_context **sp1 = A, **sp2 = B;
  59. const struct seapp_context *s1 = *sp1, *s2 = *sp2;
  60. /* Give precedence to isSystemServer=true. */
  61. if (s1->isSystemServer != s2->isSystemServer)
  62. return (s1->isSystemServer ? -1 : 1);
  63. /* Give precedence to a specified user= over an unspecified user=. */
  64. if (s1->user && !s2->user)
  65. return -1;
  66. if (!s1->user && s2->user)
  67. return 1;
  68. if (s1->user) {
  69. /* Give precedence to a fixed user= string over a prefix. */
  70. if (s1->prefix != s2->prefix)
  71. return (s2->prefix ? -1 : 1);
  72. /* Give precedence to a longer prefix over a shorter prefix. */
  73. if (s1->prefix && s1->len != s2->len)
  74. return (s1->len > s2->len) ? -1 : 1;
  75. }
  76. /* Give precedence to a specified seinfo= over an unspecified seinfo=. */
  77. if (s1->seinfo && !s2->seinfo)
  78. return -1;
  79. if (!s1->seinfo && s2->seinfo)
  80. return 1;
  81. /* Give precedence to a specified name= over an unspecified name=. */
  82. if (s1->name && !s2->name)
  83. return -1;
  84. if (!s1->name && s2->name)
  85. return 1;
  86. /* Give precedence to a specified sebool= over an unspecified sebool=. */
  87. if (s1->sebool && !s2->sebool)
  88. return -1;
  89. if (!s1->sebool && s2->sebool)
  90. return 1;
  91. /* Anything else has equal precedence. */
  92. return 0;
  93. }
  94. static struct seapp_context **seapp_contexts = NULL;
  95. static int nspec = 0;
  96. int selinux_android_seapp_context_reload(void)
  97. {
  98. FILE *fp = NULL;
  99. char line_buf[BUFSIZ];
  100. char *token;
  101. unsigned lineno;
  102. struct seapp_context *cur;
  103. char *p, *name = NULL, *value = NULL, *saveptr;
  104. size_t len;
  105. int i = 0, ret;
  106. while ((fp==NULL) && seapp_contexts_file[i])
  107. fp = fopen(seapp_contexts_file[i++], "r");
  108. if (!fp) {
  109. selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__);
  110. return -1;
  111. }
  112. nspec = 0;
  113. while (fgets(line_buf, sizeof line_buf - 1, fp)) {
  114. p = line_buf;
  115. while (isspace(*p))
  116. p++;
  117. if (*p == '#' || *p == 0)
  118. continue;
  119. nspec++;
  120. }
  121. seapp_contexts = calloc(nspec, sizeof(struct seapp_context *));
  122. if (!seapp_contexts)
  123. goto oom;
  124. rewind(fp);
  125. nspec = 0;
  126. lineno = 1;
  127. while (fgets(line_buf, sizeof line_buf - 1, fp)) {
  128. len = strlen(line_buf);
  129. if (line_buf[len - 1] == '\n')
  130. line_buf[len - 1] = 0;
  131. p = line_buf;
  132. while (isspace(*p))
  133. p++;
  134. if (*p == '#' || *p == 0)
  135. continue;
  136. cur = calloc(1, sizeof(struct seapp_context));
  137. if (!cur)
  138. goto oom;
  139. token = strtok_r(p, " \t", &saveptr);
  140. if (!token)
  141. goto err;
  142. while (1) {
  143. name = token;
  144. value = strchr(name, '=');
  145. if (!value)
  146. goto err;
  147. *value++ = 0;
  148. if (!strcasecmp(name, "isSystemServer")) {
  149. if (!strcasecmp(value, "true"))
  150. cur->isSystemServer = 1;
  151. else if (!strcasecmp(value, "false"))
  152. cur->isSystemServer = 0;
  153. else {
  154. goto err;
  155. }
  156. } else if (!strcasecmp(name, "user")) {
  157. cur->user = strdup(value);
  158. if (!cur->user)
  159. goto oom;
  160. cur->len = strlen(cur->user);
  161. if (cur->user[cur->len-1] == '*')
  162. cur->prefix = 1;
  163. } else if (!strcasecmp(name, "seinfo")) {
  164. cur->seinfo = strdup(value);
  165. if (!cur->seinfo)
  166. goto oom;
  167. } else if (!strcasecmp(name, "name")) {
  168. cur->name = strdup(value);
  169. if (!cur->name)
  170. goto oom;
  171. } else if (!strcasecmp(name, "domain")) {
  172. cur->domain = strdup(value);
  173. if (!cur->domain)
  174. goto oom;
  175. } else if (!strcasecmp(name, "type")) {
  176. cur->type = strdup(value);
  177. if (!cur->type)
  178. goto oom;
  179. } else if (!strcasecmp(name, "levelFromUid")) {
  180. if (!strcasecmp(value, "true"))
  181. cur->levelFromUid = 1;
  182. else if (!strcasecmp(value, "false"))
  183. cur->levelFromUid = 0;
  184. else {
  185. goto err;
  186. }
  187. } else if (!strcasecmp(name, "level")) {
  188. cur->level = strdup(value);
  189. if (!cur->level)
  190. goto oom;
  191. } else if (!strcasecmp(name, "sebool")) {
  192. cur->sebool = strdup(value);
  193. if (!cur->sebool)
  194. goto oom;
  195. } else
  196. goto err;
  197. token = strtok_r(NULL, " \t", &saveptr);
  198. if (!token)
  199. break;
  200. }
  201. seapp_contexts[nspec] = cur;
  202. nspec++;
  203. lineno++;
  204. }
  205. qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
  206. seapp_context_cmp);
  207. #if DEBUG
  208. {
  209. int i;
  210. for (i = 0; i < nspec; i++) {
  211. cur = seapp_contexts[i];
  212. selinux_log(SELINUX_INFO, "%s: isSystemServer=%s user=%s seinfo=%s name=%s sebool=%s -> domain=%s type=%s level=%s levelFromUid=%s",
  213. __FUNCTION__,
  214. cur->isSystemServer ? "true" : "false", cur->user,
  215. cur->seinfo, cur->name, cur->sebool, cur->domain,
  216. cur->type, cur->level,
  217. cur->levelFromUid ? "true" : "false");
  218. }
  219. }
  220. #endif
  221. ret = 0;
  222. out:
  223. fclose(fp);
  224. return ret;
  225. err:
  226. selinux_log(SELINUX_ERROR, "%s: Error reading %s, line %u, name %s, value %s\n",
  227. __FUNCTION__, seapp_contexts_file[i - 1], lineno, name, value);
  228. ret = -1;
  229. goto out;
  230. oom:
  231. selinux_log(SELINUX_ERROR,
  232. "%s: Out of memory\n", __FUNCTION__);
  233. ret = -1;
  234. goto out;
  235. }
  236. static void seapp_context_init(void)
  237. {
  238. selinux_android_seapp_context_reload();
  239. }
  240. static pthread_once_t once = PTHREAD_ONCE_INIT;
  241. #define SEAPP_TYPE 1
  242. #define SEAPP_DOMAIN 2
  243. static int seapp_context_lookup(int kind,
  244. uid_t uid,
  245. int isSystemServer,
  246. const char *seinfo,
  247. const char *pkgname,
  248. context_t ctx)
  249. {
  250. const char *username = NULL;
  251. char *end = NULL;
  252. struct passwd *pw;
  253. struct seapp_context *cur;
  254. int i;
  255. size_t n;
  256. uid_t appid = 0;
  257. appid = uid % AID_USER;
  258. if (appid < AID_APP) {
  259. for (n = 0; n < android_id_count; n++) {
  260. if (android_ids[n].aid == appid) {
  261. username = android_ids[n].name;
  262. break;
  263. }
  264. }
  265. if (!username)
  266. goto err;
  267. } else if (appid < AID_ISOLATED_START) {
  268. username = "app_";
  269. appid -= AID_APP;
  270. } else {
  271. username = "isolated";
  272. appid -= AID_ISOLATED_START;
  273. }
  274. if (appid >= MLS_CATS)
  275. goto err;
  276. for (i = 0; i < nspec; i++) {
  277. cur = seapp_contexts[i];
  278. if (cur->isSystemServer != isSystemServer)
  279. continue;
  280. if (cur->user) {
  281. if (cur->prefix) {
  282. if (strncasecmp(username, cur->user, cur->len-1))
  283. continue;
  284. } else {
  285. if (strcasecmp(username, cur->user))
  286. continue;
  287. }
  288. }
  289. if (cur->seinfo) {
  290. if (!seinfo || strcasecmp(seinfo, cur->seinfo))
  291. continue;
  292. }
  293. if (cur->name) {
  294. if (!pkgname || strcasecmp(pkgname, cur->name))
  295. continue;
  296. }
  297. if (kind == SEAPP_TYPE && !cur->type)
  298. continue;
  299. else if (kind == SEAPP_DOMAIN && !cur->domain)
  300. continue;
  301. if (cur->sebool) {
  302. int value = security_get_boolean_active(cur->sebool);
  303. if (value == 0)
  304. continue;
  305. else if (value == -1) {
  306. selinux_log(SELINUX_ERROR, \
  307. "Could not find boolean: %s ", cur->sebool);
  308. goto err;
  309. }
  310. }
  311. if (kind == SEAPP_TYPE) {
  312. if (context_type_set(ctx, cur->type))
  313. goto oom;
  314. } else if (kind == SEAPP_DOMAIN) {
  315. if (context_type_set(ctx, cur->domain))
  316. goto oom;
  317. }
  318. if (cur->levelFromUid) {
  319. char level[255];
  320. snprintf(level, sizeof level, "%s:c%lu",
  321. context_range_get(ctx), appid);
  322. if (context_range_set(ctx, level))
  323. goto oom;
  324. } else if (cur->level) {
  325. if (context_range_set(ctx, cur->level))
  326. goto oom;
  327. }
  328. break;
  329. }
  330. if (kind == SEAPP_DOMAIN && i == nspec) {
  331. /*
  332. * No match.
  333. * Fail to prevent staying in the zygote's context.
  334. */
  335. selinux_log(SELINUX_ERROR,
  336. "%s: No match for app with uid %d, seinfo %s, name %s\n",
  337. __FUNCTION__, uid, seinfo, pkgname);
  338. if (security_getenforce() == 1)
  339. goto err;
  340. }
  341. return 0;
  342. err:
  343. return -1;
  344. oom:
  345. return -2;
  346. }
  347. int selinux_android_setfilecon2(const char *pkgdir,
  348. const char *pkgname,
  349. const char *seinfo,
  350. uid_t uid)
  351. {
  352. char *orig_ctx_str = NULL, *ctx_str;
  353. context_t ctx = NULL;
  354. int rc;
  355. if (is_selinux_enabled() <= 0)
  356. return 0;
  357. __selinux_once(once, seapp_context_init);
  358. rc = getfilecon(pkgdir, &ctx_str);
  359. if (rc < 0)
  360. goto err;
  361. ctx = context_new(ctx_str);
  362. orig_ctx_str = ctx_str;
  363. if (!ctx)
  364. goto oom;
  365. rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, ctx);
  366. if (rc == -1)
  367. goto err;
  368. else if (rc == -2)
  369. goto oom;
  370. ctx_str = context_str(ctx);
  371. if (!ctx_str)
  372. goto oom;
  373. rc = security_check_context(ctx_str);
  374. if (rc < 0)
  375. goto err;
  376. if (strcmp(ctx_str, orig_ctx_str)) {
  377. rc = setfilecon(pkgdir, ctx_str);
  378. if (rc < 0)
  379. goto err;
  380. }
  381. rc = 0;
  382. out:
  383. freecon(orig_ctx_str);
  384. context_free(ctx);
  385. return rc;
  386. err:
  387. selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n",
  388. __FUNCTION__, pkgdir, uid, strerror(errno));
  389. rc = -1;
  390. goto out;
  391. oom:
  392. selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
  393. rc = -1;
  394. goto out;
  395. }
  396. int selinux_android_setfilecon(const char *pkgdir,
  397. const char *pkgname,
  398. uid_t uid)
  399. {
  400. return selinux_android_setfilecon2(pkgdir, pkgname, NULL, uid);
  401. }
  402. int selinux_android_setcontext(uid_t uid,
  403. int isSystemServer,
  404. const char *seinfo,
  405. const char *pkgname)
  406. {
  407. char *orig_ctx_str = NULL, *ctx_str;
  408. context_t ctx = NULL;
  409. int rc;
  410. if (is_selinux_enabled() <= 0)
  411. return 0;
  412. __selinux_once(once, seapp_context_init);
  413. rc = getcon(&ctx_str);
  414. if (rc)
  415. goto err;
  416. ctx = context_new(ctx_str);
  417. orig_ctx_str = ctx_str;
  418. if (!ctx)
  419. goto oom;
  420. rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, ctx);
  421. if (rc == -1)
  422. goto err;
  423. else if (rc == -2)
  424. goto oom;
  425. ctx_str = context_str(ctx);
  426. if (!ctx_str)
  427. goto oom;
  428. rc = security_check_context(ctx_str);
  429. if (rc < 0)
  430. goto err;
  431. if (strcmp(ctx_str, orig_ctx_str)) {
  432. rc = setcon(ctx_str);
  433. if (rc < 0)
  434. goto err;
  435. }
  436. rc = 0;
  437. out:
  438. freecon(orig_ctx_str);
  439. context_free(ctx);
  440. avc_netlink_close();
  441. return rc;
  442. err:
  443. if (isSystemServer)
  444. selinux_log(SELINUX_ERROR,
  445. "%s: Error setting context for system server: %s\n",
  446. __FUNCTION__, strerror(errno));
  447. else
  448. selinux_log(SELINUX_ERROR,
  449. "%s: Error setting context for app with uid %d, seinfo %s: %s\n",
  450. __FUNCTION__, uid, seinfo, strerror(errno));
  451. rc = -1;
  452. goto out;
  453. oom:
  454. selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
  455. rc = -1;
  456. goto out;
  457. }
  458. static struct selabel_handle *sehandle = NULL;
  459. static struct selabel_handle *file_context_open(void)
  460. {
  461. struct selabel_handle *h;
  462. int i = 0;
  463. h = NULL;
  464. while ((h == NULL) && seopts[i].value) {
  465. h = selabel_open(SELABEL_CTX_FILE, &seopts[i], 1);
  466. i++;
  467. }
  468. if (!h)
  469. selinux_log(SELINUX_ERROR, "%s: Error getting sehandle label (%s)\n",
  470. __FUNCTION__, strerror(errno));
  471. return h;
  472. }
  473. static void file_context_init(void)
  474. {
  475. sehandle = file_context_open();
  476. }
  477. static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
  478. int selinux_android_restorecon(const char *pathname)
  479. {
  480. __selinux_once(fc_once, file_context_init);
  481. int ret;
  482. if (!sehandle)
  483. goto bail;
  484. struct stat sb;
  485. if (lstat(pathname, &sb) < 0)
  486. goto err;
  487. char *oldcontext, *newcontext;
  488. if (lgetfilecon(pathname, &oldcontext) < 0)
  489. goto err;
  490. if (selabel_lookup(sehandle, &newcontext, pathname, sb.st_mode) < 0)
  491. goto err;
  492. if (strcmp(newcontext, "<<none>>") && strcmp(oldcontext, newcontext))
  493. if (lsetfilecon(pathname, newcontext) < 0)
  494. goto err;
  495. ret = 0;
  496. out:
  497. if (oldcontext)
  498. freecon(oldcontext);
  499. if (newcontext)
  500. freecon(newcontext);
  501. return ret;
  502. err:
  503. selinux_log(SELINUX_ERROR,
  504. "%s: Error restoring context for %s (%s)\n",
  505. __FUNCTION__, pathname, strerror(errno));
  506. bail:
  507. ret = -1;
  508. goto out;
  509. }
  510. struct selabel_handle* selinux_android_file_context_handle(void)
  511. {
  512. return file_context_open();
  513. }
  514. int selinux_android_reload_policy(void)
  515. {
  516. char path[PATH_MAX];
  517. int fd = -1, rc;
  518. struct stat sb;
  519. void *map = NULL;
  520. int i = 0;
  521. while (fd < 0 && sepolicy_file[i]) {
  522. snprintf(path, sizeof(path), "%s",
  523. sepolicy_file[i]);
  524. fd = open(path, O_RDONLY);
  525. i++;
  526. }
  527. if (fd < 0) {
  528. selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
  529. strerror(errno));
  530. return -1;
  531. }
  532. if (fstat(fd, &sb) < 0) {
  533. selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
  534. path, strerror(errno));
  535. close(fd);
  536. return -1;
  537. }
  538. map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  539. if (map == MAP_FAILED) {
  540. selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
  541. path, strerror(errno));
  542. close(fd);
  543. return -1;
  544. }
  545. rc = security_load_policy(map, sb.st_size);
  546. if (rc < 0) {
  547. selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n",
  548. strerror(errno));
  549. munmap(map, sb.st_size);
  550. close(fd);
  551. return -1;
  552. }
  553. munmap(map, sb.st_size);
  554. close(fd);
  555. selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", path);
  556. return 0;
  557. }
  558. int selinux_android_load_policy(void)
  559. {
  560. mkdir(SELINUXMNT, 0755);
  561. if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, NULL)) {
  562. if (errno == ENODEV) {
  563. /* SELinux not enabled in kernel */
  564. return -1;
  565. }
  566. selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n",
  567. strerror(errno));
  568. return -1;
  569. }
  570. set_selinuxmnt(SELINUXMNT);
  571. return selinux_android_reload_policy();
  572. }