policy_parser.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
  4. */
  5. #include <linux/err.h>
  6. #include <linux/slab.h>
  7. #include <linux/parser.h>
  8. #include <linux/types.h>
  9. #include <linux/ctype.h>
  10. #include "policy.h"
  11. #include "policy_parser.h"
  12. #include "digest.h"
  13. #define START_COMMENT '#'
  14. #define IPE_POLICY_DELIM " \t"
  15. #define IPE_LINE_DELIM "\n\r"
  16. /**
  17. * new_parsed_policy() - Allocate and initialize a parsed policy.
  18. *
  19. * Return:
  20. * * a pointer to the ipe_parsed_policy structure - Success
  21. * * %-ENOMEM - Out of memory (OOM)
  22. */
  23. static struct ipe_parsed_policy *new_parsed_policy(void)
  24. {
  25. struct ipe_parsed_policy *p = NULL;
  26. struct ipe_op_table *t = NULL;
  27. size_t i = 0;
  28. p = kzalloc(sizeof(*p), GFP_KERNEL);
  29. if (!p)
  30. return ERR_PTR(-ENOMEM);
  31. p->global_default_action = IPE_ACTION_INVALID;
  32. for (i = 0; i < ARRAY_SIZE(p->rules); ++i) {
  33. t = &p->rules[i];
  34. t->default_action = IPE_ACTION_INVALID;
  35. INIT_LIST_HEAD(&t->rules);
  36. }
  37. return p;
  38. }
  39. /**
  40. * remove_comment() - Truncate all chars following START_COMMENT in a string.
  41. *
  42. * @line: Supplies a policy line string for preprocessing.
  43. */
  44. static void remove_comment(char *line)
  45. {
  46. line = strchr(line, START_COMMENT);
  47. if (line)
  48. *line = '\0';
  49. }
  50. /**
  51. * remove_trailing_spaces() - Truncate all trailing spaces in a string.
  52. *
  53. * @line: Supplies a policy line string for preprocessing.
  54. *
  55. * Return: The length of truncated string.
  56. */
  57. static size_t remove_trailing_spaces(char *line)
  58. {
  59. size_t i = 0;
  60. i = strlen(line);
  61. while (i > 0 && isspace(line[i - 1]))
  62. i--;
  63. line[i] = '\0';
  64. return i;
  65. }
  66. /**
  67. * parse_version() - Parse policy version.
  68. * @ver: Supplies a version string to be parsed.
  69. * @p: Supplies the partial parsed policy.
  70. *
  71. * Return:
  72. * * %0 - Success
  73. * * %-EBADMSG - Version string is invalid
  74. * * %-ERANGE - Version number overflow
  75. * * %-EINVAL - Parsing error
  76. */
  77. static int parse_version(char *ver, struct ipe_parsed_policy *p)
  78. {
  79. u16 *const cv[] = { &p->version.major, &p->version.minor, &p->version.rev };
  80. size_t sep_count = 0;
  81. char *token;
  82. int rc = 0;
  83. while ((token = strsep(&ver, ".")) != NULL) {
  84. /* prevent overflow */
  85. if (sep_count >= ARRAY_SIZE(cv))
  86. return -EBADMSG;
  87. rc = kstrtou16(token, 10, cv[sep_count]);
  88. if (rc)
  89. return rc;
  90. ++sep_count;
  91. }
  92. /* prevent underflow */
  93. if (sep_count != ARRAY_SIZE(cv))
  94. return -EBADMSG;
  95. return 0;
  96. }
  97. enum header_opt {
  98. IPE_HEADER_POLICY_NAME = 0,
  99. IPE_HEADER_POLICY_VERSION,
  100. __IPE_HEADER_MAX
  101. };
  102. static const match_table_t header_tokens = {
  103. {IPE_HEADER_POLICY_NAME, "policy_name=%s"},
  104. {IPE_HEADER_POLICY_VERSION, "policy_version=%s"},
  105. {__IPE_HEADER_MAX, NULL}
  106. };
  107. /**
  108. * parse_header() - Parse policy header information.
  109. * @line: Supplies header line to be parsed.
  110. * @p: Supplies the partial parsed policy.
  111. *
  112. * Return:
  113. * * %0 - Success
  114. * * %-EBADMSG - Header string is invalid
  115. * * %-ENOMEM - Out of memory (OOM)
  116. * * %-ERANGE - Version number overflow
  117. * * %-EINVAL - Version parsing error
  118. */
  119. static int parse_header(char *line, struct ipe_parsed_policy *p)
  120. {
  121. substring_t args[MAX_OPT_ARGS];
  122. char *t, *ver = NULL;
  123. size_t idx = 0;
  124. int rc = 0;
  125. while ((t = strsep(&line, IPE_POLICY_DELIM)) != NULL) {
  126. int token;
  127. if (*t == '\0')
  128. continue;
  129. if (idx >= __IPE_HEADER_MAX) {
  130. rc = -EBADMSG;
  131. goto out;
  132. }
  133. token = match_token(t, header_tokens, args);
  134. if (token != idx) {
  135. rc = -EBADMSG;
  136. goto out;
  137. }
  138. switch (token) {
  139. case IPE_HEADER_POLICY_NAME:
  140. p->name = match_strdup(&args[0]);
  141. if (!p->name)
  142. rc = -ENOMEM;
  143. break;
  144. case IPE_HEADER_POLICY_VERSION:
  145. ver = match_strdup(&args[0]);
  146. if (!ver) {
  147. rc = -ENOMEM;
  148. break;
  149. }
  150. rc = parse_version(ver, p);
  151. break;
  152. default:
  153. rc = -EBADMSG;
  154. }
  155. if (rc)
  156. goto out;
  157. ++idx;
  158. }
  159. if (idx != __IPE_HEADER_MAX)
  160. rc = -EBADMSG;
  161. out:
  162. kfree(ver);
  163. return rc;
  164. }
  165. /**
  166. * token_default() - Determine if the given token is "DEFAULT".
  167. * @token: Supplies the token string to be compared.
  168. *
  169. * Return:
  170. * * %false - The token is not "DEFAULT"
  171. * * %true - The token is "DEFAULT"
  172. */
  173. static bool token_default(char *token)
  174. {
  175. return !strcmp(token, "DEFAULT");
  176. }
  177. /**
  178. * free_rule() - Free the supplied ipe_rule struct.
  179. * @r: Supplies the ipe_rule struct to be freed.
  180. *
  181. * Free a ipe_rule struct @r. Note @r must be removed from any lists before
  182. * calling this function.
  183. */
  184. static void free_rule(struct ipe_rule *r)
  185. {
  186. struct ipe_prop *p, *t;
  187. if (IS_ERR_OR_NULL(r))
  188. return;
  189. list_for_each_entry_safe(p, t, &r->props, next) {
  190. list_del(&p->next);
  191. ipe_digest_free(p->value);
  192. kfree(p);
  193. }
  194. kfree(r);
  195. }
  196. static const match_table_t operation_tokens = {
  197. {IPE_OP_EXEC, "op=EXECUTE"},
  198. {IPE_OP_FIRMWARE, "op=FIRMWARE"},
  199. {IPE_OP_KERNEL_MODULE, "op=KMODULE"},
  200. {IPE_OP_KEXEC_IMAGE, "op=KEXEC_IMAGE"},
  201. {IPE_OP_KEXEC_INITRAMFS, "op=KEXEC_INITRAMFS"},
  202. {IPE_OP_POLICY, "op=POLICY"},
  203. {IPE_OP_X509, "op=X509_CERT"},
  204. {IPE_OP_INVALID, NULL}
  205. };
  206. /**
  207. * parse_operation() - Parse the operation type given a token string.
  208. * @t: Supplies the token string to be parsed.
  209. *
  210. * Return: The parsed operation type.
  211. */
  212. static enum ipe_op_type parse_operation(char *t)
  213. {
  214. substring_t args[MAX_OPT_ARGS];
  215. return match_token(t, operation_tokens, args);
  216. }
  217. static const match_table_t action_tokens = {
  218. {IPE_ACTION_ALLOW, "action=ALLOW"},
  219. {IPE_ACTION_DENY, "action=DENY"},
  220. {IPE_ACTION_INVALID, NULL}
  221. };
  222. /**
  223. * parse_action() - Parse the action type given a token string.
  224. * @t: Supplies the token string to be parsed.
  225. *
  226. * Return: The parsed action type.
  227. */
  228. static enum ipe_action_type parse_action(char *t)
  229. {
  230. substring_t args[MAX_OPT_ARGS];
  231. return match_token(t, action_tokens, args);
  232. }
  233. static const match_table_t property_tokens = {
  234. {IPE_PROP_BOOT_VERIFIED_FALSE, "boot_verified=FALSE"},
  235. {IPE_PROP_BOOT_VERIFIED_TRUE, "boot_verified=TRUE"},
  236. {IPE_PROP_DMV_ROOTHASH, "dmverity_roothash=%s"},
  237. {IPE_PROP_DMV_SIG_FALSE, "dmverity_signature=FALSE"},
  238. {IPE_PROP_DMV_SIG_TRUE, "dmverity_signature=TRUE"},
  239. {IPE_PROP_FSV_DIGEST, "fsverity_digest=%s"},
  240. {IPE_PROP_FSV_SIG_FALSE, "fsverity_signature=FALSE"},
  241. {IPE_PROP_FSV_SIG_TRUE, "fsverity_signature=TRUE"},
  242. {IPE_PROP_INVALID, NULL}
  243. };
  244. /**
  245. * parse_property() - Parse a rule property given a token string.
  246. * @t: Supplies the token string to be parsed.
  247. * @r: Supplies the ipe_rule the parsed property will be associated with.
  248. *
  249. * This function parses and associates a property with an IPE rule based
  250. * on a token string.
  251. *
  252. * Return:
  253. * * %0 - Success
  254. * * %-ENOMEM - Out of memory (OOM)
  255. * * %-EBADMSG - The supplied token cannot be parsed
  256. */
  257. static int parse_property(char *t, struct ipe_rule *r)
  258. {
  259. substring_t args[MAX_OPT_ARGS];
  260. struct ipe_prop *p = NULL;
  261. int rc = 0;
  262. int token;
  263. char *dup = NULL;
  264. p = kzalloc(sizeof(*p), GFP_KERNEL);
  265. if (!p)
  266. return -ENOMEM;
  267. token = match_token(t, property_tokens, args);
  268. switch (token) {
  269. case IPE_PROP_DMV_ROOTHASH:
  270. case IPE_PROP_FSV_DIGEST:
  271. dup = match_strdup(&args[0]);
  272. if (!dup) {
  273. rc = -ENOMEM;
  274. goto err;
  275. }
  276. p->value = ipe_digest_parse(dup);
  277. if (IS_ERR(p->value)) {
  278. rc = PTR_ERR(p->value);
  279. goto err;
  280. }
  281. fallthrough;
  282. case IPE_PROP_BOOT_VERIFIED_FALSE:
  283. case IPE_PROP_BOOT_VERIFIED_TRUE:
  284. case IPE_PROP_DMV_SIG_FALSE:
  285. case IPE_PROP_DMV_SIG_TRUE:
  286. case IPE_PROP_FSV_SIG_FALSE:
  287. case IPE_PROP_FSV_SIG_TRUE:
  288. p->type = token;
  289. break;
  290. default:
  291. rc = -EBADMSG;
  292. break;
  293. }
  294. if (rc)
  295. goto err;
  296. list_add_tail(&p->next, &r->props);
  297. out:
  298. kfree(dup);
  299. return rc;
  300. err:
  301. kfree(p);
  302. goto out;
  303. }
  304. /**
  305. * parse_rule() - parse a policy rule line.
  306. * @line: Supplies rule line to be parsed.
  307. * @p: Supplies the partial parsed policy.
  308. *
  309. * Return:
  310. * * 0 - Success
  311. * * %-ENOMEM - Out of memory (OOM)
  312. * * %-EBADMSG - Policy syntax error
  313. */
  314. static int parse_rule(char *line, struct ipe_parsed_policy *p)
  315. {
  316. enum ipe_action_type action = IPE_ACTION_INVALID;
  317. enum ipe_op_type op = IPE_OP_INVALID;
  318. bool is_default_rule = false;
  319. struct ipe_rule *r = NULL;
  320. bool first_token = true;
  321. bool op_parsed = false;
  322. int rc = 0;
  323. char *t;
  324. if (IS_ERR_OR_NULL(line))
  325. return -EBADMSG;
  326. r = kzalloc(sizeof(*r), GFP_KERNEL);
  327. if (!r)
  328. return -ENOMEM;
  329. INIT_LIST_HEAD(&r->next);
  330. INIT_LIST_HEAD(&r->props);
  331. while (t = strsep(&line, IPE_POLICY_DELIM), line) {
  332. if (*t == '\0')
  333. continue;
  334. if (first_token && token_default(t)) {
  335. is_default_rule = true;
  336. } else {
  337. if (!op_parsed) {
  338. op = parse_operation(t);
  339. if (op == IPE_OP_INVALID)
  340. rc = -EBADMSG;
  341. else
  342. op_parsed = true;
  343. } else {
  344. rc = parse_property(t, r);
  345. }
  346. }
  347. if (rc)
  348. goto err;
  349. first_token = false;
  350. }
  351. action = parse_action(t);
  352. if (action == IPE_ACTION_INVALID) {
  353. rc = -EBADMSG;
  354. goto err;
  355. }
  356. if (is_default_rule) {
  357. if (!list_empty(&r->props)) {
  358. rc = -EBADMSG;
  359. } else if (op == IPE_OP_INVALID) {
  360. if (p->global_default_action != IPE_ACTION_INVALID)
  361. rc = -EBADMSG;
  362. else
  363. p->global_default_action = action;
  364. } else {
  365. if (p->rules[op].default_action != IPE_ACTION_INVALID)
  366. rc = -EBADMSG;
  367. else
  368. p->rules[op].default_action = action;
  369. }
  370. } else if (op != IPE_OP_INVALID && action != IPE_ACTION_INVALID) {
  371. r->op = op;
  372. r->action = action;
  373. } else {
  374. rc = -EBADMSG;
  375. }
  376. if (rc)
  377. goto err;
  378. if (!is_default_rule)
  379. list_add_tail(&r->next, &p->rules[op].rules);
  380. else
  381. free_rule(r);
  382. return rc;
  383. err:
  384. free_rule(r);
  385. return rc;
  386. }
  387. /**
  388. * ipe_free_parsed_policy() - free a parsed policy structure.
  389. * @p: Supplies the parsed policy.
  390. */
  391. void ipe_free_parsed_policy(struct ipe_parsed_policy *p)
  392. {
  393. struct ipe_rule *pp, *t;
  394. size_t i = 0;
  395. if (IS_ERR_OR_NULL(p))
  396. return;
  397. for (i = 0; i < ARRAY_SIZE(p->rules); ++i)
  398. list_for_each_entry_safe(pp, t, &p->rules[i].rules, next) {
  399. list_del(&pp->next);
  400. free_rule(pp);
  401. }
  402. kfree(p->name);
  403. kfree(p);
  404. }
  405. /**
  406. * validate_policy() - validate a parsed policy.
  407. * @p: Supplies the fully parsed policy.
  408. *
  409. * Given a policy structure that was just parsed, validate that all
  410. * operations have their default rules or a global default rule is set.
  411. *
  412. * Return:
  413. * * %0 - Success
  414. * * %-EBADMSG - Policy is invalid
  415. */
  416. static int validate_policy(const struct ipe_parsed_policy *p)
  417. {
  418. size_t i = 0;
  419. if (p->global_default_action != IPE_ACTION_INVALID)
  420. return 0;
  421. for (i = 0; i < ARRAY_SIZE(p->rules); ++i) {
  422. if (p->rules[i].default_action == IPE_ACTION_INVALID)
  423. return -EBADMSG;
  424. }
  425. return 0;
  426. }
  427. /**
  428. * ipe_parse_policy() - Given a string, parse the string into an IPE policy.
  429. * @p: partially filled ipe_policy structure to populate with the result.
  430. * it must have text and textlen set.
  431. *
  432. * Return:
  433. * * %0 - Success
  434. * * %-EBADMSG - Policy is invalid
  435. * * %-ENOMEM - Out of Memory
  436. * * %-ERANGE - Policy version number overflow
  437. * * %-EINVAL - Policy version parsing error
  438. */
  439. int ipe_parse_policy(struct ipe_policy *p)
  440. {
  441. struct ipe_parsed_policy *pp = NULL;
  442. char *policy = NULL, *dup = NULL;
  443. bool header_parsed = false;
  444. char *line = NULL;
  445. size_t len;
  446. int rc = 0;
  447. if (!p->textlen)
  448. return -EBADMSG;
  449. policy = kmemdup_nul(p->text, p->textlen, GFP_KERNEL);
  450. if (!policy)
  451. return -ENOMEM;
  452. dup = policy;
  453. pp = new_parsed_policy();
  454. if (IS_ERR(pp)) {
  455. rc = PTR_ERR(pp);
  456. goto out;
  457. }
  458. while ((line = strsep(&policy, IPE_LINE_DELIM)) != NULL) {
  459. remove_comment(line);
  460. len = remove_trailing_spaces(line);
  461. if (!len)
  462. continue;
  463. if (!header_parsed) {
  464. rc = parse_header(line, pp);
  465. if (rc)
  466. goto err;
  467. header_parsed = true;
  468. } else {
  469. rc = parse_rule(line, pp);
  470. if (rc)
  471. goto err;
  472. }
  473. }
  474. if (!header_parsed || validate_policy(pp)) {
  475. rc = -EBADMSG;
  476. goto err;
  477. }
  478. p->parsed = pp;
  479. out:
  480. kfree(dup);
  481. return rc;
  482. err:
  483. ipe_free_parsed_policy(pp);
  484. goto out;
  485. }