util.c 27 KB

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