util.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. /*
  2. * security/tomoyo/util.c
  3. *
  4. * Copyright (C) 2005-2011 NTT DATA CORPORATION
  5. */
  6. #include <linux/slab.h>
  7. #include "common.h"
  8. /* Lock for protecting policy. */
  9. DEFINE_MUTEX(tomoyo_policy_lock);
  10. /* Has /sbin/init started? */
  11. bool tomoyo_policy_loaded;
  12. /*
  13. * Mapping table from "enum tomoyo_mac_index" to
  14. * "enum tomoyo_mac_category_index".
  15. */
  16. const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = {
  17. /* CONFIG::file group */
  18. [TOMOYO_MAC_FILE_EXECUTE] = TOMOYO_MAC_CATEGORY_FILE,
  19. [TOMOYO_MAC_FILE_OPEN] = TOMOYO_MAC_CATEGORY_FILE,
  20. [TOMOYO_MAC_FILE_CREATE] = TOMOYO_MAC_CATEGORY_FILE,
  21. [TOMOYO_MAC_FILE_UNLINK] = TOMOYO_MAC_CATEGORY_FILE,
  22. [TOMOYO_MAC_FILE_GETATTR] = TOMOYO_MAC_CATEGORY_FILE,
  23. [TOMOYO_MAC_FILE_MKDIR] = TOMOYO_MAC_CATEGORY_FILE,
  24. [TOMOYO_MAC_FILE_RMDIR] = TOMOYO_MAC_CATEGORY_FILE,
  25. [TOMOYO_MAC_FILE_MKFIFO] = TOMOYO_MAC_CATEGORY_FILE,
  26. [TOMOYO_MAC_FILE_MKSOCK] = TOMOYO_MAC_CATEGORY_FILE,
  27. [TOMOYO_MAC_FILE_TRUNCATE] = TOMOYO_MAC_CATEGORY_FILE,
  28. [TOMOYO_MAC_FILE_SYMLINK] = TOMOYO_MAC_CATEGORY_FILE,
  29. [TOMOYO_MAC_FILE_MKBLOCK] = TOMOYO_MAC_CATEGORY_FILE,
  30. [TOMOYO_MAC_FILE_MKCHAR] = TOMOYO_MAC_CATEGORY_FILE,
  31. [TOMOYO_MAC_FILE_LINK] = TOMOYO_MAC_CATEGORY_FILE,
  32. [TOMOYO_MAC_FILE_RENAME] = TOMOYO_MAC_CATEGORY_FILE,
  33. [TOMOYO_MAC_FILE_CHMOD] = TOMOYO_MAC_CATEGORY_FILE,
  34. [TOMOYO_MAC_FILE_CHOWN] = TOMOYO_MAC_CATEGORY_FILE,
  35. [TOMOYO_MAC_FILE_CHGRP] = TOMOYO_MAC_CATEGORY_FILE,
  36. [TOMOYO_MAC_FILE_IOCTL] = TOMOYO_MAC_CATEGORY_FILE,
  37. [TOMOYO_MAC_FILE_CHROOT] = TOMOYO_MAC_CATEGORY_FILE,
  38. [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE,
  39. [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE,
  40. [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE,
  41. };
  42. /**
  43. * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
  44. *
  45. * @time: Seconds since 1970/01/01 00:00:00.
  46. * @stamp: Pointer to "struct tomoyo_time".
  47. *
  48. * Returns nothing.
  49. *
  50. * This function does not handle Y2038 problem.
  51. */
  52. void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp)
  53. {
  54. static const u16 tomoyo_eom[2][12] = {
  55. { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
  56. { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
  57. };
  58. u16 y;
  59. u8 m;
  60. bool r;
  61. stamp->sec = time % 60;
  62. time /= 60;
  63. stamp->min = time % 60;
  64. time /= 60;
  65. stamp->hour = time % 24;
  66. time /= 24;
  67. for (y = 1970; ; y++) {
  68. const unsigned short days = (y & 3) ? 365 : 366;
  69. if (time < days)
  70. break;
  71. time -= days;
  72. }
  73. r = (y & 3) == 0;
  74. for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++)
  75. ;
  76. if (m)
  77. time -= tomoyo_eom[r][m - 1];
  78. stamp->year = y;
  79. stamp->month = ++m;
  80. stamp->day = ++time;
  81. }
  82. /**
  83. * tomoyo_permstr - Find permission keywords.
  84. *
  85. * @string: String representation for permissions in foo/bar/buz format.
  86. * @keyword: Keyword to find from @string/
  87. *
  88. * Returns ture if @keyword was found in @string, false otherwise.
  89. *
  90. * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
  91. */
  92. bool tomoyo_permstr(const char *string, const char *keyword)
  93. {
  94. const char *cp = strstr(string, keyword);
  95. if (cp)
  96. return cp == string || *(cp - 1) == '/';
  97. return false;
  98. }
  99. /**
  100. * tomoyo_read_token - Read a word from a line.
  101. *
  102. * @param: Pointer to "struct tomoyo_acl_param".
  103. *
  104. * Returns a word on success, "" otherwise.
  105. *
  106. * To allow the caller to skip NULL check, this function returns "" rather than
  107. * NULL if there is no more words to read.
  108. */
  109. char *tomoyo_read_token(struct tomoyo_acl_param *param)
  110. {
  111. char *pos = param->data;
  112. char *del = strchr(pos, ' ');
  113. if (del)
  114. *del++ = '\0';
  115. else
  116. del = pos + strlen(pos);
  117. param->data = del;
  118. return pos;
  119. }
  120. /**
  121. * tomoyo_parse_ulong - Parse an "unsigned long" value.
  122. *
  123. * @result: Pointer to "unsigned long".
  124. * @str: Pointer to string to parse.
  125. *
  126. * Returns one of values in "enum tomoyo_value_type".
  127. *
  128. * The @src is updated to point the first character after the value
  129. * on success.
  130. */
  131. u8 tomoyo_parse_ulong(unsigned long *result, char **str)
  132. {
  133. const char *cp = *str;
  134. char *ep;
  135. int base = 10;
  136. if (*cp == '0') {
  137. char c = *(cp + 1);
  138. if (c == 'x' || c == 'X') {
  139. base = 16;
  140. cp += 2;
  141. } else if (c >= '0' && c <= '7') {
  142. base = 8;
  143. cp++;
  144. }
  145. }
  146. *result = simple_strtoul(cp, &ep, base);
  147. if (cp == ep)
  148. return TOMOYO_VALUE_TYPE_INVALID;
  149. *str = ep;
  150. switch (base) {
  151. case 16:
  152. return TOMOYO_VALUE_TYPE_HEXADECIMAL;
  153. case 8:
  154. return TOMOYO_VALUE_TYPE_OCTAL;
  155. default:
  156. return TOMOYO_VALUE_TYPE_DECIMAL;
  157. }
  158. }
  159. /**
  160. * tomoyo_print_ulong - Print an "unsigned long" value.
  161. *
  162. * @buffer: Pointer to buffer.
  163. * @buffer_len: Size of @buffer.
  164. * @value: An "unsigned long" value.
  165. * @type: Type of @value.
  166. *
  167. * Returns nothing.
  168. */
  169. void tomoyo_print_ulong(char *buffer, const int buffer_len,
  170. const unsigned long value, const u8 type)
  171. {
  172. if (type == TOMOYO_VALUE_TYPE_DECIMAL)
  173. snprintf(buffer, buffer_len, "%lu", value);
  174. else if (type == TOMOYO_VALUE_TYPE_OCTAL)
  175. snprintf(buffer, buffer_len, "0%lo", value);
  176. else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
  177. snprintf(buffer, buffer_len, "0x%lX", value);
  178. else
  179. snprintf(buffer, buffer_len, "type(%u)", type);
  180. }
  181. /**
  182. * tomoyo_parse_name_union - Parse a tomoyo_name_union.
  183. *
  184. * @param: Pointer to "struct tomoyo_acl_param".
  185. * @ptr: Pointer to "struct tomoyo_name_union".
  186. *
  187. * Returns true on success, false otherwise.
  188. */
  189. bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
  190. struct tomoyo_name_union *ptr)
  191. {
  192. char *filename;
  193. if (param->data[0] == '@') {
  194. param->data++;
  195. ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
  196. return ptr->group != NULL;
  197. }
  198. filename = tomoyo_read_token(param);
  199. if (!tomoyo_correct_word(filename))
  200. return false;
  201. ptr->filename = tomoyo_get_name(filename);
  202. return ptr->filename != NULL;
  203. }
  204. /**
  205. * tomoyo_parse_number_union - Parse a tomoyo_number_union.
  206. *
  207. * @param: Pointer to "struct tomoyo_acl_param".
  208. * @ptr: Pointer to "struct tomoyo_number_union".
  209. *
  210. * Returns true on success, false otherwise.
  211. */
  212. bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
  213. struct tomoyo_number_union *ptr)
  214. {
  215. char *data;
  216. u8 type;
  217. unsigned long v;
  218. memset(ptr, 0, sizeof(*ptr));
  219. if (param->data[0] == '@') {
  220. param->data++;
  221. ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP);
  222. return ptr->group != NULL;
  223. }
  224. data = tomoyo_read_token(param);
  225. type = tomoyo_parse_ulong(&v, &data);
  226. if (type == TOMOYO_VALUE_TYPE_INVALID)
  227. return false;
  228. ptr->values[0] = v;
  229. ptr->value_type[0] = type;
  230. if (!*data) {
  231. ptr->values[1] = v;
  232. ptr->value_type[1] = type;
  233. return true;
  234. }
  235. if (*data++ != '-')
  236. return false;
  237. type = tomoyo_parse_ulong(&v, &data);
  238. if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
  239. return false;
  240. ptr->values[1] = v;
  241. ptr->value_type[1] = type;
  242. return true;
  243. }
  244. /**
  245. * tomoyo_byte_range - Check whether the string is a \ooo style octal value.
  246. *
  247. * @str: Pointer to the string.
  248. *
  249. * Returns true if @str is a \ooo style octal value, false otherwise.
  250. *
  251. * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
  252. * This function verifies that \ooo is in valid range.
  253. */
  254. static inline bool tomoyo_byte_range(const char *str)
  255. {
  256. return *str >= '0' && *str++ <= '3' &&
  257. *str >= '0' && *str++ <= '7' &&
  258. *str >= '0' && *str <= '7';
  259. }
  260. /**
  261. * tomoyo_alphabet_char - Check whether the character is an alphabet.
  262. *
  263. * @c: The character to check.
  264. *
  265. * Returns true if @c is an alphabet character, false otherwise.
  266. */
  267. static inline bool tomoyo_alphabet_char(const char c)
  268. {
  269. return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
  270. }
  271. /**
  272. * tomoyo_make_byte - Make byte value from three octal characters.
  273. *
  274. * @c1: The first character.
  275. * @c2: The second character.
  276. * @c3: The third character.
  277. *
  278. * Returns byte value.
  279. */
  280. static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
  281. {
  282. return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
  283. }
  284. /**
  285. * tomoyo_valid - Check whether the character is a valid char.
  286. *
  287. * @c: The character to check.
  288. *
  289. * Returns true if @c is a valid character, false otherwise.
  290. */
  291. static inline bool tomoyo_valid(const unsigned char c)
  292. {
  293. return c > ' ' && c < 127;
  294. }
  295. /**
  296. * tomoyo_invalid - Check whether the character is an invalid char.
  297. *
  298. * @c: The character to check.
  299. *
  300. * Returns true if @c is an invalid character, false otherwise.
  301. */
  302. static inline bool tomoyo_invalid(const unsigned char c)
  303. {
  304. return c && (c <= ' ' || c >= 127);
  305. }
  306. /**
  307. * tomoyo_str_starts - Check whether the given string starts with the given keyword.
  308. *
  309. * @src: Pointer to pointer to the string.
  310. * @find: Pointer to the keyword.
  311. *
  312. * Returns true if @src starts with @find, false otherwise.
  313. *
  314. * The @src is updated to point the first character after the @find
  315. * if @src starts with @find.
  316. */
  317. bool tomoyo_str_starts(char **src, const char *find)
  318. {
  319. const int len = strlen(find);
  320. char *tmp = *src;
  321. if (strncmp(tmp, find, len))
  322. return false;
  323. tmp += len;
  324. *src = tmp;
  325. return true;
  326. }
  327. /**
  328. * tomoyo_normalize_line - Format string.
  329. *
  330. * @buffer: The line to normalize.
  331. *
  332. * Leading and trailing whitespaces are removed.
  333. * Multiple whitespaces are packed into single space.
  334. *
  335. * Returns nothing.
  336. */
  337. void tomoyo_normalize_line(unsigned char *buffer)
  338. {
  339. unsigned char *sp = buffer;
  340. unsigned char *dp = buffer;
  341. bool first = true;
  342. while (tomoyo_invalid(*sp))
  343. sp++;
  344. while (*sp) {
  345. if (!first)
  346. *dp++ = ' ';
  347. first = false;
  348. while (tomoyo_valid(*sp))
  349. *dp++ = *sp++;
  350. while (tomoyo_invalid(*sp))
  351. sp++;
  352. }
  353. *dp = '\0';
  354. }
  355. /**
  356. * tomoyo_correct_word2 - Validate a string.
  357. *
  358. * @string: The string to check. Maybe non-'\0'-terminated.
  359. * @len: Length of @string.
  360. *
  361. * Check whether the given string follows the naming rules.
  362. * Returns true if @string follows the naming rules, false otherwise.
  363. */
  364. static bool tomoyo_correct_word2(const char *string, size_t len)
  365. {
  366. const char *const start = string;
  367. bool in_repetition = false;
  368. unsigned char c;
  369. unsigned char d;
  370. unsigned char e;
  371. if (!len)
  372. goto out;
  373. while (len--) {
  374. c = *string++;
  375. if (c == '\\') {
  376. if (!len--)
  377. goto out;
  378. c = *string++;
  379. switch (c) {
  380. case '\\': /* "\\" */
  381. continue;
  382. case '$': /* "\$" */
  383. case '+': /* "\+" */
  384. case '?': /* "\?" */
  385. case '*': /* "\*" */
  386. case '@': /* "\@" */
  387. case 'x': /* "\x" */
  388. case 'X': /* "\X" */
  389. case 'a': /* "\a" */
  390. case 'A': /* "\A" */
  391. case '-': /* "\-" */
  392. continue;
  393. case '{': /* "/\{" */
  394. if (string - 3 < start || *(string - 3) != '/')
  395. break;
  396. in_repetition = true;
  397. continue;
  398. case '}': /* "\}/" */
  399. if (*string != '/')
  400. break;
  401. if (!in_repetition)
  402. break;
  403. in_repetition = false;
  404. continue;
  405. case '0': /* "\ooo" */
  406. case '1':
  407. case '2':
  408. case '3':
  409. if (!len-- || !len--)
  410. break;
  411. d = *string++;
  412. e = *string++;
  413. if (d < '0' || d > '7' || e < '0' || e > '7')
  414. break;
  415. c = tomoyo_make_byte(c, d, e);
  416. if (tomoyo_invalid(c))
  417. continue; /* pattern is not \000 */
  418. }
  419. goto out;
  420. } else if (in_repetition && c == '/') {
  421. goto out;
  422. } else if (tomoyo_invalid(c)) {
  423. goto out;
  424. }
  425. }
  426. if (in_repetition)
  427. goto out;
  428. return true;
  429. out:
  430. return false;
  431. }
  432. /**
  433. * tomoyo_correct_word - Validate a string.
  434. *
  435. * @string: The string to check.
  436. *
  437. * Check whether the given string follows the naming rules.
  438. * Returns true if @string follows the naming rules, false otherwise.
  439. */
  440. bool tomoyo_correct_word(const char *string)
  441. {
  442. return tomoyo_correct_word2(string, strlen(string));
  443. }
  444. /**
  445. * tomoyo_correct_path - Validate a pathname.
  446. *
  447. * @filename: The pathname to check.
  448. *
  449. * Check whether the given pathname follows the naming rules.
  450. * Returns true if @filename follows the naming rules, false otherwise.
  451. */
  452. bool tomoyo_correct_path(const char *filename)
  453. {
  454. return *filename == '/' && tomoyo_correct_word(filename);
  455. }
  456. /**
  457. * tomoyo_correct_domain - Check whether the given domainname follows the naming rules.
  458. *
  459. * @domainname: The domainname to check.
  460. *
  461. * Returns true if @domainname follows the naming rules, false otherwise.
  462. */
  463. bool tomoyo_correct_domain(const unsigned char *domainname)
  464. {
  465. if (!domainname || !tomoyo_domain_def(domainname))
  466. return false;
  467. domainname = strchr(domainname, ' ');
  468. if (!domainname++)
  469. return true;
  470. while (1) {
  471. const unsigned char *cp = strchr(domainname, ' ');
  472. if (!cp)
  473. break;
  474. if (*domainname != '/' ||
  475. !tomoyo_correct_word2(domainname, cp - domainname))
  476. return false;
  477. domainname = cp + 1;
  478. }
  479. return tomoyo_correct_path(domainname);
  480. }
  481. /**
  482. * tomoyo_domain_def - Check whether the given token can be a domainname.
  483. *
  484. * @buffer: The token to check.
  485. *
  486. * Returns true if @buffer possibly be a domainname, false otherwise.
  487. */
  488. bool tomoyo_domain_def(const unsigned char *buffer)
  489. {
  490. const unsigned char *cp;
  491. int len;
  492. if (*buffer != '<')
  493. return false;
  494. cp = strchr(buffer, ' ');
  495. if (!cp)
  496. len = strlen(buffer);
  497. else
  498. len = cp - buffer;
  499. if (buffer[len - 1] != '>' ||
  500. !tomoyo_correct_word2(buffer + 1, len - 2))
  501. return false;
  502. return true;
  503. }
  504. /**
  505. * tomoyo_find_domain - Find a domain by the given name.
  506. *
  507. * @domainname: The domainname to find.
  508. *
  509. * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
  510. *
  511. * Caller holds tomoyo_read_lock().
  512. */
  513. struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
  514. {
  515. struct tomoyo_domain_info *domain;
  516. struct tomoyo_path_info name;
  517. name.name = domainname;
  518. tomoyo_fill_path_info(&name);
  519. list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
  520. if (!domain->is_deleted &&
  521. !tomoyo_pathcmp(&name, domain->domainname))
  522. return domain;
  523. }
  524. return NULL;
  525. }
  526. /**
  527. * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
  528. *
  529. * @filename: The string to evaluate.
  530. *
  531. * Returns the initial length without a pattern in @filename.
  532. */
  533. static int tomoyo_const_part_length(const char *filename)
  534. {
  535. char c;
  536. int len = 0;
  537. if (!filename)
  538. return 0;
  539. while ((c = *filename++) != '\0') {
  540. if (c != '\\') {
  541. len++;
  542. continue;
  543. }
  544. c = *filename++;
  545. switch (c) {
  546. case '\\': /* "\\" */
  547. len += 2;
  548. continue;
  549. case '0': /* "\ooo" */
  550. case '1':
  551. case '2':
  552. case '3':
  553. c = *filename++;
  554. if (c < '0' || c > '7')
  555. break;
  556. c = *filename++;
  557. if (c < '0' || c > '7')
  558. break;
  559. len += 4;
  560. continue;
  561. }
  562. break;
  563. }
  564. return len;
  565. }
  566. /**
  567. * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
  568. *
  569. * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
  570. *
  571. * The caller sets "struct tomoyo_path_info"->name.
  572. */
  573. void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
  574. {
  575. const char *name = ptr->name;
  576. const int len = strlen(name);
  577. ptr->const_len = tomoyo_const_part_length(name);
  578. ptr->is_dir = len && (name[len - 1] == '/');
  579. ptr->is_patterned = (ptr->const_len < len);
  580. ptr->hash = full_name_hash(name, len);
  581. }
  582. /**
  583. * tomoyo_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
  584. *
  585. * @filename: The start of string to check.
  586. * @filename_end: The end of string to check.
  587. * @pattern: The start of pattern to compare.
  588. * @pattern_end: The end of pattern to compare.
  589. *
  590. * Returns true if @filename matches @pattern, false otherwise.
  591. */
  592. static bool tomoyo_file_matches_pattern2(const char *filename,
  593. const char *filename_end,
  594. const char *pattern,
  595. const char *pattern_end)
  596. {
  597. while (filename < filename_end && pattern < pattern_end) {
  598. char c;
  599. if (*pattern != '\\') {
  600. if (*filename++ != *pattern++)
  601. return false;
  602. continue;
  603. }
  604. c = *filename;
  605. pattern++;
  606. switch (*pattern) {
  607. int i;
  608. int j;
  609. case '?':
  610. if (c == '/') {
  611. return false;
  612. } else if (c == '\\') {
  613. if (filename[1] == '\\')
  614. filename++;
  615. else if (tomoyo_byte_range(filename + 1))
  616. filename += 3;
  617. else
  618. return false;
  619. }
  620. break;
  621. case '\\':
  622. if (c != '\\')
  623. return false;
  624. if (*++filename != '\\')
  625. return false;
  626. break;
  627. case '+':
  628. if (!isdigit(c))
  629. return false;
  630. break;
  631. case 'x':
  632. if (!isxdigit(c))
  633. return false;
  634. break;
  635. case 'a':
  636. if (!tomoyo_alphabet_char(c))
  637. return false;
  638. break;
  639. case '0':
  640. case '1':
  641. case '2':
  642. case '3':
  643. if (c == '\\' && tomoyo_byte_range(filename + 1)
  644. && strncmp(filename + 1, pattern, 3) == 0) {
  645. filename += 3;
  646. pattern += 2;
  647. break;
  648. }
  649. return false; /* Not matched. */
  650. case '*':
  651. case '@':
  652. for (i = 0; i <= filename_end - filename; i++) {
  653. if (tomoyo_file_matches_pattern2(
  654. filename + i, filename_end,
  655. pattern + 1, pattern_end))
  656. return true;
  657. c = filename[i];
  658. if (c == '.' && *pattern == '@')
  659. break;
  660. if (c != '\\')
  661. continue;
  662. if (filename[i + 1] == '\\')
  663. i++;
  664. else if (tomoyo_byte_range(filename + i + 1))
  665. i += 3;
  666. else
  667. break; /* Bad pattern. */
  668. }
  669. return false; /* Not matched. */
  670. default:
  671. j = 0;
  672. c = *pattern;
  673. if (c == '$') {
  674. while (isdigit(filename[j]))
  675. j++;
  676. } else if (c == 'X') {
  677. while (isxdigit(filename[j]))
  678. j++;
  679. } else if (c == 'A') {
  680. while (tomoyo_alphabet_char(filename[j]))
  681. j++;
  682. }
  683. for (i = 1; i <= j; i++) {
  684. if (tomoyo_file_matches_pattern2(
  685. filename + i, filename_end,
  686. pattern + 1, pattern_end))
  687. return true;
  688. }
  689. return false; /* Not matched or bad pattern. */
  690. }
  691. filename++;
  692. pattern++;
  693. }
  694. while (*pattern == '\\' &&
  695. (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
  696. pattern += 2;
  697. return filename == filename_end && pattern == pattern_end;
  698. }
  699. /**
  700. * tomoyo_file_matches_pattern - Pattern matching without '/' character.
  701. *
  702. * @filename: The start of string to check.
  703. * @filename_end: The end of string to check.
  704. * @pattern: The start of pattern to compare.
  705. * @pattern_end: The end of pattern to compare.
  706. *
  707. * Returns true if @filename matches @pattern, false otherwise.
  708. */
  709. static bool tomoyo_file_matches_pattern(const char *filename,
  710. const char *filename_end,
  711. const char *pattern,
  712. const char *pattern_end)
  713. {
  714. const char *pattern_start = pattern;
  715. bool first = true;
  716. bool result;
  717. while (pattern < pattern_end - 1) {
  718. /* Split at "\-" pattern. */
  719. if (*pattern++ != '\\' || *pattern++ != '-')
  720. continue;
  721. result = tomoyo_file_matches_pattern2(filename,
  722. filename_end,
  723. pattern_start,
  724. pattern - 2);
  725. if (first)
  726. result = !result;
  727. if (result)
  728. return false;
  729. first = false;
  730. pattern_start = pattern;
  731. }
  732. result = tomoyo_file_matches_pattern2(filename, filename_end,
  733. pattern_start, pattern_end);
  734. return first ? result : !result;
  735. }
  736. /**
  737. * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
  738. *
  739. * @f: The start of string to check.
  740. * @p: The start of pattern to compare.
  741. *
  742. * Returns true if @f matches @p, false otherwise.
  743. */
  744. static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
  745. {
  746. const char *f_delimiter;
  747. const char *p_delimiter;
  748. while (*f && *p) {
  749. f_delimiter = strchr(f, '/');
  750. if (!f_delimiter)
  751. f_delimiter = f + strlen(f);
  752. p_delimiter = strchr(p, '/');
  753. if (!p_delimiter)
  754. p_delimiter = p + strlen(p);
  755. if (*p == '\\' && *(p + 1) == '{')
  756. goto recursive;
  757. if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
  758. p_delimiter))
  759. return false;
  760. f = f_delimiter;
  761. if (*f)
  762. f++;
  763. p = p_delimiter;
  764. if (*p)
  765. p++;
  766. }
  767. /* Ignore trailing "\*" and "\@" in @pattern. */
  768. while (*p == '\\' &&
  769. (*(p + 1) == '*' || *(p + 1) == '@'))
  770. p += 2;
  771. return !*f && !*p;
  772. recursive:
  773. /*
  774. * The "\{" pattern is permitted only after '/' character.
  775. * This guarantees that below "*(p - 1)" is safe.
  776. * Also, the "\}" pattern is permitted only before '/' character
  777. * so that "\{" + "\}" pair will not break the "\-" operator.
  778. */
  779. if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
  780. *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
  781. return false; /* Bad pattern. */
  782. do {
  783. /* Compare current component with pattern. */
  784. if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
  785. p_delimiter - 2))
  786. break;
  787. /* Proceed to next component. */
  788. f = f_delimiter;
  789. if (!*f)
  790. break;
  791. f++;
  792. /* Continue comparison. */
  793. if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
  794. return true;
  795. f_delimiter = strchr(f, '/');
  796. } while (f_delimiter);
  797. return false; /* Not matched. */
  798. }
  799. /**
  800. * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
  801. *
  802. * @filename: The filename to check.
  803. * @pattern: The pattern to compare.
  804. *
  805. * Returns true if matches, false otherwise.
  806. *
  807. * The following patterns are available.
  808. * \\ \ itself.
  809. * \ooo Octal representation of a byte.
  810. * \* Zero or more repetitions of characters other than '/'.
  811. * \@ Zero or more repetitions of characters other than '/' or '.'.
  812. * \? 1 byte character other than '/'.
  813. * \$ One or more repetitions of decimal digits.
  814. * \+ 1 decimal digit.
  815. * \X One or more repetitions of hexadecimal digits.
  816. * \x 1 hexadecimal digit.
  817. * \A One or more repetitions of alphabet characters.
  818. * \a 1 alphabet character.
  819. *
  820. * \- Subtraction operator.
  821. *
  822. * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
  823. * /dir/dir/dir/ ).
  824. */
  825. bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
  826. const struct tomoyo_path_info *pattern)
  827. {
  828. const char *f = filename->name;
  829. const char *p = pattern->name;
  830. const int len = pattern->const_len;
  831. /* If @pattern doesn't contain pattern, I can use strcmp(). */
  832. if (!pattern->is_patterned)
  833. return !tomoyo_pathcmp(filename, pattern);
  834. /* Don't compare directory and non-directory. */
  835. if (filename->is_dir != pattern->is_dir)
  836. return false;
  837. /* Compare the initial length without patterns. */
  838. if (strncmp(f, p, len))
  839. return false;
  840. f += len;
  841. p += len;
  842. return tomoyo_path_matches_pattern2(f, p);
  843. }
  844. /**
  845. * tomoyo_get_exe - Get tomoyo_realpath() of current process.
  846. *
  847. * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
  848. *
  849. * This function uses kzalloc(), so the caller must call kfree()
  850. * if this function didn't return NULL.
  851. */
  852. const char *tomoyo_get_exe(void)
  853. {
  854. struct mm_struct *mm = current->mm;
  855. struct vm_area_struct *vma;
  856. const char *cp = NULL;
  857. if (!mm)
  858. return NULL;
  859. down_read(&mm->mmap_sem);
  860. for (vma = mm->mmap; vma; vma = vma->vm_next) {
  861. if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
  862. cp = tomoyo_realpath_from_path(&vma->vm_file->f_path);
  863. break;
  864. }
  865. }
  866. up_read(&mm->mmap_sem);
  867. return cp;
  868. }
  869. /**
  870. * tomoyo_get_mode - Get MAC mode.
  871. *
  872. * @ns: Pointer to "struct tomoyo_policy_namespace".
  873. * @profile: Profile number.
  874. * @index: Index number of functionality.
  875. *
  876. * Returns mode.
  877. */
  878. int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
  879. const u8 index)
  880. {
  881. u8 mode;
  882. const u8 category = TOMOYO_MAC_CATEGORY_FILE;
  883. if (!tomoyo_policy_loaded)
  884. return TOMOYO_CONFIG_DISABLED;
  885. mode = tomoyo_profile(ns, profile)->config[index];
  886. if (mode == TOMOYO_CONFIG_USE_DEFAULT)
  887. mode = tomoyo_profile(ns, profile)->config[category];
  888. if (mode == TOMOYO_CONFIG_USE_DEFAULT)
  889. mode = tomoyo_profile(ns, profile)->default_config;
  890. return mode & 3;
  891. }
  892. /**
  893. * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members.
  894. *
  895. * @r: Pointer to "struct tomoyo_request_info" to initialize.
  896. * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain().
  897. * @index: Index number of functionality.
  898. *
  899. * Returns mode.
  900. */
  901. int tomoyo_init_request_info(struct tomoyo_request_info *r,
  902. struct tomoyo_domain_info *domain, const u8 index)
  903. {
  904. u8 profile;
  905. memset(r, 0, sizeof(*r));
  906. if (!domain)
  907. domain = tomoyo_domain();
  908. r->domain = domain;
  909. profile = domain->profile;
  910. r->profile = profile;
  911. r->type = index;
  912. r->mode = tomoyo_get_mode(domain->ns, profile, index);
  913. return r->mode;
  914. }
  915. /**
  916. * tomoyo_domain_quota_is_ok - Check for domain's quota.
  917. *
  918. * @r: Pointer to "struct tomoyo_request_info".
  919. *
  920. * Returns true if the domain is not exceeded quota, false otherwise.
  921. *
  922. * Caller holds tomoyo_read_lock().
  923. */
  924. bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
  925. {
  926. unsigned int count = 0;
  927. struct tomoyo_domain_info *domain = r->domain;
  928. struct tomoyo_acl_info *ptr;
  929. if (r->mode != TOMOYO_CONFIG_LEARNING)
  930. return false;
  931. if (!domain)
  932. return true;
  933. list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
  934. u16 perm;
  935. u8 i;
  936. if (ptr->is_deleted)
  937. continue;
  938. switch (ptr->type) {
  939. case TOMOYO_TYPE_PATH_ACL:
  940. perm = container_of(ptr, struct tomoyo_path_acl, head)
  941. ->perm;
  942. break;
  943. case TOMOYO_TYPE_PATH2_ACL:
  944. perm = container_of(ptr, struct tomoyo_path2_acl, head)
  945. ->perm;
  946. break;
  947. case TOMOYO_TYPE_PATH_NUMBER_ACL:
  948. perm = container_of(ptr, struct tomoyo_path_number_acl,
  949. head)->perm;
  950. break;
  951. case TOMOYO_TYPE_MKDEV_ACL:
  952. perm = container_of(ptr, struct tomoyo_mkdev_acl,
  953. head)->perm;
  954. break;
  955. default:
  956. perm = 1;
  957. }
  958. for (i = 0; i < 16; i++)
  959. if (perm & (1 << i))
  960. count++;
  961. }
  962. if (count < tomoyo_profile(domain->ns, domain->profile)->
  963. pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
  964. return true;
  965. if (!domain->flags[TOMOYO_DIF_QUOTA_WARNED]) {
  966. domain->flags[TOMOYO_DIF_QUOTA_WARNED] = true;
  967. /* r->granted = false; */
  968. tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
  969. printk(KERN_WARNING "WARNING: "
  970. "Domain '%s' has too many ACLs to hold. "
  971. "Stopped learning mode.\n", domain->domainname->name);
  972. }
  973. return false;
  974. }