domain.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /*
  2. * security/tomoyo/domain.c
  3. *
  4. * Implementation of the Domain-Based Mandatory Access Control.
  5. *
  6. * Copyright (C) 2005-2009 NTT DATA CORPORATION
  7. *
  8. * Version: 2.2.0-pre 2009/02/01
  9. *
  10. */
  11. #include "common.h"
  12. #include "tomoyo.h"
  13. #include "realpath.h"
  14. #include <linux/binfmts.h>
  15. /* Variables definitions.*/
  16. /* The initial domain. */
  17. struct tomoyo_domain_info tomoyo_kernel_domain;
  18. /* The list for "struct tomoyo_domain_info". */
  19. LIST_HEAD(tomoyo_domain_list);
  20. DECLARE_RWSEM(tomoyo_domain_list_lock);
  21. /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */
  22. struct tomoyo_domain_initializer_entry {
  23. struct list_head list;
  24. const struct tomoyo_path_info *domainname; /* This may be NULL */
  25. const struct tomoyo_path_info *program;
  26. bool is_deleted;
  27. bool is_not; /* True if this entry is "no_initialize_domain". */
  28. /* True if the domainname is tomoyo_get_last_name(). */
  29. bool is_last_name;
  30. };
  31. /* Structure for "keep_domain" and "no_keep_domain" keyword. */
  32. struct tomoyo_domain_keeper_entry {
  33. struct list_head list;
  34. const struct tomoyo_path_info *domainname;
  35. const struct tomoyo_path_info *program; /* This may be NULL */
  36. bool is_deleted;
  37. bool is_not; /* True if this entry is "no_keep_domain". */
  38. /* True if the domainname is tomoyo_get_last_name(). */
  39. bool is_last_name;
  40. };
  41. /* Structure for "alias" keyword. */
  42. struct tomoyo_alias_entry {
  43. struct list_head list;
  44. const struct tomoyo_path_info *original_name;
  45. const struct tomoyo_path_info *aliased_name;
  46. bool is_deleted;
  47. };
  48. /**
  49. * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
  50. *
  51. * @domain: Pointer to "struct tomoyo_domain_info".
  52. * @is_delete: True if it is a delete request.
  53. * @flags: Flags to set or clear.
  54. *
  55. * Returns nothing.
  56. */
  57. void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
  58. const bool is_delete, const u8 flags)
  59. {
  60. /* We need to serialize because this is bitfield operation. */
  61. static DEFINE_SPINLOCK(lock);
  62. /***** CRITICAL SECTION START *****/
  63. spin_lock(&lock);
  64. if (!is_delete)
  65. domain->flags |= flags;
  66. else
  67. domain->flags &= ~flags;
  68. spin_unlock(&lock);
  69. /***** CRITICAL SECTION END *****/
  70. }
  71. /**
  72. * tomoyo_get_last_name - Get last component of a domainname.
  73. *
  74. * @domain: Pointer to "struct tomoyo_domain_info".
  75. *
  76. * Returns the last component of the domainname.
  77. */
  78. const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
  79. {
  80. const char *cp0 = domain->domainname->name;
  81. const char *cp1 = strrchr(cp0, ' ');
  82. if (cp1)
  83. return cp1 + 1;
  84. return cp0;
  85. }
  86. /* The list for "struct tomoyo_domain_initializer_entry". */
  87. static LIST_HEAD(tomoyo_domain_initializer_list);
  88. static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
  89. /**
  90. * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
  91. *
  92. * @domainname: The name of domain. May be NULL.
  93. * @program: The name of program.
  94. * @is_not: True if it is "no_initialize_domain" entry.
  95. * @is_delete: True if it is a delete request.
  96. *
  97. * Returns 0 on success, negative value otherwise.
  98. */
  99. static int tomoyo_update_domain_initializer_entry(const char *domainname,
  100. const char *program,
  101. const bool is_not,
  102. const bool is_delete)
  103. {
  104. struct tomoyo_domain_initializer_entry *new_entry;
  105. struct tomoyo_domain_initializer_entry *ptr;
  106. const struct tomoyo_path_info *saved_program;
  107. const struct tomoyo_path_info *saved_domainname = NULL;
  108. int error = -ENOMEM;
  109. bool is_last_name = false;
  110. if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
  111. return -EINVAL; /* No patterns allowed. */
  112. if (domainname) {
  113. if (!tomoyo_is_domain_def(domainname) &&
  114. tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
  115. is_last_name = true;
  116. else if (!tomoyo_is_correct_domain(domainname, __func__))
  117. return -EINVAL;
  118. saved_domainname = tomoyo_save_name(domainname);
  119. if (!saved_domainname)
  120. return -ENOMEM;
  121. }
  122. saved_program = tomoyo_save_name(program);
  123. if (!saved_program)
  124. return -ENOMEM;
  125. /***** EXCLUSIVE SECTION START *****/
  126. down_write(&tomoyo_domain_initializer_list_lock);
  127. list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
  128. if (ptr->is_not != is_not ||
  129. ptr->domainname != saved_domainname ||
  130. ptr->program != saved_program)
  131. continue;
  132. ptr->is_deleted = is_delete;
  133. error = 0;
  134. goto out;
  135. }
  136. if (is_delete) {
  137. error = -ENOENT;
  138. goto out;
  139. }
  140. new_entry = tomoyo_alloc_element(sizeof(*new_entry));
  141. if (!new_entry)
  142. goto out;
  143. new_entry->domainname = saved_domainname;
  144. new_entry->program = saved_program;
  145. new_entry->is_not = is_not;
  146. new_entry->is_last_name = is_last_name;
  147. list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
  148. error = 0;
  149. out:
  150. up_write(&tomoyo_domain_initializer_list_lock);
  151. /***** EXCLUSIVE SECTION END *****/
  152. return error;
  153. }
  154. /**
  155. * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
  156. *
  157. * @head: Pointer to "struct tomoyo_io_buffer".
  158. *
  159. * Returns true on success, false otherwise.
  160. */
  161. bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
  162. {
  163. struct list_head *pos;
  164. bool done = true;
  165. down_read(&tomoyo_domain_initializer_list_lock);
  166. list_for_each_cookie(pos, head->read_var2,
  167. &tomoyo_domain_initializer_list) {
  168. const char *no;
  169. const char *from = "";
  170. const char *domain = "";
  171. struct tomoyo_domain_initializer_entry *ptr;
  172. ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
  173. list);
  174. if (ptr->is_deleted)
  175. continue;
  176. no = ptr->is_not ? "no_" : "";
  177. if (ptr->domainname) {
  178. from = " from ";
  179. domain = ptr->domainname->name;
  180. }
  181. if (!tomoyo_io_printf(head,
  182. "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
  183. "%s%s%s\n", no, ptr->program->name, from,
  184. domain)) {
  185. done = false;
  186. break;
  187. }
  188. }
  189. up_read(&tomoyo_domain_initializer_list_lock);
  190. return done;
  191. }
  192. /**
  193. * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
  194. *
  195. * @data: String to parse.
  196. * @is_not: True if it is "no_initialize_domain" entry.
  197. * @is_delete: True if it is a delete request.
  198. *
  199. * Returns 0 on success, negative value otherwise.
  200. */
  201. int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
  202. const bool is_delete)
  203. {
  204. char *cp = strstr(data, " from ");
  205. if (cp) {
  206. *cp = '\0';
  207. return tomoyo_update_domain_initializer_entry(cp + 6, data,
  208. is_not,
  209. is_delete);
  210. }
  211. return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
  212. is_delete);
  213. }
  214. /**
  215. * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
  216. *
  217. * @domainname: The name of domain.
  218. * @program: The name of program.
  219. * @last_name: The last component of @domainname.
  220. *
  221. * Returns true if executing @program reinitializes domain transition,
  222. * false otherwise.
  223. */
  224. static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
  225. domainname,
  226. const struct tomoyo_path_info *program,
  227. const struct tomoyo_path_info *
  228. last_name)
  229. {
  230. struct tomoyo_domain_initializer_entry *ptr;
  231. bool flag = false;
  232. down_read(&tomoyo_domain_initializer_list_lock);
  233. list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
  234. if (ptr->is_deleted)
  235. continue;
  236. if (ptr->domainname) {
  237. if (!ptr->is_last_name) {
  238. if (ptr->domainname != domainname)
  239. continue;
  240. } else {
  241. if (tomoyo_pathcmp(ptr->domainname, last_name))
  242. continue;
  243. }
  244. }
  245. if (tomoyo_pathcmp(ptr->program, program))
  246. continue;
  247. if (ptr->is_not) {
  248. flag = false;
  249. break;
  250. }
  251. flag = true;
  252. }
  253. up_read(&tomoyo_domain_initializer_list_lock);
  254. return flag;
  255. }
  256. /* The list for "struct tomoyo_domain_keeper_entry". */
  257. static LIST_HEAD(tomoyo_domain_keeper_list);
  258. static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
  259. /**
  260. * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
  261. *
  262. * @domainname: The name of domain.
  263. * @program: The name of program. May be NULL.
  264. * @is_not: True if it is "no_keep_domain" entry.
  265. * @is_delete: True if it is a delete request.
  266. *
  267. * Returns 0 on success, negative value otherwise.
  268. */
  269. static int tomoyo_update_domain_keeper_entry(const char *domainname,
  270. const char *program,
  271. const bool is_not,
  272. const bool is_delete)
  273. {
  274. struct tomoyo_domain_keeper_entry *new_entry;
  275. struct tomoyo_domain_keeper_entry *ptr;
  276. const struct tomoyo_path_info *saved_domainname;
  277. const struct tomoyo_path_info *saved_program = NULL;
  278. static DEFINE_MUTEX(lock);
  279. int error = -ENOMEM;
  280. bool is_last_name = false;
  281. if (!tomoyo_is_domain_def(domainname) &&
  282. tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
  283. is_last_name = true;
  284. else if (!tomoyo_is_correct_domain(domainname, __func__))
  285. return -EINVAL;
  286. if (program) {
  287. if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
  288. return -EINVAL;
  289. saved_program = tomoyo_save_name(program);
  290. if (!saved_program)
  291. return -ENOMEM;
  292. }
  293. saved_domainname = tomoyo_save_name(domainname);
  294. if (!saved_domainname)
  295. return -ENOMEM;
  296. /***** EXCLUSIVE SECTION START *****/
  297. down_write(&tomoyo_domain_keeper_list_lock);
  298. list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
  299. if (ptr->is_not != is_not ||
  300. ptr->domainname != saved_domainname ||
  301. ptr->program != saved_program)
  302. continue;
  303. ptr->is_deleted = is_delete;
  304. error = 0;
  305. goto out;
  306. }
  307. if (is_delete) {
  308. error = -ENOENT;
  309. goto out;
  310. }
  311. new_entry = tomoyo_alloc_element(sizeof(*new_entry));
  312. if (!new_entry)
  313. goto out;
  314. new_entry->domainname = saved_domainname;
  315. new_entry->program = saved_program;
  316. new_entry->is_not = is_not;
  317. new_entry->is_last_name = is_last_name;
  318. list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
  319. error = 0;
  320. out:
  321. up_write(&tomoyo_domain_keeper_list_lock);
  322. /***** EXCLUSIVE SECTION END *****/
  323. return error;
  324. }
  325. /**
  326. * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
  327. *
  328. * @data: String to parse.
  329. * @is_not: True if it is "no_keep_domain" entry.
  330. * @is_delete: True if it is a delete request.
  331. *
  332. */
  333. int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
  334. const bool is_delete)
  335. {
  336. char *cp = strstr(data, " from ");
  337. if (cp) {
  338. *cp = '\0';
  339. return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
  340. is_delete);
  341. }
  342. return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
  343. }
  344. /**
  345. * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
  346. *
  347. * @head: Pointer to "struct tomoyo_io_buffer".
  348. *
  349. * Returns true on success, false otherwise.
  350. */
  351. bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
  352. {
  353. struct list_head *pos;
  354. bool done = true;
  355. down_read(&tomoyo_domain_keeper_list_lock);
  356. list_for_each_cookie(pos, head->read_var2,
  357. &tomoyo_domain_keeper_list) {
  358. struct tomoyo_domain_keeper_entry *ptr;
  359. const char *no;
  360. const char *from = "";
  361. const char *program = "";
  362. ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
  363. if (ptr->is_deleted)
  364. continue;
  365. no = ptr->is_not ? "no_" : "";
  366. if (ptr->program) {
  367. from = " from ";
  368. program = ptr->program->name;
  369. }
  370. if (!tomoyo_io_printf(head,
  371. "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
  372. "%s%s%s\n", no, program, from,
  373. ptr->domainname->name)) {
  374. done = false;
  375. break;
  376. }
  377. }
  378. up_read(&tomoyo_domain_keeper_list_lock);
  379. return done;
  380. }
  381. /**
  382. * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
  383. *
  384. * @domainname: The name of domain.
  385. * @program: The name of program.
  386. * @last_name: The last component of @domainname.
  387. *
  388. * Returns true if executing @program supresses domain transition,
  389. * false otherwise.
  390. */
  391. static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
  392. const struct tomoyo_path_info *program,
  393. const struct tomoyo_path_info *last_name)
  394. {
  395. struct tomoyo_domain_keeper_entry *ptr;
  396. bool flag = false;
  397. down_read(&tomoyo_domain_keeper_list_lock);
  398. list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
  399. if (ptr->is_deleted)
  400. continue;
  401. if (!ptr->is_last_name) {
  402. if (ptr->domainname != domainname)
  403. continue;
  404. } else {
  405. if (tomoyo_pathcmp(ptr->domainname, last_name))
  406. continue;
  407. }
  408. if (ptr->program && tomoyo_pathcmp(ptr->program, program))
  409. continue;
  410. if (ptr->is_not) {
  411. flag = false;
  412. break;
  413. }
  414. flag = true;
  415. }
  416. up_read(&tomoyo_domain_keeper_list_lock);
  417. return flag;
  418. }
  419. /* The list for "struct tomoyo_alias_entry". */
  420. static LIST_HEAD(tomoyo_alias_list);
  421. static DECLARE_RWSEM(tomoyo_alias_list_lock);
  422. /**
  423. * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
  424. *
  425. * @original_name: The original program's real name.
  426. * @aliased_name: The symbolic program's symbolic link's name.
  427. * @is_delete: True if it is a delete request.
  428. *
  429. * Returns 0 on success, negative value otherwise.
  430. */
  431. static int tomoyo_update_alias_entry(const char *original_name,
  432. const char *aliased_name,
  433. const bool is_delete)
  434. {
  435. struct tomoyo_alias_entry *new_entry;
  436. struct tomoyo_alias_entry *ptr;
  437. const struct tomoyo_path_info *saved_original_name;
  438. const struct tomoyo_path_info *saved_aliased_name;
  439. int error = -ENOMEM;
  440. if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
  441. !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
  442. return -EINVAL; /* No patterns allowed. */
  443. saved_original_name = tomoyo_save_name(original_name);
  444. saved_aliased_name = tomoyo_save_name(aliased_name);
  445. if (!saved_original_name || !saved_aliased_name)
  446. return -ENOMEM;
  447. /***** EXCLUSIVE SECTION START *****/
  448. down_write(&tomoyo_alias_list_lock);
  449. list_for_each_entry(ptr, &tomoyo_alias_list, list) {
  450. if (ptr->original_name != saved_original_name ||
  451. ptr->aliased_name != saved_aliased_name)
  452. continue;
  453. ptr->is_deleted = is_delete;
  454. error = 0;
  455. goto out;
  456. }
  457. if (is_delete) {
  458. error = -ENOENT;
  459. goto out;
  460. }
  461. new_entry = tomoyo_alloc_element(sizeof(*new_entry));
  462. if (!new_entry)
  463. goto out;
  464. new_entry->original_name = saved_original_name;
  465. new_entry->aliased_name = saved_aliased_name;
  466. list_add_tail(&new_entry->list, &tomoyo_alias_list);
  467. error = 0;
  468. out:
  469. up_write(&tomoyo_alias_list_lock);
  470. /***** EXCLUSIVE SECTION END *****/
  471. return error;
  472. }
  473. /**
  474. * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
  475. *
  476. * @head: Pointer to "struct tomoyo_io_buffer".
  477. *
  478. * Returns true on success, false otherwise.
  479. */
  480. bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
  481. {
  482. struct list_head *pos;
  483. bool done = true;
  484. down_read(&tomoyo_alias_list_lock);
  485. list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
  486. struct tomoyo_alias_entry *ptr;
  487. ptr = list_entry(pos, struct tomoyo_alias_entry, list);
  488. if (ptr->is_deleted)
  489. continue;
  490. if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
  491. ptr->original_name->name,
  492. ptr->aliased_name->name)) {
  493. done = false;
  494. break;
  495. }
  496. }
  497. up_read(&tomoyo_alias_list_lock);
  498. return done;
  499. }
  500. /**
  501. * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
  502. *
  503. * @data: String to parse.
  504. * @is_delete: True if it is a delete request.
  505. *
  506. * Returns 0 on success, negative value otherwise.
  507. */
  508. int tomoyo_write_alias_policy(char *data, const bool is_delete)
  509. {
  510. char *cp = strchr(data, ' ');
  511. if (!cp)
  512. return -EINVAL;
  513. *cp++ = '\0';
  514. return tomoyo_update_alias_entry(data, cp, is_delete);
  515. }
  516. /* Domain create/delete handler. */
  517. /**
  518. * tomoyo_delete_domain - Delete a domain.
  519. *
  520. * @domainname: The name of domain.
  521. *
  522. * Returns 0.
  523. */
  524. int tomoyo_delete_domain(char *domainname)
  525. {
  526. struct tomoyo_domain_info *domain;
  527. struct tomoyo_path_info name;
  528. name.name = domainname;
  529. tomoyo_fill_path_info(&name);
  530. /***** EXCLUSIVE SECTION START *****/
  531. down_write(&tomoyo_domain_list_lock);
  532. /* Is there an active domain? */
  533. list_for_each_entry(domain, &tomoyo_domain_list, list) {
  534. /* Never delete tomoyo_kernel_domain */
  535. if (domain == &tomoyo_kernel_domain)
  536. continue;
  537. if (domain->is_deleted ||
  538. tomoyo_pathcmp(domain->domainname, &name))
  539. continue;
  540. domain->is_deleted = true;
  541. break;
  542. }
  543. up_write(&tomoyo_domain_list_lock);
  544. /***** EXCLUSIVE SECTION END *****/
  545. return 0;
  546. }
  547. /**
  548. * tomoyo_find_or_assign_new_domain - Create a domain.
  549. *
  550. * @domainname: The name of domain.
  551. * @profile: Profile number to assign if the domain was newly created.
  552. *
  553. * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
  554. */
  555. struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
  556. domainname,
  557. const u8 profile)
  558. {
  559. struct tomoyo_domain_info *domain = NULL;
  560. const struct tomoyo_path_info *saved_domainname;
  561. /***** EXCLUSIVE SECTION START *****/
  562. down_write(&tomoyo_domain_list_lock);
  563. domain = tomoyo_find_domain(domainname);
  564. if (domain)
  565. goto out;
  566. if (!tomoyo_is_correct_domain(domainname, __func__))
  567. goto out;
  568. saved_domainname = tomoyo_save_name(domainname);
  569. if (!saved_domainname)
  570. goto out;
  571. /* Can I reuse memory of deleted domain? */
  572. list_for_each_entry(domain, &tomoyo_domain_list, list) {
  573. struct task_struct *p;
  574. struct tomoyo_acl_info *ptr;
  575. bool flag;
  576. if (!domain->is_deleted ||
  577. domain->domainname != saved_domainname)
  578. continue;
  579. flag = false;
  580. /***** CRITICAL SECTION START *****/
  581. read_lock(&tasklist_lock);
  582. for_each_process(p) {
  583. if (tomoyo_real_domain(p) != domain)
  584. continue;
  585. flag = true;
  586. break;
  587. }
  588. read_unlock(&tasklist_lock);
  589. /***** CRITICAL SECTION END *****/
  590. if (flag)
  591. continue;
  592. list_for_each_entry(ptr, &domain->acl_info_list, list) {
  593. ptr->type |= TOMOYO_ACL_DELETED;
  594. }
  595. tomoyo_set_domain_flag(domain, true, domain->flags);
  596. domain->profile = profile;
  597. domain->quota_warned = false;
  598. mb(); /* Avoid out-of-order execution. */
  599. domain->is_deleted = false;
  600. goto out;
  601. }
  602. /* No memory reusable. Create using new memory. */
  603. domain = tomoyo_alloc_element(sizeof(*domain));
  604. if (domain) {
  605. INIT_LIST_HEAD(&domain->acl_info_list);
  606. domain->domainname = saved_domainname;
  607. domain->profile = profile;
  608. list_add_tail(&domain->list, &tomoyo_domain_list);
  609. }
  610. out:
  611. up_write(&tomoyo_domain_list_lock);
  612. /***** EXCLUSIVE SECTION END *****/
  613. return domain;
  614. }
  615. /**
  616. * tomoyo_find_next_domain - Find a domain.
  617. *
  618. * @bprm: Pointer to "struct linux_binprm".
  619. * @next_domain: Pointer to pointer to "struct tomoyo_domain_info".
  620. *
  621. * Returns 0 on success, negative value otherwise.
  622. */
  623. int tomoyo_find_next_domain(struct linux_binprm *bprm,
  624. struct tomoyo_domain_info **next_domain)
  625. {
  626. /*
  627. * This function assumes that the size of buffer returned by
  628. * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
  629. */
  630. struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
  631. struct tomoyo_domain_info *old_domain = tomoyo_domain();
  632. struct tomoyo_domain_info *domain = NULL;
  633. const char *old_domain_name = old_domain->domainname->name;
  634. const char *original_name = bprm->filename;
  635. char *new_domain_name = NULL;
  636. char *real_program_name = NULL;
  637. char *symlink_program_name = NULL;
  638. const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
  639. const bool is_enforce = (mode == 3);
  640. int retval = -ENOMEM;
  641. struct tomoyo_path_info r; /* real name */
  642. struct tomoyo_path_info s; /* symlink name */
  643. struct tomoyo_path_info l; /* last name */
  644. static bool initialized;
  645. if (!tmp)
  646. goto out;
  647. if (!initialized) {
  648. /*
  649. * Built-in initializers. This is needed because policies are
  650. * not loaded until starting /sbin/init.
  651. */
  652. tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
  653. false, false);
  654. tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
  655. false, false);
  656. initialized = true;
  657. }
  658. /* Get tomoyo_realpath of program. */
  659. retval = -ENOENT;
  660. /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
  661. real_program_name = tomoyo_realpath(original_name);
  662. if (!real_program_name)
  663. goto out;
  664. /* Get tomoyo_realpath of symbolic link. */
  665. symlink_program_name = tomoyo_realpath_nofollow(original_name);
  666. if (!symlink_program_name)
  667. goto out;
  668. r.name = real_program_name;
  669. tomoyo_fill_path_info(&r);
  670. s.name = symlink_program_name;
  671. tomoyo_fill_path_info(&s);
  672. l.name = tomoyo_get_last_name(old_domain);
  673. tomoyo_fill_path_info(&l);
  674. /* Check 'alias' directive. */
  675. if (tomoyo_pathcmp(&r, &s)) {
  676. struct tomoyo_alias_entry *ptr;
  677. /* Is this program allowed to be called via symbolic links? */
  678. down_read(&tomoyo_alias_list_lock);
  679. list_for_each_entry(ptr, &tomoyo_alias_list, list) {
  680. if (ptr->is_deleted ||
  681. tomoyo_pathcmp(&r, ptr->original_name) ||
  682. tomoyo_pathcmp(&s, ptr->aliased_name))
  683. continue;
  684. memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
  685. strncpy(real_program_name, ptr->aliased_name->name,
  686. TOMOYO_MAX_PATHNAME_LEN - 1);
  687. tomoyo_fill_path_info(&r);
  688. break;
  689. }
  690. up_read(&tomoyo_alias_list_lock);
  691. }
  692. /* Check execute permission. */
  693. retval = tomoyo_check_exec_perm(old_domain, &r, tmp);
  694. if (retval < 0)
  695. goto out;
  696. new_domain_name = tmp->buffer;
  697. if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
  698. /* Transit to the child of tomoyo_kernel_domain domain. */
  699. snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
  700. TOMOYO_ROOT_NAME " " "%s", real_program_name);
  701. } else if (old_domain == &tomoyo_kernel_domain &&
  702. !tomoyo_policy_loaded) {
  703. /*
  704. * Needn't to transit from kernel domain before starting
  705. * /sbin/init. But transit from kernel domain if executing
  706. * initializers because they might start before /sbin/init.
  707. */
  708. domain = old_domain;
  709. } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
  710. /* Keep current domain. */
  711. domain = old_domain;
  712. } else {
  713. /* Normal domain transition. */
  714. snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
  715. "%s %s", old_domain_name, real_program_name);
  716. }
  717. if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
  718. goto done;
  719. down_read(&tomoyo_domain_list_lock);
  720. domain = tomoyo_find_domain(new_domain_name);
  721. up_read(&tomoyo_domain_list_lock);
  722. if (domain)
  723. goto done;
  724. if (is_enforce)
  725. goto done;
  726. domain = tomoyo_find_or_assign_new_domain(new_domain_name,
  727. old_domain->profile);
  728. done:
  729. if (domain)
  730. goto out;
  731. printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
  732. new_domain_name);
  733. if (is_enforce)
  734. retval = -EPERM;
  735. else
  736. tomoyo_set_domain_flag(old_domain, false,
  737. TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
  738. out:
  739. tomoyo_free(real_program_name);
  740. tomoyo_free(symlink_program_name);
  741. *next_domain = domain ? domain : old_domain;
  742. tomoyo_free(tmp);
  743. return retval;
  744. }