domain.c 22 KB

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