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