domain.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  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))
  126. return -EINVAL;
  127. if (domainname) {
  128. if (!tomoyo_is_domain_def(domainname) &&
  129. tomoyo_is_correct_path(domainname))
  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))
  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))
  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_aggregator_list is used for holding list of rewrite table for
  461. * execve() request. Some programs provides similar functionality. This keyword
  462. * allows users to aggregate such programs.
  463. *
  464. * Entries are added by
  465. *
  466. * # echo 'aggregator /usr/bin/vi /./editor' > \
  467. * /sys/kernel/security/tomoyo/exception_policy
  468. * # echo 'aggregator /usr/bin/emacs /./editor' > \
  469. * /sys/kernel/security/tomoyo/exception_policy
  470. *
  471. * and are deleted by
  472. *
  473. * # echo 'delete aggregator /usr/bin/vi /./editor' > \
  474. * /sys/kernel/security/tomoyo/exception_policy
  475. * # echo 'delete aggregator /usr/bin/emacs /./editor' > \
  476. * /sys/kernel/security/tomoyo/exception_policy
  477. *
  478. * and all entries are retrieved by
  479. *
  480. * # grep ^aggregator /sys/kernel/security/tomoyo/exception_policy
  481. *
  482. * In the example above, if /usr/bin/vi or /usr/bin/emacs are executed,
  483. * permission is checked for /./editor and domainname which the current process
  484. * will belong to after execve() succeeds is calculated using /./editor .
  485. */
  486. LIST_HEAD(tomoyo_aggregator_list);
  487. /**
  488. * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list.
  489. *
  490. * @original_name: The original program's name.
  491. * @aggregated_name: The program name to use.
  492. * @is_delete: True if it is a delete request.
  493. *
  494. * Returns 0 on success, negative value otherwise.
  495. *
  496. * Caller holds tomoyo_read_lock().
  497. */
  498. static int tomoyo_update_aggregator_entry(const char *original_name,
  499. const char *aggregated_name,
  500. const bool is_delete)
  501. {
  502. struct tomoyo_aggregator_entry *ptr;
  503. struct tomoyo_aggregator_entry e = { };
  504. int error = is_delete ? -ENOENT : -ENOMEM;
  505. if (!tomoyo_is_correct_path(original_name) ||
  506. !tomoyo_is_correct_path(aggregated_name))
  507. return -EINVAL;
  508. e.original_name = tomoyo_get_name(original_name);
  509. e.aggregated_name = tomoyo_get_name(aggregated_name);
  510. if (!e.original_name || !e.aggregated_name ||
  511. e.aggregated_name->is_patterned) /* No patterns allowed. */
  512. goto out;
  513. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  514. goto out;
  515. list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, list) {
  516. if (!tomoyo_is_same_aggregator_entry(ptr, &e))
  517. continue;
  518. ptr->is_deleted = is_delete;
  519. error = 0;
  520. break;
  521. }
  522. if (!is_delete && error) {
  523. struct tomoyo_aggregator_entry *entry =
  524. tomoyo_commit_ok(&e, sizeof(e));
  525. if (entry) {
  526. list_add_tail_rcu(&entry->list,
  527. &tomoyo_aggregator_list);
  528. error = 0;
  529. }
  530. }
  531. mutex_unlock(&tomoyo_policy_lock);
  532. out:
  533. tomoyo_put_name(e.original_name);
  534. tomoyo_put_name(e.aggregated_name);
  535. return error;
  536. }
  537. /**
  538. * tomoyo_read_aggregator_policy - Read "struct tomoyo_aggregator_entry" list.
  539. *
  540. * @head: Pointer to "struct tomoyo_io_buffer".
  541. *
  542. * Returns true on success, false otherwise.
  543. *
  544. * Caller holds tomoyo_read_lock().
  545. */
  546. bool tomoyo_read_aggregator_policy(struct tomoyo_io_buffer *head)
  547. {
  548. struct list_head *pos;
  549. bool done = true;
  550. list_for_each_cookie(pos, head->read_var2, &tomoyo_aggregator_list) {
  551. struct tomoyo_aggregator_entry *ptr;
  552. ptr = list_entry(pos, struct tomoyo_aggregator_entry, list);
  553. if (ptr->is_deleted)
  554. continue;
  555. done = tomoyo_io_printf(head, TOMOYO_KEYWORD_AGGREGATOR
  556. "%s %s\n", ptr->original_name->name,
  557. ptr->aggregated_name->name);
  558. if (!done)
  559. break;
  560. }
  561. return done;
  562. }
  563. /**
  564. * tomoyo_write_aggregator_policy - Write "struct tomoyo_aggregator_entry" list.
  565. *
  566. * @data: String to parse.
  567. * @is_delete: True if it is a delete request.
  568. *
  569. * Returns 0 on success, negative value otherwise.
  570. *
  571. * Caller holds tomoyo_read_lock().
  572. */
  573. int tomoyo_write_aggregator_policy(char *data, const bool is_delete)
  574. {
  575. char *cp = strchr(data, ' ');
  576. if (!cp)
  577. return -EINVAL;
  578. *cp++ = '\0';
  579. return tomoyo_update_aggregator_entry(data, cp, is_delete);
  580. }
  581. /*
  582. * tomoyo_alias_list is used for holding list of symlink's pathnames which are
  583. * allowed to be passed to an execve() request. Normally, the domainname which
  584. * the current process will belong to after execve() succeeds is calculated
  585. * using dereferenced pathnames. But some programs behave differently depending
  586. * on the name passed to argv[0]. For busybox, calculating domainname using
  587. * dereferenced pathnames will cause all programs in the busybox to belong to
  588. * the same domain. Thus, TOMOYO provides a way to allow use of symlink's
  589. * pathname for checking execve()'s permission and calculating domainname which
  590. * the current process will belong to after execve() succeeds.
  591. *
  592. * An entry is added by
  593. *
  594. * # echo 'alias /bin/busybox /bin/cat' > \
  595. * /sys/kernel/security/tomoyo/exception_policy
  596. *
  597. * and is deleted by
  598. *
  599. * # echo 'delete alias /bin/busybox /bin/cat' > \
  600. * /sys/kernel/security/tomoyo/exception_policy
  601. *
  602. * and all entries are retrieved by
  603. *
  604. * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
  605. *
  606. * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
  607. * of /bin/cat is requested, permission is checked for /bin/cat rather than
  608. * /bin/busybox and domainname which the current process will belong to after
  609. * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
  610. */
  611. LIST_HEAD(tomoyo_alias_list);
  612. /**
  613. * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
  614. *
  615. * @original_name: The original program's real name.
  616. * @aliased_name: The symbolic program's symbolic link's name.
  617. * @is_delete: True if it is a delete request.
  618. *
  619. * Returns 0 on success, negative value otherwise.
  620. *
  621. * Caller holds tomoyo_read_lock().
  622. */
  623. static int tomoyo_update_alias_entry(const char *original_name,
  624. const char *aliased_name,
  625. const bool is_delete)
  626. {
  627. struct tomoyo_alias_entry *ptr;
  628. struct tomoyo_alias_entry e = { };
  629. int error = is_delete ? -ENOENT : -ENOMEM;
  630. if (!tomoyo_is_correct_path(original_name) ||
  631. !tomoyo_is_correct_path(aliased_name))
  632. return -EINVAL;
  633. e.original_name = tomoyo_get_name(original_name);
  634. e.aliased_name = tomoyo_get_name(aliased_name);
  635. if (!e.original_name || !e.aliased_name ||
  636. e.original_name->is_patterned || e.aliased_name->is_patterned)
  637. goto out; /* No patterns allowed. */
  638. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  639. goto out;
  640. list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
  641. if (!tomoyo_is_same_alias_entry(ptr, &e))
  642. continue;
  643. ptr->is_deleted = is_delete;
  644. error = 0;
  645. break;
  646. }
  647. if (!is_delete && error) {
  648. struct tomoyo_alias_entry *entry =
  649. tomoyo_commit_ok(&e, sizeof(e));
  650. if (entry) {
  651. list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
  652. error = 0;
  653. }
  654. }
  655. mutex_unlock(&tomoyo_policy_lock);
  656. out:
  657. tomoyo_put_name(e.original_name);
  658. tomoyo_put_name(e.aliased_name);
  659. return error;
  660. }
  661. /**
  662. * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
  663. *
  664. * @head: Pointer to "struct tomoyo_io_buffer".
  665. *
  666. * Returns true on success, false otherwise.
  667. *
  668. * Caller holds tomoyo_read_lock().
  669. */
  670. bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
  671. {
  672. struct list_head *pos;
  673. bool done = true;
  674. list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
  675. struct tomoyo_alias_entry *ptr;
  676. ptr = list_entry(pos, struct tomoyo_alias_entry, list);
  677. if (ptr->is_deleted)
  678. continue;
  679. done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
  680. ptr->original_name->name,
  681. ptr->aliased_name->name);
  682. if (!done)
  683. break;
  684. }
  685. return done;
  686. }
  687. /**
  688. * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
  689. *
  690. * @data: String to parse.
  691. * @is_delete: True if it is a delete request.
  692. *
  693. * Returns 0 on success, negative value otherwise.
  694. *
  695. * Caller holds tomoyo_read_lock().
  696. */
  697. int tomoyo_write_alias_policy(char *data, const bool is_delete)
  698. {
  699. char *cp = strchr(data, ' ');
  700. if (!cp)
  701. return -EINVAL;
  702. *cp++ = '\0';
  703. return tomoyo_update_alias_entry(data, cp, is_delete);
  704. }
  705. /**
  706. * tomoyo_find_or_assign_new_domain - Create a domain.
  707. *
  708. * @domainname: The name of domain.
  709. * @profile: Profile number to assign if the domain was newly created.
  710. *
  711. * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
  712. *
  713. * Caller holds tomoyo_read_lock().
  714. */
  715. struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
  716. domainname,
  717. const u8 profile)
  718. {
  719. struct tomoyo_domain_info *entry;
  720. struct tomoyo_domain_info *domain = NULL;
  721. const struct tomoyo_path_info *saved_domainname;
  722. bool found = false;
  723. if (!tomoyo_is_correct_domain(domainname))
  724. return NULL;
  725. saved_domainname = tomoyo_get_name(domainname);
  726. if (!saved_domainname)
  727. return NULL;
  728. entry = kzalloc(sizeof(*entry), GFP_NOFS);
  729. if (mutex_lock_interruptible(&tomoyo_policy_lock))
  730. goto out;
  731. list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
  732. if (domain->is_deleted ||
  733. tomoyo_pathcmp(saved_domainname, domain->domainname))
  734. continue;
  735. found = true;
  736. break;
  737. }
  738. if (!found && tomoyo_memory_ok(entry)) {
  739. INIT_LIST_HEAD(&entry->acl_info_list);
  740. entry->domainname = saved_domainname;
  741. saved_domainname = NULL;
  742. entry->profile = profile;
  743. list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
  744. domain = entry;
  745. entry = NULL;
  746. found = true;
  747. }
  748. mutex_unlock(&tomoyo_policy_lock);
  749. out:
  750. tomoyo_put_name(saved_domainname);
  751. kfree(entry);
  752. return found ? domain : NULL;
  753. }
  754. /**
  755. * tomoyo_find_next_domain - Find a domain.
  756. *
  757. * @bprm: Pointer to "struct linux_binprm".
  758. *
  759. * Returns 0 on success, negative value otherwise.
  760. *
  761. * Caller holds tomoyo_read_lock().
  762. */
  763. int tomoyo_find_next_domain(struct linux_binprm *bprm)
  764. {
  765. struct tomoyo_request_info r;
  766. char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
  767. struct tomoyo_domain_info *old_domain = tomoyo_domain();
  768. struct tomoyo_domain_info *domain = NULL;
  769. const char *old_domain_name = old_domain->domainname->name;
  770. const char *original_name = bprm->filename;
  771. const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
  772. const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
  773. int retval = -ENOMEM;
  774. bool need_kfree = false;
  775. struct tomoyo_path_info rn = { }; /* real name */
  776. struct tomoyo_path_info sn = { }; /* symlink name */
  777. struct tomoyo_path_info ln; /* last name */
  778. ln.name = tomoyo_get_last_name(old_domain);
  779. tomoyo_fill_path_info(&ln);
  780. tomoyo_init_request_info(&r, NULL);
  781. if (!tmp)
  782. goto out;
  783. retry:
  784. if (need_kfree) {
  785. kfree(rn.name);
  786. need_kfree = false;
  787. }
  788. /* Get tomoyo_realpath of program. */
  789. retval = -ENOENT;
  790. rn.name = tomoyo_realpath(original_name);
  791. if (!rn.name)
  792. goto out;
  793. tomoyo_fill_path_info(&rn);
  794. need_kfree = true;
  795. /* Get tomoyo_realpath of symbolic link. */
  796. sn.name = tomoyo_realpath_nofollow(original_name);
  797. if (!sn.name)
  798. goto out;
  799. tomoyo_fill_path_info(&sn);
  800. /* Check 'alias' directive. */
  801. if (tomoyo_pathcmp(&rn, &sn)) {
  802. struct tomoyo_alias_entry *ptr;
  803. /* Is this program allowed to be called via symbolic links? */
  804. list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
  805. if (ptr->is_deleted ||
  806. tomoyo_pathcmp(&rn, ptr->original_name) ||
  807. tomoyo_pathcmp(&sn, ptr->aliased_name))
  808. continue;
  809. kfree(rn.name);
  810. need_kfree = false;
  811. /* This is OK because it is read only. */
  812. rn = *ptr->aliased_name;
  813. break;
  814. }
  815. }
  816. /* Check 'aggregator' directive. */
  817. {
  818. struct tomoyo_aggregator_entry *ptr;
  819. list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, list) {
  820. if (ptr->is_deleted ||
  821. !tomoyo_path_matches_pattern(&rn,
  822. ptr->original_name))
  823. continue;
  824. if (need_kfree)
  825. kfree(rn.name);
  826. need_kfree = false;
  827. /* This is OK because it is read only. */
  828. rn = *ptr->aggregated_name;
  829. break;
  830. }
  831. }
  832. /* Check execute permission. */
  833. retval = tomoyo_check_exec_perm(old_domain, &rn);
  834. if (retval == TOMOYO_RETRY_REQUEST)
  835. goto retry;
  836. if (retval < 0)
  837. goto out;
  838. if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) {
  839. /* Transit to the child of tomoyo_kernel_domain domain. */
  840. snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
  841. TOMOYO_ROOT_NAME " " "%s", rn.name);
  842. } else if (old_domain == &tomoyo_kernel_domain &&
  843. !tomoyo_policy_loaded) {
  844. /*
  845. * Needn't to transit from kernel domain before starting
  846. * /sbin/init. But transit from kernel domain if executing
  847. * initializers because they might start before /sbin/init.
  848. */
  849. domain = old_domain;
  850. } else if (tomoyo_is_domain_keeper(old_domain->domainname, &rn, &ln)) {
  851. /* Keep current domain. */
  852. domain = old_domain;
  853. } else {
  854. /* Normal domain transition. */
  855. snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
  856. "%s %s", old_domain_name, rn.name);
  857. }
  858. if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
  859. goto done;
  860. domain = tomoyo_find_domain(tmp);
  861. if (domain)
  862. goto done;
  863. if (is_enforce) {
  864. int error = tomoyo_supervisor(&r, "# wants to create domain\n"
  865. "%s\n", tmp);
  866. if (error == TOMOYO_RETRY_REQUEST)
  867. goto retry;
  868. if (error < 0)
  869. goto done;
  870. }
  871. domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile);
  872. done:
  873. if (domain)
  874. goto out;
  875. printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
  876. if (is_enforce)
  877. retval = -EPERM;
  878. else
  879. old_domain->transition_failed = true;
  880. out:
  881. if (!domain)
  882. domain = old_domain;
  883. /* Update reference count on "struct tomoyo_domain_info". */
  884. atomic_inc(&domain->users);
  885. bprm->cred->security = domain;
  886. if (need_kfree)
  887. kfree(rn.name);
  888. kfree(sn.name);
  889. kfree(tmp);
  890. return retval;
  891. }