domain.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  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_domain_list is used for holding list of domains.
  16. * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
  17. * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
  18. *
  19. * An entry is added by
  20. *
  21. * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
  22. * /sys/kernel/security/tomoyo/domain_policy
  23. *
  24. * and is deleted by
  25. *
  26. * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
  27. * /sys/kernel/security/tomoyo/domain_policy
  28. *
  29. * and all entries are retrieved by
  30. *
  31. * # cat /sys/kernel/security/tomoyo/domain_policy
  32. *
  33. * A domain is added by
  34. *
  35. * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
  36. *
  37. * and is deleted by
  38. *
  39. * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
  40. *
  41. * and all domains are retrieved by
  42. *
  43. * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
  44. *
  45. * Normally, a domainname is monotonically getting longer because a domainname
  46. * which the process will belong to if an execve() operation succeeds is
  47. * defined as a concatenation of "current domainname" + "pathname passed to
  48. * execve()".
  49. * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
  50. * exceptions.
  51. */
  52. LIST_HEAD(tomoyo_domain_list);
  53. /**
  54. * tomoyo_get_last_name - Get last component of a domainname.
  55. *
  56. * @domain: Pointer to "struct tomoyo_domain_info".
  57. *
  58. * Returns the last component of the domainname.
  59. */
  60. const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
  61. {
  62. const char *cp0 = domain->domainname->name;
  63. const char *cp1 = strrchr(cp0, ' ');
  64. if (cp1)
  65. return cp1 + 1;
  66. return cp0;
  67. }
  68. /*
  69. * tomoyo_domain_initializer_list is used for holding list of programs which
  70. * triggers reinitialization of domainname. Normally, a domainname is
  71. * monotonically getting longer. But sometimes, we restart daemon programs.
  72. * It would be convenient for us that "a daemon started upon system boot" and
  73. * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO
  74. * provides a way to shorten domainnames.
  75. *
  76. * An entry is added by
  77. *
  78. * # echo 'initialize_domain /usr/sbin/httpd' > \
  79. * /sys/kernel/security/tomoyo/exception_policy
  80. *
  81. * and is deleted by
  82. *
  83. * # echo 'delete initialize_domain /usr/sbin/httpd' > \
  84. * /sys/kernel/security/tomoyo/exception_policy
  85. *
  86. * and all entries are retrieved by
  87. *
  88. * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
  89. *
  90. * In the example above, /usr/sbin/httpd will belong to
  91. * "<kernel> /usr/sbin/httpd" domain.
  92. *
  93. * You may specify a domainname using "from" keyword.
  94. * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
  95. * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd"
  96. * domain to belong to "<kernel> /usr/sbin/httpd" domain.
  97. *
  98. * You may add "no_" prefix to "initialize_domain".
  99. * "initialize_domain /usr/sbin/httpd" and
  100. * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
  101. * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
  102. * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
  103. */
  104. LIST_HEAD(tomoyo_domain_initializer_list);
  105. /**
  106. * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
  107. *
  108. * @domainname: The name of domain. May be NULL.
  109. * @program: The name of program.
  110. * @is_not: True if it is "no_initialize_domain" entry.
  111. * @is_delete: True if it is a delete request.
  112. *
  113. * Returns 0 on success, negative value otherwise.
  114. *
  115. * Caller holds tomoyo_read_lock().
  116. */
  117. static int tomoyo_update_domain_initializer_entry(const char *domainname,
  118. const char *program,
  119. const bool is_not,
  120. const bool is_delete)
  121. {
  122. struct tomoyo_domain_initializer_entry *ptr;
  123. struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
  124. int error = is_delete ? -ENOENT : -ENOMEM;
  125. if (!tomoyo_is_correct_path(program, 1, -1, -1))
  126. return -EINVAL; /* No patterns allowed. */
  127. if (domainname) {
  128. if (!tomoyo_is_domain_def(domainname) &&
  129. tomoyo_is_correct_path(domainname, 1, -1, -1))
  130. e.is_last_name = true;
  131. else if (!tomoyo_is_correct_domain(domainname))
  132. return -EINVAL;
  133. e.domainname = tomoyo_get_name(domainname);
  134. if (!e.domainname)
  135. goto out;
  136. }
  137. e.program = tomoyo_get_name(program);
  138. if (!e.program)
  139. goto out;
  140. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  141. goto out;
  142. list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
  143. if (!tomoyo_is_same_domain_initializer_entry(ptr, &e))
  144. continue;
  145. ptr->is_deleted = is_delete;
  146. error = 0;
  147. break;
  148. }
  149. if (!is_delete && error) {
  150. struct tomoyo_domain_initializer_entry *entry =
  151. tomoyo_commit_ok(&e, sizeof(e));
  152. if (entry) {
  153. list_add_tail_rcu(&entry->list,
  154. &tomoyo_domain_initializer_list);
  155. error = 0;
  156. }
  157. }
  158. mutex_unlock(&tomoyo_policy_lock);
  159. out:
  160. tomoyo_put_name(e.domainname);
  161. tomoyo_put_name(e.program);
  162. return error;
  163. }
  164. /**
  165. * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
  166. *
  167. * @head: Pointer to "struct tomoyo_io_buffer".
  168. *
  169. * Returns true on success, false otherwise.
  170. *
  171. * Caller holds tomoyo_read_lock().
  172. */
  173. bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
  174. {
  175. struct list_head *pos;
  176. bool done = true;
  177. list_for_each_cookie(pos, head->read_var2,
  178. &tomoyo_domain_initializer_list) {
  179. const char *no;
  180. const char *from = "";
  181. const char *domain = "";
  182. struct tomoyo_domain_initializer_entry *ptr;
  183. ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
  184. list);
  185. if (ptr->is_deleted)
  186. continue;
  187. no = ptr->is_not ? "no_" : "";
  188. if (ptr->domainname) {
  189. from = " from ";
  190. domain = ptr->domainname->name;
  191. }
  192. done = tomoyo_io_printf(head,
  193. "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
  194. "%s%s%s\n", no, ptr->program->name,
  195. from, domain);
  196. if (!done)
  197. break;
  198. }
  199. return done;
  200. }
  201. /**
  202. * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
  203. *
  204. * @data: String to parse.
  205. * @is_not: True if it is "no_initialize_domain" entry.
  206. * @is_delete: True if it is a delete request.
  207. *
  208. * Returns 0 on success, negative value otherwise.
  209. *
  210. * Caller holds tomoyo_read_lock().
  211. */
  212. int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
  213. const bool is_delete)
  214. {
  215. char *cp = strstr(data, " from ");
  216. if (cp) {
  217. *cp = '\0';
  218. return tomoyo_update_domain_initializer_entry(cp + 6, data,
  219. is_not,
  220. is_delete);
  221. }
  222. return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
  223. is_delete);
  224. }
  225. /**
  226. * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
  227. *
  228. * @domainname: The name of domain.
  229. * @program: The name of program.
  230. * @last_name: The last component of @domainname.
  231. *
  232. * Returns true if executing @program reinitializes domain transition,
  233. * false otherwise.
  234. *
  235. * Caller holds tomoyo_read_lock().
  236. */
  237. static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
  238. domainname,
  239. const struct tomoyo_path_info *program,
  240. const struct tomoyo_path_info *
  241. last_name)
  242. {
  243. struct tomoyo_domain_initializer_entry *ptr;
  244. bool flag = false;
  245. list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
  246. if (ptr->is_deleted)
  247. continue;
  248. if (ptr->domainname) {
  249. if (!ptr->is_last_name) {
  250. if (ptr->domainname != domainname)
  251. continue;
  252. } else {
  253. if (tomoyo_pathcmp(ptr->domainname, last_name))
  254. continue;
  255. }
  256. }
  257. if (tomoyo_pathcmp(ptr->program, program))
  258. continue;
  259. if (ptr->is_not) {
  260. flag = false;
  261. break;
  262. }
  263. flag = true;
  264. }
  265. return flag;
  266. }
  267. /*
  268. * tomoyo_domain_keeper_list is used for holding list of domainnames which
  269. * suppresses domain transition. Normally, a domainname is monotonically
  270. * getting longer. But sometimes, we want to suppress domain transition.
  271. * It would be convenient for us that programs executed from a login session
  272. * belong to the same domain. Thus, TOMOYO provides a way to suppress domain
  273. * transition.
  274. *
  275. * An entry is added by
  276. *
  277. * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
  278. * /sys/kernel/security/tomoyo/exception_policy
  279. *
  280. * and is deleted by
  281. *
  282. * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
  283. * /sys/kernel/security/tomoyo/exception_policy
  284. *
  285. * and all entries are retrieved by
  286. *
  287. * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
  288. *
  289. * In the example above, any process which belongs to
  290. * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
  291. * unless explicitly specified by "initialize_domain" or "no_keep_domain".
  292. *
  293. * You may specify a program using "from" keyword.
  294. * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
  295. * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
  296. * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
  297. *
  298. * You may add "no_" prefix to "keep_domain".
  299. * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
  300. * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
  301. * cause "/usr/bin/passwd" to belong to
  302. * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
  303. * explicitly specified by "initialize_domain".
  304. */
  305. LIST_HEAD(tomoyo_domain_keeper_list);
  306. /**
  307. * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
  308. *
  309. * @domainname: The name of domain.
  310. * @program: The name of program. May be NULL.
  311. * @is_not: True if it is "no_keep_domain" entry.
  312. * @is_delete: True if it is a delete request.
  313. *
  314. * Returns 0 on success, negative value otherwise.
  315. *
  316. * Caller holds tomoyo_read_lock().
  317. */
  318. static int tomoyo_update_domain_keeper_entry(const char *domainname,
  319. const char *program,
  320. const bool is_not,
  321. const bool is_delete)
  322. {
  323. struct tomoyo_domain_keeper_entry *ptr;
  324. struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
  325. int error = is_delete ? -ENOENT : -ENOMEM;
  326. if (!tomoyo_is_domain_def(domainname) &&
  327. tomoyo_is_correct_path(domainname, 1, -1, -1))
  328. e.is_last_name = true;
  329. else if (!tomoyo_is_correct_domain(domainname))
  330. return -EINVAL;
  331. if (program) {
  332. if (!tomoyo_is_correct_path(program, 1, -1, -1))
  333. return -EINVAL;
  334. e.program = tomoyo_get_name(program);
  335. if (!e.program)
  336. goto out;
  337. }
  338. e.domainname = tomoyo_get_name(domainname);
  339. if (!e.domainname)
  340. goto out;
  341. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  342. goto out;
  343. list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
  344. if (!tomoyo_is_same_domain_keeper_entry(ptr, &e))
  345. continue;
  346. ptr->is_deleted = is_delete;
  347. error = 0;
  348. break;
  349. }
  350. if (!is_delete && error) {
  351. struct tomoyo_domain_keeper_entry *entry =
  352. tomoyo_commit_ok(&e, sizeof(e));
  353. if (entry) {
  354. list_add_tail_rcu(&entry->list,
  355. &tomoyo_domain_keeper_list);
  356. error = 0;
  357. }
  358. }
  359. mutex_unlock(&tomoyo_policy_lock);
  360. out:
  361. tomoyo_put_name(e.domainname);
  362. tomoyo_put_name(e.program);
  363. return error;
  364. }
  365. /**
  366. * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
  367. *
  368. * @data: String to parse.
  369. * @is_not: True if it is "no_keep_domain" entry.
  370. * @is_delete: True if it is a delete request.
  371. *
  372. * Caller holds tomoyo_read_lock().
  373. */
  374. int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
  375. const bool is_delete)
  376. {
  377. char *cp = strstr(data, " from ");
  378. if (cp) {
  379. *cp = '\0';
  380. return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
  381. is_delete);
  382. }
  383. return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
  384. }
  385. /**
  386. * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
  387. *
  388. * @head: Pointer to "struct tomoyo_io_buffer".
  389. *
  390. * Returns true on success, false otherwise.
  391. *
  392. * Caller holds tomoyo_read_lock().
  393. */
  394. bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
  395. {
  396. struct list_head *pos;
  397. bool done = true;
  398. list_for_each_cookie(pos, head->read_var2,
  399. &tomoyo_domain_keeper_list) {
  400. struct tomoyo_domain_keeper_entry *ptr;
  401. const char *no;
  402. const char *from = "";
  403. const char *program = "";
  404. ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
  405. if (ptr->is_deleted)
  406. continue;
  407. no = ptr->is_not ? "no_" : "";
  408. if (ptr->program) {
  409. from = " from ";
  410. program = ptr->program->name;
  411. }
  412. done = tomoyo_io_printf(head,
  413. "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
  414. "%s%s%s\n", no, program, from,
  415. ptr->domainname->name);
  416. if (!done)
  417. break;
  418. }
  419. return done;
  420. }
  421. /**
  422. * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
  423. *
  424. * @domainname: The name of domain.
  425. * @program: The name of program.
  426. * @last_name: The last component of @domainname.
  427. *
  428. * Returns true if executing @program supresses domain transition,
  429. * false otherwise.
  430. *
  431. * Caller holds tomoyo_read_lock().
  432. */
  433. static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
  434. const struct tomoyo_path_info *program,
  435. const struct tomoyo_path_info *last_name)
  436. {
  437. struct tomoyo_domain_keeper_entry *ptr;
  438. bool flag = false;
  439. list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
  440. if (ptr->is_deleted)
  441. continue;
  442. if (!ptr->is_last_name) {
  443. if (ptr->domainname != domainname)
  444. continue;
  445. } else {
  446. if (tomoyo_pathcmp(ptr->domainname, last_name))
  447. continue;
  448. }
  449. if (ptr->program && tomoyo_pathcmp(ptr->program, program))
  450. continue;
  451. if (ptr->is_not) {
  452. flag = false;
  453. break;
  454. }
  455. flag = true;
  456. }
  457. return flag;
  458. }
  459. /*
  460. * tomoyo_alias_list is used for holding list of symlink's pathnames which are
  461. * allowed to be passed to an execve() request. Normally, the domainname which
  462. * the current process will belong to after execve() succeeds is calculated
  463. * using dereferenced pathnames. But some programs behave differently depending
  464. * on the name passed to argv[0]. For busybox, calculating domainname using
  465. * dereferenced pathnames will cause all programs in the busybox to belong to
  466. * the same domain. Thus, TOMOYO provides a way to allow use of symlink's
  467. * pathname for checking execve()'s permission and calculating domainname which
  468. * the current process will belong to after execve() succeeds.
  469. *
  470. * An entry is added by
  471. *
  472. * # echo 'alias /bin/busybox /bin/cat' > \
  473. * /sys/kernel/security/tomoyo/exception_policy
  474. *
  475. * and is deleted by
  476. *
  477. * # echo 'delete alias /bin/busybox /bin/cat' > \
  478. * /sys/kernel/security/tomoyo/exception_policy
  479. *
  480. * and all entries are retrieved by
  481. *
  482. * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
  483. *
  484. * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
  485. * of /bin/cat is requested, permission is checked for /bin/cat rather than
  486. * /bin/busybox and domainname which the current process will belong to after
  487. * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
  488. */
  489. LIST_HEAD(tomoyo_alias_list);
  490. /**
  491. * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
  492. *
  493. * @original_name: The original program's real name.
  494. * @aliased_name: The symbolic program's symbolic link's name.
  495. * @is_delete: True if it is a delete request.
  496. *
  497. * Returns 0 on success, negative value otherwise.
  498. *
  499. * Caller holds tomoyo_read_lock().
  500. */
  501. static int tomoyo_update_alias_entry(const char *original_name,
  502. const char *aliased_name,
  503. const bool is_delete)
  504. {
  505. struct tomoyo_alias_entry *ptr;
  506. struct tomoyo_alias_entry e = { };
  507. int error = is_delete ? -ENOENT : -ENOMEM;
  508. if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
  509. !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
  510. return -EINVAL; /* No patterns allowed. */
  511. e.original_name = tomoyo_get_name(original_name);
  512. e.aliased_name = tomoyo_get_name(aliased_name);
  513. if (!e.original_name || !e.aliased_name)
  514. goto out;
  515. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  516. goto out;
  517. list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
  518. if (!tomoyo_is_same_alias_entry(ptr, &e))
  519. continue;
  520. ptr->is_deleted = is_delete;
  521. error = 0;
  522. break;
  523. }
  524. if (!is_delete && error) {
  525. struct tomoyo_alias_entry *entry =
  526. tomoyo_commit_ok(&e, sizeof(e));
  527. if (entry) {
  528. list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
  529. error = 0;
  530. }
  531. }
  532. mutex_unlock(&tomoyo_policy_lock);
  533. out:
  534. tomoyo_put_name(e.original_name);
  535. tomoyo_put_name(e.aliased_name);
  536. return error;
  537. }
  538. /**
  539. * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
  540. *
  541. * @head: Pointer to "struct tomoyo_io_buffer".
  542. *
  543. * Returns true on success, false otherwise.
  544. *
  545. * Caller holds tomoyo_read_lock().
  546. */
  547. bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
  548. {
  549. struct list_head *pos;
  550. bool done = true;
  551. list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
  552. struct tomoyo_alias_entry *ptr;
  553. ptr = list_entry(pos, struct tomoyo_alias_entry, list);
  554. if (ptr->is_deleted)
  555. continue;
  556. done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
  557. ptr->original_name->name,
  558. ptr->aliased_name->name);
  559. if (!done)
  560. break;
  561. }
  562. return done;
  563. }
  564. /**
  565. * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
  566. *
  567. * @data: String to parse.
  568. * @is_delete: True if it is a delete request.
  569. *
  570. * Returns 0 on success, negative value otherwise.
  571. *
  572. * Caller holds tomoyo_read_lock().
  573. */
  574. int tomoyo_write_alias_policy(char *data, const bool is_delete)
  575. {
  576. char *cp = strchr(data, ' ');
  577. if (!cp)
  578. return -EINVAL;
  579. *cp++ = '\0';
  580. return tomoyo_update_alias_entry(data, cp, is_delete);
  581. }
  582. /**
  583. * tomoyo_find_or_assign_new_domain - Create a domain.
  584. *
  585. * @domainname: The name of domain.
  586. * @profile: Profile number to assign if the domain was newly created.
  587. *
  588. * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
  589. *
  590. * Caller holds tomoyo_read_lock().
  591. */
  592. struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
  593. domainname,
  594. const u8 profile)
  595. {
  596. struct tomoyo_domain_info *entry;
  597. struct tomoyo_domain_info *domain = NULL;
  598. const struct tomoyo_path_info *saved_domainname;
  599. bool found = false;
  600. if (!tomoyo_is_correct_domain(domainname))
  601. return NULL;
  602. saved_domainname = tomoyo_get_name(domainname);
  603. if (!saved_domainname)
  604. return NULL;
  605. entry = kzalloc(sizeof(*entry), GFP_NOFS);
  606. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  607. goto out;
  608. list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
  609. if (domain->is_deleted ||
  610. tomoyo_pathcmp(saved_domainname, domain->domainname))
  611. continue;
  612. found = true;
  613. break;
  614. }
  615. if (!found && tomoyo_memory_ok(entry)) {
  616. INIT_LIST_HEAD(&entry->acl_info_list);
  617. entry->domainname = saved_domainname;
  618. saved_domainname = NULL;
  619. entry->profile = profile;
  620. list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
  621. domain = entry;
  622. entry = NULL;
  623. found = true;
  624. }
  625. mutex_unlock(&tomoyo_policy_lock);
  626. out:
  627. tomoyo_put_name(saved_domainname);
  628. kfree(entry);
  629. return found ? domain : NULL;
  630. }
  631. /**
  632. * tomoyo_find_next_domain - Find a domain.
  633. *
  634. * @bprm: Pointer to "struct linux_binprm".
  635. *
  636. * Returns 0 on success, negative value otherwise.
  637. *
  638. * Caller holds tomoyo_read_lock().
  639. */
  640. int tomoyo_find_next_domain(struct linux_binprm *bprm)
  641. {
  642. struct tomoyo_request_info r;
  643. /*
  644. * This function assumes that the size of buffer returned by
  645. * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
  646. */
  647. struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS);
  648. struct tomoyo_domain_info *old_domain = tomoyo_domain();
  649. struct tomoyo_domain_info *domain = NULL;
  650. const char *old_domain_name = old_domain->domainname->name;
  651. const char *original_name = bprm->filename;
  652. char *new_domain_name = NULL;
  653. char *real_program_name = NULL;
  654. char *symlink_program_name = NULL;
  655. const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
  656. const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
  657. int retval = -ENOMEM;
  658. struct tomoyo_path_info rn; /* real name */
  659. struct tomoyo_path_info sn; /* symlink name */
  660. struct tomoyo_path_info ln; /* last name */
  661. tomoyo_init_request_info(&r, NULL);
  662. if (!tmp)
  663. goto out;
  664. retry:
  665. /* Get tomoyo_realpath of program. */
  666. retval = -ENOENT;
  667. /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
  668. real_program_name = tomoyo_realpath(original_name);
  669. if (!real_program_name)
  670. goto out;
  671. /* Get tomoyo_realpath of symbolic link. */
  672. symlink_program_name = tomoyo_realpath_nofollow(original_name);
  673. if (!symlink_program_name)
  674. goto out;
  675. rn.name = real_program_name;
  676. tomoyo_fill_path_info(&rn);
  677. sn.name = symlink_program_name;
  678. tomoyo_fill_path_info(&sn);
  679. ln.name = tomoyo_get_last_name(old_domain);
  680. tomoyo_fill_path_info(&ln);
  681. /* Check 'alias' directive. */
  682. if (tomoyo_pathcmp(&rn, &sn)) {
  683. struct tomoyo_alias_entry *ptr;
  684. /* Is this program allowed to be called via symbolic links? */
  685. list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
  686. if (ptr->is_deleted ||
  687. tomoyo_pathcmp(&rn, ptr->original_name) ||
  688. tomoyo_pathcmp(&sn, ptr->aliased_name))
  689. continue;
  690. memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
  691. strncpy(real_program_name, ptr->aliased_name->name,
  692. TOMOYO_MAX_PATHNAME_LEN - 1);
  693. tomoyo_fill_path_info(&rn);
  694. break;
  695. }
  696. }
  697. /* Check execute permission. */
  698. retval = tomoyo_check_exec_perm(old_domain, &rn);
  699. if (retval == TOMOYO_RETRY_REQUEST)
  700. goto retry;
  701. if (retval < 0)
  702. goto out;
  703. new_domain_name = tmp->buffer;
  704. if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) {
  705. /* Transit to the child of tomoyo_kernel_domain domain. */
  706. snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
  707. TOMOYO_ROOT_NAME " " "%s", real_program_name);
  708. } else if (old_domain == &tomoyo_kernel_domain &&
  709. !tomoyo_policy_loaded) {
  710. /*
  711. * Needn't to transit from kernel domain before starting
  712. * /sbin/init. But transit from kernel domain if executing
  713. * initializers because they might start before /sbin/init.
  714. */
  715. domain = old_domain;
  716. } else if (tomoyo_is_domain_keeper(old_domain->domainname, &rn, &ln)) {
  717. /* Keep current domain. */
  718. domain = old_domain;
  719. } else {
  720. /* Normal domain transition. */
  721. snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
  722. "%s %s", old_domain_name, real_program_name);
  723. }
  724. if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
  725. goto done;
  726. domain = tomoyo_find_domain(new_domain_name);
  727. if (domain)
  728. goto done;
  729. if (is_enforce) {
  730. int error = tomoyo_supervisor(&r, "# wants to create domain\n"
  731. "%s\n", new_domain_name);
  732. if (error == TOMOYO_RETRY_REQUEST)
  733. goto retry;
  734. if (error < 0)
  735. goto done;
  736. }
  737. domain = tomoyo_find_or_assign_new_domain(new_domain_name,
  738. old_domain->profile);
  739. done:
  740. if (domain)
  741. goto out;
  742. printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
  743. new_domain_name);
  744. if (is_enforce)
  745. retval = -EPERM;
  746. else
  747. old_domain->transition_failed = true;
  748. out:
  749. if (!domain)
  750. domain = old_domain;
  751. /* Update reference count on "struct tomoyo_domain_info". */
  752. atomic_inc(&domain->users);
  753. bprm->cred->security = domain;
  754. kfree(real_program_name);
  755. kfree(symlink_program_name);
  756. kfree(tmp);
  757. return retval;
  758. }