domain.c 28 KB

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