domain.c 28 KB

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