file.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  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. static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
  47. [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
  48. [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
  49. [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN,
  50. [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN,
  51. [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK,
  52. [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR,
  53. [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR,
  54. [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE,
  55. [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK,
  56. [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT,
  57. [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
  58. };
  59. static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
  60. [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
  61. [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
  62. };
  63. static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
  64. [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
  65. [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
  66. [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
  67. };
  68. static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
  69. [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
  70. [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
  71. [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
  72. [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
  73. [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL,
  74. [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD,
  75. [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN,
  76. [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
  77. };
  78. void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
  79. {
  80. if (!ptr)
  81. return;
  82. if (ptr->is_group)
  83. tomoyo_put_group(ptr->group);
  84. else
  85. tomoyo_put_name(ptr->filename);
  86. }
  87. const struct tomoyo_path_info *
  88. tomoyo_compare_name_union(const struct tomoyo_path_info *name,
  89. const struct tomoyo_name_union *ptr)
  90. {
  91. if (ptr->is_group)
  92. return tomoyo_path_matches_group(name, ptr->group);
  93. if (tomoyo_path_matches_pattern(name, ptr->filename))
  94. return ptr->filename;
  95. return NULL;
  96. }
  97. void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
  98. {
  99. if (ptr && ptr->is_group)
  100. tomoyo_put_group(ptr->group);
  101. }
  102. bool tomoyo_compare_number_union(const unsigned long value,
  103. const struct tomoyo_number_union *ptr)
  104. {
  105. if (ptr->is_group)
  106. return tomoyo_number_matches_group(value, value, ptr->group);
  107. return value >= ptr->values[0] && value <= ptr->values[1];
  108. }
  109. static void tomoyo_add_slash(struct tomoyo_path_info *buf)
  110. {
  111. if (buf->is_dir)
  112. return;
  113. /*
  114. * This is OK because tomoyo_encode() reserves space for appending "/".
  115. */
  116. strcat((char *) buf->name, "/");
  117. tomoyo_fill_path_info(buf);
  118. }
  119. /**
  120. * tomoyo_get_realpath - Get realpath.
  121. *
  122. * @buf: Pointer to "struct tomoyo_path_info".
  123. * @path: Pointer to "struct path".
  124. *
  125. * Returns true on success, false otherwise.
  126. */
  127. static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
  128. {
  129. buf->name = tomoyo_realpath_from_path(path);
  130. if (buf->name) {
  131. tomoyo_fill_path_info(buf);
  132. return true;
  133. }
  134. return false;
  135. }
  136. /**
  137. * tomoyo_audit_path_log - Audit path request log.
  138. *
  139. * @r: Pointer to "struct tomoyo_request_info".
  140. *
  141. * Returns 0 on success, negative value otherwise.
  142. */
  143. static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
  144. {
  145. const char *operation = tomoyo_path_keyword[r->param.path.operation];
  146. const struct tomoyo_path_info *filename = r->param.path.filename;
  147. if (r->granted)
  148. return 0;
  149. tomoyo_warn_log(r, "%s %s", operation, filename->name);
  150. return tomoyo_supervisor(r, "allow_%s %s\n", operation,
  151. filename->name);
  152. }
  153. /**
  154. * tomoyo_audit_path2_log - Audit path/path request log.
  155. *
  156. * @r: Pointer to "struct tomoyo_request_info".
  157. *
  158. * Returns 0 on success, negative value otherwise.
  159. */
  160. static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
  161. {
  162. const char *operation = tomoyo_path2_keyword[r->param.path2.operation];
  163. const struct tomoyo_path_info *filename1 = r->param.path2.filename1;
  164. const struct tomoyo_path_info *filename2 = r->param.path2.filename2;
  165. if (r->granted)
  166. return 0;
  167. tomoyo_warn_log(r, "%s %s %s", operation, filename1->name,
  168. filename2->name);
  169. return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
  170. filename1->name, filename2->name);
  171. }
  172. /**
  173. * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
  174. *
  175. * @r: Pointer to "struct tomoyo_request_info".
  176. *
  177. * Returns 0 on success, negative value otherwise.
  178. */
  179. static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
  180. {
  181. const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation];
  182. const struct tomoyo_path_info *filename = r->param.mkdev.filename;
  183. const unsigned int major = r->param.mkdev.major;
  184. const unsigned int minor = r->param.mkdev.minor;
  185. const unsigned int mode = r->param.mkdev.mode;
  186. if (r->granted)
  187. return 0;
  188. tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode,
  189. major, minor);
  190. return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation,
  191. filename->name, mode, major, minor);
  192. }
  193. /**
  194. * tomoyo_audit_path_number_log - Audit path/number request log.
  195. *
  196. * @r: Pointer to "struct tomoyo_request_info".
  197. * @error: Error code.
  198. *
  199. * Returns 0 on success, negative value otherwise.
  200. */
  201. static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
  202. {
  203. const u8 type = r->param.path_number.operation;
  204. u8 radix;
  205. const struct tomoyo_path_info *filename = r->param.path_number.filename;
  206. const char *operation = tomoyo_path_number_keyword[type];
  207. char buffer[64];
  208. if (r->granted)
  209. return 0;
  210. switch (type) {
  211. case TOMOYO_TYPE_CREATE:
  212. case TOMOYO_TYPE_MKDIR:
  213. case TOMOYO_TYPE_MKFIFO:
  214. case TOMOYO_TYPE_MKSOCK:
  215. case TOMOYO_TYPE_CHMOD:
  216. radix = TOMOYO_VALUE_TYPE_OCTAL;
  217. break;
  218. case TOMOYO_TYPE_IOCTL:
  219. radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
  220. break;
  221. default:
  222. radix = TOMOYO_VALUE_TYPE_DECIMAL;
  223. break;
  224. }
  225. tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
  226. radix);
  227. tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer);
  228. return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
  229. filename->name, buffer);
  230. }
  231. static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
  232. const struct tomoyo_acl_info *ptr)
  233. {
  234. const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
  235. head);
  236. if (acl->perm & (1 << r->param.path.operation)) {
  237. r->param.path.matched_path =
  238. tomoyo_compare_name_union(r->param.path.filename,
  239. &acl->name);
  240. return r->param.path.matched_path != NULL;
  241. }
  242. return false;
  243. }
  244. static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
  245. const struct tomoyo_acl_info *ptr)
  246. {
  247. const struct tomoyo_path_number_acl *acl =
  248. container_of(ptr, typeof(*acl), head);
  249. return (acl->perm & (1 << r->param.path_number.operation)) &&
  250. tomoyo_compare_number_union(r->param.path_number.number,
  251. &acl->number) &&
  252. tomoyo_compare_name_union(r->param.path_number.filename,
  253. &acl->name);
  254. }
  255. static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
  256. const struct tomoyo_acl_info *ptr)
  257. {
  258. const struct tomoyo_path2_acl *acl =
  259. container_of(ptr, typeof(*acl), head);
  260. return (acl->perm & (1 << r->param.path2.operation)) &&
  261. tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
  262. && tomoyo_compare_name_union(r->param.path2.filename2,
  263. &acl->name2);
  264. }
  265. static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
  266. const struct tomoyo_acl_info *ptr)
  267. {
  268. const struct tomoyo_mkdev_acl *acl =
  269. container_of(ptr, typeof(*acl), head);
  270. return (acl->perm & (1 << r->param.mkdev.operation)) &&
  271. tomoyo_compare_number_union(r->param.mkdev.mode,
  272. &acl->mode) &&
  273. tomoyo_compare_number_union(r->param.mkdev.major,
  274. &acl->major) &&
  275. tomoyo_compare_number_union(r->param.mkdev.minor,
  276. &acl->minor) &&
  277. tomoyo_compare_name_union(r->param.mkdev.filename,
  278. &acl->name);
  279. }
  280. static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
  281. const struct tomoyo_acl_info *b)
  282. {
  283. const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
  284. const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
  285. return tomoyo_same_acl_head(&p1->head, &p2->head) &&
  286. tomoyo_same_name_union(&p1->name, &p2->name);
  287. }
  288. /**
  289. * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
  290. *
  291. * @a: Pointer to "struct tomoyo_acl_info".
  292. * @b: Pointer to "struct tomoyo_acl_info".
  293. * @is_delete: True for @a &= ~@b, false for @a |= @b.
  294. *
  295. * Returns true if @a is empty, false otherwise.
  296. */
  297. static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
  298. struct tomoyo_acl_info *b,
  299. const bool is_delete)
  300. {
  301. u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
  302. ->perm;
  303. u16 perm = *a_perm;
  304. const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
  305. if (is_delete)
  306. perm &= ~b_perm;
  307. else
  308. perm |= b_perm;
  309. *a_perm = perm;
  310. return !perm;
  311. }
  312. /**
  313. * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
  314. *
  315. * @type: Type of operation.
  316. * @filename: Filename.
  317. * @domain: Pointer to "struct tomoyo_domain_info".
  318. * @is_delete: True if it is a delete request.
  319. *
  320. * Returns 0 on success, negative value otherwise.
  321. *
  322. * Caller holds tomoyo_read_lock().
  323. */
  324. static int tomoyo_update_path_acl(const u8 type, const char *filename,
  325. struct tomoyo_domain_info * const domain,
  326. const bool is_delete)
  327. {
  328. struct tomoyo_path_acl e = {
  329. .head.type = TOMOYO_TYPE_PATH_ACL,
  330. .perm = 1 << type
  331. };
  332. int error;
  333. if (!tomoyo_parse_name_union(filename, &e.name))
  334. return -EINVAL;
  335. error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  336. tomoyo_same_path_acl,
  337. tomoyo_merge_path_acl);
  338. tomoyo_put_name_union(&e.name);
  339. return error;
  340. }
  341. static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
  342. const struct tomoyo_acl_info *b)
  343. {
  344. const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1),
  345. head);
  346. const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2),
  347. head);
  348. return tomoyo_same_acl_head(&p1->head, &p2->head)
  349. && tomoyo_same_name_union(&p1->name, &p2->name)
  350. && tomoyo_same_number_union(&p1->mode, &p2->mode)
  351. && tomoyo_same_number_union(&p1->major, &p2->major)
  352. && tomoyo_same_number_union(&p1->minor, &p2->minor);
  353. }
  354. static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
  355. struct tomoyo_acl_info *b,
  356. const bool is_delete)
  357. {
  358. u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
  359. head)->perm;
  360. u8 perm = *a_perm;
  361. const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
  362. ->perm;
  363. if (is_delete)
  364. perm &= ~b_perm;
  365. else
  366. perm |= b_perm;
  367. *a_perm = perm;
  368. return !perm;
  369. }
  370. /**
  371. * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
  372. *
  373. * @type: Type of operation.
  374. * @filename: Filename.
  375. * @mode: Create mode.
  376. * @major: Device major number.
  377. * @minor: Device minor number.
  378. * @domain: Pointer to "struct tomoyo_domain_info".
  379. * @is_delete: True if it is a delete request.
  380. *
  381. * Returns 0 on success, negative value otherwise.
  382. *
  383. * Caller holds tomoyo_read_lock().
  384. */
  385. static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
  386. char *mode, char *major, char *minor,
  387. struct tomoyo_domain_info * const
  388. domain, const bool is_delete)
  389. {
  390. struct tomoyo_mkdev_acl e = {
  391. .head.type = TOMOYO_TYPE_MKDEV_ACL,
  392. .perm = 1 << type
  393. };
  394. int error = is_delete ? -ENOENT : -ENOMEM;
  395. if (!tomoyo_parse_name_union(filename, &e.name) ||
  396. !tomoyo_parse_number_union(mode, &e.mode) ||
  397. !tomoyo_parse_number_union(major, &e.major) ||
  398. !tomoyo_parse_number_union(minor, &e.minor))
  399. goto out;
  400. error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  401. tomoyo_same_mkdev_acl,
  402. tomoyo_merge_mkdev_acl);
  403. out:
  404. tomoyo_put_name_union(&e.name);
  405. tomoyo_put_number_union(&e.mode);
  406. tomoyo_put_number_union(&e.major);
  407. tomoyo_put_number_union(&e.minor);
  408. return error;
  409. }
  410. static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
  411. const struct tomoyo_acl_info *b)
  412. {
  413. const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
  414. const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
  415. return tomoyo_same_acl_head(&p1->head, &p2->head)
  416. && tomoyo_same_name_union(&p1->name1, &p2->name1)
  417. && tomoyo_same_name_union(&p1->name2, &p2->name2);
  418. }
  419. static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
  420. struct tomoyo_acl_info *b,
  421. const bool is_delete)
  422. {
  423. u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
  424. ->perm;
  425. u8 perm = *a_perm;
  426. const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
  427. if (is_delete)
  428. perm &= ~b_perm;
  429. else
  430. perm |= b_perm;
  431. *a_perm = perm;
  432. return !perm;
  433. }
  434. /**
  435. * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
  436. *
  437. * @type: Type of operation.
  438. * @filename1: First filename.
  439. * @filename2: Second filename.
  440. * @domain: Pointer to "struct tomoyo_domain_info".
  441. * @is_delete: True if it is a delete request.
  442. *
  443. * Returns 0 on success, negative value otherwise.
  444. *
  445. * Caller holds tomoyo_read_lock().
  446. */
  447. static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
  448. const char *filename2,
  449. struct tomoyo_domain_info * const domain,
  450. const bool is_delete)
  451. {
  452. struct tomoyo_path2_acl e = {
  453. .head.type = TOMOYO_TYPE_PATH2_ACL,
  454. .perm = 1 << type
  455. };
  456. int error = is_delete ? -ENOENT : -ENOMEM;
  457. if (!tomoyo_parse_name_union(filename1, &e.name1) ||
  458. !tomoyo_parse_name_union(filename2, &e.name2))
  459. goto out;
  460. error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  461. tomoyo_same_path2_acl,
  462. tomoyo_merge_path2_acl);
  463. out:
  464. tomoyo_put_name_union(&e.name1);
  465. tomoyo_put_name_union(&e.name2);
  466. return error;
  467. }
  468. /**
  469. * tomoyo_path_permission - Check permission for single path operation.
  470. *
  471. * @r: Pointer to "struct tomoyo_request_info".
  472. * @operation: Type of operation.
  473. * @filename: Filename to check.
  474. *
  475. * Returns 0 on success, negative value otherwise.
  476. *
  477. * Caller holds tomoyo_read_lock().
  478. */
  479. int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
  480. const struct tomoyo_path_info *filename)
  481. {
  482. int error;
  483. r->type = tomoyo_p2mac[operation];
  484. r->mode = tomoyo_get_mode(r->profile, r->type);
  485. if (r->mode == TOMOYO_CONFIG_DISABLED)
  486. return 0;
  487. r->param_type = TOMOYO_TYPE_PATH_ACL;
  488. r->param.path.filename = filename;
  489. r->param.path.operation = operation;
  490. do {
  491. tomoyo_check_acl(r, tomoyo_check_path_acl);
  492. error = tomoyo_audit_path_log(r);
  493. /*
  494. * Do not retry for execute request, for alias may have
  495. * changed.
  496. */
  497. } while (error == TOMOYO_RETRY_REQUEST &&
  498. operation != TOMOYO_TYPE_EXECUTE);
  499. return error;
  500. }
  501. static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
  502. const struct tomoyo_acl_info *b)
  503. {
  504. const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
  505. head);
  506. const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
  507. head);
  508. return tomoyo_same_acl_head(&p1->head, &p2->head)
  509. && tomoyo_same_name_union(&p1->name, &p2->name)
  510. && tomoyo_same_number_union(&p1->number, &p2->number);
  511. }
  512. static bool tomoyo_merge_path_number_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_path_number_acl,
  517. head)->perm;
  518. u8 perm = *a_perm;
  519. const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
  520. ->perm;
  521. if (is_delete)
  522. perm &= ~b_perm;
  523. else
  524. perm |= b_perm;
  525. *a_perm = perm;
  526. return !perm;
  527. }
  528. /**
  529. * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
  530. *
  531. * @type: Type of operation.
  532. * @filename: Filename.
  533. * @number: Number.
  534. * @domain: Pointer to "struct tomoyo_domain_info".
  535. * @is_delete: True if it is a delete request.
  536. *
  537. * Returns 0 on success, negative value otherwise.
  538. */
  539. static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
  540. char *number,
  541. struct tomoyo_domain_info * const
  542. domain,
  543. const bool is_delete)
  544. {
  545. struct tomoyo_path_number_acl e = {
  546. .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
  547. .perm = 1 << type
  548. };
  549. int error = is_delete ? -ENOENT : -ENOMEM;
  550. if (!tomoyo_parse_name_union(filename, &e.name))
  551. return -EINVAL;
  552. if (!tomoyo_parse_number_union(number, &e.number))
  553. goto out;
  554. error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  555. tomoyo_same_path_number_acl,
  556. tomoyo_merge_path_number_acl);
  557. out:
  558. tomoyo_put_name_union(&e.name);
  559. tomoyo_put_number_union(&e.number);
  560. return error;
  561. }
  562. /**
  563. * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
  564. *
  565. * @type: Type of operation.
  566. * @path: Pointer to "struct path".
  567. * @number: Number.
  568. *
  569. * Returns 0 on success, negative value otherwise.
  570. */
  571. int tomoyo_path_number_perm(const u8 type, struct path *path,
  572. unsigned long number)
  573. {
  574. struct tomoyo_request_info r;
  575. int error = -ENOMEM;
  576. struct tomoyo_path_info buf;
  577. int idx;
  578. if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
  579. == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry)
  580. return 0;
  581. idx = tomoyo_read_lock();
  582. if (!tomoyo_get_realpath(&buf, path))
  583. goto out;
  584. if (type == TOMOYO_TYPE_MKDIR)
  585. tomoyo_add_slash(&buf);
  586. r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
  587. r.param.path_number.operation = type;
  588. r.param.path_number.filename = &buf;
  589. r.param.path_number.number = number;
  590. do {
  591. tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
  592. error = tomoyo_audit_path_number_log(&r);
  593. } while (error == TOMOYO_RETRY_REQUEST);
  594. kfree(buf.name);
  595. out:
  596. tomoyo_read_unlock(idx);
  597. if (r.mode != TOMOYO_CONFIG_ENFORCING)
  598. error = 0;
  599. return error;
  600. }
  601. /**
  602. * tomoyo_check_open_permission - Check permission for "read" and "write".
  603. *
  604. * @domain: Pointer to "struct tomoyo_domain_info".
  605. * @path: Pointer to "struct path".
  606. * @flag: Flags for open().
  607. *
  608. * Returns 0 on success, negative value otherwise.
  609. */
  610. int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
  611. struct path *path, const int flag)
  612. {
  613. const u8 acc_mode = ACC_MODE(flag);
  614. int error = 0;
  615. struct tomoyo_path_info buf;
  616. struct tomoyo_request_info r;
  617. int idx;
  618. if (!path->mnt)
  619. return 0;
  620. buf.name = NULL;
  621. r.mode = TOMOYO_CONFIG_DISABLED;
  622. idx = tomoyo_read_lock();
  623. if (acc_mode &&
  624. tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
  625. != TOMOYO_CONFIG_DISABLED) {
  626. if (!tomoyo_get_realpath(&buf, path)) {
  627. error = -ENOMEM;
  628. goto out;
  629. }
  630. if (acc_mode & MAY_READ)
  631. error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
  632. &buf);
  633. if (!error && (acc_mode & MAY_WRITE))
  634. error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
  635. TOMOYO_TYPE_APPEND :
  636. TOMOYO_TYPE_WRITE,
  637. &buf);
  638. }
  639. out:
  640. kfree(buf.name);
  641. tomoyo_read_unlock(idx);
  642. if (r.mode != TOMOYO_CONFIG_ENFORCING)
  643. error = 0;
  644. return error;
  645. }
  646. /**
  647. * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
  648. *
  649. * @operation: Type of operation.
  650. * @path: Pointer to "struct path".
  651. *
  652. * Returns 0 on success, negative value otherwise.
  653. */
  654. int tomoyo_path_perm(const u8 operation, struct path *path)
  655. {
  656. struct tomoyo_request_info r;
  657. int error;
  658. struct tomoyo_path_info buf;
  659. bool is_enforce;
  660. int idx;
  661. if (!path->mnt)
  662. return 0;
  663. if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
  664. == TOMOYO_CONFIG_DISABLED)
  665. return 0;
  666. is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
  667. error = -ENOMEM;
  668. buf.name = NULL;
  669. idx = tomoyo_read_lock();
  670. if (!tomoyo_get_realpath(&buf, path))
  671. goto out;
  672. switch (operation) {
  673. case TOMOYO_TYPE_RMDIR:
  674. case TOMOYO_TYPE_CHROOT:
  675. tomoyo_add_slash(&buf);
  676. break;
  677. }
  678. error = tomoyo_path_permission(&r, operation, &buf);
  679. out:
  680. kfree(buf.name);
  681. tomoyo_read_unlock(idx);
  682. if (!is_enforce)
  683. error = 0;
  684. return error;
  685. }
  686. /**
  687. * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
  688. *
  689. * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
  690. * @path: Pointer to "struct path".
  691. * @mode: Create mode.
  692. * @dev: Device number.
  693. *
  694. * Returns 0 on success, negative value otherwise.
  695. */
  696. int tomoyo_mkdev_perm(const u8 operation, struct path *path,
  697. const unsigned int mode, unsigned int dev)
  698. {
  699. struct tomoyo_request_info r;
  700. int error = -ENOMEM;
  701. struct tomoyo_path_info buf;
  702. int idx;
  703. if (!path->mnt ||
  704. tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
  705. == TOMOYO_CONFIG_DISABLED)
  706. return 0;
  707. idx = tomoyo_read_lock();
  708. error = -ENOMEM;
  709. if (tomoyo_get_realpath(&buf, path)) {
  710. dev = new_decode_dev(dev);
  711. r.param_type = TOMOYO_TYPE_MKDEV_ACL;
  712. r.param.mkdev.filename = &buf;
  713. r.param.mkdev.operation = operation;
  714. r.param.mkdev.mode = mode;
  715. r.param.mkdev.major = MAJOR(dev);
  716. r.param.mkdev.minor = MINOR(dev);
  717. tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
  718. error = tomoyo_audit_mkdev_log(&r);
  719. kfree(buf.name);
  720. }
  721. tomoyo_read_unlock(idx);
  722. if (r.mode != TOMOYO_CONFIG_ENFORCING)
  723. error = 0;
  724. return error;
  725. }
  726. /**
  727. * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
  728. *
  729. * @operation: Type of operation.
  730. * @path1: Pointer to "struct path".
  731. * @path2: Pointer to "struct path".
  732. *
  733. * Returns 0 on success, negative value otherwise.
  734. */
  735. int tomoyo_path2_perm(const u8 operation, struct path *path1,
  736. struct path *path2)
  737. {
  738. int error = -ENOMEM;
  739. struct tomoyo_path_info buf1;
  740. struct tomoyo_path_info buf2;
  741. struct tomoyo_request_info r;
  742. int idx;
  743. if (!path1->mnt || !path2->mnt ||
  744. tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
  745. == TOMOYO_CONFIG_DISABLED)
  746. return 0;
  747. buf1.name = NULL;
  748. buf2.name = NULL;
  749. idx = tomoyo_read_lock();
  750. if (!tomoyo_get_realpath(&buf1, path1) ||
  751. !tomoyo_get_realpath(&buf2, path2))
  752. goto out;
  753. switch (operation) {
  754. struct dentry *dentry;
  755. case TOMOYO_TYPE_RENAME:
  756. case TOMOYO_TYPE_LINK:
  757. dentry = path1->dentry;
  758. if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
  759. break;
  760. /* fall through */
  761. case TOMOYO_TYPE_PIVOT_ROOT:
  762. tomoyo_add_slash(&buf1);
  763. tomoyo_add_slash(&buf2);
  764. break;
  765. }
  766. r.param_type = TOMOYO_TYPE_PATH2_ACL;
  767. r.param.path2.operation = operation;
  768. r.param.path2.filename1 = &buf1;
  769. r.param.path2.filename2 = &buf2;
  770. do {
  771. tomoyo_check_acl(&r, tomoyo_check_path2_acl);
  772. error = tomoyo_audit_path2_log(&r);
  773. } while (error == TOMOYO_RETRY_REQUEST);
  774. out:
  775. kfree(buf1.name);
  776. kfree(buf2.name);
  777. tomoyo_read_unlock(idx);
  778. if (r.mode != TOMOYO_CONFIG_ENFORCING)
  779. error = 0;
  780. return error;
  781. }
  782. /**
  783. * tomoyo_write_file - Update file related list.
  784. *
  785. * @data: String to parse.
  786. * @domain: Pointer to "struct tomoyo_domain_info".
  787. * @is_delete: True if it is a delete request.
  788. *
  789. * Returns 0 on success, negative value otherwise.
  790. *
  791. * Caller holds tomoyo_read_lock().
  792. */
  793. int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain,
  794. const bool is_delete)
  795. {
  796. char *w[5];
  797. u8 type;
  798. if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
  799. return -EINVAL;
  800. if (strncmp(w[0], "allow_", 6))
  801. goto out;
  802. w[0] += 6;
  803. for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
  804. if (strcmp(w[0], tomoyo_path_keyword[type]))
  805. continue;
  806. return tomoyo_update_path_acl(type, w[1], domain, is_delete);
  807. }
  808. if (!w[2][0])
  809. goto out;
  810. for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
  811. if (strcmp(w[0], tomoyo_path2_keyword[type]))
  812. continue;
  813. return tomoyo_update_path2_acl(type, w[1], w[2], domain,
  814. is_delete);
  815. }
  816. for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) {
  817. if (strcmp(w[0], tomoyo_path_number_keyword[type]))
  818. continue;
  819. return tomoyo_update_path_number_acl(type, w[1], w[2], domain,
  820. is_delete);
  821. }
  822. if (!w[3][0] || !w[4][0])
  823. goto out;
  824. for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) {
  825. if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
  826. continue;
  827. return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
  828. w[4], domain, is_delete);
  829. }
  830. out:
  831. return -EINVAL;
  832. }