file.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * security/tomoyo/file.c
  4. *
  5. * Copyright (C) 2005-2011 NTT DATA CORPORATION
  6. */
  7. #include "common.h"
  8. #include <linux/slab.h>
  9. /*
  10. * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
  11. */
  12. static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
  13. [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
  14. [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
  15. [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN,
  16. [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN,
  17. [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK,
  18. [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR,
  19. [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR,
  20. [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE,
  21. [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK,
  22. [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT,
  23. [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
  24. };
  25. /*
  26. * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
  27. */
  28. const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
  29. [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
  30. [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
  31. };
  32. /*
  33. * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
  34. */
  35. const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
  36. [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
  37. [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
  38. [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
  39. };
  40. /*
  41. * Mapping table from "enum tomoyo_path_number_acl_index" to
  42. * "enum tomoyo_mac_index".
  43. */
  44. const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
  45. [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
  46. [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
  47. [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
  48. [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
  49. [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL,
  50. [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD,
  51. [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN,
  52. [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
  53. };
  54. /**
  55. * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
  56. *
  57. * @ptr: Pointer to "struct tomoyo_name_union".
  58. *
  59. * Returns nothing.
  60. */
  61. void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
  62. {
  63. tomoyo_put_group(ptr->group);
  64. tomoyo_put_name(ptr->filename);
  65. }
  66. /**
  67. * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
  68. *
  69. * @name: Pointer to "struct tomoyo_path_info".
  70. * @ptr: Pointer to "struct tomoyo_name_union".
  71. *
  72. * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
  73. */
  74. const struct tomoyo_path_info *
  75. tomoyo_compare_name_union(const struct tomoyo_path_info *name,
  76. const struct tomoyo_name_union *ptr)
  77. {
  78. if (ptr->group)
  79. return tomoyo_path_matches_group(name, ptr->group);
  80. if (tomoyo_path_matches_pattern(name, ptr->filename))
  81. return ptr->filename;
  82. return NULL;
  83. }
  84. /**
  85. * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
  86. *
  87. * @ptr: Pointer to "struct tomoyo_number_union".
  88. *
  89. * Returns nothing.
  90. */
  91. void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
  92. {
  93. tomoyo_put_group(ptr->group);
  94. }
  95. /**
  96. * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
  97. *
  98. * @value: Number to check.
  99. * @ptr: Pointer to "struct tomoyo_number_union".
  100. *
  101. * Returns true if @value matches @ptr, false otherwise.
  102. */
  103. bool tomoyo_compare_number_union(const unsigned long value,
  104. const struct tomoyo_number_union *ptr)
  105. {
  106. if (ptr->group)
  107. return tomoyo_number_matches_group(value, value, ptr->group);
  108. return value >= ptr->values[0] && value <= ptr->values[1];
  109. }
  110. /**
  111. * tomoyo_add_slash - Add trailing '/' if needed.
  112. *
  113. * @buf: Pointer to "struct tomoyo_path_info".
  114. *
  115. * Returns nothing.
  116. *
  117. * @buf must be generated by tomoyo_encode() because this function does not
  118. * allocate memory for adding '/'.
  119. */
  120. static void tomoyo_add_slash(struct tomoyo_path_info *buf)
  121. {
  122. if (buf->is_dir)
  123. return;
  124. /*
  125. * This is OK because tomoyo_encode() reserves space for appending "/".
  126. */
  127. strcat((char *) buf->name, "/");
  128. tomoyo_fill_path_info(buf);
  129. }
  130. /**
  131. * tomoyo_get_realpath - Get realpath.
  132. *
  133. * @buf: Pointer to "struct tomoyo_path_info".
  134. * @path: Pointer to "struct path".
  135. *
  136. * Returns true on success, false otherwise.
  137. */
  138. static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path)
  139. {
  140. buf->name = tomoyo_realpath_from_path(path);
  141. if (buf->name) {
  142. tomoyo_fill_path_info(buf);
  143. return true;
  144. }
  145. return false;
  146. }
  147. /**
  148. * tomoyo_audit_path_log - Audit path request log.
  149. *
  150. * @r: Pointer to "struct tomoyo_request_info".
  151. *
  152. * Returns 0 on success, negative value otherwise.
  153. */
  154. static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
  155. {
  156. return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
  157. [r->param.path.operation],
  158. r->param.path.filename->name);
  159. }
  160. /**
  161. * tomoyo_audit_path2_log - Audit path/path request log.
  162. *
  163. * @r: Pointer to "struct tomoyo_request_info".
  164. *
  165. * Returns 0 on success, negative value otherwise.
  166. */
  167. static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
  168. {
  169. return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
  170. [tomoyo_pp2mac[r->param.path2.operation]],
  171. r->param.path2.filename1->name,
  172. r->param.path2.filename2->name);
  173. }
  174. /**
  175. * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
  176. *
  177. * @r: Pointer to "struct tomoyo_request_info".
  178. *
  179. * Returns 0 on success, negative value otherwise.
  180. */
  181. static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
  182. {
  183. return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
  184. tomoyo_mac_keywords
  185. [tomoyo_pnnn2mac[r->param.mkdev.operation]],
  186. r->param.mkdev.filename->name,
  187. r->param.mkdev.mode, r->param.mkdev.major,
  188. r->param.mkdev.minor);
  189. }
  190. /**
  191. * tomoyo_audit_path_number_log - Audit path/number request log.
  192. *
  193. * @r: Pointer to "struct tomoyo_request_info".
  194. *
  195. * Returns 0 on success, negative value otherwise.
  196. */
  197. static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
  198. {
  199. const u8 type = r->param.path_number.operation;
  200. u8 radix;
  201. char buffer[64];
  202. switch (type) {
  203. case TOMOYO_TYPE_CREATE:
  204. case TOMOYO_TYPE_MKDIR:
  205. case TOMOYO_TYPE_MKFIFO:
  206. case TOMOYO_TYPE_MKSOCK:
  207. case TOMOYO_TYPE_CHMOD:
  208. radix = TOMOYO_VALUE_TYPE_OCTAL;
  209. break;
  210. case TOMOYO_TYPE_IOCTL:
  211. radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
  212. break;
  213. default:
  214. radix = TOMOYO_VALUE_TYPE_DECIMAL;
  215. break;
  216. }
  217. tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
  218. radix);
  219. return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
  220. [tomoyo_pn2mac[type]],
  221. r->param.path_number.filename->name, buffer);
  222. }
  223. /**
  224. * tomoyo_check_path_acl - Check permission for path operation.
  225. *
  226. * @r: Pointer to "struct tomoyo_request_info".
  227. * @ptr: Pointer to "struct tomoyo_acl_info".
  228. *
  229. * Returns true if granted, false otherwise.
  230. *
  231. * To be able to use wildcard for domain transition, this function sets
  232. * matching entry on success. Since the caller holds tomoyo_read_lock(),
  233. * it is safe to set matching entry.
  234. */
  235. static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
  236. const struct tomoyo_acl_info *ptr)
  237. {
  238. const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
  239. head);
  240. if (acl->perm & (1 << r->param.path.operation)) {
  241. r->param.path.matched_path =
  242. tomoyo_compare_name_union(r->param.path.filename,
  243. &acl->name);
  244. return r->param.path.matched_path != NULL;
  245. }
  246. return false;
  247. }
  248. /**
  249. * tomoyo_check_path_number_acl - Check permission for path number operation.
  250. *
  251. * @r: Pointer to "struct tomoyo_request_info".
  252. * @ptr: Pointer to "struct tomoyo_acl_info".
  253. *
  254. * Returns true if granted, false otherwise.
  255. */
  256. static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
  257. const struct tomoyo_acl_info *ptr)
  258. {
  259. const struct tomoyo_path_number_acl *acl =
  260. container_of(ptr, typeof(*acl), head);
  261. return (acl->perm & (1 << r->param.path_number.operation)) &&
  262. tomoyo_compare_number_union(r->param.path_number.number,
  263. &acl->number) &&
  264. tomoyo_compare_name_union(r->param.path_number.filename,
  265. &acl->name);
  266. }
  267. /**
  268. * tomoyo_check_path2_acl - Check permission for path path operation.
  269. *
  270. * @r: Pointer to "struct tomoyo_request_info".
  271. * @ptr: Pointer to "struct tomoyo_acl_info".
  272. *
  273. * Returns true if granted, false otherwise.
  274. */
  275. static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
  276. const struct tomoyo_acl_info *ptr)
  277. {
  278. const struct tomoyo_path2_acl *acl =
  279. container_of(ptr, typeof(*acl), head);
  280. return (acl->perm & (1 << r->param.path2.operation)) &&
  281. tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
  282. && tomoyo_compare_name_union(r->param.path2.filename2,
  283. &acl->name2);
  284. }
  285. /**
  286. * tomoyo_check_mkdev_acl - Check permission for path number number number operation.
  287. *
  288. * @r: Pointer to "struct tomoyo_request_info".
  289. * @ptr: Pointer to "struct tomoyo_acl_info".
  290. *
  291. * Returns true if granted, false otherwise.
  292. */
  293. static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
  294. const struct tomoyo_acl_info *ptr)
  295. {
  296. const struct tomoyo_mkdev_acl *acl =
  297. container_of(ptr, typeof(*acl), head);
  298. return (acl->perm & (1 << r->param.mkdev.operation)) &&
  299. tomoyo_compare_number_union(r->param.mkdev.mode,
  300. &acl->mode) &&
  301. tomoyo_compare_number_union(r->param.mkdev.major,
  302. &acl->major) &&
  303. tomoyo_compare_number_union(r->param.mkdev.minor,
  304. &acl->minor) &&
  305. tomoyo_compare_name_union(r->param.mkdev.filename,
  306. &acl->name);
  307. }
  308. /**
  309. * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
  310. *
  311. * @a: Pointer to "struct tomoyo_acl_info".
  312. * @b: Pointer to "struct tomoyo_acl_info".
  313. *
  314. * Returns true if @a == @b except permission bits, false otherwise.
  315. */
  316. static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
  317. const struct tomoyo_acl_info *b)
  318. {
  319. const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
  320. const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
  321. return tomoyo_same_name_union(&p1->name, &p2->name);
  322. }
  323. /**
  324. * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
  325. *
  326. * @a: Pointer to "struct tomoyo_acl_info".
  327. * @b: Pointer to "struct tomoyo_acl_info".
  328. * @is_delete: True for @a &= ~@b, false for @a |= @b.
  329. *
  330. * Returns true if @a is empty, false otherwise.
  331. */
  332. static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
  333. struct tomoyo_acl_info *b,
  334. const bool is_delete)
  335. {
  336. u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
  337. ->perm;
  338. u16 perm = READ_ONCE(*a_perm);
  339. const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
  340. if (is_delete)
  341. perm &= ~b_perm;
  342. else
  343. perm |= b_perm;
  344. WRITE_ONCE(*a_perm, perm);
  345. return !perm;
  346. }
  347. /**
  348. * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
  349. *
  350. * @perm: Permission.
  351. * @param: Pointer to "struct tomoyo_acl_param".
  352. *
  353. * Returns 0 on success, negative value otherwise.
  354. *
  355. * Caller holds tomoyo_read_lock().
  356. */
  357. static int tomoyo_update_path_acl(const u16 perm,
  358. struct tomoyo_acl_param *param)
  359. {
  360. struct tomoyo_path_acl e = {
  361. .head.type = TOMOYO_TYPE_PATH_ACL,
  362. .perm = perm
  363. };
  364. int error;
  365. if (!tomoyo_parse_name_union(param, &e.name))
  366. error = -EINVAL;
  367. else
  368. error = tomoyo_update_domain(&e.head, sizeof(e), param,
  369. tomoyo_same_path_acl,
  370. tomoyo_merge_path_acl);
  371. tomoyo_put_name_union(&e.name);
  372. return error;
  373. }
  374. /**
  375. * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
  376. *
  377. * @a: Pointer to "struct tomoyo_acl_info".
  378. * @b: Pointer to "struct tomoyo_acl_info".
  379. *
  380. * Returns true if @a == @b except permission bits, false otherwise.
  381. */
  382. static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
  383. const struct tomoyo_acl_info *b)
  384. {
  385. const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
  386. const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
  387. return tomoyo_same_name_union(&p1->name, &p2->name) &&
  388. tomoyo_same_number_union(&p1->mode, &p2->mode) &&
  389. tomoyo_same_number_union(&p1->major, &p2->major) &&
  390. tomoyo_same_number_union(&p1->minor, &p2->minor);
  391. }
  392. /**
  393. * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
  394. *
  395. * @a: Pointer to "struct tomoyo_acl_info".
  396. * @b: Pointer to "struct tomoyo_acl_info".
  397. * @is_delete: True for @a &= ~@b, false for @a |= @b.
  398. *
  399. * Returns true if @a is empty, false otherwise.
  400. */
  401. static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
  402. struct tomoyo_acl_info *b,
  403. const bool is_delete)
  404. {
  405. u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
  406. head)->perm;
  407. u8 perm = READ_ONCE(*a_perm);
  408. const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
  409. ->perm;
  410. if (is_delete)
  411. perm &= ~b_perm;
  412. else
  413. perm |= b_perm;
  414. WRITE_ONCE(*a_perm, perm);
  415. return !perm;
  416. }
  417. /**
  418. * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
  419. *
  420. * @perm: Permission.
  421. * @param: Pointer to "struct tomoyo_acl_param".
  422. *
  423. * Returns 0 on success, negative value otherwise.
  424. *
  425. * Caller holds tomoyo_read_lock().
  426. */
  427. static int tomoyo_update_mkdev_acl(const u8 perm,
  428. struct tomoyo_acl_param *param)
  429. {
  430. struct tomoyo_mkdev_acl e = {
  431. .head.type = TOMOYO_TYPE_MKDEV_ACL,
  432. .perm = perm
  433. };
  434. int error;
  435. if (!tomoyo_parse_name_union(param, &e.name) ||
  436. !tomoyo_parse_number_union(param, &e.mode) ||
  437. !tomoyo_parse_number_union(param, &e.major) ||
  438. !tomoyo_parse_number_union(param, &e.minor))
  439. error = -EINVAL;
  440. else
  441. error = tomoyo_update_domain(&e.head, sizeof(e), param,
  442. tomoyo_same_mkdev_acl,
  443. tomoyo_merge_mkdev_acl);
  444. tomoyo_put_name_union(&e.name);
  445. tomoyo_put_number_union(&e.mode);
  446. tomoyo_put_number_union(&e.major);
  447. tomoyo_put_number_union(&e.minor);
  448. return error;
  449. }
  450. /**
  451. * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
  452. *
  453. * @a: Pointer to "struct tomoyo_acl_info".
  454. * @b: Pointer to "struct tomoyo_acl_info".
  455. *
  456. * Returns true if @a == @b except permission bits, false otherwise.
  457. */
  458. static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
  459. const struct tomoyo_acl_info *b)
  460. {
  461. const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
  462. const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
  463. return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
  464. tomoyo_same_name_union(&p1->name2, &p2->name2);
  465. }
  466. /**
  467. * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
  468. *
  469. * @a: Pointer to "struct tomoyo_acl_info".
  470. * @b: Pointer to "struct tomoyo_acl_info".
  471. * @is_delete: True for @a &= ~@b, false for @a |= @b.
  472. *
  473. * Returns true if @a is empty, false otherwise.
  474. */
  475. static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
  476. struct tomoyo_acl_info *b,
  477. const bool is_delete)
  478. {
  479. u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
  480. ->perm;
  481. u8 perm = READ_ONCE(*a_perm);
  482. const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
  483. if (is_delete)
  484. perm &= ~b_perm;
  485. else
  486. perm |= b_perm;
  487. WRITE_ONCE(*a_perm, perm);
  488. return !perm;
  489. }
  490. /**
  491. * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
  492. *
  493. * @perm: Permission.
  494. * @param: Pointer to "struct tomoyo_acl_param".
  495. *
  496. * Returns 0 on success, negative value otherwise.
  497. *
  498. * Caller holds tomoyo_read_lock().
  499. */
  500. static int tomoyo_update_path2_acl(const u8 perm,
  501. struct tomoyo_acl_param *param)
  502. {
  503. struct tomoyo_path2_acl e = {
  504. .head.type = TOMOYO_TYPE_PATH2_ACL,
  505. .perm = perm
  506. };
  507. int error;
  508. if (!tomoyo_parse_name_union(param, &e.name1) ||
  509. !tomoyo_parse_name_union(param, &e.name2))
  510. error = -EINVAL;
  511. else
  512. error = tomoyo_update_domain(&e.head, sizeof(e), param,
  513. tomoyo_same_path2_acl,
  514. tomoyo_merge_path2_acl);
  515. tomoyo_put_name_union(&e.name1);
  516. tomoyo_put_name_union(&e.name2);
  517. return error;
  518. }
  519. /**
  520. * tomoyo_path_permission - Check permission for single path operation.
  521. *
  522. * @r: Pointer to "struct tomoyo_request_info".
  523. * @operation: Type of operation.
  524. * @filename: Filename to check.
  525. *
  526. * Returns 0 on success, negative value otherwise.
  527. *
  528. * Caller holds tomoyo_read_lock().
  529. */
  530. static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
  531. const struct tomoyo_path_info *filename)
  532. {
  533. int error;
  534. r->type = tomoyo_p2mac[operation];
  535. r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
  536. if (r->mode == TOMOYO_CONFIG_DISABLED)
  537. return 0;
  538. r->param_type = TOMOYO_TYPE_PATH_ACL;
  539. r->param.path.filename = filename;
  540. r->param.path.operation = operation;
  541. do {
  542. tomoyo_check_acl(r, tomoyo_check_path_acl);
  543. error = tomoyo_audit_path_log(r);
  544. } while (error == TOMOYO_RETRY_REQUEST);
  545. return error;
  546. }
  547. /**
  548. * tomoyo_execute_permission - Check permission for execute operation.
  549. *
  550. * @r: Pointer to "struct tomoyo_request_info".
  551. * @filename: Filename to check.
  552. *
  553. * Returns 0 on success, negative value otherwise.
  554. *
  555. * Caller holds tomoyo_read_lock().
  556. */
  557. int tomoyo_execute_permission(struct tomoyo_request_info *r,
  558. const struct tomoyo_path_info *filename)
  559. {
  560. /*
  561. * Unlike other permission checks, this check is done regardless of
  562. * profile mode settings in order to check for domain transition
  563. * preference.
  564. */
  565. r->type = TOMOYO_MAC_FILE_EXECUTE;
  566. r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
  567. r->param_type = TOMOYO_TYPE_PATH_ACL;
  568. r->param.path.filename = filename;
  569. r->param.path.operation = TOMOYO_TYPE_EXECUTE;
  570. tomoyo_check_acl(r, tomoyo_check_path_acl);
  571. r->ee->transition = r->matched_acl && r->matched_acl->cond ?
  572. r->matched_acl->cond->transit : NULL;
  573. if (r->mode != TOMOYO_CONFIG_DISABLED)
  574. return tomoyo_audit_path_log(r);
  575. return 0;
  576. }
  577. /**
  578. * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
  579. *
  580. * @a: Pointer to "struct tomoyo_acl_info".
  581. * @b: Pointer to "struct tomoyo_acl_info".
  582. *
  583. * Returns true if @a == @b except permission bits, false otherwise.
  584. */
  585. static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
  586. const struct tomoyo_acl_info *b)
  587. {
  588. const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
  589. head);
  590. const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
  591. head);
  592. return tomoyo_same_name_union(&p1->name, &p2->name) &&
  593. tomoyo_same_number_union(&p1->number, &p2->number);
  594. }
  595. /**
  596. * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
  597. *
  598. * @a: Pointer to "struct tomoyo_acl_info".
  599. * @b: Pointer to "struct tomoyo_acl_info".
  600. * @is_delete: True for @a &= ~@b, false for @a |= @b.
  601. *
  602. * Returns true if @a is empty, false otherwise.
  603. */
  604. static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
  605. struct tomoyo_acl_info *b,
  606. const bool is_delete)
  607. {
  608. u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
  609. head)->perm;
  610. u8 perm = READ_ONCE(*a_perm);
  611. const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
  612. ->perm;
  613. if (is_delete)
  614. perm &= ~b_perm;
  615. else
  616. perm |= b_perm;
  617. WRITE_ONCE(*a_perm, perm);
  618. return !perm;
  619. }
  620. /**
  621. * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
  622. *
  623. * @perm: Permission.
  624. * @param: Pointer to "struct tomoyo_acl_param".
  625. *
  626. * Returns 0 on success, negative value otherwise.
  627. */
  628. static int tomoyo_update_path_number_acl(const u8 perm,
  629. struct tomoyo_acl_param *param)
  630. {
  631. struct tomoyo_path_number_acl e = {
  632. .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
  633. .perm = perm
  634. };
  635. int error;
  636. if (!tomoyo_parse_name_union(param, &e.name) ||
  637. !tomoyo_parse_number_union(param, &e.number))
  638. error = -EINVAL;
  639. else
  640. error = tomoyo_update_domain(&e.head, sizeof(e), param,
  641. tomoyo_same_path_number_acl,
  642. tomoyo_merge_path_number_acl);
  643. tomoyo_put_name_union(&e.name);
  644. tomoyo_put_number_union(&e.number);
  645. return error;
  646. }
  647. /**
  648. * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
  649. *
  650. * @type: Type of operation.
  651. * @path: Pointer to "struct path".
  652. * @number: Number.
  653. *
  654. * Returns 0 on success, negative value otherwise.
  655. */
  656. int tomoyo_path_number_perm(const u8 type, const struct path *path,
  657. unsigned long number)
  658. {
  659. struct tomoyo_request_info r;
  660. struct tomoyo_obj_info obj = {
  661. .path1 = { .mnt = path->mnt, .dentry = path->dentry },
  662. };
  663. int error = -ENOMEM;
  664. struct tomoyo_path_info buf;
  665. int idx;
  666. if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
  667. == TOMOYO_CONFIG_DISABLED || !path->dentry)
  668. return 0;
  669. idx = tomoyo_read_lock();
  670. if (!tomoyo_get_realpath(&buf, path))
  671. goto out;
  672. r.obj = &obj;
  673. if (type == TOMOYO_TYPE_MKDIR)
  674. tomoyo_add_slash(&buf);
  675. r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
  676. r.param.path_number.operation = type;
  677. r.param.path_number.filename = &buf;
  678. r.param.path_number.number = number;
  679. do {
  680. tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
  681. error = tomoyo_audit_path_number_log(&r);
  682. } while (error == TOMOYO_RETRY_REQUEST);
  683. kfree(buf.name);
  684. out:
  685. tomoyo_read_unlock(idx);
  686. if (r.mode != TOMOYO_CONFIG_ENFORCING)
  687. error = 0;
  688. return error;
  689. }
  690. /**
  691. * tomoyo_check_open_permission - Check permission for "read" and "write".
  692. *
  693. * @domain: Pointer to "struct tomoyo_domain_info".
  694. * @path: Pointer to "struct path".
  695. * @flag: Flags for open().
  696. *
  697. * Returns 0 on success, negative value otherwise.
  698. */
  699. int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
  700. const struct path *path, const int flag)
  701. {
  702. const u8 acc_mode = ACC_MODE(flag);
  703. int error = 0;
  704. struct tomoyo_path_info buf;
  705. struct tomoyo_request_info r;
  706. struct tomoyo_obj_info obj = {
  707. .path1 = { .mnt = path->mnt, .dentry = path->dentry },
  708. };
  709. int idx;
  710. buf.name = NULL;
  711. r.mode = TOMOYO_CONFIG_DISABLED;
  712. idx = tomoyo_read_lock();
  713. if (acc_mode &&
  714. tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
  715. != TOMOYO_CONFIG_DISABLED) {
  716. if (!tomoyo_get_realpath(&buf, path)) {
  717. error = -ENOMEM;
  718. goto out;
  719. }
  720. r.obj = &obj;
  721. if (acc_mode & MAY_READ)
  722. error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
  723. &buf);
  724. if (!error && (acc_mode & MAY_WRITE))
  725. error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
  726. TOMOYO_TYPE_APPEND :
  727. TOMOYO_TYPE_WRITE,
  728. &buf);
  729. }
  730. out:
  731. kfree(buf.name);
  732. tomoyo_read_unlock(idx);
  733. if (r.mode != TOMOYO_CONFIG_ENFORCING)
  734. error = 0;
  735. return error;
  736. }
  737. /**
  738. * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
  739. *
  740. * @operation: Type of operation.
  741. * @path: Pointer to "struct path".
  742. * @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
  743. * NULL otherwise.
  744. *
  745. * Returns 0 on success, negative value otherwise.
  746. */
  747. int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target)
  748. {
  749. struct tomoyo_request_info r;
  750. struct tomoyo_obj_info obj = {
  751. .path1 = { .mnt = path->mnt, .dentry = path->dentry },
  752. };
  753. int error;
  754. struct tomoyo_path_info buf;
  755. bool is_enforce;
  756. struct tomoyo_path_info symlink_target;
  757. int idx;
  758. if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
  759. == TOMOYO_CONFIG_DISABLED)
  760. return 0;
  761. is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
  762. error = -ENOMEM;
  763. buf.name = NULL;
  764. idx = tomoyo_read_lock();
  765. if (!tomoyo_get_realpath(&buf, path))
  766. goto out;
  767. r.obj = &obj;
  768. switch (operation) {
  769. case TOMOYO_TYPE_RMDIR:
  770. case TOMOYO_TYPE_CHROOT:
  771. tomoyo_add_slash(&buf);
  772. break;
  773. case TOMOYO_TYPE_SYMLINK:
  774. symlink_target.name = tomoyo_encode(target);
  775. if (!symlink_target.name)
  776. goto out;
  777. tomoyo_fill_path_info(&symlink_target);
  778. obj.symlink_target = &symlink_target;
  779. break;
  780. }
  781. error = tomoyo_path_permission(&r, operation, &buf);
  782. if (operation == TOMOYO_TYPE_SYMLINK)
  783. kfree(symlink_target.name);
  784. out:
  785. kfree(buf.name);
  786. tomoyo_read_unlock(idx);
  787. if (!is_enforce)
  788. error = 0;
  789. return error;
  790. }
  791. /**
  792. * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
  793. *
  794. * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
  795. * @path: Pointer to "struct path".
  796. * @mode: Create mode.
  797. * @dev: Device number.
  798. *
  799. * Returns 0 on success, negative value otherwise.
  800. */
  801. int tomoyo_mkdev_perm(const u8 operation, const struct path *path,
  802. const unsigned int mode, unsigned int dev)
  803. {
  804. struct tomoyo_request_info r;
  805. struct tomoyo_obj_info obj = {
  806. .path1 = { .mnt = path->mnt, .dentry = path->dentry },
  807. };
  808. int error = -ENOMEM;
  809. struct tomoyo_path_info buf;
  810. int idx;
  811. if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
  812. == TOMOYO_CONFIG_DISABLED)
  813. return 0;
  814. idx = tomoyo_read_lock();
  815. error = -ENOMEM;
  816. if (tomoyo_get_realpath(&buf, path)) {
  817. r.obj = &obj;
  818. dev = new_decode_dev(dev);
  819. r.param_type = TOMOYO_TYPE_MKDEV_ACL;
  820. r.param.mkdev.filename = &buf;
  821. r.param.mkdev.operation = operation;
  822. r.param.mkdev.mode = mode;
  823. r.param.mkdev.major = MAJOR(dev);
  824. r.param.mkdev.minor = MINOR(dev);
  825. tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
  826. error = tomoyo_audit_mkdev_log(&r);
  827. kfree(buf.name);
  828. }
  829. tomoyo_read_unlock(idx);
  830. if (r.mode != TOMOYO_CONFIG_ENFORCING)
  831. error = 0;
  832. return error;
  833. }
  834. /**
  835. * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
  836. *
  837. * @operation: Type of operation.
  838. * @path1: Pointer to "struct path".
  839. * @path2: Pointer to "struct path".
  840. *
  841. * Returns 0 on success, negative value otherwise.
  842. */
  843. int tomoyo_path2_perm(const u8 operation, const struct path *path1,
  844. const struct path *path2)
  845. {
  846. int error = -ENOMEM;
  847. struct tomoyo_path_info buf1;
  848. struct tomoyo_path_info buf2;
  849. struct tomoyo_request_info r;
  850. struct tomoyo_obj_info obj = {
  851. .path1 = { .mnt = path1->mnt, .dentry = path1->dentry },
  852. .path2 = { .mnt = path2->mnt, .dentry = path2->dentry }
  853. };
  854. int idx;
  855. if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
  856. == TOMOYO_CONFIG_DISABLED)
  857. return 0;
  858. buf1.name = NULL;
  859. buf2.name = NULL;
  860. idx = tomoyo_read_lock();
  861. if (!tomoyo_get_realpath(&buf1, path1) ||
  862. !tomoyo_get_realpath(&buf2, path2))
  863. goto out;
  864. switch (operation) {
  865. case TOMOYO_TYPE_RENAME:
  866. case TOMOYO_TYPE_LINK:
  867. if (!d_is_dir(path1->dentry))
  868. break;
  869. fallthrough;
  870. case TOMOYO_TYPE_PIVOT_ROOT:
  871. tomoyo_add_slash(&buf1);
  872. tomoyo_add_slash(&buf2);
  873. break;
  874. }
  875. r.obj = &obj;
  876. r.param_type = TOMOYO_TYPE_PATH2_ACL;
  877. r.param.path2.operation = operation;
  878. r.param.path2.filename1 = &buf1;
  879. r.param.path2.filename2 = &buf2;
  880. do {
  881. tomoyo_check_acl(&r, tomoyo_check_path2_acl);
  882. error = tomoyo_audit_path2_log(&r);
  883. } while (error == TOMOYO_RETRY_REQUEST);
  884. out:
  885. kfree(buf1.name);
  886. kfree(buf2.name);
  887. tomoyo_read_unlock(idx);
  888. if (r.mode != TOMOYO_CONFIG_ENFORCING)
  889. error = 0;
  890. return error;
  891. }
  892. /**
  893. * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
  894. *
  895. * @a: Pointer to "struct tomoyo_acl_info".
  896. * @b: Pointer to "struct tomoyo_acl_info".
  897. *
  898. * Returns true if @a == @b, false otherwise.
  899. */
  900. static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
  901. const struct tomoyo_acl_info *b)
  902. {
  903. const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
  904. const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
  905. return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
  906. tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
  907. tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
  908. tomoyo_same_number_union(&p1->flags, &p2->flags);
  909. }
  910. /**
  911. * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
  912. *
  913. * @param: Pointer to "struct tomoyo_acl_param".
  914. *
  915. * Returns 0 on success, negative value otherwise.
  916. *
  917. * Caller holds tomoyo_read_lock().
  918. */
  919. static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
  920. {
  921. struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
  922. int error;
  923. if (!tomoyo_parse_name_union(param, &e.dev_name) ||
  924. !tomoyo_parse_name_union(param, &e.dir_name) ||
  925. !tomoyo_parse_name_union(param, &e.fs_type) ||
  926. !tomoyo_parse_number_union(param, &e.flags))
  927. error = -EINVAL;
  928. else
  929. error = tomoyo_update_domain(&e.head, sizeof(e), param,
  930. tomoyo_same_mount_acl, NULL);
  931. tomoyo_put_name_union(&e.dev_name);
  932. tomoyo_put_name_union(&e.dir_name);
  933. tomoyo_put_name_union(&e.fs_type);
  934. tomoyo_put_number_union(&e.flags);
  935. return error;
  936. }
  937. /**
  938. * tomoyo_write_file - Update file related list.
  939. *
  940. * @param: Pointer to "struct tomoyo_acl_param".
  941. *
  942. * Returns 0 on success, negative value otherwise.
  943. *
  944. * Caller holds tomoyo_read_lock().
  945. */
  946. int tomoyo_write_file(struct tomoyo_acl_param *param)
  947. {
  948. u16 perm = 0;
  949. u8 type;
  950. const char *operation = tomoyo_read_token(param);
  951. for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
  952. if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
  953. perm |= 1 << type;
  954. if (perm)
  955. return tomoyo_update_path_acl(perm, param);
  956. for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
  957. if (tomoyo_permstr(operation,
  958. tomoyo_mac_keywords[tomoyo_pp2mac[type]]))
  959. perm |= 1 << type;
  960. if (perm)
  961. return tomoyo_update_path2_acl(perm, param);
  962. for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
  963. if (tomoyo_permstr(operation,
  964. tomoyo_mac_keywords[tomoyo_pn2mac[type]]))
  965. perm |= 1 << type;
  966. if (perm)
  967. return tomoyo_update_path_number_acl(perm, param);
  968. for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
  969. if (tomoyo_permstr(operation,
  970. tomoyo_mac_keywords[tomoyo_pnnn2mac[type]]))
  971. perm |= 1 << type;
  972. if (perm)
  973. return tomoyo_update_mkdev_acl(perm, param);
  974. if (tomoyo_permstr(operation,
  975. tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT]))
  976. return tomoyo_update_mount_acl(param);
  977. return -EINVAL;
  978. }