domain.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /*
  2. * security/tomoyo/domain.c
  3. *
  4. * Domain transition functions for TOMOYO.
  5. *
  6. * Copyright (C) 2005-2010 NTT DATA CORPORATION
  7. */
  8. #include "common.h"
  9. #include <linux/binfmts.h>
  10. #include <linux/slab.h>
  11. /* Variables definitions.*/
  12. /* The initial domain. */
  13. struct tomoyo_domain_info tomoyo_kernel_domain;
  14. /**
  15. * tomoyo_update_policy - Update an entry for exception policy.
  16. *
  17. * @new_entry: Pointer to "struct tomoyo_acl_info".
  18. * @size: Size of @new_entry in bytes.
  19. * @param: Pointer to "struct tomoyo_acl_param".
  20. * @check_duplicate: Callback function to find duplicated entry.
  21. *
  22. * Returns 0 on success, negative value otherwise.
  23. *
  24. * Caller holds tomoyo_read_lock().
  25. */
  26. int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
  27. struct tomoyo_acl_param *param,
  28. bool (*check_duplicate) (const struct tomoyo_acl_head
  29. *,
  30. const struct tomoyo_acl_head
  31. *))
  32. {
  33. int error = param->is_delete ? -ENOENT : -ENOMEM;
  34. struct tomoyo_acl_head *entry;
  35. struct list_head *list = param->list;
  36. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  37. return -ENOMEM;
  38. list_for_each_entry_rcu(entry, list, list) {
  39. if (!check_duplicate(entry, new_entry))
  40. continue;
  41. entry->is_deleted = param->is_delete;
  42. error = 0;
  43. break;
  44. }
  45. if (error && !param->is_delete) {
  46. entry = tomoyo_commit_ok(new_entry, size);
  47. if (entry) {
  48. list_add_tail_rcu(&entry->list, list);
  49. error = 0;
  50. }
  51. }
  52. mutex_unlock(&tomoyo_policy_lock);
  53. return error;
  54. }
  55. /**
  56. * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry.
  57. *
  58. * @a: Pointer to "struct tomoyo_acl_info".
  59. * @b: Pointer to "struct tomoyo_acl_info".
  60. *
  61. * Returns true if @a == @b, false otherwise.
  62. */
  63. static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
  64. const struct tomoyo_acl_info *b)
  65. {
  66. return a->type == b->type;
  67. }
  68. /**
  69. * tomoyo_update_domain - Update an entry for domain policy.
  70. *
  71. * @new_entry: Pointer to "struct tomoyo_acl_info".
  72. * @size: Size of @new_entry in bytes.
  73. * @param: Pointer to "struct tomoyo_acl_param".
  74. * @check_duplicate: Callback function to find duplicated entry.
  75. * @merge_duplicate: Callback function to merge duplicated entry.
  76. *
  77. * Returns 0 on success, negative value otherwise.
  78. *
  79. * Caller holds tomoyo_read_lock().
  80. */
  81. int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
  82. struct tomoyo_acl_param *param,
  83. bool (*check_duplicate) (const struct tomoyo_acl_info
  84. *,
  85. const struct tomoyo_acl_info
  86. *),
  87. bool (*merge_duplicate) (struct tomoyo_acl_info *,
  88. struct tomoyo_acl_info *,
  89. const bool))
  90. {
  91. const bool is_delete = param->is_delete;
  92. int error = is_delete ? -ENOENT : -ENOMEM;
  93. struct tomoyo_acl_info *entry;
  94. struct list_head * const list = param->list;
  95. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  96. return error;
  97. list_for_each_entry_rcu(entry, list, list) {
  98. if (!tomoyo_same_acl_head(entry, new_entry) ||
  99. !check_duplicate(entry, new_entry))
  100. continue;
  101. if (merge_duplicate)
  102. entry->is_deleted = merge_duplicate(entry, new_entry,
  103. is_delete);
  104. else
  105. entry->is_deleted = is_delete;
  106. error = 0;
  107. break;
  108. }
  109. if (error && !is_delete) {
  110. entry = tomoyo_commit_ok(new_entry, size);
  111. if (entry) {
  112. list_add_tail_rcu(&entry->list, list);
  113. error = 0;
  114. }
  115. }
  116. mutex_unlock(&tomoyo_policy_lock);
  117. return error;
  118. }
  119. void tomoyo_check_acl(struct tomoyo_request_info *r,
  120. bool (*check_entry) (struct tomoyo_request_info *,
  121. const struct tomoyo_acl_info *))
  122. {
  123. const struct tomoyo_domain_info *domain = r->domain;
  124. struct tomoyo_acl_info *ptr;
  125. list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
  126. if (ptr->is_deleted || ptr->type != r->param_type)
  127. continue;
  128. if (check_entry(r, ptr)) {
  129. r->granted = true;
  130. return;
  131. }
  132. }
  133. r->granted = false;
  134. }
  135. /* The list for "struct tomoyo_domain_info". */
  136. LIST_HEAD(tomoyo_domain_list);
  137. struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
  138. struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
  139. /**
  140. * tomoyo_last_word - Get last component of a domainname.
  141. *
  142. * @domainname: Domainname to check.
  143. *
  144. * Returns the last word of @domainname.
  145. */
  146. static const char *tomoyo_last_word(const char *name)
  147. {
  148. const char *cp = strrchr(name, ' ');
  149. if (cp)
  150. return cp + 1;
  151. return name;
  152. }
  153. /**
  154. * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry.
  155. *
  156. * @a: Pointer to "struct tomoyo_acl_head".
  157. * @b: Pointer to "struct tomoyo_acl_head".
  158. *
  159. * Returns true if @a == @b, false otherwise.
  160. */
  161. static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
  162. const struct tomoyo_acl_head *b)
  163. {
  164. const struct tomoyo_transition_control *p1 = container_of(a,
  165. typeof(*p1),
  166. head);
  167. const struct tomoyo_transition_control *p2 = container_of(b,
  168. typeof(*p2),
  169. head);
  170. return p1->type == p2->type && p1->is_last_name == p2->is_last_name
  171. && p1->domainname == p2->domainname
  172. && p1->program == p2->program;
  173. }
  174. /**
  175. * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
  176. *
  177. * @param: Pointer to "struct tomoyo_acl_param".
  178. * @type: Type of this entry.
  179. *
  180. * Returns 0 on success, negative value otherwise.
  181. */
  182. int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
  183. const u8 type)
  184. {
  185. struct tomoyo_transition_control e = { .type = type };
  186. int error = param->is_delete ? -ENOENT : -ENOMEM;
  187. char *program = param->data;
  188. char *domainname = strstr(program, " from ");
  189. if (domainname) {
  190. *domainname = '\0';
  191. domainname += 6;
  192. } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
  193. type == TOMOYO_TRANSITION_CONTROL_KEEP) {
  194. domainname = program;
  195. program = NULL;
  196. }
  197. if (program) {
  198. if (!tomoyo_correct_path(program))
  199. return -EINVAL;
  200. e.program = tomoyo_get_name(program);
  201. if (!e.program)
  202. goto out;
  203. }
  204. if (domainname) {
  205. if (!tomoyo_correct_domain(domainname)) {
  206. if (!tomoyo_correct_path(domainname))
  207. goto out;
  208. e.is_last_name = true;
  209. }
  210. e.domainname = tomoyo_get_name(domainname);
  211. if (!e.domainname)
  212. goto out;
  213. }
  214. param->list = &tomoyo_policy_list[TOMOYO_ID_TRANSITION_CONTROL];
  215. error = tomoyo_update_policy(&e.head, sizeof(e), param,
  216. tomoyo_same_transition_control);
  217. out:
  218. tomoyo_put_name(e.domainname);
  219. tomoyo_put_name(e.program);
  220. return error;
  221. }
  222. /**
  223. * tomoyo_transition_type - Get domain transition type.
  224. *
  225. * @domainname: The name of domain.
  226. * @program: The name of program.
  227. *
  228. * Returns TOMOYO_TRANSITION_CONTROL_INITIALIZE if executing @program
  229. * reinitializes domain transition, TOMOYO_TRANSITION_CONTROL_KEEP if executing
  230. * @program suppresses domain transition, others otherwise.
  231. *
  232. * Caller holds tomoyo_read_lock().
  233. */
  234. static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
  235. const struct tomoyo_path_info *program)
  236. {
  237. const struct tomoyo_transition_control *ptr;
  238. const char *last_name = tomoyo_last_word(domainname->name);
  239. u8 type;
  240. for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) {
  241. next:
  242. list_for_each_entry_rcu(ptr, &tomoyo_policy_list
  243. [TOMOYO_ID_TRANSITION_CONTROL],
  244. head.list) {
  245. if (ptr->head.is_deleted || ptr->type != type)
  246. continue;
  247. if (ptr->domainname) {
  248. if (!ptr->is_last_name) {
  249. if (ptr->domainname != domainname)
  250. continue;
  251. } else {
  252. /*
  253. * Use direct strcmp() since this is
  254. * unlikely used.
  255. */
  256. if (strcmp(ptr->domainname->name,
  257. last_name))
  258. continue;
  259. }
  260. }
  261. if (ptr->program &&
  262. tomoyo_pathcmp(ptr->program, program))
  263. continue;
  264. if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) {
  265. /*
  266. * Do not check for initialize_domain if
  267. * no_initialize_domain matched.
  268. */
  269. type = TOMOYO_TRANSITION_CONTROL_NO_KEEP;
  270. goto next;
  271. }
  272. goto done;
  273. }
  274. }
  275. done:
  276. return type;
  277. }
  278. /**
  279. * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry.
  280. *
  281. * @a: Pointer to "struct tomoyo_acl_head".
  282. * @b: Pointer to "struct tomoyo_acl_head".
  283. *
  284. * Returns true if @a == @b, false otherwise.
  285. */
  286. static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
  287. const struct tomoyo_acl_head *b)
  288. {
  289. const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1),
  290. head);
  291. const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2),
  292. head);
  293. return p1->original_name == p2->original_name &&
  294. p1->aggregated_name == p2->aggregated_name;
  295. }
  296. /**
  297. * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
  298. *
  299. * @param: Pointer to "struct tomoyo_acl_param".
  300. *
  301. * Returns 0 on success, negative value otherwise.
  302. *
  303. * Caller holds tomoyo_read_lock().
  304. */
  305. int tomoyo_write_aggregator(struct tomoyo_acl_param *param)
  306. {
  307. struct tomoyo_aggregator e = { };
  308. int error = param->is_delete ? -ENOENT : -ENOMEM;
  309. const char *original_name = tomoyo_read_token(param);
  310. const char *aggregated_name = tomoyo_read_token(param);
  311. if (!tomoyo_correct_word(original_name) ||
  312. !tomoyo_correct_path(aggregated_name))
  313. return -EINVAL;
  314. e.original_name = tomoyo_get_name(original_name);
  315. e.aggregated_name = tomoyo_get_name(aggregated_name);
  316. if (!e.original_name || !e.aggregated_name ||
  317. e.aggregated_name->is_patterned) /* No patterns allowed. */
  318. goto out;
  319. param->list = &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR];
  320. error = tomoyo_update_policy(&e.head, sizeof(e), param,
  321. tomoyo_same_aggregator);
  322. out:
  323. tomoyo_put_name(e.original_name);
  324. tomoyo_put_name(e.aggregated_name);
  325. return error;
  326. }
  327. /**
  328. * tomoyo_assign_domain - Create a domain.
  329. *
  330. * @domainname: The name of domain.
  331. * @profile: Profile number to assign if the domain was newly created.
  332. *
  333. * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
  334. *
  335. * Caller holds tomoyo_read_lock().
  336. */
  337. struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
  338. const u8 profile)
  339. {
  340. struct tomoyo_domain_info *entry;
  341. struct tomoyo_domain_info *domain = NULL;
  342. const struct tomoyo_path_info *saved_domainname;
  343. bool found = false;
  344. if (!tomoyo_correct_domain(domainname))
  345. return NULL;
  346. saved_domainname = tomoyo_get_name(domainname);
  347. if (!saved_domainname)
  348. return NULL;
  349. entry = kzalloc(sizeof(*entry), GFP_NOFS);
  350. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  351. goto out;
  352. list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
  353. if (domain->is_deleted ||
  354. tomoyo_pathcmp(saved_domainname, domain->domainname))
  355. continue;
  356. found = true;
  357. break;
  358. }
  359. if (!found && tomoyo_memory_ok(entry)) {
  360. INIT_LIST_HEAD(&entry->acl_info_list);
  361. entry->domainname = saved_domainname;
  362. saved_domainname = NULL;
  363. entry->profile = profile;
  364. list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
  365. domain = entry;
  366. entry = NULL;
  367. found = true;
  368. }
  369. mutex_unlock(&tomoyo_policy_lock);
  370. out:
  371. tomoyo_put_name(saved_domainname);
  372. kfree(entry);
  373. return found ? domain : NULL;
  374. }
  375. /**
  376. * tomoyo_find_next_domain - Find a domain.
  377. *
  378. * @bprm: Pointer to "struct linux_binprm".
  379. *
  380. * Returns 0 on success, negative value otherwise.
  381. *
  382. * Caller holds tomoyo_read_lock().
  383. */
  384. int tomoyo_find_next_domain(struct linux_binprm *bprm)
  385. {
  386. struct tomoyo_request_info r;
  387. char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
  388. struct tomoyo_domain_info *old_domain = tomoyo_domain();
  389. struct tomoyo_domain_info *domain = NULL;
  390. const char *original_name = bprm->filename;
  391. u8 mode;
  392. bool is_enforce;
  393. int retval = -ENOMEM;
  394. bool need_kfree = false;
  395. struct tomoyo_path_info rn = { }; /* real name */
  396. mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
  397. is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
  398. if (!tmp)
  399. goto out;
  400. retry:
  401. if (need_kfree) {
  402. kfree(rn.name);
  403. need_kfree = false;
  404. }
  405. /* Get symlink's pathname of program. */
  406. retval = -ENOENT;
  407. rn.name = tomoyo_realpath_nofollow(original_name);
  408. if (!rn.name)
  409. goto out;
  410. tomoyo_fill_path_info(&rn);
  411. need_kfree = true;
  412. /* Check 'aggregator' directive. */
  413. {
  414. struct tomoyo_aggregator *ptr;
  415. list_for_each_entry_rcu(ptr, &tomoyo_policy_list
  416. [TOMOYO_ID_AGGREGATOR], head.list) {
  417. if (ptr->head.is_deleted ||
  418. !tomoyo_path_matches_pattern(&rn,
  419. ptr->original_name))
  420. continue;
  421. kfree(rn.name);
  422. need_kfree = false;
  423. /* This is OK because it is read only. */
  424. rn = *ptr->aggregated_name;
  425. break;
  426. }
  427. }
  428. /* Check execute permission. */
  429. retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn);
  430. if (retval == TOMOYO_RETRY_REQUEST)
  431. goto retry;
  432. if (retval < 0)
  433. goto out;
  434. /*
  435. * To be able to specify domainnames with wildcards, use the
  436. * pathname specified in the policy (which may contain
  437. * wildcard) rather than the pathname passed to execve()
  438. * (which never contains wildcard).
  439. */
  440. if (r.param.path.matched_path) {
  441. if (need_kfree)
  442. kfree(rn.name);
  443. need_kfree = false;
  444. /* This is OK because it is read only. */
  445. rn = *r.param.path.matched_path;
  446. }
  447. /* Calculate domain to transit to. */
  448. switch (tomoyo_transition_type(old_domain->domainname, &rn)) {
  449. case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
  450. /* Transit to the child of tomoyo_kernel_domain domain. */
  451. snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " "
  452. "%s", rn.name);
  453. break;
  454. case TOMOYO_TRANSITION_CONTROL_KEEP:
  455. /* Keep current domain. */
  456. domain = old_domain;
  457. break;
  458. default:
  459. if (old_domain == &tomoyo_kernel_domain &&
  460. !tomoyo_policy_loaded) {
  461. /*
  462. * Needn't to transit from kernel domain before
  463. * starting /sbin/init. But transit from kernel domain
  464. * if executing initializers because they might start
  465. * before /sbin/init.
  466. */
  467. domain = old_domain;
  468. } else {
  469. /* Normal domain transition. */
  470. snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
  471. old_domain->domainname->name, rn.name);
  472. }
  473. break;
  474. }
  475. if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
  476. goto done;
  477. domain = tomoyo_find_domain(tmp);
  478. if (!domain)
  479. domain = tomoyo_assign_domain(tmp, old_domain->profile);
  480. done:
  481. if (domain)
  482. goto out;
  483. printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
  484. if (is_enforce)
  485. retval = -EPERM;
  486. else
  487. old_domain->transition_failed = true;
  488. out:
  489. if (!domain)
  490. domain = old_domain;
  491. /* Update reference count on "struct tomoyo_domain_info". */
  492. atomic_inc(&domain->users);
  493. bprm->cred->security = domain;
  494. if (need_kfree)
  495. kfree(rn.name);
  496. kfree(tmp);
  497. return retval;
  498. }