domain.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  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. new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
  236. mutex_lock(&tomoyo_policy_lock);
  237. list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
  238. if (ptr->is_not != is_not ||
  239. ptr->domainname != saved_domainname ||
  240. ptr->program != saved_program)
  241. continue;
  242. ptr->is_deleted = is_delete;
  243. error = 0;
  244. goto out;
  245. }
  246. if (is_delete) {
  247. error = -ENOENT;
  248. goto out;
  249. }
  250. if (!tomoyo_memory_ok(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. new_entry = NULL;
  258. error = 0;
  259. out:
  260. mutex_unlock(&tomoyo_policy_lock);
  261. kfree(new_entry);
  262. return error;
  263. }
  264. /**
  265. * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
  266. *
  267. * @head: Pointer to "struct tomoyo_io_buffer".
  268. *
  269. * Returns true on success, false otherwise.
  270. *
  271. * Caller holds tomoyo_read_lock().
  272. */
  273. bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
  274. {
  275. struct list_head *pos;
  276. bool done = true;
  277. list_for_each_cookie(pos, head->read_var2,
  278. &tomoyo_domain_initializer_list) {
  279. const char *no;
  280. const char *from = "";
  281. const char *domain = "";
  282. struct tomoyo_domain_initializer_entry *ptr;
  283. ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
  284. list);
  285. if (ptr->is_deleted)
  286. continue;
  287. no = ptr->is_not ? "no_" : "";
  288. if (ptr->domainname) {
  289. from = " from ";
  290. domain = ptr->domainname->name;
  291. }
  292. done = tomoyo_io_printf(head,
  293. "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
  294. "%s%s%s\n", no, ptr->program->name,
  295. from, domain);
  296. if (!done)
  297. break;
  298. }
  299. return done;
  300. }
  301. /**
  302. * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
  303. *
  304. * @data: String to parse.
  305. * @is_not: True if it is "no_initialize_domain" entry.
  306. * @is_delete: True if it is a delete request.
  307. *
  308. * Returns 0 on success, negative value otherwise.
  309. *
  310. * Caller holds tomoyo_read_lock().
  311. */
  312. int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
  313. const bool is_delete)
  314. {
  315. char *cp = strstr(data, " from ");
  316. if (cp) {
  317. *cp = '\0';
  318. return tomoyo_update_domain_initializer_entry(cp + 6, data,
  319. is_not,
  320. is_delete);
  321. }
  322. return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
  323. is_delete);
  324. }
  325. /**
  326. * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
  327. *
  328. * @domainname: The name of domain.
  329. * @program: The name of program.
  330. * @last_name: The last component of @domainname.
  331. *
  332. * Returns true if executing @program reinitializes domain transition,
  333. * false otherwise.
  334. *
  335. * Caller holds tomoyo_read_lock().
  336. */
  337. static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
  338. domainname,
  339. const struct tomoyo_path_info *program,
  340. const struct tomoyo_path_info *
  341. last_name)
  342. {
  343. struct tomoyo_domain_initializer_entry *ptr;
  344. bool flag = false;
  345. list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
  346. if (ptr->is_deleted)
  347. continue;
  348. if (ptr->domainname) {
  349. if (!ptr->is_last_name) {
  350. if (ptr->domainname != domainname)
  351. continue;
  352. } else {
  353. if (tomoyo_pathcmp(ptr->domainname, last_name))
  354. continue;
  355. }
  356. }
  357. if (tomoyo_pathcmp(ptr->program, program))
  358. continue;
  359. if (ptr->is_not) {
  360. flag = false;
  361. break;
  362. }
  363. flag = true;
  364. }
  365. return flag;
  366. }
  367. /*
  368. * tomoyo_domain_keeper_list is used for holding list of domainnames which
  369. * suppresses domain transition. Normally, a domainname is monotonically
  370. * getting longer. But sometimes, we want to suppress domain transition.
  371. * It would be convenient for us that programs executed from a login session
  372. * belong to the same domain. Thus, TOMOYO provides a way to suppress domain
  373. * transition.
  374. *
  375. * An entry is added by
  376. *
  377. * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
  378. * /sys/kernel/security/tomoyo/exception_policy
  379. *
  380. * and is deleted by
  381. *
  382. * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
  383. * /sys/kernel/security/tomoyo/exception_policy
  384. *
  385. * and all entries are retrieved by
  386. *
  387. * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
  388. *
  389. * In the example above, any process which belongs to
  390. * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
  391. * unless explicitly specified by "initialize_domain" or "no_keep_domain".
  392. *
  393. * You may specify a program using "from" keyword.
  394. * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
  395. * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
  396. * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
  397. *
  398. * You may add "no_" prefix to "keep_domain".
  399. * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
  400. * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
  401. * cause "/usr/bin/passwd" to belong to
  402. * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
  403. * explicitly specified by "initialize_domain".
  404. */
  405. static LIST_HEAD(tomoyo_domain_keeper_list);
  406. /**
  407. * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
  408. *
  409. * @domainname: The name of domain.
  410. * @program: The name of program. May be NULL.
  411. * @is_not: True if it is "no_keep_domain" entry.
  412. * @is_delete: True if it is a delete request.
  413. *
  414. * Returns 0 on success, negative value otherwise.
  415. *
  416. * Caller holds tomoyo_read_lock().
  417. */
  418. static int tomoyo_update_domain_keeper_entry(const char *domainname,
  419. const char *program,
  420. const bool is_not,
  421. const bool is_delete)
  422. {
  423. struct tomoyo_domain_keeper_entry *new_entry;
  424. struct tomoyo_domain_keeper_entry *ptr;
  425. const struct tomoyo_path_info *saved_domainname;
  426. const struct tomoyo_path_info *saved_program = NULL;
  427. int error = -ENOMEM;
  428. bool is_last_name = false;
  429. if (!tomoyo_is_domain_def(domainname) &&
  430. tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
  431. is_last_name = true;
  432. else if (!tomoyo_is_correct_domain(domainname, __func__))
  433. return -EINVAL;
  434. if (program) {
  435. if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
  436. return -EINVAL;
  437. saved_program = tomoyo_save_name(program);
  438. if (!saved_program)
  439. return -ENOMEM;
  440. }
  441. saved_domainname = tomoyo_save_name(domainname);
  442. if (!saved_domainname)
  443. return -ENOMEM;
  444. new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
  445. mutex_lock(&tomoyo_policy_lock);
  446. list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
  447. if (ptr->is_not != is_not ||
  448. ptr->domainname != saved_domainname ||
  449. ptr->program != saved_program)
  450. continue;
  451. ptr->is_deleted = is_delete;
  452. error = 0;
  453. goto out;
  454. }
  455. if (is_delete) {
  456. error = -ENOENT;
  457. goto out;
  458. }
  459. if (!tomoyo_memory_ok(new_entry))
  460. goto out;
  461. new_entry->domainname = saved_domainname;
  462. new_entry->program = saved_program;
  463. new_entry->is_not = is_not;
  464. new_entry->is_last_name = is_last_name;
  465. list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list);
  466. new_entry = NULL;
  467. error = 0;
  468. out:
  469. mutex_unlock(&tomoyo_policy_lock);
  470. kfree(new_entry);
  471. return error;
  472. }
  473. /**
  474. * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
  475. *
  476. * @data: String to parse.
  477. * @is_not: True if it is "no_keep_domain" entry.
  478. * @is_delete: True if it is a delete request.
  479. *
  480. * Caller holds tomoyo_read_lock().
  481. */
  482. int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
  483. const bool is_delete)
  484. {
  485. char *cp = strstr(data, " from ");
  486. if (cp) {
  487. *cp = '\0';
  488. return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
  489. is_delete);
  490. }
  491. return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
  492. }
  493. /**
  494. * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
  495. *
  496. * @head: Pointer to "struct tomoyo_io_buffer".
  497. *
  498. * Returns true on success, false otherwise.
  499. *
  500. * Caller holds tomoyo_read_lock().
  501. */
  502. bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
  503. {
  504. struct list_head *pos;
  505. bool done = true;
  506. list_for_each_cookie(pos, head->read_var2,
  507. &tomoyo_domain_keeper_list) {
  508. struct tomoyo_domain_keeper_entry *ptr;
  509. const char *no;
  510. const char *from = "";
  511. const char *program = "";
  512. ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
  513. if (ptr->is_deleted)
  514. continue;
  515. no = ptr->is_not ? "no_" : "";
  516. if (ptr->program) {
  517. from = " from ";
  518. program = ptr->program->name;
  519. }
  520. done = tomoyo_io_printf(head,
  521. "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
  522. "%s%s%s\n", no, program, from,
  523. ptr->domainname->name);
  524. if (!done)
  525. break;
  526. }
  527. return done;
  528. }
  529. /**
  530. * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
  531. *
  532. * @domainname: The name of domain.
  533. * @program: The name of program.
  534. * @last_name: The last component of @domainname.
  535. *
  536. * Returns true if executing @program supresses domain transition,
  537. * false otherwise.
  538. *
  539. * Caller holds tomoyo_read_lock().
  540. */
  541. static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
  542. const struct tomoyo_path_info *program,
  543. const struct tomoyo_path_info *last_name)
  544. {
  545. struct tomoyo_domain_keeper_entry *ptr;
  546. bool flag = false;
  547. list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
  548. if (ptr->is_deleted)
  549. continue;
  550. if (!ptr->is_last_name) {
  551. if (ptr->domainname != domainname)
  552. continue;
  553. } else {
  554. if (tomoyo_pathcmp(ptr->domainname, last_name))
  555. continue;
  556. }
  557. if (ptr->program && tomoyo_pathcmp(ptr->program, program))
  558. continue;
  559. if (ptr->is_not) {
  560. flag = false;
  561. break;
  562. }
  563. flag = true;
  564. }
  565. return flag;
  566. }
  567. /*
  568. * tomoyo_alias_list is used for holding list of symlink's pathnames which are
  569. * allowed to be passed to an execve() request. Normally, the domainname which
  570. * the current process will belong to after execve() succeeds is calculated
  571. * using dereferenced pathnames. But some programs behave differently depending
  572. * on the name passed to argv[0]. For busybox, calculating domainname using
  573. * dereferenced pathnames will cause all programs in the busybox to belong to
  574. * the same domain. Thus, TOMOYO provides a way to allow use of symlink's
  575. * pathname for checking execve()'s permission and calculating domainname which
  576. * the current process will belong to after execve() succeeds.
  577. *
  578. * An entry is added by
  579. *
  580. * # echo 'alias /bin/busybox /bin/cat' > \
  581. * /sys/kernel/security/tomoyo/exception_policy
  582. *
  583. * and is deleted by
  584. *
  585. * # echo 'delete alias /bin/busybox /bin/cat' > \
  586. * /sys/kernel/security/tomoyo/exception_policy
  587. *
  588. * and all entries are retrieved by
  589. *
  590. * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
  591. *
  592. * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
  593. * of /bin/cat is requested, permission is checked for /bin/cat rather than
  594. * /bin/busybox and domainname which the current process will belong to after
  595. * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
  596. */
  597. static LIST_HEAD(tomoyo_alias_list);
  598. /**
  599. * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
  600. *
  601. * @original_name: The original program's real name.
  602. * @aliased_name: The symbolic program's symbolic link's name.
  603. * @is_delete: True if it is a delete request.
  604. *
  605. * Returns 0 on success, negative value otherwise.
  606. *
  607. * Caller holds tomoyo_read_lock().
  608. */
  609. static int tomoyo_update_alias_entry(const char *original_name,
  610. const char *aliased_name,
  611. const bool is_delete)
  612. {
  613. struct tomoyo_alias_entry *new_entry;
  614. struct tomoyo_alias_entry *ptr;
  615. const struct tomoyo_path_info *saved_original_name;
  616. const struct tomoyo_path_info *saved_aliased_name;
  617. int error = -ENOMEM;
  618. if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
  619. !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
  620. return -EINVAL; /* No patterns allowed. */
  621. saved_original_name = tomoyo_save_name(original_name);
  622. saved_aliased_name = tomoyo_save_name(aliased_name);
  623. if (!saved_original_name || !saved_aliased_name)
  624. return -ENOMEM;
  625. new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
  626. mutex_lock(&tomoyo_policy_lock);
  627. list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
  628. if (ptr->original_name != saved_original_name ||
  629. ptr->aliased_name != saved_aliased_name)
  630. continue;
  631. ptr->is_deleted = is_delete;
  632. error = 0;
  633. goto out;
  634. }
  635. if (is_delete) {
  636. error = -ENOENT;
  637. goto out;
  638. }
  639. if (!tomoyo_memory_ok(new_entry))
  640. goto out;
  641. new_entry->original_name = saved_original_name;
  642. new_entry->aliased_name = saved_aliased_name;
  643. list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list);
  644. new_entry = NULL;
  645. error = 0;
  646. out:
  647. mutex_unlock(&tomoyo_policy_lock);
  648. kfree(new_entry);
  649. return error;
  650. }
  651. /**
  652. * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
  653. *
  654. * @head: Pointer to "struct tomoyo_io_buffer".
  655. *
  656. * Returns true on success, false otherwise.
  657. *
  658. * Caller holds tomoyo_read_lock().
  659. */
  660. bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
  661. {
  662. struct list_head *pos;
  663. bool done = true;
  664. list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
  665. struct tomoyo_alias_entry *ptr;
  666. ptr = list_entry(pos, struct tomoyo_alias_entry, list);
  667. if (ptr->is_deleted)
  668. continue;
  669. done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
  670. ptr->original_name->name,
  671. ptr->aliased_name->name);
  672. if (!done)
  673. break;
  674. }
  675. return done;
  676. }
  677. /**
  678. * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
  679. *
  680. * @data: String to parse.
  681. * @is_delete: True if it is a delete request.
  682. *
  683. * Returns 0 on success, negative value otherwise.
  684. *
  685. * Caller holds tomoyo_read_lock().
  686. */
  687. int tomoyo_write_alias_policy(char *data, const bool is_delete)
  688. {
  689. char *cp = strchr(data, ' ');
  690. if (!cp)
  691. return -EINVAL;
  692. *cp++ = '\0';
  693. return tomoyo_update_alias_entry(data, cp, is_delete);
  694. }
  695. /**
  696. * tomoyo_find_or_assign_new_domain - Create a domain.
  697. *
  698. * @domainname: The name of domain.
  699. * @profile: Profile number to assign if the domain was newly created.
  700. *
  701. * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
  702. *
  703. * Caller holds tomoyo_read_lock().
  704. */
  705. struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
  706. domainname,
  707. const u8 profile)
  708. {
  709. struct tomoyo_domain_info *domain;
  710. const struct tomoyo_path_info *saved_domainname;
  711. mutex_lock(&tomoyo_policy_lock);
  712. domain = tomoyo_find_domain(domainname);
  713. if (domain)
  714. goto out;
  715. if (!tomoyo_is_correct_domain(domainname, __func__))
  716. goto out;
  717. saved_domainname = tomoyo_save_name(domainname);
  718. if (!saved_domainname)
  719. goto out;
  720. domain = kmalloc(sizeof(*domain), GFP_KERNEL);
  721. if (tomoyo_memory_ok(domain)) {
  722. INIT_LIST_HEAD(&domain->acl_info_list);
  723. domain->domainname = saved_domainname;
  724. domain->profile = profile;
  725. list_add_tail_rcu(&domain->list, &tomoyo_domain_list);
  726. } else {
  727. kfree(domain);
  728. domain = NULL;
  729. }
  730. out:
  731. mutex_unlock(&tomoyo_policy_lock);
  732. return domain;
  733. }
  734. /**
  735. * tomoyo_find_next_domain - Find a domain.
  736. *
  737. * @bprm: Pointer to "struct linux_binprm".
  738. *
  739. * Returns 0 on success, negative value otherwise.
  740. *
  741. * Caller holds tomoyo_read_lock().
  742. */
  743. int tomoyo_find_next_domain(struct linux_binprm *bprm)
  744. {
  745. /*
  746. * This function assumes that the size of buffer returned by
  747. * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
  748. */
  749. struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
  750. struct tomoyo_domain_info *old_domain = tomoyo_domain();
  751. struct tomoyo_domain_info *domain = NULL;
  752. const char *old_domain_name = old_domain->domainname->name;
  753. const char *original_name = bprm->filename;
  754. char *new_domain_name = NULL;
  755. char *real_program_name = NULL;
  756. char *symlink_program_name = NULL;
  757. const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
  758. const bool is_enforce = (mode == 3);
  759. int retval = -ENOMEM;
  760. struct tomoyo_path_info r; /* real name */
  761. struct tomoyo_path_info s; /* symlink name */
  762. struct tomoyo_path_info l; /* last name */
  763. static bool initialized;
  764. if (!tmp)
  765. goto out;
  766. if (!initialized) {
  767. /*
  768. * Built-in initializers. This is needed because policies are
  769. * not loaded until starting /sbin/init.
  770. */
  771. tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
  772. false, false);
  773. tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
  774. false, false);
  775. initialized = true;
  776. }
  777. /* Get tomoyo_realpath of program. */
  778. retval = -ENOENT;
  779. /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
  780. real_program_name = tomoyo_realpath(original_name);
  781. if (!real_program_name)
  782. goto out;
  783. /* Get tomoyo_realpath of symbolic link. */
  784. symlink_program_name = tomoyo_realpath_nofollow(original_name);
  785. if (!symlink_program_name)
  786. goto out;
  787. r.name = real_program_name;
  788. tomoyo_fill_path_info(&r);
  789. s.name = symlink_program_name;
  790. tomoyo_fill_path_info(&s);
  791. l.name = tomoyo_get_last_name(old_domain);
  792. tomoyo_fill_path_info(&l);
  793. /* Check 'alias' directive. */
  794. if (tomoyo_pathcmp(&r, &s)) {
  795. struct tomoyo_alias_entry *ptr;
  796. /* Is this program allowed to be called via symbolic links? */
  797. list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
  798. if (ptr->is_deleted ||
  799. tomoyo_pathcmp(&r, ptr->original_name) ||
  800. tomoyo_pathcmp(&s, ptr->aliased_name))
  801. continue;
  802. memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
  803. strncpy(real_program_name, ptr->aliased_name->name,
  804. TOMOYO_MAX_PATHNAME_LEN - 1);
  805. tomoyo_fill_path_info(&r);
  806. break;
  807. }
  808. }
  809. /* Check execute permission. */
  810. retval = tomoyo_check_exec_perm(old_domain, &r);
  811. if (retval < 0)
  812. goto out;
  813. new_domain_name = tmp->buffer;
  814. if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
  815. /* Transit to the child of tomoyo_kernel_domain domain. */
  816. snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
  817. TOMOYO_ROOT_NAME " " "%s", real_program_name);
  818. } else if (old_domain == &tomoyo_kernel_domain &&
  819. !tomoyo_policy_loaded) {
  820. /*
  821. * Needn't to transit from kernel domain before starting
  822. * /sbin/init. But transit from kernel domain if executing
  823. * initializers because they might start before /sbin/init.
  824. */
  825. domain = old_domain;
  826. } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
  827. /* Keep current domain. */
  828. domain = old_domain;
  829. } else {
  830. /* Normal domain transition. */
  831. snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
  832. "%s %s", old_domain_name, real_program_name);
  833. }
  834. if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
  835. goto done;
  836. domain = tomoyo_find_domain(new_domain_name);
  837. if (domain)
  838. goto done;
  839. if (is_enforce)
  840. goto done;
  841. domain = tomoyo_find_or_assign_new_domain(new_domain_name,
  842. old_domain->profile);
  843. done:
  844. if (domain)
  845. goto out;
  846. printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
  847. new_domain_name);
  848. if (is_enforce)
  849. retval = -EPERM;
  850. else
  851. tomoyo_set_domain_flag(old_domain, false,
  852. TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
  853. out:
  854. if (!domain)
  855. domain = old_domain;
  856. bprm->cred->security = domain;
  857. tomoyo_free(real_program_name);
  858. tomoyo_free(symlink_program_name);
  859. tomoyo_free(tmp);
  860. return retval;
  861. }