domain.c 27 KB

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