condition.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * security/tomoyo/condition.c
  4. *
  5. * Copyright (C) 2005-2011 NTT DATA CORPORATION
  6. */
  7. #include "common.h"
  8. #include <linux/slab.h>
  9. /* List of "struct tomoyo_condition". */
  10. LIST_HEAD(tomoyo_condition_list);
  11. /**
  12. * tomoyo_argv - Check argv[] in "struct linux_binbrm".
  13. *
  14. * @index: Index number of @arg_ptr.
  15. * @arg_ptr: Contents of argv[@index].
  16. * @argc: Length of @argv.
  17. * @argv: Pointer to "struct tomoyo_argv".
  18. * @checked: Set to true if @argv[@index] was found.
  19. *
  20. * Returns true on success, false otherwise.
  21. */
  22. static bool tomoyo_argv(const unsigned int index, const char *arg_ptr,
  23. const int argc, const struct tomoyo_argv *argv,
  24. u8 *checked)
  25. {
  26. int i;
  27. struct tomoyo_path_info arg;
  28. arg.name = arg_ptr;
  29. for (i = 0; i < argc; argv++, checked++, i++) {
  30. bool result;
  31. if (index != argv->index)
  32. continue;
  33. *checked = 1;
  34. tomoyo_fill_path_info(&arg);
  35. result = tomoyo_path_matches_pattern(&arg, argv->value);
  36. if (argv->is_not)
  37. result = !result;
  38. if (!result)
  39. return false;
  40. }
  41. return true;
  42. }
  43. /**
  44. * tomoyo_envp - Check envp[] in "struct linux_binbrm".
  45. *
  46. * @env_name: The name of environment variable.
  47. * @env_value: The value of environment variable.
  48. * @envc: Length of @envp.
  49. * @envp: Pointer to "struct tomoyo_envp".
  50. * @checked: Set to true if @envp[@env_name] was found.
  51. *
  52. * Returns true on success, false otherwise.
  53. */
  54. static bool tomoyo_envp(const char *env_name, const char *env_value,
  55. const int envc, const struct tomoyo_envp *envp,
  56. u8 *checked)
  57. {
  58. int i;
  59. struct tomoyo_path_info name;
  60. struct tomoyo_path_info value;
  61. name.name = env_name;
  62. tomoyo_fill_path_info(&name);
  63. value.name = env_value;
  64. tomoyo_fill_path_info(&value);
  65. for (i = 0; i < envc; envp++, checked++, i++) {
  66. bool result;
  67. if (!tomoyo_path_matches_pattern(&name, envp->name))
  68. continue;
  69. *checked = 1;
  70. if (envp->value) {
  71. result = tomoyo_path_matches_pattern(&value,
  72. envp->value);
  73. if (envp->is_not)
  74. result = !result;
  75. } else {
  76. result = true;
  77. if (!envp->is_not)
  78. result = !result;
  79. }
  80. if (!result)
  81. return false;
  82. }
  83. return true;
  84. }
  85. /**
  86. * tomoyo_scan_bprm - Scan "struct linux_binprm".
  87. *
  88. * @ee: Pointer to "struct tomoyo_execve".
  89. * @argc: Length of @argc.
  90. * @argv: Pointer to "struct tomoyo_argv".
  91. * @envc: Length of @envp.
  92. * @envp: Poiner to "struct tomoyo_envp".
  93. *
  94. * Returns true on success, false otherwise.
  95. */
  96. static bool tomoyo_scan_bprm(struct tomoyo_execve *ee,
  97. const u16 argc, const struct tomoyo_argv *argv,
  98. const u16 envc, const struct tomoyo_envp *envp)
  99. {
  100. struct linux_binprm *bprm = ee->bprm;
  101. struct tomoyo_page_dump *dump = &ee->dump;
  102. char *arg_ptr = ee->tmp;
  103. int arg_len = 0;
  104. unsigned long pos = bprm->p;
  105. int offset = pos % PAGE_SIZE;
  106. int argv_count = bprm->argc;
  107. int envp_count = bprm->envc;
  108. bool result = true;
  109. u8 local_checked[32];
  110. u8 *checked;
  111. if (argc + envc <= sizeof(local_checked)) {
  112. checked = local_checked;
  113. memset(local_checked, 0, sizeof(local_checked));
  114. } else {
  115. checked = kzalloc(argc + envc, GFP_NOFS);
  116. if (!checked)
  117. return false;
  118. }
  119. while (argv_count || envp_count) {
  120. if (!tomoyo_dump_page(bprm, pos, dump)) {
  121. result = false;
  122. goto out;
  123. }
  124. pos += PAGE_SIZE - offset;
  125. while (offset < PAGE_SIZE) {
  126. /* Read. */
  127. const char *kaddr = dump->data;
  128. const unsigned char c = kaddr[offset++];
  129. if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
  130. if (c == '\\') {
  131. arg_ptr[arg_len++] = '\\';
  132. arg_ptr[arg_len++] = '\\';
  133. } else if (c > ' ' && c < 127) {
  134. arg_ptr[arg_len++] = c;
  135. } else {
  136. arg_ptr[arg_len++] = '\\';
  137. arg_ptr[arg_len++] = (c >> 6) + '0';
  138. arg_ptr[arg_len++] =
  139. ((c >> 3) & 7) + '0';
  140. arg_ptr[arg_len++] = (c & 7) + '0';
  141. }
  142. } else {
  143. arg_ptr[arg_len] = '\0';
  144. }
  145. if (c)
  146. continue;
  147. /* Check. */
  148. if (argv_count) {
  149. if (!tomoyo_argv(bprm->argc - argv_count,
  150. arg_ptr, argc, argv,
  151. checked)) {
  152. result = false;
  153. break;
  154. }
  155. argv_count--;
  156. } else if (envp_count) {
  157. char *cp = strchr(arg_ptr, '=');
  158. if (cp) {
  159. *cp = '\0';
  160. if (!tomoyo_envp(arg_ptr, cp + 1,
  161. envc, envp,
  162. checked + argc)) {
  163. result = false;
  164. break;
  165. }
  166. }
  167. envp_count--;
  168. } else {
  169. break;
  170. }
  171. arg_len = 0;
  172. }
  173. offset = 0;
  174. if (!result)
  175. break;
  176. }
  177. out:
  178. if (result) {
  179. int i;
  180. /* Check not-yet-checked entries. */
  181. for (i = 0; i < argc; i++) {
  182. if (checked[i])
  183. continue;
  184. /*
  185. * Return true only if all unchecked indexes in
  186. * bprm->argv[] are not matched.
  187. */
  188. if (argv[i].is_not)
  189. continue;
  190. result = false;
  191. break;
  192. }
  193. for (i = 0; i < envc; envp++, i++) {
  194. if (checked[argc + i])
  195. continue;
  196. /*
  197. * Return true only if all unchecked environ variables
  198. * in bprm->envp[] are either undefined or not matched.
  199. */
  200. if ((!envp->value && !envp->is_not) ||
  201. (envp->value && envp->is_not))
  202. continue;
  203. result = false;
  204. break;
  205. }
  206. }
  207. if (checked != local_checked)
  208. kfree(checked);
  209. return result;
  210. }
  211. /**
  212. * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition".
  213. *
  214. * @file: Pointer to "struct file".
  215. * @ptr: Pointer to "struct tomoyo_name_union".
  216. * @match: True if "exec.realpath=", false if "exec.realpath!=".
  217. *
  218. * Returns true on success, false otherwise.
  219. */
  220. static bool tomoyo_scan_exec_realpath(struct file *file,
  221. const struct tomoyo_name_union *ptr,
  222. const bool match)
  223. {
  224. bool result;
  225. struct tomoyo_path_info exe;
  226. if (!file)
  227. return false;
  228. exe.name = tomoyo_realpath_from_path(&file->f_path);
  229. if (!exe.name)
  230. return false;
  231. tomoyo_fill_path_info(&exe);
  232. result = tomoyo_compare_name_union(&exe, ptr);
  233. kfree(exe.name);
  234. return result == match;
  235. }
  236. /**
  237. * tomoyo_get_dqword - tomoyo_get_name() for a quoted string.
  238. *
  239. * @start: String to save.
  240. *
  241. * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
  242. */
  243. static const struct tomoyo_path_info *tomoyo_get_dqword(char *start)
  244. {
  245. char *cp = start + strlen(start) - 1;
  246. if (cp == start || *start++ != '"' || *cp != '"')
  247. return NULL;
  248. *cp = '\0';
  249. if (*start && !tomoyo_correct_word(start))
  250. return NULL;
  251. return tomoyo_get_name(start);
  252. }
  253. /**
  254. * tomoyo_parse_name_union_quoted - Parse a quoted word.
  255. *
  256. * @param: Pointer to "struct tomoyo_acl_param".
  257. * @ptr: Pointer to "struct tomoyo_name_union".
  258. *
  259. * Returns true on success, false otherwise.
  260. */
  261. static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param,
  262. struct tomoyo_name_union *ptr)
  263. {
  264. char *filename = param->data;
  265. if (*filename == '@')
  266. return tomoyo_parse_name_union(param, ptr);
  267. ptr->filename = tomoyo_get_dqword(filename);
  268. return ptr->filename != NULL;
  269. }
  270. /**
  271. * tomoyo_parse_argv - Parse an argv[] condition part.
  272. *
  273. * @left: Lefthand value.
  274. * @right: Righthand value.
  275. * @argv: Pointer to "struct tomoyo_argv".
  276. *
  277. * Returns true on success, false otherwise.
  278. */
  279. static bool tomoyo_parse_argv(char *left, char *right,
  280. struct tomoyo_argv *argv)
  281. {
  282. if (tomoyo_parse_ulong(&argv->index, &left) !=
  283. TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left)
  284. return false;
  285. argv->value = tomoyo_get_dqword(right);
  286. return argv->value != NULL;
  287. }
  288. /**
  289. * tomoyo_parse_envp - Parse an envp[] condition part.
  290. *
  291. * @left: Lefthand value.
  292. * @right: Righthand value.
  293. * @envp: Pointer to "struct tomoyo_envp".
  294. *
  295. * Returns true on success, false otherwise.
  296. */
  297. static bool tomoyo_parse_envp(char *left, char *right,
  298. struct tomoyo_envp *envp)
  299. {
  300. const struct tomoyo_path_info *name;
  301. const struct tomoyo_path_info *value;
  302. char *cp = left + strlen(left) - 1;
  303. if (*cp-- != ']' || *cp != '"')
  304. goto out;
  305. *cp = '\0';
  306. if (!tomoyo_correct_word(left))
  307. goto out;
  308. name = tomoyo_get_name(left);
  309. if (!name)
  310. goto out;
  311. if (!strcmp(right, "NULL")) {
  312. value = NULL;
  313. } else {
  314. value = tomoyo_get_dqword(right);
  315. if (!value) {
  316. tomoyo_put_name(name);
  317. goto out;
  318. }
  319. }
  320. envp->name = name;
  321. envp->value = value;
  322. return true;
  323. out:
  324. return false;
  325. }
  326. /**
  327. * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
  328. *
  329. * @a: Pointer to "struct tomoyo_condition".
  330. * @b: Pointer to "struct tomoyo_condition".
  331. *
  332. * Returns true if @a == @b, false otherwise.
  333. */
  334. static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
  335. const struct tomoyo_condition *b)
  336. {
  337. return a->size == b->size && a->condc == b->condc &&
  338. a->numbers_count == b->numbers_count &&
  339. a->names_count == b->names_count &&
  340. a->argc == b->argc && a->envc == b->envc &&
  341. a->grant_log == b->grant_log && a->transit == b->transit &&
  342. !memcmp(a + 1, b + 1, a->size - sizeof(*a));
  343. }
  344. /**
  345. * tomoyo_condition_type - Get condition type.
  346. *
  347. * @word: Keyword string.
  348. *
  349. * Returns one of values in "enum tomoyo_conditions_index" on success,
  350. * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
  351. */
  352. static u8 tomoyo_condition_type(const char *word)
  353. {
  354. u8 i;
  355. for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
  356. if (!strcmp(word, tomoyo_condition_keyword[i]))
  357. break;
  358. }
  359. return i;
  360. }
  361. /* Define this to enable debug mode. */
  362. /* #define DEBUG_CONDITION */
  363. #ifdef DEBUG_CONDITION
  364. #define dprintk printk
  365. #else
  366. #define dprintk(...) do { } while (0)
  367. #endif
  368. /**
  369. * tomoyo_commit_condition - Commit "struct tomoyo_condition".
  370. *
  371. * @entry: Pointer to "struct tomoyo_condition".
  372. *
  373. * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
  374. *
  375. * This function merges duplicated entries. This function returns NULL if
  376. * @entry is not duplicated but memory quota for policy has exceeded.
  377. */
  378. static struct tomoyo_condition *tomoyo_commit_condition
  379. (struct tomoyo_condition *entry)
  380. {
  381. struct tomoyo_condition *ptr;
  382. bool found = false;
  383. if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
  384. dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
  385. ptr = NULL;
  386. found = true;
  387. goto out;
  388. }
  389. list_for_each_entry(ptr, &tomoyo_condition_list, head.list) {
  390. if (!tomoyo_same_condition(ptr, entry) ||
  391. atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
  392. continue;
  393. /* Same entry found. Share this entry. */
  394. atomic_inc(&ptr->head.users);
  395. found = true;
  396. break;
  397. }
  398. if (!found) {
  399. if (tomoyo_memory_ok(entry)) {
  400. atomic_set(&entry->head.users, 1);
  401. list_add(&entry->head.list, &tomoyo_condition_list);
  402. } else {
  403. found = true;
  404. ptr = NULL;
  405. }
  406. }
  407. mutex_unlock(&tomoyo_policy_lock);
  408. out:
  409. if (found) {
  410. tomoyo_del_condition(&entry->head.list);
  411. kfree(entry);
  412. entry = ptr;
  413. }
  414. return entry;
  415. }
  416. /**
  417. * tomoyo_get_transit_preference - Parse domain transition preference for execve().
  418. *
  419. * @param: Pointer to "struct tomoyo_acl_param".
  420. * @e: Pointer to "struct tomoyo_condition".
  421. *
  422. * Returns the condition string part.
  423. */
  424. static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param,
  425. struct tomoyo_condition *e)
  426. {
  427. char * const pos = param->data;
  428. bool flag;
  429. if (*pos == '<') {
  430. e->transit = tomoyo_get_domainname(param);
  431. goto done;
  432. }
  433. {
  434. char *cp = strchr(pos, ' ');
  435. if (cp)
  436. *cp = '\0';
  437. flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") ||
  438. !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
  439. !strcmp(pos, "child") || !strcmp(pos, "parent");
  440. if (cp)
  441. *cp = ' ';
  442. }
  443. if (!flag)
  444. return pos;
  445. e->transit = tomoyo_get_name(tomoyo_read_token(param));
  446. done:
  447. if (e->transit)
  448. return param->data;
  449. /*
  450. * Return a bad read-only condition string that will let
  451. * tomoyo_get_condition() return NULL.
  452. */
  453. return "/";
  454. }
  455. /**
  456. * tomoyo_get_condition - Parse condition part.
  457. *
  458. * @param: Pointer to "struct tomoyo_acl_param".
  459. *
  460. * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
  461. */
  462. struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
  463. {
  464. struct tomoyo_condition *entry = NULL;
  465. struct tomoyo_condition_element *condp = NULL;
  466. struct tomoyo_number_union *numbers_p = NULL;
  467. struct tomoyo_name_union *names_p = NULL;
  468. struct tomoyo_argv *argv = NULL;
  469. struct tomoyo_envp *envp = NULL;
  470. struct tomoyo_condition e = { };
  471. char * const start_of_string =
  472. tomoyo_get_transit_preference(param, &e);
  473. char * const end_of_string = start_of_string + strlen(start_of_string);
  474. char *pos;
  475. rerun:
  476. pos = start_of_string;
  477. while (1) {
  478. u8 left = -1;
  479. u8 right = -1;
  480. char *left_word = pos;
  481. char *cp;
  482. char *right_word;
  483. bool is_not;
  484. if (!*left_word)
  485. break;
  486. /*
  487. * Since left-hand condition does not allow use of "path_group"
  488. * or "number_group" and environment variable's names do not
  489. * accept '=', it is guaranteed that the original line consists
  490. * of one or more repetition of $left$operator$right blocks
  491. * where "$left is free from '=' and ' '" and "$operator is
  492. * either '=' or '!='" and "$right is free from ' '".
  493. * Therefore, we can reconstruct the original line at the end
  494. * of dry run even if we overwrite $operator with '\0'.
  495. */
  496. cp = strchr(pos, ' ');
  497. if (cp) {
  498. *cp = '\0'; /* Will restore later. */
  499. pos = cp + 1;
  500. } else {
  501. pos = "";
  502. }
  503. right_word = strchr(left_word, '=');
  504. if (!right_word || right_word == left_word)
  505. goto out;
  506. is_not = *(right_word - 1) == '!';
  507. if (is_not)
  508. *(right_word++ - 1) = '\0'; /* Will restore later. */
  509. else if (*(right_word + 1) != '=')
  510. *right_word++ = '\0'; /* Will restore later. */
  511. else
  512. goto out;
  513. dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
  514. is_not ? "!" : "", right_word);
  515. if (!strcmp(left_word, "grant_log")) {
  516. if (entry) {
  517. if (is_not ||
  518. entry->grant_log != TOMOYO_GRANTLOG_AUTO)
  519. goto out;
  520. else if (!strcmp(right_word, "yes"))
  521. entry->grant_log = TOMOYO_GRANTLOG_YES;
  522. else if (!strcmp(right_word, "no"))
  523. entry->grant_log = TOMOYO_GRANTLOG_NO;
  524. else
  525. goto out;
  526. }
  527. continue;
  528. }
  529. if (!strncmp(left_word, "exec.argv[", 10)) {
  530. if (!argv) {
  531. e.argc++;
  532. e.condc++;
  533. } else {
  534. e.argc--;
  535. e.condc--;
  536. left = TOMOYO_ARGV_ENTRY;
  537. argv->is_not = is_not;
  538. if (!tomoyo_parse_argv(left_word + 10,
  539. right_word, argv++))
  540. goto out;
  541. }
  542. goto store_value;
  543. }
  544. if (!strncmp(left_word, "exec.envp[\"", 11)) {
  545. if (!envp) {
  546. e.envc++;
  547. e.condc++;
  548. } else {
  549. e.envc--;
  550. e.condc--;
  551. left = TOMOYO_ENVP_ENTRY;
  552. envp->is_not = is_not;
  553. if (!tomoyo_parse_envp(left_word + 11,
  554. right_word, envp++))
  555. goto out;
  556. }
  557. goto store_value;
  558. }
  559. left = tomoyo_condition_type(left_word);
  560. dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
  561. left);
  562. if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
  563. if (!numbers_p) {
  564. e.numbers_count++;
  565. } else {
  566. e.numbers_count--;
  567. left = TOMOYO_NUMBER_UNION;
  568. param->data = left_word;
  569. if (*left_word == '@' ||
  570. !tomoyo_parse_number_union(param,
  571. numbers_p++))
  572. goto out;
  573. }
  574. }
  575. if (!condp)
  576. e.condc++;
  577. else
  578. e.condc--;
  579. if (left == TOMOYO_EXEC_REALPATH ||
  580. left == TOMOYO_SYMLINK_TARGET) {
  581. if (!names_p) {
  582. e.names_count++;
  583. } else {
  584. e.names_count--;
  585. right = TOMOYO_NAME_UNION;
  586. param->data = right_word;
  587. if (!tomoyo_parse_name_union_quoted(param,
  588. names_p++))
  589. goto out;
  590. }
  591. goto store_value;
  592. }
  593. right = tomoyo_condition_type(right_word);
  594. if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
  595. if (!numbers_p) {
  596. e.numbers_count++;
  597. } else {
  598. e.numbers_count--;
  599. right = TOMOYO_NUMBER_UNION;
  600. param->data = right_word;
  601. if (!tomoyo_parse_number_union(param,
  602. numbers_p++))
  603. goto out;
  604. }
  605. }
  606. store_value:
  607. if (!condp) {
  608. dprintk(KERN_WARNING "%u: dry_run left=%u right=%u match=%u\n",
  609. __LINE__, left, right, !is_not);
  610. continue;
  611. }
  612. condp->left = left;
  613. condp->right = right;
  614. condp->equals = !is_not;
  615. dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
  616. __LINE__, condp->left, condp->right,
  617. condp->equals);
  618. condp++;
  619. }
  620. dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
  621. __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
  622. e.envc);
  623. if (entry) {
  624. BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
  625. e.condc);
  626. return tomoyo_commit_condition(entry);
  627. }
  628. e.size = sizeof(*entry)
  629. + e.condc * sizeof(struct tomoyo_condition_element)
  630. + e.numbers_count * sizeof(struct tomoyo_number_union)
  631. + e.names_count * sizeof(struct tomoyo_name_union)
  632. + e.argc * sizeof(struct tomoyo_argv)
  633. + e.envc * sizeof(struct tomoyo_envp);
  634. entry = kzalloc(e.size, GFP_NOFS);
  635. if (!entry)
  636. goto out2;
  637. *entry = e;
  638. e.transit = NULL;
  639. condp = (struct tomoyo_condition_element *) (entry + 1);
  640. numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
  641. names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
  642. argv = (struct tomoyo_argv *) (names_p + e.names_count);
  643. envp = (struct tomoyo_envp *) (argv + e.argc);
  644. {
  645. bool flag = false;
  646. for (pos = start_of_string; pos < end_of_string; pos++) {
  647. if (*pos)
  648. continue;
  649. if (flag) /* Restore " ". */
  650. *pos = ' ';
  651. else if (*(pos + 1) == '=') /* Restore "!=". */
  652. *pos = '!';
  653. else /* Restore "=". */
  654. *pos = '=';
  655. flag = !flag;
  656. }
  657. }
  658. goto rerun;
  659. out:
  660. dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
  661. if (entry) {
  662. tomoyo_del_condition(&entry->head.list);
  663. kfree(entry);
  664. }
  665. out2:
  666. tomoyo_put_name(e.transit);
  667. return NULL;
  668. }
  669. /**
  670. * tomoyo_get_attributes - Revalidate "struct inode".
  671. *
  672. * @obj: Pointer to "struct tomoyo_obj_info".
  673. *
  674. * Returns nothing.
  675. */
  676. void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
  677. {
  678. u8 i;
  679. struct dentry *dentry = NULL;
  680. for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
  681. struct inode *inode;
  682. switch (i) {
  683. case TOMOYO_PATH1:
  684. dentry = obj->path1.dentry;
  685. if (!dentry)
  686. continue;
  687. break;
  688. case TOMOYO_PATH2:
  689. dentry = obj->path2.dentry;
  690. if (!dentry)
  691. continue;
  692. break;
  693. default:
  694. if (!dentry)
  695. continue;
  696. dentry = dget_parent(dentry);
  697. break;
  698. }
  699. inode = d_backing_inode(dentry);
  700. if (inode) {
  701. struct tomoyo_mini_stat *stat = &obj->stat[i];
  702. stat->uid = inode->i_uid;
  703. stat->gid = inode->i_gid;
  704. stat->ino = inode->i_ino;
  705. stat->mode = inode->i_mode;
  706. stat->dev = inode->i_sb->s_dev;
  707. stat->rdev = inode->i_rdev;
  708. obj->stat_valid[i] = true;
  709. }
  710. if (i & 1) /* TOMOYO_PATH1_PARENT or TOMOYO_PATH2_PARENT */
  711. dput(dentry);
  712. }
  713. }
  714. /**
  715. * tomoyo_condition - Check condition part.
  716. *
  717. * @r: Pointer to "struct tomoyo_request_info".
  718. * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
  719. *
  720. * Returns true on success, false otherwise.
  721. *
  722. * Caller holds tomoyo_read_lock().
  723. */
  724. bool tomoyo_condition(struct tomoyo_request_info *r,
  725. const struct tomoyo_condition *cond)
  726. {
  727. u32 i;
  728. unsigned long min_v[2] = { 0, 0 };
  729. unsigned long max_v[2] = { 0, 0 };
  730. const struct tomoyo_condition_element *condp;
  731. const struct tomoyo_number_union *numbers_p;
  732. const struct tomoyo_name_union *names_p;
  733. const struct tomoyo_argv *argv;
  734. const struct tomoyo_envp *envp;
  735. struct tomoyo_obj_info *obj;
  736. u16 condc;
  737. u16 argc;
  738. u16 envc;
  739. struct linux_binprm *bprm = NULL;
  740. if (!cond)
  741. return true;
  742. condc = cond->condc;
  743. argc = cond->argc;
  744. envc = cond->envc;
  745. obj = r->obj;
  746. if (r->ee)
  747. bprm = r->ee->bprm;
  748. if (!bprm && (argc || envc))
  749. return false;
  750. condp = (struct tomoyo_condition_element *) (cond + 1);
  751. numbers_p = (const struct tomoyo_number_union *) (condp + condc);
  752. names_p = (const struct tomoyo_name_union *)
  753. (numbers_p + cond->numbers_count);
  754. argv = (const struct tomoyo_argv *) (names_p + cond->names_count);
  755. envp = (const struct tomoyo_envp *) (argv + argc);
  756. for (i = 0; i < condc; i++) {
  757. const bool match = condp->equals;
  758. const u8 left = condp->left;
  759. const u8 right = condp->right;
  760. bool is_bitop[2] = { false, false };
  761. u8 j;
  762. condp++;
  763. /* Check argv[] and envp[] later. */
  764. if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
  765. continue;
  766. /* Check string expressions. */
  767. if (right == TOMOYO_NAME_UNION) {
  768. const struct tomoyo_name_union *ptr = names_p++;
  769. struct tomoyo_path_info *symlink;
  770. struct tomoyo_execve *ee;
  771. struct file *file;
  772. switch (left) {
  773. case TOMOYO_SYMLINK_TARGET:
  774. symlink = obj ? obj->symlink_target : NULL;
  775. if (!symlink ||
  776. !tomoyo_compare_name_union(symlink, ptr)
  777. == match)
  778. goto out;
  779. break;
  780. case TOMOYO_EXEC_REALPATH:
  781. ee = r->ee;
  782. file = ee ? ee->bprm->file : NULL;
  783. if (!tomoyo_scan_exec_realpath(file, ptr,
  784. match))
  785. goto out;
  786. break;
  787. }
  788. continue;
  789. }
  790. /* Check numeric or bit-op expressions. */
  791. for (j = 0; j < 2; j++) {
  792. const u8 index = j ? right : left;
  793. unsigned long value = 0;
  794. switch (index) {
  795. case TOMOYO_TASK_UID:
  796. value = from_kuid(&init_user_ns, current_uid());
  797. break;
  798. case TOMOYO_TASK_EUID:
  799. value = from_kuid(&init_user_ns, current_euid());
  800. break;
  801. case TOMOYO_TASK_SUID:
  802. value = from_kuid(&init_user_ns, current_suid());
  803. break;
  804. case TOMOYO_TASK_FSUID:
  805. value = from_kuid(&init_user_ns, current_fsuid());
  806. break;
  807. case TOMOYO_TASK_GID:
  808. value = from_kgid(&init_user_ns, current_gid());
  809. break;
  810. case TOMOYO_TASK_EGID:
  811. value = from_kgid(&init_user_ns, current_egid());
  812. break;
  813. case TOMOYO_TASK_SGID:
  814. value = from_kgid(&init_user_ns, current_sgid());
  815. break;
  816. case TOMOYO_TASK_FSGID:
  817. value = from_kgid(&init_user_ns, current_fsgid());
  818. break;
  819. case TOMOYO_TASK_PID:
  820. value = tomoyo_sys_getpid();
  821. break;
  822. case TOMOYO_TASK_PPID:
  823. value = tomoyo_sys_getppid();
  824. break;
  825. case TOMOYO_TYPE_IS_SOCKET:
  826. value = S_IFSOCK;
  827. break;
  828. case TOMOYO_TYPE_IS_SYMLINK:
  829. value = S_IFLNK;
  830. break;
  831. case TOMOYO_TYPE_IS_FILE:
  832. value = S_IFREG;
  833. break;
  834. case TOMOYO_TYPE_IS_BLOCK_DEV:
  835. value = S_IFBLK;
  836. break;
  837. case TOMOYO_TYPE_IS_DIRECTORY:
  838. value = S_IFDIR;
  839. break;
  840. case TOMOYO_TYPE_IS_CHAR_DEV:
  841. value = S_IFCHR;
  842. break;
  843. case TOMOYO_TYPE_IS_FIFO:
  844. value = S_IFIFO;
  845. break;
  846. case TOMOYO_MODE_SETUID:
  847. value = S_ISUID;
  848. break;
  849. case TOMOYO_MODE_SETGID:
  850. value = S_ISGID;
  851. break;
  852. case TOMOYO_MODE_STICKY:
  853. value = S_ISVTX;
  854. break;
  855. case TOMOYO_MODE_OWNER_READ:
  856. value = 0400;
  857. break;
  858. case TOMOYO_MODE_OWNER_WRITE:
  859. value = 0200;
  860. break;
  861. case TOMOYO_MODE_OWNER_EXECUTE:
  862. value = 0100;
  863. break;
  864. case TOMOYO_MODE_GROUP_READ:
  865. value = 0040;
  866. break;
  867. case TOMOYO_MODE_GROUP_WRITE:
  868. value = 0020;
  869. break;
  870. case TOMOYO_MODE_GROUP_EXECUTE:
  871. value = 0010;
  872. break;
  873. case TOMOYO_MODE_OTHERS_READ:
  874. value = 0004;
  875. break;
  876. case TOMOYO_MODE_OTHERS_WRITE:
  877. value = 0002;
  878. break;
  879. case TOMOYO_MODE_OTHERS_EXECUTE:
  880. value = 0001;
  881. break;
  882. case TOMOYO_EXEC_ARGC:
  883. if (!bprm)
  884. goto out;
  885. value = bprm->argc;
  886. break;
  887. case TOMOYO_EXEC_ENVC:
  888. if (!bprm)
  889. goto out;
  890. value = bprm->envc;
  891. break;
  892. case TOMOYO_NUMBER_UNION:
  893. /* Fetch values later. */
  894. break;
  895. default:
  896. if (!obj)
  897. goto out;
  898. if (!obj->validate_done) {
  899. tomoyo_get_attributes(obj);
  900. obj->validate_done = true;
  901. }
  902. {
  903. u8 stat_index;
  904. struct tomoyo_mini_stat *stat;
  905. switch (index) {
  906. case TOMOYO_PATH1_UID:
  907. case TOMOYO_PATH1_GID:
  908. case TOMOYO_PATH1_INO:
  909. case TOMOYO_PATH1_MAJOR:
  910. case TOMOYO_PATH1_MINOR:
  911. case TOMOYO_PATH1_TYPE:
  912. case TOMOYO_PATH1_DEV_MAJOR:
  913. case TOMOYO_PATH1_DEV_MINOR:
  914. case TOMOYO_PATH1_PERM:
  915. stat_index = TOMOYO_PATH1;
  916. break;
  917. case TOMOYO_PATH2_UID:
  918. case TOMOYO_PATH2_GID:
  919. case TOMOYO_PATH2_INO:
  920. case TOMOYO_PATH2_MAJOR:
  921. case TOMOYO_PATH2_MINOR:
  922. case TOMOYO_PATH2_TYPE:
  923. case TOMOYO_PATH2_DEV_MAJOR:
  924. case TOMOYO_PATH2_DEV_MINOR:
  925. case TOMOYO_PATH2_PERM:
  926. stat_index = TOMOYO_PATH2;
  927. break;
  928. case TOMOYO_PATH1_PARENT_UID:
  929. case TOMOYO_PATH1_PARENT_GID:
  930. case TOMOYO_PATH1_PARENT_INO:
  931. case TOMOYO_PATH1_PARENT_PERM:
  932. stat_index =
  933. TOMOYO_PATH1_PARENT;
  934. break;
  935. case TOMOYO_PATH2_PARENT_UID:
  936. case TOMOYO_PATH2_PARENT_GID:
  937. case TOMOYO_PATH2_PARENT_INO:
  938. case TOMOYO_PATH2_PARENT_PERM:
  939. stat_index =
  940. TOMOYO_PATH2_PARENT;
  941. break;
  942. default:
  943. goto out;
  944. }
  945. if (!obj->stat_valid[stat_index])
  946. goto out;
  947. stat = &obj->stat[stat_index];
  948. switch (index) {
  949. case TOMOYO_PATH1_UID:
  950. case TOMOYO_PATH2_UID:
  951. case TOMOYO_PATH1_PARENT_UID:
  952. case TOMOYO_PATH2_PARENT_UID:
  953. value = from_kuid(&init_user_ns, stat->uid);
  954. break;
  955. case TOMOYO_PATH1_GID:
  956. case TOMOYO_PATH2_GID:
  957. case TOMOYO_PATH1_PARENT_GID:
  958. case TOMOYO_PATH2_PARENT_GID:
  959. value = from_kgid(&init_user_ns, stat->gid);
  960. break;
  961. case TOMOYO_PATH1_INO:
  962. case TOMOYO_PATH2_INO:
  963. case TOMOYO_PATH1_PARENT_INO:
  964. case TOMOYO_PATH2_PARENT_INO:
  965. value = stat->ino;
  966. break;
  967. case TOMOYO_PATH1_MAJOR:
  968. case TOMOYO_PATH2_MAJOR:
  969. value = MAJOR(stat->dev);
  970. break;
  971. case TOMOYO_PATH1_MINOR:
  972. case TOMOYO_PATH2_MINOR:
  973. value = MINOR(stat->dev);
  974. break;
  975. case TOMOYO_PATH1_TYPE:
  976. case TOMOYO_PATH2_TYPE:
  977. value = stat->mode & S_IFMT;
  978. break;
  979. case TOMOYO_PATH1_DEV_MAJOR:
  980. case TOMOYO_PATH2_DEV_MAJOR:
  981. value = MAJOR(stat->rdev);
  982. break;
  983. case TOMOYO_PATH1_DEV_MINOR:
  984. case TOMOYO_PATH2_DEV_MINOR:
  985. value = MINOR(stat->rdev);
  986. break;
  987. case TOMOYO_PATH1_PERM:
  988. case TOMOYO_PATH2_PERM:
  989. case TOMOYO_PATH1_PARENT_PERM:
  990. case TOMOYO_PATH2_PARENT_PERM:
  991. value = stat->mode & S_IALLUGO;
  992. break;
  993. }
  994. }
  995. break;
  996. }
  997. max_v[j] = value;
  998. min_v[j] = value;
  999. switch (index) {
  1000. case TOMOYO_MODE_SETUID:
  1001. case TOMOYO_MODE_SETGID:
  1002. case TOMOYO_MODE_STICKY:
  1003. case TOMOYO_MODE_OWNER_READ:
  1004. case TOMOYO_MODE_OWNER_WRITE:
  1005. case TOMOYO_MODE_OWNER_EXECUTE:
  1006. case TOMOYO_MODE_GROUP_READ:
  1007. case TOMOYO_MODE_GROUP_WRITE:
  1008. case TOMOYO_MODE_GROUP_EXECUTE:
  1009. case TOMOYO_MODE_OTHERS_READ:
  1010. case TOMOYO_MODE_OTHERS_WRITE:
  1011. case TOMOYO_MODE_OTHERS_EXECUTE:
  1012. is_bitop[j] = true;
  1013. }
  1014. }
  1015. if (left == TOMOYO_NUMBER_UNION) {
  1016. /* Fetch values now. */
  1017. const struct tomoyo_number_union *ptr = numbers_p++;
  1018. min_v[0] = ptr->values[0];
  1019. max_v[0] = ptr->values[1];
  1020. }
  1021. if (right == TOMOYO_NUMBER_UNION) {
  1022. /* Fetch values now. */
  1023. const struct tomoyo_number_union *ptr = numbers_p++;
  1024. if (ptr->group) {
  1025. if (tomoyo_number_matches_group(min_v[0],
  1026. max_v[0],
  1027. ptr->group)
  1028. == match)
  1029. continue;
  1030. } else {
  1031. if ((min_v[0] <= ptr->values[1] &&
  1032. max_v[0] >= ptr->values[0]) == match)
  1033. continue;
  1034. }
  1035. goto out;
  1036. }
  1037. /*
  1038. * Bit operation is valid only when counterpart value
  1039. * represents permission.
  1040. */
  1041. if (is_bitop[0] && is_bitop[1]) {
  1042. goto out;
  1043. } else if (is_bitop[0]) {
  1044. switch (right) {
  1045. case TOMOYO_PATH1_PERM:
  1046. case TOMOYO_PATH1_PARENT_PERM:
  1047. case TOMOYO_PATH2_PERM:
  1048. case TOMOYO_PATH2_PARENT_PERM:
  1049. if (!(max_v[0] & max_v[1]) == !match)
  1050. continue;
  1051. }
  1052. goto out;
  1053. } else if (is_bitop[1]) {
  1054. switch (left) {
  1055. case TOMOYO_PATH1_PERM:
  1056. case TOMOYO_PATH1_PARENT_PERM:
  1057. case TOMOYO_PATH2_PERM:
  1058. case TOMOYO_PATH2_PARENT_PERM:
  1059. if (!(max_v[0] & max_v[1]) == !match)
  1060. continue;
  1061. }
  1062. goto out;
  1063. }
  1064. /* Normal value range comparison. */
  1065. if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
  1066. continue;
  1067. out:
  1068. return false;
  1069. }
  1070. /* Check argv[] and envp[] now. */
  1071. if (r->ee && (argc || envc))
  1072. return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp);
  1073. return true;
  1074. }