util.c 27 KB

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