file.c 29 KB

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