file.c 29 KB

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