file.c 34 KB

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