domain.c 24 KB

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