file.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228
  1. /*
  2. * security/tomoyo/file.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. #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
  15. /* Structure for "allow_read" keyword. */
  16. struct tomoyo_globally_readable_file_entry {
  17. struct list_head list;
  18. const struct tomoyo_path_info *filename;
  19. bool is_deleted;
  20. };
  21. /* Structure for "file_pattern" keyword. */
  22. struct tomoyo_pattern_entry {
  23. struct list_head list;
  24. const struct tomoyo_path_info *pattern;
  25. bool is_deleted;
  26. };
  27. /* Structure for "deny_rewrite" keyword. */
  28. struct tomoyo_no_rewrite_entry {
  29. struct list_head list;
  30. const struct tomoyo_path_info *pattern;
  31. bool is_deleted;
  32. };
  33. /* Keyword array for single path operations. */
  34. static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
  35. [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
  36. [TOMOYO_TYPE_EXECUTE_ACL] = "execute",
  37. [TOMOYO_TYPE_READ_ACL] = "read",
  38. [TOMOYO_TYPE_WRITE_ACL] = "write",
  39. [TOMOYO_TYPE_CREATE_ACL] = "create",
  40. [TOMOYO_TYPE_UNLINK_ACL] = "unlink",
  41. [TOMOYO_TYPE_MKDIR_ACL] = "mkdir",
  42. [TOMOYO_TYPE_RMDIR_ACL] = "rmdir",
  43. [TOMOYO_TYPE_MKFIFO_ACL] = "mkfifo",
  44. [TOMOYO_TYPE_MKSOCK_ACL] = "mksock",
  45. [TOMOYO_TYPE_MKBLOCK_ACL] = "mkblock",
  46. [TOMOYO_TYPE_MKCHAR_ACL] = "mkchar",
  47. [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate",
  48. [TOMOYO_TYPE_SYMLINK_ACL] = "symlink",
  49. [TOMOYO_TYPE_REWRITE_ACL] = "rewrite",
  50. };
  51. /* Keyword array for double path operations. */
  52. static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
  53. [TOMOYO_TYPE_LINK_ACL] = "link",
  54. [TOMOYO_TYPE_RENAME_ACL] = "rename",
  55. };
  56. /**
  57. * tomoyo_sp2keyword - Get the name of single path operation.
  58. *
  59. * @operation: Type of operation.
  60. *
  61. * Returns the name of single path operation.
  62. */
  63. const char *tomoyo_sp2keyword(const u8 operation)
  64. {
  65. return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
  66. ? tomoyo_sp_keyword[operation] : NULL;
  67. }
  68. /**
  69. * tomoyo_dp2keyword - Get the name of double path operation.
  70. *
  71. * @operation: Type of operation.
  72. *
  73. * Returns the name of double path operation.
  74. */
  75. const char *tomoyo_dp2keyword(const u8 operation)
  76. {
  77. return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
  78. ? tomoyo_dp_keyword[operation] : NULL;
  79. }
  80. /**
  81. * tomoyo_strendswith - Check whether the token ends with the given token.
  82. *
  83. * @name: The token to check.
  84. * @tail: The token to find.
  85. *
  86. * Returns true if @name ends with @tail, false otherwise.
  87. */
  88. static bool tomoyo_strendswith(const char *name, const char *tail)
  89. {
  90. int len;
  91. if (!name || !tail)
  92. return false;
  93. len = strlen(name) - strlen(tail);
  94. return len >= 0 && !strcmp(name + len, tail);
  95. }
  96. /**
  97. * tomoyo_get_path - Get realpath.
  98. *
  99. * @path: Pointer to "struct path".
  100. *
  101. * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
  102. */
  103. static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
  104. {
  105. int error;
  106. struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
  107. if (!buf)
  108. return NULL;
  109. /* Reserve one byte for appending "/". */
  110. error = tomoyo_realpath_from_path2(path, buf->body,
  111. sizeof(buf->body) - 2);
  112. if (!error) {
  113. buf->head.name = buf->body;
  114. tomoyo_fill_path_info(&buf->head);
  115. return &buf->head;
  116. }
  117. tomoyo_free(buf);
  118. return NULL;
  119. }
  120. /* Lock for domain->acl_info_list. */
  121. DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
  122. static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
  123. const char *filename2,
  124. struct tomoyo_domain_info *
  125. const domain, const bool is_delete);
  126. static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
  127. struct tomoyo_domain_info *
  128. const domain, const bool is_delete);
  129. /* The list for "struct tomoyo_globally_readable_file_entry". */
  130. static LIST_HEAD(tomoyo_globally_readable_list);
  131. static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
  132. /**
  133. * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
  134. *
  135. * @filename: Filename unconditionally permitted to open() for reading.
  136. * @is_delete: True if it is a delete request.
  137. *
  138. * Returns 0 on success, negative value otherwise.
  139. */
  140. static int tomoyo_update_globally_readable_entry(const char *filename,
  141. const bool is_delete)
  142. {
  143. struct tomoyo_globally_readable_file_entry *new_entry;
  144. struct tomoyo_globally_readable_file_entry *ptr;
  145. const struct tomoyo_path_info *saved_filename;
  146. int error = -ENOMEM;
  147. if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
  148. return -EINVAL;
  149. saved_filename = tomoyo_save_name(filename);
  150. if (!saved_filename)
  151. return -ENOMEM;
  152. down_write(&tomoyo_globally_readable_list_lock);
  153. list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
  154. if (ptr->filename != saved_filename)
  155. continue;
  156. ptr->is_deleted = is_delete;
  157. error = 0;
  158. goto out;
  159. }
  160. if (is_delete) {
  161. error = -ENOENT;
  162. goto out;
  163. }
  164. new_entry = tomoyo_alloc_element(sizeof(*new_entry));
  165. if (!new_entry)
  166. goto out;
  167. new_entry->filename = saved_filename;
  168. list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
  169. error = 0;
  170. out:
  171. up_write(&tomoyo_globally_readable_list_lock);
  172. return error;
  173. }
  174. /**
  175. * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
  176. *
  177. * @filename: The filename to check.
  178. *
  179. * Returns true if any domain can open @filename for reading, false otherwise.
  180. */
  181. static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
  182. filename)
  183. {
  184. struct tomoyo_globally_readable_file_entry *ptr;
  185. bool found = false;
  186. down_read(&tomoyo_globally_readable_list_lock);
  187. list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
  188. if (!ptr->is_deleted &&
  189. tomoyo_path_matches_pattern(filename, ptr->filename)) {
  190. found = true;
  191. break;
  192. }
  193. }
  194. up_read(&tomoyo_globally_readable_list_lock);
  195. return found;
  196. }
  197. /**
  198. * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list.
  199. *
  200. * @data: String to parse.
  201. * @is_delete: True if it is a delete request.
  202. *
  203. * Returns 0 on success, negative value otherwise.
  204. */
  205. int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
  206. {
  207. return tomoyo_update_globally_readable_entry(data, is_delete);
  208. }
  209. /**
  210. * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list.
  211. *
  212. * @head: Pointer to "struct tomoyo_io_buffer".
  213. *
  214. * Returns true on success, false otherwise.
  215. */
  216. bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
  217. {
  218. struct list_head *pos;
  219. bool done = true;
  220. down_read(&tomoyo_globally_readable_list_lock);
  221. list_for_each_cookie(pos, head->read_var2,
  222. &tomoyo_globally_readable_list) {
  223. struct tomoyo_globally_readable_file_entry *ptr;
  224. ptr = list_entry(pos,
  225. struct tomoyo_globally_readable_file_entry,
  226. list);
  227. if (ptr->is_deleted)
  228. continue;
  229. done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
  230. ptr->filename->name);
  231. if (!done)
  232. break;
  233. }
  234. up_read(&tomoyo_globally_readable_list_lock);
  235. return done;
  236. }
  237. /* The list for "struct tomoyo_pattern_entry". */
  238. static LIST_HEAD(tomoyo_pattern_list);
  239. static DECLARE_RWSEM(tomoyo_pattern_list_lock);
  240. /**
  241. * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
  242. *
  243. * @pattern: Pathname pattern.
  244. * @is_delete: True if it is a delete request.
  245. *
  246. * Returns 0 on success, negative value otherwise.
  247. */
  248. static int tomoyo_update_file_pattern_entry(const char *pattern,
  249. const bool is_delete)
  250. {
  251. struct tomoyo_pattern_entry *new_entry;
  252. struct tomoyo_pattern_entry *ptr;
  253. const struct tomoyo_path_info *saved_pattern;
  254. int error = -ENOMEM;
  255. if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
  256. return -EINVAL;
  257. saved_pattern = tomoyo_save_name(pattern);
  258. if (!saved_pattern)
  259. return -ENOMEM;
  260. down_write(&tomoyo_pattern_list_lock);
  261. list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
  262. if (saved_pattern != ptr->pattern)
  263. continue;
  264. ptr->is_deleted = is_delete;
  265. error = 0;
  266. goto out;
  267. }
  268. if (is_delete) {
  269. error = -ENOENT;
  270. goto out;
  271. }
  272. new_entry = tomoyo_alloc_element(sizeof(*new_entry));
  273. if (!new_entry)
  274. goto out;
  275. new_entry->pattern = saved_pattern;
  276. list_add_tail(&new_entry->list, &tomoyo_pattern_list);
  277. error = 0;
  278. out:
  279. up_write(&tomoyo_pattern_list_lock);
  280. return error;
  281. }
  282. /**
  283. * tomoyo_get_file_pattern - Get patterned pathname.
  284. *
  285. * @filename: The filename to find patterned pathname.
  286. *
  287. * Returns pointer to pathname pattern if matched, @filename otherwise.
  288. */
  289. static const struct tomoyo_path_info *
  290. tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
  291. {
  292. struct tomoyo_pattern_entry *ptr;
  293. const struct tomoyo_path_info *pattern = NULL;
  294. down_read(&tomoyo_pattern_list_lock);
  295. list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
  296. if (ptr->is_deleted)
  297. continue;
  298. if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
  299. continue;
  300. pattern = ptr->pattern;
  301. if (tomoyo_strendswith(pattern->name, "/\\*")) {
  302. /* Do nothing. Try to find the better match. */
  303. } else {
  304. /* This would be the better match. Use this. */
  305. break;
  306. }
  307. }
  308. up_read(&tomoyo_pattern_list_lock);
  309. if (pattern)
  310. filename = pattern;
  311. return filename;
  312. }
  313. /**
  314. * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
  315. *
  316. * @data: String to parse.
  317. * @is_delete: True if it is a delete request.
  318. *
  319. * Returns 0 on success, negative value otherwise.
  320. */
  321. int tomoyo_write_pattern_policy(char *data, const bool is_delete)
  322. {
  323. return tomoyo_update_file_pattern_entry(data, is_delete);
  324. }
  325. /**
  326. * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list.
  327. *
  328. * @head: Pointer to "struct tomoyo_io_buffer".
  329. *
  330. * Returns true on success, false otherwise.
  331. */
  332. bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
  333. {
  334. struct list_head *pos;
  335. bool done = true;
  336. down_read(&tomoyo_pattern_list_lock);
  337. list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
  338. struct tomoyo_pattern_entry *ptr;
  339. ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
  340. if (ptr->is_deleted)
  341. continue;
  342. done = tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN
  343. "%s\n", ptr->pattern->name);
  344. if (!done)
  345. break;
  346. }
  347. up_read(&tomoyo_pattern_list_lock);
  348. return done;
  349. }
  350. /* The list for "struct tomoyo_no_rewrite_entry". */
  351. static LIST_HEAD(tomoyo_no_rewrite_list);
  352. static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
  353. /**
  354. * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
  355. *
  356. * @pattern: Pathname pattern that are not rewritable by default.
  357. * @is_delete: True if it is a delete request.
  358. *
  359. * Returns 0 on success, negative value otherwise.
  360. */
  361. static int tomoyo_update_no_rewrite_entry(const char *pattern,
  362. const bool is_delete)
  363. {
  364. struct tomoyo_no_rewrite_entry *new_entry, *ptr;
  365. const struct tomoyo_path_info *saved_pattern;
  366. int error = -ENOMEM;
  367. if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
  368. return -EINVAL;
  369. saved_pattern = tomoyo_save_name(pattern);
  370. if (!saved_pattern)
  371. return -ENOMEM;
  372. down_write(&tomoyo_no_rewrite_list_lock);
  373. list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
  374. if (ptr->pattern != saved_pattern)
  375. continue;
  376. ptr->is_deleted = is_delete;
  377. error = 0;
  378. goto out;
  379. }
  380. if (is_delete) {
  381. error = -ENOENT;
  382. goto out;
  383. }
  384. new_entry = tomoyo_alloc_element(sizeof(*new_entry));
  385. if (!new_entry)
  386. goto out;
  387. new_entry->pattern = saved_pattern;
  388. list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
  389. error = 0;
  390. out:
  391. up_write(&tomoyo_no_rewrite_list_lock);
  392. return error;
  393. }
  394. /**
  395. * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
  396. *
  397. * @filename: Filename to check.
  398. *
  399. * Returns true if @filename is specified by "deny_rewrite" directive,
  400. * false otherwise.
  401. */
  402. static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
  403. {
  404. struct tomoyo_no_rewrite_entry *ptr;
  405. bool found = false;
  406. down_read(&tomoyo_no_rewrite_list_lock);
  407. list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
  408. if (ptr->is_deleted)
  409. continue;
  410. if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
  411. continue;
  412. found = true;
  413. break;
  414. }
  415. up_read(&tomoyo_no_rewrite_list_lock);
  416. return found;
  417. }
  418. /**
  419. * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
  420. *
  421. * @data: String to parse.
  422. * @is_delete: True if it is a delete request.
  423. *
  424. * Returns 0 on success, negative value otherwise.
  425. */
  426. int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
  427. {
  428. return tomoyo_update_no_rewrite_entry(data, is_delete);
  429. }
  430. /**
  431. * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list.
  432. *
  433. * @head: Pointer to "struct tomoyo_io_buffer".
  434. *
  435. * Returns true on success, false otherwise.
  436. */
  437. bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
  438. {
  439. struct list_head *pos;
  440. bool done = true;
  441. down_read(&tomoyo_no_rewrite_list_lock);
  442. list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
  443. struct tomoyo_no_rewrite_entry *ptr;
  444. ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
  445. if (ptr->is_deleted)
  446. continue;
  447. done = tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE
  448. "%s\n", ptr->pattern->name);
  449. if (!done)
  450. break;
  451. }
  452. up_read(&tomoyo_no_rewrite_list_lock);
  453. return done;
  454. }
  455. /**
  456. * tomoyo_update_file_acl - Update file's read/write/execute ACL.
  457. *
  458. * @filename: Filename.
  459. * @perm: Permission (between 1 to 7).
  460. * @domain: Pointer to "struct tomoyo_domain_info".
  461. * @is_delete: True if it is a delete request.
  462. *
  463. * Returns 0 on success, negative value otherwise.
  464. *
  465. * This is legacy support interface for older policy syntax.
  466. * Current policy syntax uses "allow_read/write" instead of "6",
  467. * "allow_read" instead of "4", "allow_write" instead of "2",
  468. * "allow_execute" instead of "1".
  469. */
  470. static int tomoyo_update_file_acl(const char *filename, u8 perm,
  471. struct tomoyo_domain_info * const domain,
  472. const bool is_delete)
  473. {
  474. if (perm > 7 || !perm) {
  475. printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
  476. __func__, perm, filename);
  477. return -EINVAL;
  478. }
  479. if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
  480. /*
  481. * Only 'allow_mkdir' and 'allow_rmdir' are valid for
  482. * directory permissions.
  483. */
  484. return 0;
  485. if (perm & 4)
  486. tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
  487. domain, is_delete);
  488. if (perm & 2)
  489. tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
  490. domain, is_delete);
  491. if (perm & 1)
  492. tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
  493. filename, domain, is_delete);
  494. return 0;
  495. }
  496. /**
  497. * tomoyo_check_single_path_acl2 - Check permission for single path operation.
  498. *
  499. * @domain: Pointer to "struct tomoyo_domain_info".
  500. * @filename: Filename to check.
  501. * @perm: Permission.
  502. * @may_use_pattern: True if patterned ACL is permitted.
  503. *
  504. * Returns 0 on success, -EPERM otherwise.
  505. */
  506. static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
  507. domain,
  508. const struct tomoyo_path_info *
  509. filename,
  510. const u16 perm,
  511. const bool may_use_pattern)
  512. {
  513. struct tomoyo_acl_info *ptr;
  514. int error = -EPERM;
  515. down_read(&tomoyo_domain_acl_info_list_lock);
  516. list_for_each_entry(ptr, &domain->acl_info_list, list) {
  517. struct tomoyo_single_path_acl_record *acl;
  518. if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
  519. continue;
  520. acl = container_of(ptr, struct tomoyo_single_path_acl_record,
  521. head);
  522. if (!(acl->perm & perm))
  523. continue;
  524. if (may_use_pattern || !acl->filename->is_patterned) {
  525. if (!tomoyo_path_matches_pattern(filename,
  526. acl->filename))
  527. continue;
  528. } else {
  529. continue;
  530. }
  531. error = 0;
  532. break;
  533. }
  534. up_read(&tomoyo_domain_acl_info_list_lock);
  535. return error;
  536. }
  537. /**
  538. * tomoyo_check_file_acl - Check permission for opening files.
  539. *
  540. * @domain: Pointer to "struct tomoyo_domain_info".
  541. * @filename: Filename to check.
  542. * @operation: Mode ("read" or "write" or "read/write" or "execute").
  543. *
  544. * Returns 0 on success, -EPERM otherwise.
  545. */
  546. static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
  547. const struct tomoyo_path_info *filename,
  548. const u8 operation)
  549. {
  550. u16 perm = 0;
  551. if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
  552. return 0;
  553. if (operation == 6)
  554. perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
  555. else if (operation == 4)
  556. perm = 1 << TOMOYO_TYPE_READ_ACL;
  557. else if (operation == 2)
  558. perm = 1 << TOMOYO_TYPE_WRITE_ACL;
  559. else if (operation == 1)
  560. perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
  561. else
  562. BUG();
  563. return tomoyo_check_single_path_acl2(domain, filename, perm,
  564. operation != 1);
  565. }
  566. /**
  567. * tomoyo_check_file_perm2 - Check permission for opening files.
  568. *
  569. * @domain: Pointer to "struct tomoyo_domain_info".
  570. * @filename: Filename to check.
  571. * @perm: Mode ("read" or "write" or "read/write" or "execute").
  572. * @operation: Operation name passed used for verbose mode.
  573. * @mode: Access control mode.
  574. *
  575. * Returns 0 on success, negative value otherwise.
  576. */
  577. static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
  578. const struct tomoyo_path_info *filename,
  579. const u8 perm, const char *operation,
  580. const u8 mode)
  581. {
  582. const bool is_enforce = (mode == 3);
  583. const char *msg = "<unknown>";
  584. int error = 0;
  585. if (!filename)
  586. return 0;
  587. error = tomoyo_check_file_acl(domain, filename, perm);
  588. if (error && perm == 4 &&
  589. (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
  590. && tomoyo_is_globally_readable_file(filename))
  591. error = 0;
  592. if (perm == 6)
  593. msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
  594. else if (perm == 4)
  595. msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
  596. else if (perm == 2)
  597. msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
  598. else if (perm == 1)
  599. msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
  600. else
  601. BUG();
  602. if (!error)
  603. return 0;
  604. if (tomoyo_verbose_mode(domain))
  605. printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
  606. "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
  607. filename->name, tomoyo_get_last_name(domain));
  608. if (is_enforce)
  609. return error;
  610. if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
  611. /* Don't use patterns for execute permission. */
  612. const struct tomoyo_path_info *patterned_file = (perm != 1) ?
  613. tomoyo_get_file_pattern(filename) : filename;
  614. tomoyo_update_file_acl(patterned_file->name, perm,
  615. domain, false);
  616. }
  617. return 0;
  618. }
  619. /**
  620. * tomoyo_write_file_policy - Update file related list.
  621. *
  622. * @data: String to parse.
  623. * @domain: Pointer to "struct tomoyo_domain_info".
  624. * @is_delete: True if it is a delete request.
  625. *
  626. * Returns 0 on success, negative value otherwise.
  627. */
  628. int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
  629. const bool is_delete)
  630. {
  631. char *filename = strchr(data, ' ');
  632. char *filename2;
  633. unsigned int perm;
  634. u8 type;
  635. if (!filename)
  636. return -EINVAL;
  637. *filename++ = '\0';
  638. if (sscanf(data, "%u", &perm) == 1)
  639. return tomoyo_update_file_acl(filename, (u8) perm, domain,
  640. is_delete);
  641. if (strncmp(data, "allow_", 6))
  642. goto out;
  643. data += 6;
  644. for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
  645. if (strcmp(data, tomoyo_sp_keyword[type]))
  646. continue;
  647. return tomoyo_update_single_path_acl(type, filename,
  648. domain, is_delete);
  649. }
  650. filename2 = strchr(filename, ' ');
  651. if (!filename2)
  652. goto out;
  653. *filename2++ = '\0';
  654. for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
  655. if (strcmp(data, tomoyo_dp_keyword[type]))
  656. continue;
  657. return tomoyo_update_double_path_acl(type, filename, filename2,
  658. domain, is_delete);
  659. }
  660. out:
  661. return -EINVAL;
  662. }
  663. /**
  664. * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
  665. *
  666. * @type: Type of operation.
  667. * @filename: Filename.
  668. * @domain: Pointer to "struct tomoyo_domain_info".
  669. * @is_delete: True if it is a delete request.
  670. *
  671. * Returns 0 on success, negative value otherwise.
  672. */
  673. static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
  674. struct tomoyo_domain_info *
  675. const domain, const bool is_delete)
  676. {
  677. static const u16 rw_mask =
  678. (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
  679. const struct tomoyo_path_info *saved_filename;
  680. struct tomoyo_acl_info *ptr;
  681. struct tomoyo_single_path_acl_record *acl;
  682. int error = -ENOMEM;
  683. const u16 perm = 1 << type;
  684. if (!domain)
  685. return -EINVAL;
  686. if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
  687. return -EINVAL;
  688. saved_filename = tomoyo_save_name(filename);
  689. if (!saved_filename)
  690. return -ENOMEM;
  691. down_write(&tomoyo_domain_acl_info_list_lock);
  692. if (is_delete)
  693. goto delete;
  694. list_for_each_entry(ptr, &domain->acl_info_list, list) {
  695. if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
  696. continue;
  697. acl = container_of(ptr, struct tomoyo_single_path_acl_record,
  698. head);
  699. if (acl->filename != saved_filename)
  700. continue;
  701. /* Special case. Clear all bits if marked as deleted. */
  702. if (ptr->type & TOMOYO_ACL_DELETED)
  703. acl->perm = 0;
  704. acl->perm |= perm;
  705. if ((acl->perm & rw_mask) == rw_mask)
  706. acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
  707. else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
  708. acl->perm |= rw_mask;
  709. ptr->type &= ~TOMOYO_ACL_DELETED;
  710. error = 0;
  711. goto out;
  712. }
  713. /* Not found. Append it to the tail. */
  714. acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
  715. if (!acl)
  716. goto out;
  717. acl->perm = perm;
  718. if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
  719. acl->perm |= rw_mask;
  720. acl->filename = saved_filename;
  721. list_add_tail(&acl->head.list, &domain->acl_info_list);
  722. error = 0;
  723. goto out;
  724. delete:
  725. error = -ENOENT;
  726. list_for_each_entry(ptr, &domain->acl_info_list, list) {
  727. if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
  728. continue;
  729. acl = container_of(ptr, struct tomoyo_single_path_acl_record,
  730. head);
  731. if (acl->filename != saved_filename)
  732. continue;
  733. acl->perm &= ~perm;
  734. if ((acl->perm & rw_mask) != rw_mask)
  735. acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
  736. else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
  737. acl->perm &= ~rw_mask;
  738. if (!acl->perm)
  739. ptr->type |= TOMOYO_ACL_DELETED;
  740. error = 0;
  741. break;
  742. }
  743. out:
  744. up_write(&tomoyo_domain_acl_info_list_lock);
  745. return error;
  746. }
  747. /**
  748. * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
  749. *
  750. * @type: Type of operation.
  751. * @filename1: First filename.
  752. * @filename2: Second filename.
  753. * @domain: Pointer to "struct tomoyo_domain_info".
  754. * @is_delete: True if it is a delete request.
  755. *
  756. * Returns 0 on success, negative value otherwise.
  757. */
  758. static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
  759. const char *filename2,
  760. struct tomoyo_domain_info *
  761. const domain, const bool is_delete)
  762. {
  763. const struct tomoyo_path_info *saved_filename1;
  764. const struct tomoyo_path_info *saved_filename2;
  765. struct tomoyo_acl_info *ptr;
  766. struct tomoyo_double_path_acl_record *acl;
  767. int error = -ENOMEM;
  768. const u8 perm = 1 << type;
  769. if (!domain)
  770. return -EINVAL;
  771. if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
  772. !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
  773. return -EINVAL;
  774. saved_filename1 = tomoyo_save_name(filename1);
  775. saved_filename2 = tomoyo_save_name(filename2);
  776. if (!saved_filename1 || !saved_filename2)
  777. return -ENOMEM;
  778. down_write(&tomoyo_domain_acl_info_list_lock);
  779. if (is_delete)
  780. goto delete;
  781. list_for_each_entry(ptr, &domain->acl_info_list, list) {
  782. if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
  783. continue;
  784. acl = container_of(ptr, struct tomoyo_double_path_acl_record,
  785. head);
  786. if (acl->filename1 != saved_filename1 ||
  787. acl->filename2 != saved_filename2)
  788. continue;
  789. /* Special case. Clear all bits if marked as deleted. */
  790. if (ptr->type & TOMOYO_ACL_DELETED)
  791. acl->perm = 0;
  792. acl->perm |= perm;
  793. ptr->type &= ~TOMOYO_ACL_DELETED;
  794. error = 0;
  795. goto out;
  796. }
  797. /* Not found. Append it to the tail. */
  798. acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
  799. if (!acl)
  800. goto out;
  801. acl->perm = perm;
  802. acl->filename1 = saved_filename1;
  803. acl->filename2 = saved_filename2;
  804. list_add_tail(&acl->head.list, &domain->acl_info_list);
  805. error = 0;
  806. goto out;
  807. delete:
  808. error = -ENOENT;
  809. list_for_each_entry(ptr, &domain->acl_info_list, list) {
  810. if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
  811. continue;
  812. acl = container_of(ptr, struct tomoyo_double_path_acl_record,
  813. head);
  814. if (acl->filename1 != saved_filename1 ||
  815. acl->filename2 != saved_filename2)
  816. continue;
  817. acl->perm &= ~perm;
  818. if (!acl->perm)
  819. ptr->type |= TOMOYO_ACL_DELETED;
  820. error = 0;
  821. break;
  822. }
  823. out:
  824. up_write(&tomoyo_domain_acl_info_list_lock);
  825. return error;
  826. }
  827. /**
  828. * tomoyo_check_single_path_acl - Check permission for single path operation.
  829. *
  830. * @domain: Pointer to "struct tomoyo_domain_info".
  831. * @type: Type of operation.
  832. * @filename: Filename to check.
  833. *
  834. * Returns 0 on success, negative value otherwise.
  835. */
  836. static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
  837. const u8 type,
  838. const struct tomoyo_path_info *filename)
  839. {
  840. if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
  841. return 0;
  842. return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
  843. }
  844. /**
  845. * tomoyo_check_double_path_acl - Check permission for double path operation.
  846. *
  847. * @domain: Pointer to "struct tomoyo_domain_info".
  848. * @type: Type of operation.
  849. * @filename1: First filename to check.
  850. * @filename2: Second filename to check.
  851. *
  852. * Returns 0 on success, -EPERM otherwise.
  853. */
  854. static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
  855. const u8 type,
  856. const struct tomoyo_path_info *
  857. filename1,
  858. const struct tomoyo_path_info *
  859. filename2)
  860. {
  861. struct tomoyo_acl_info *ptr;
  862. const u8 perm = 1 << type;
  863. int error = -EPERM;
  864. if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
  865. return 0;
  866. down_read(&tomoyo_domain_acl_info_list_lock);
  867. list_for_each_entry(ptr, &domain->acl_info_list, list) {
  868. struct tomoyo_double_path_acl_record *acl;
  869. if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
  870. continue;
  871. acl = container_of(ptr, struct tomoyo_double_path_acl_record,
  872. head);
  873. if (!(acl->perm & perm))
  874. continue;
  875. if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
  876. continue;
  877. if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
  878. continue;
  879. error = 0;
  880. break;
  881. }
  882. up_read(&tomoyo_domain_acl_info_list_lock);
  883. return error;
  884. }
  885. /**
  886. * tomoyo_check_single_path_permission2 - Check permission for single path operation.
  887. *
  888. * @domain: Pointer to "struct tomoyo_domain_info".
  889. * @operation: Type of operation.
  890. * @filename: Filename to check.
  891. * @mode: Access control mode.
  892. *
  893. * Returns 0 on success, negative value otherwise.
  894. */
  895. static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
  896. const domain, u8 operation,
  897. const struct tomoyo_path_info *
  898. filename, const u8 mode)
  899. {
  900. const char *msg;
  901. int error;
  902. const bool is_enforce = (mode == 3);
  903. if (!mode)
  904. return 0;
  905. next:
  906. error = tomoyo_check_single_path_acl(domain, operation, filename);
  907. msg = tomoyo_sp2keyword(operation);
  908. if (!error)
  909. goto ok;
  910. if (tomoyo_verbose_mode(domain))
  911. printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
  912. tomoyo_get_msg(is_enforce), msg, filename->name,
  913. tomoyo_get_last_name(domain));
  914. if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
  915. const char *name = tomoyo_get_file_pattern(filename)->name;
  916. tomoyo_update_single_path_acl(operation, name, domain, false);
  917. }
  918. if (!is_enforce)
  919. error = 0;
  920. ok:
  921. /*
  922. * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
  923. * we need to check "allow_rewrite" permission if the filename is
  924. * specified by "deny_rewrite" keyword.
  925. */
  926. if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
  927. tomoyo_is_no_rewrite_file(filename)) {
  928. operation = TOMOYO_TYPE_REWRITE_ACL;
  929. goto next;
  930. }
  931. return error;
  932. }
  933. /**
  934. * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write".
  935. *
  936. * @domain: Pointer to "struct tomoyo_domain_info".
  937. * @filename: Filename to check.
  938. * @perm: Mode ("read" or "write" or "read/write").
  939. * Returns 0 on success, negative value otherwise.
  940. */
  941. int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
  942. const char *filename, const u8 perm)
  943. {
  944. struct tomoyo_path_info name;
  945. const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
  946. if (!mode)
  947. return 0;
  948. name.name = filename;
  949. tomoyo_fill_path_info(&name);
  950. return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
  951. }
  952. /**
  953. * tomoyo_check_exec_perm - Check permission for "execute".
  954. *
  955. * @domain: Pointer to "struct tomoyo_domain_info".
  956. * @filename: Check permission for "execute".
  957. * @tmp: Buffer for temporary use.
  958. *
  959. * Returns 0 on success, negativevalue otherwise.
  960. */
  961. int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
  962. const struct tomoyo_path_info *filename,
  963. struct tomoyo_page_buffer *tmp)
  964. {
  965. const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
  966. if (!mode)
  967. return 0;
  968. return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode);
  969. }
  970. /**
  971. * tomoyo_check_open_permission - Check permission for "read" and "write".
  972. *
  973. * @domain: Pointer to "struct tomoyo_domain_info".
  974. * @path: Pointer to "struct path".
  975. * @flag: Flags for open().
  976. *
  977. * Returns 0 on success, negative value otherwise.
  978. */
  979. int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
  980. struct path *path, const int flag)
  981. {
  982. const u8 acc_mode = ACC_MODE(flag);
  983. int error = -ENOMEM;
  984. struct tomoyo_path_info *buf;
  985. const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
  986. const bool is_enforce = (mode == 3);
  987. if (!mode || !path->mnt)
  988. return 0;
  989. if (acc_mode == 0)
  990. return 0;
  991. if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
  992. /*
  993. * I don't check directories here because mkdir() and rmdir()
  994. * don't call me.
  995. */
  996. return 0;
  997. buf = tomoyo_get_path(path);
  998. if (!buf)
  999. goto out;
  1000. error = 0;
  1001. /*
  1002. * If the filename is specified by "deny_rewrite" keyword,
  1003. * we need to check "allow_rewrite" permission when the filename is not
  1004. * opened for append mode or the filename is truncated at open time.
  1005. */
  1006. if ((acc_mode & MAY_WRITE) &&
  1007. ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
  1008. (tomoyo_is_no_rewrite_file(buf))) {
  1009. error = tomoyo_check_single_path_permission2(domain,
  1010. TOMOYO_TYPE_REWRITE_ACL,
  1011. buf, mode);
  1012. }
  1013. if (!error)
  1014. error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
  1015. mode);
  1016. if (!error && (flag & O_TRUNC))
  1017. error = tomoyo_check_single_path_permission2(domain,
  1018. TOMOYO_TYPE_TRUNCATE_ACL,
  1019. buf, mode);
  1020. out:
  1021. tomoyo_free(buf);
  1022. if (!is_enforce)
  1023. error = 0;
  1024. return error;
  1025. }
  1026. /**
  1027. * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
  1028. *
  1029. * @domain: Pointer to "struct tomoyo_domain_info".
  1030. * @operation: Type of operation.
  1031. * @path: Pointer to "struct path".
  1032. *
  1033. * Returns 0 on success, negative value otherwise.
  1034. */
  1035. int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
  1036. const u8 operation, struct path *path)
  1037. {
  1038. int error = -ENOMEM;
  1039. struct tomoyo_path_info *buf;
  1040. const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
  1041. const bool is_enforce = (mode == 3);
  1042. if (!mode || !path->mnt)
  1043. return 0;
  1044. buf = tomoyo_get_path(path);
  1045. if (!buf)
  1046. goto out;
  1047. switch (operation) {
  1048. case TOMOYO_TYPE_MKDIR_ACL:
  1049. case TOMOYO_TYPE_RMDIR_ACL:
  1050. if (!buf->is_dir) {
  1051. /*
  1052. * tomoyo_get_path() reserves space for appending "/."
  1053. */
  1054. strcat((char *) buf->name, "/");
  1055. tomoyo_fill_path_info(buf);
  1056. }
  1057. }
  1058. error = tomoyo_check_single_path_permission2(domain, operation, buf,
  1059. mode);
  1060. out:
  1061. tomoyo_free(buf);
  1062. if (!is_enforce)
  1063. error = 0;
  1064. return error;
  1065. }
  1066. /**
  1067. * tomoyo_check_rewrite_permission - Check permission for "rewrite".
  1068. *
  1069. * @domain: Pointer to "struct tomoyo_domain_info".
  1070. * @filp: Pointer to "struct file".
  1071. *
  1072. * Returns 0 on success, negative value otherwise.
  1073. */
  1074. int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
  1075. struct file *filp)
  1076. {
  1077. int error = -ENOMEM;
  1078. const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
  1079. const bool is_enforce = (mode == 3);
  1080. struct tomoyo_path_info *buf;
  1081. if (!mode || !filp->f_path.mnt)
  1082. return 0;
  1083. buf = tomoyo_get_path(&filp->f_path);
  1084. if (!buf)
  1085. goto out;
  1086. if (!tomoyo_is_no_rewrite_file(buf)) {
  1087. error = 0;
  1088. goto out;
  1089. }
  1090. error = tomoyo_check_single_path_permission2(domain,
  1091. TOMOYO_TYPE_REWRITE_ACL,
  1092. buf, mode);
  1093. out:
  1094. tomoyo_free(buf);
  1095. if (!is_enforce)
  1096. error = 0;
  1097. return error;
  1098. }
  1099. /**
  1100. * tomoyo_check_2path_perm - Check permission for "rename" and "link".
  1101. *
  1102. * @domain: Pointer to "struct tomoyo_domain_info".
  1103. * @operation: Type of operation.
  1104. * @path1: Pointer to "struct path".
  1105. * @path2: Pointer to "struct path".
  1106. *
  1107. * Returns 0 on success, negative value otherwise.
  1108. */
  1109. int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
  1110. const u8 operation, struct path *path1,
  1111. struct path *path2)
  1112. {
  1113. int error = -ENOMEM;
  1114. struct tomoyo_path_info *buf1, *buf2;
  1115. const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
  1116. const bool is_enforce = (mode == 3);
  1117. const char *msg;
  1118. if (!mode || !path1->mnt || !path2->mnt)
  1119. return 0;
  1120. buf1 = tomoyo_get_path(path1);
  1121. buf2 = tomoyo_get_path(path2);
  1122. if (!buf1 || !buf2)
  1123. goto out;
  1124. {
  1125. struct dentry *dentry = path1->dentry;
  1126. if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
  1127. /*
  1128. * tomoyo_get_path() reserves space for appending "/."
  1129. */
  1130. if (!buf1->is_dir) {
  1131. strcat((char *) buf1->name, "/");
  1132. tomoyo_fill_path_info(buf1);
  1133. }
  1134. if (!buf2->is_dir) {
  1135. strcat((char *) buf2->name, "/");
  1136. tomoyo_fill_path_info(buf2);
  1137. }
  1138. }
  1139. }
  1140. error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
  1141. msg = tomoyo_dp2keyword(operation);
  1142. if (!error)
  1143. goto out;
  1144. if (tomoyo_verbose_mode(domain))
  1145. printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
  1146. "denied for %s\n", tomoyo_get_msg(is_enforce),
  1147. msg, buf1->name, buf2->name,
  1148. tomoyo_get_last_name(domain));
  1149. if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
  1150. const char *name1 = tomoyo_get_file_pattern(buf1)->name;
  1151. const char *name2 = tomoyo_get_file_pattern(buf2)->name;
  1152. tomoyo_update_double_path_acl(operation, name1, name2, domain,
  1153. false);
  1154. }
  1155. out:
  1156. tomoyo_free(buf1);
  1157. tomoyo_free(buf2);
  1158. if (!is_enforce)
  1159. error = 0;
  1160. return error;
  1161. }