condition.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  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 "
  609. "match=%u\n", __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) /* i == TOMOYO_PATH1_PARENT ||
  711. i == TOMOYO_PATH2_PARENT */
  712. dput(dentry);
  713. }
  714. }
  715. /**
  716. * tomoyo_condition - Check condition part.
  717. *
  718. * @r: Pointer to "struct tomoyo_request_info".
  719. * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
  720. *
  721. * Returns true on success, false otherwise.
  722. *
  723. * Caller holds tomoyo_read_lock().
  724. */
  725. bool tomoyo_condition(struct tomoyo_request_info *r,
  726. const struct tomoyo_condition *cond)
  727. {
  728. u32 i;
  729. unsigned long min_v[2] = { 0, 0 };
  730. unsigned long max_v[2] = { 0, 0 };
  731. const struct tomoyo_condition_element *condp;
  732. const struct tomoyo_number_union *numbers_p;
  733. const struct tomoyo_name_union *names_p;
  734. const struct tomoyo_argv *argv;
  735. const struct tomoyo_envp *envp;
  736. struct tomoyo_obj_info *obj;
  737. u16 condc;
  738. u16 argc;
  739. u16 envc;
  740. struct linux_binprm *bprm = NULL;
  741. if (!cond)
  742. return true;
  743. condc = cond->condc;
  744. argc = cond->argc;
  745. envc = cond->envc;
  746. obj = r->obj;
  747. if (r->ee)
  748. bprm = r->ee->bprm;
  749. if (!bprm && (argc || envc))
  750. return false;
  751. condp = (struct tomoyo_condition_element *) (cond + 1);
  752. numbers_p = (const struct tomoyo_number_union *) (condp + condc);
  753. names_p = (const struct tomoyo_name_union *)
  754. (numbers_p + cond->numbers_count);
  755. argv = (const struct tomoyo_argv *) (names_p + cond->names_count);
  756. envp = (const struct tomoyo_envp *) (argv + argc);
  757. for (i = 0; i < condc; i++) {
  758. const bool match = condp->equals;
  759. const u8 left = condp->left;
  760. const u8 right = condp->right;
  761. bool is_bitop[2] = { false, false };
  762. u8 j;
  763. condp++;
  764. /* Check argv[] and envp[] later. */
  765. if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
  766. continue;
  767. /* Check string expressions. */
  768. if (right == TOMOYO_NAME_UNION) {
  769. const struct tomoyo_name_union *ptr = names_p++;
  770. switch (left) {
  771. struct tomoyo_path_info *symlink;
  772. struct tomoyo_execve *ee;
  773. struct file *file;
  774. case TOMOYO_SYMLINK_TARGET:
  775. symlink = obj ? obj->symlink_target : NULL;
  776. if (!symlink ||
  777. !tomoyo_compare_name_union(symlink, ptr)
  778. == match)
  779. goto out;
  780. break;
  781. case TOMOYO_EXEC_REALPATH:
  782. ee = r->ee;
  783. file = ee ? ee->bprm->file : NULL;
  784. if (!tomoyo_scan_exec_realpath(file, ptr,
  785. match))
  786. goto out;
  787. break;
  788. }
  789. continue;
  790. }
  791. /* Check numeric or bit-op expressions. */
  792. for (j = 0; j < 2; j++) {
  793. const u8 index = j ? right : left;
  794. unsigned long value = 0;
  795. switch (index) {
  796. case TOMOYO_TASK_UID:
  797. value = from_kuid(&init_user_ns, current_uid());
  798. break;
  799. case TOMOYO_TASK_EUID:
  800. value = from_kuid(&init_user_ns, current_euid());
  801. break;
  802. case TOMOYO_TASK_SUID:
  803. value = from_kuid(&init_user_ns, current_suid());
  804. break;
  805. case TOMOYO_TASK_FSUID:
  806. value = from_kuid(&init_user_ns, current_fsuid());
  807. break;
  808. case TOMOYO_TASK_GID:
  809. value = from_kgid(&init_user_ns, current_gid());
  810. break;
  811. case TOMOYO_TASK_EGID:
  812. value = from_kgid(&init_user_ns, current_egid());
  813. break;
  814. case TOMOYO_TASK_SGID:
  815. value = from_kgid(&init_user_ns, current_sgid());
  816. break;
  817. case TOMOYO_TASK_FSGID:
  818. value = from_kgid(&init_user_ns, current_fsgid());
  819. break;
  820. case TOMOYO_TASK_PID:
  821. value = tomoyo_sys_getpid();
  822. break;
  823. case TOMOYO_TASK_PPID:
  824. value = tomoyo_sys_getppid();
  825. break;
  826. case TOMOYO_TYPE_IS_SOCKET:
  827. value = S_IFSOCK;
  828. break;
  829. case TOMOYO_TYPE_IS_SYMLINK:
  830. value = S_IFLNK;
  831. break;
  832. case TOMOYO_TYPE_IS_FILE:
  833. value = S_IFREG;
  834. break;
  835. case TOMOYO_TYPE_IS_BLOCK_DEV:
  836. value = S_IFBLK;
  837. break;
  838. case TOMOYO_TYPE_IS_DIRECTORY:
  839. value = S_IFDIR;
  840. break;
  841. case TOMOYO_TYPE_IS_CHAR_DEV:
  842. value = S_IFCHR;
  843. break;
  844. case TOMOYO_TYPE_IS_FIFO:
  845. value = S_IFIFO;
  846. break;
  847. case TOMOYO_MODE_SETUID:
  848. value = S_ISUID;
  849. break;
  850. case TOMOYO_MODE_SETGID:
  851. value = S_ISGID;
  852. break;
  853. case TOMOYO_MODE_STICKY:
  854. value = S_ISVTX;
  855. break;
  856. case TOMOYO_MODE_OWNER_READ:
  857. value = S_IRUSR;
  858. break;
  859. case TOMOYO_MODE_OWNER_WRITE:
  860. value = S_IWUSR;
  861. break;
  862. case TOMOYO_MODE_OWNER_EXECUTE:
  863. value = S_IXUSR;
  864. break;
  865. case TOMOYO_MODE_GROUP_READ:
  866. value = S_IRGRP;
  867. break;
  868. case TOMOYO_MODE_GROUP_WRITE:
  869. value = S_IWGRP;
  870. break;
  871. case TOMOYO_MODE_GROUP_EXECUTE:
  872. value = S_IXGRP;
  873. break;
  874. case TOMOYO_MODE_OTHERS_READ:
  875. value = S_IROTH;
  876. break;
  877. case TOMOYO_MODE_OTHERS_WRITE:
  878. value = S_IWOTH;
  879. break;
  880. case TOMOYO_MODE_OTHERS_EXECUTE:
  881. value = S_IXOTH;
  882. break;
  883. case TOMOYO_EXEC_ARGC:
  884. if (!bprm)
  885. goto out;
  886. value = bprm->argc;
  887. break;
  888. case TOMOYO_EXEC_ENVC:
  889. if (!bprm)
  890. goto out;
  891. value = bprm->envc;
  892. break;
  893. case TOMOYO_NUMBER_UNION:
  894. /* Fetch values later. */
  895. break;
  896. default:
  897. if (!obj)
  898. goto out;
  899. if (!obj->validate_done) {
  900. tomoyo_get_attributes(obj);
  901. obj->validate_done = true;
  902. }
  903. {
  904. u8 stat_index;
  905. struct tomoyo_mini_stat *stat;
  906. switch (index) {
  907. case TOMOYO_PATH1_UID:
  908. case TOMOYO_PATH1_GID:
  909. case TOMOYO_PATH1_INO:
  910. case TOMOYO_PATH1_MAJOR:
  911. case TOMOYO_PATH1_MINOR:
  912. case TOMOYO_PATH1_TYPE:
  913. case TOMOYO_PATH1_DEV_MAJOR:
  914. case TOMOYO_PATH1_DEV_MINOR:
  915. case TOMOYO_PATH1_PERM:
  916. stat_index = TOMOYO_PATH1;
  917. break;
  918. case TOMOYO_PATH2_UID:
  919. case TOMOYO_PATH2_GID:
  920. case TOMOYO_PATH2_INO:
  921. case TOMOYO_PATH2_MAJOR:
  922. case TOMOYO_PATH2_MINOR:
  923. case TOMOYO_PATH2_TYPE:
  924. case TOMOYO_PATH2_DEV_MAJOR:
  925. case TOMOYO_PATH2_DEV_MINOR:
  926. case TOMOYO_PATH2_PERM:
  927. stat_index = TOMOYO_PATH2;
  928. break;
  929. case TOMOYO_PATH1_PARENT_UID:
  930. case TOMOYO_PATH1_PARENT_GID:
  931. case TOMOYO_PATH1_PARENT_INO:
  932. case TOMOYO_PATH1_PARENT_PERM:
  933. stat_index =
  934. TOMOYO_PATH1_PARENT;
  935. break;
  936. case TOMOYO_PATH2_PARENT_UID:
  937. case TOMOYO_PATH2_PARENT_GID:
  938. case TOMOYO_PATH2_PARENT_INO:
  939. case TOMOYO_PATH2_PARENT_PERM:
  940. stat_index =
  941. TOMOYO_PATH2_PARENT;
  942. break;
  943. default:
  944. goto out;
  945. }
  946. if (!obj->stat_valid[stat_index])
  947. goto out;
  948. stat = &obj->stat[stat_index];
  949. switch (index) {
  950. case TOMOYO_PATH1_UID:
  951. case TOMOYO_PATH2_UID:
  952. case TOMOYO_PATH1_PARENT_UID:
  953. case TOMOYO_PATH2_PARENT_UID:
  954. value = from_kuid(&init_user_ns, stat->uid);
  955. break;
  956. case TOMOYO_PATH1_GID:
  957. case TOMOYO_PATH2_GID:
  958. case TOMOYO_PATH1_PARENT_GID:
  959. case TOMOYO_PATH2_PARENT_GID:
  960. value = from_kgid(&init_user_ns, stat->gid);
  961. break;
  962. case TOMOYO_PATH1_INO:
  963. case TOMOYO_PATH2_INO:
  964. case TOMOYO_PATH1_PARENT_INO:
  965. case TOMOYO_PATH2_PARENT_INO:
  966. value = stat->ino;
  967. break;
  968. case TOMOYO_PATH1_MAJOR:
  969. case TOMOYO_PATH2_MAJOR:
  970. value = MAJOR(stat->dev);
  971. break;
  972. case TOMOYO_PATH1_MINOR:
  973. case TOMOYO_PATH2_MINOR:
  974. value = MINOR(stat->dev);
  975. break;
  976. case TOMOYO_PATH1_TYPE:
  977. case TOMOYO_PATH2_TYPE:
  978. value = stat->mode & S_IFMT;
  979. break;
  980. case TOMOYO_PATH1_DEV_MAJOR:
  981. case TOMOYO_PATH2_DEV_MAJOR:
  982. value = MAJOR(stat->rdev);
  983. break;
  984. case TOMOYO_PATH1_DEV_MINOR:
  985. case TOMOYO_PATH2_DEV_MINOR:
  986. value = MINOR(stat->rdev);
  987. break;
  988. case TOMOYO_PATH1_PERM:
  989. case TOMOYO_PATH2_PERM:
  990. case TOMOYO_PATH1_PARENT_PERM:
  991. case TOMOYO_PATH2_PARENT_PERM:
  992. value = stat->mode & S_IALLUGO;
  993. break;
  994. }
  995. }
  996. break;
  997. }
  998. max_v[j] = value;
  999. min_v[j] = value;
  1000. switch (index) {
  1001. case TOMOYO_MODE_SETUID:
  1002. case TOMOYO_MODE_SETGID:
  1003. case TOMOYO_MODE_STICKY:
  1004. case TOMOYO_MODE_OWNER_READ:
  1005. case TOMOYO_MODE_OWNER_WRITE:
  1006. case TOMOYO_MODE_OWNER_EXECUTE:
  1007. case TOMOYO_MODE_GROUP_READ:
  1008. case TOMOYO_MODE_GROUP_WRITE:
  1009. case TOMOYO_MODE_GROUP_EXECUTE:
  1010. case TOMOYO_MODE_OTHERS_READ:
  1011. case TOMOYO_MODE_OTHERS_WRITE:
  1012. case TOMOYO_MODE_OTHERS_EXECUTE:
  1013. is_bitop[j] = true;
  1014. }
  1015. }
  1016. if (left == TOMOYO_NUMBER_UNION) {
  1017. /* Fetch values now. */
  1018. const struct tomoyo_number_union *ptr = numbers_p++;
  1019. min_v[0] = ptr->values[0];
  1020. max_v[0] = ptr->values[1];
  1021. }
  1022. if (right == TOMOYO_NUMBER_UNION) {
  1023. /* Fetch values now. */
  1024. const struct tomoyo_number_union *ptr = numbers_p++;
  1025. if (ptr->group) {
  1026. if (tomoyo_number_matches_group(min_v[0],
  1027. max_v[0],
  1028. ptr->group)
  1029. == match)
  1030. continue;
  1031. } else {
  1032. if ((min_v[0] <= ptr->values[1] &&
  1033. max_v[0] >= ptr->values[0]) == match)
  1034. continue;
  1035. }
  1036. goto out;
  1037. }
  1038. /*
  1039. * Bit operation is valid only when counterpart value
  1040. * represents permission.
  1041. */
  1042. if (is_bitop[0] && is_bitop[1]) {
  1043. goto out;
  1044. } else if (is_bitop[0]) {
  1045. switch (right) {
  1046. case TOMOYO_PATH1_PERM:
  1047. case TOMOYO_PATH1_PARENT_PERM:
  1048. case TOMOYO_PATH2_PERM:
  1049. case TOMOYO_PATH2_PARENT_PERM:
  1050. if (!(max_v[0] & max_v[1]) == !match)
  1051. continue;
  1052. }
  1053. goto out;
  1054. } else if (is_bitop[1]) {
  1055. switch (left) {
  1056. case TOMOYO_PATH1_PERM:
  1057. case TOMOYO_PATH1_PARENT_PERM:
  1058. case TOMOYO_PATH2_PERM:
  1059. case TOMOYO_PATH2_PARENT_PERM:
  1060. if (!(max_v[0] & max_v[1]) == !match)
  1061. continue;
  1062. }
  1063. goto out;
  1064. }
  1065. /* Normal value range comparison. */
  1066. if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
  1067. continue;
  1068. out:
  1069. return false;
  1070. }
  1071. /* Check argv[] and envp[] now. */
  1072. if (r->ee && (argc || envc))
  1073. return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp);
  1074. return true;
  1075. }