domain.c 28 KB

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