| @@ -74,7 +74,7 @@ struct ima_rule_entry { · 73 unmodified lines |
| 74 | 74 | int pcr; |
| 75 | 75 | struct { |
| 76 | 76 | void *rule; /* LSM file metadata specific */ |
| 77 | | − void *args_p; /* audit value */ |
| 77 | + char *args_p; /* audit value */ |
| 78 | 78 | int type; /* audit type */ |
| 79 | 79 | } lsm[MAX_LSM_RULES]; |
| 80 | 80 | char *fsname; |
| @@ -258,9 +258,24 @@ static void ima_lsm_free_rule(struct ima_rule_entry *entry) · 177 unmodified lines |
| 258 | 258 | int i; |
| 259 | 259 | |
| 260 | 260 | for (i = 0; i < MAX_LSM_RULES; i++) { |
| 261 | | − kfree(entry->lsm[i].rule); |
| 261 | + security_filter_rule_free(entry->lsm[i].rule); |
| 262 | 262 | kfree(entry->lsm[i].args_p); |
| 263 | 263 | } |
| 264 | +} |
| 265 | + |
| 266 | +static void ima_free_rule(struct ima_rule_entry *entry) |
| 267 | +{ |
| 268 | + if (!entry) |
| 269 | + return; |
| 270 | + |
| 271 | + /* |
| 272 | + * entry->template->fields may be allocated in ima_parse_rule() but that |
| 273 | + * reference is owned by the corresponding ima_template_desc element in |
| 274 | + * the defined_templates list and cannot be freed here |
| 275 | + */ |
| 276 | + kfree(entry->fsname); |
| 277 | + kfree(entry->keyrings); |
| 278 | + ima_lsm_free_rule(entry); |
| 264 | 279 | kfree(entry); |
| 265 | 280 | } |
| 266 | 281 | |
| @@ -285,10 +300,13 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) · 18 unmodified lines |
| 285 | 300 | continue; |
| 286 | 301 | |
| 287 | 302 | nentry->lsm[i].type = entry->lsm[i].type; |
| 288 | | − nentry->lsm[i].args_p = kstrdup(entry->lsm[i].args_p, |
| 289 | | − GFP_KERNEL); |
| 290 | | − if (!nentry->lsm[i].args_p) |
| 291 | | − goto out_err; |
| 303 | + nentry->lsm[i].args_p = entry->lsm[i].args_p; |
| 304 | + /* |
| 305 | + * Remove the reference from entry so that the associated |
| 306 | + * memory will not be freed during a later call to |
| 307 | + * ima_lsm_free_rule(entry). |
| 308 | + */ |
| 309 | + entry->lsm[i].args_p = NULL; |
| 292 | 310 | |
| 293 | 311 | security_filter_rule_init(nentry->lsm[i].type, |
| 294 | 312 | Audit_equal, |
| @@ -296,13 +314,9 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) · 1 unmodified line |
| 296 | 314 | &nentry->lsm[i].rule); |
| 297 | 315 | if (!nentry->lsm[i].rule) |
| 298 | 316 | pr_warn("rule for LSM \'%s\' is undefined\n", |
| 299 | | − (char *)entry->lsm[i].args_p); |
| 317 | + nentry->lsm[i].args_p); |
| 300 | 318 | } |
| 301 | 319 | return nentry; |
| 302 | | − |
| 303 | | −out_err: |
| 304 | | − ima_lsm_free_rule(nentry); |
| 305 | | − return NULL; |
| 306 | 320 | } |
| 307 | 321 | |
| 308 | 322 | static int ima_lsm_update_rule(struct ima_rule_entry *entry) |
| @@ -315,11 +329,29 @@ static int ima_lsm_update_rule(struct ima_rule_entry *entry) · 6 unmodified lines |
| 315 | 329 | |
| 316 | 330 | list_replace_rcu(&entry->list, &nentry->list); |
| 317 | 331 | synchronize_rcu(); |
| 332 | + /* |
| 333 | + * ima_lsm_copy_rule() shallow copied all references, except for the |
| 334 | + * LSM references, from entry to nentry so we only want to free the LSM |
| 335 | + * references and the entry itself. All other memory refrences will now |
| 336 | + * be owned by nentry. |
| 337 | + */ |
| 318 | 338 | ima_lsm_free_rule(entry); |
| 339 | + kfree(entry); |
| 319 | 340 | |
| 320 | 341 | return 0; |
| 321 | 342 | } |
| 322 | 343 | |
| 344 | +static bool ima_rule_contains_lsm_cond(struct ima_rule_entry *entry) |
| 345 | +{ |
| 346 | + int i; |
| 347 | + |
| 348 | + for (i = 0; i < MAX_LSM_RULES; i++) |
| 349 | + if (entry->lsm[i].args_p) |
| 350 | + return true; |
| 351 | + |
| 352 | + return false; |
| 353 | +} |
| 354 | + |
| 323 | 355 | /* |
| 324 | 356 | * The LSM policy can be reloaded, leaving the IMA LSM based rules referring |
| 325 | 357 | * to the old, stale LSM policy. Update the IMA LSM based rules to reflect |
| @@ -328,17 +360,10 @@ static int ima_lsm_update_rule(struct ima_rule_entry *entry) · 2 unmodified lines |
| 328 | 360 | static void ima_lsm_update_rules(void) |
| 329 | 361 | { |
| 330 | 362 | struct ima_rule_entry *entry, *e; |
| 331 | | − int i, result, needs_update; |
| 363 | + int result; |
| 332 | 364 | |
| 333 | 365 | list_for_each_entry_safe(entry, e, &ima_policy_rules, list) { |
| 334 | | − needs_update = 0; |
| 335 | | − for (i = 0; i < MAX_LSM_RULES; i++) { |
| 336 | | − if (entry->lsm[i].args_p) { |
| 337 | | − needs_update = 1; |
| 338 | | − break; |
| 339 | | − } |
| 340 | | − } |
| 341 | | − if (!needs_update) |
| 366 | + if (!ima_rule_contains_lsm_cond(entry)) |
| 342 | 367 | continue; |
| 343 | 368 | |
| 344 | 369 | result = ima_lsm_update_rule(entry); |
| @@ -418,13 +443,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, · 73 unmodified lines |
| 418 | 443 | { |
| 419 | 444 | int i; |
| 420 | 445 | |
| 421 | | − if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) { |
| 422 | | − if ((rule->flags & IMA_FUNC) && (rule->func == func)) { |
| 423 | | − if (func == KEY_CHECK) |
| 424 | | − return ima_match_keyring(rule, keyring, cred); |
| 425 | | − return true; |
| 426 | | − } |
| 427 | | − return false; |
| 446 | + if (func == KEY_CHECK) { |
| 447 | + return (rule->flags & IMA_FUNC) && (rule->func == func) && |
| 448 | + ima_match_keyring(rule, keyring, cred); |
| 428 | 449 | } |
| 429 | 450 | if ((rule->flags & IMA_FUNC) && |
| 430 | 451 | (rule->func != func && func != POST_SETATTR)) |
| @@ -886,10 +907,11 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, · 455 unmodified lines |
| 886 | 907 | &entry->lsm[lsm_rule].rule); |
| 887 | 908 | if (!entry->lsm[lsm_rule].rule) { |
| 888 | 909 | pr_warn("rule for LSM \'%s\' is undefined\n", |
| 889 | | − (char *)entry->lsm[lsm_rule].args_p); |
| 910 | + entry->lsm[lsm_rule].args_p); |
| 890 | 911 | |
| 891 | 912 | if (ima_rules == &ima_default_rules) { |
| 892 | 913 | kfree(entry->lsm[lsm_rule].args_p); |
| 914 | + entry->lsm[lsm_rule].args_p = NULL; |
| 893 | 915 | result = -EINVAL; |
| 894 | 916 | } else |
| 895 | 917 | result = 0; |
| @@ -949,6 +971,96 @@ static void check_template_modsig(const struct ima_template_desc *template) · 53 unmodified lines |
| 949 | 971 | #undef MSG |
| 950 | 972 | } |
| 951 | 973 | |
| 974 | +static bool ima_validate_rule(struct ima_rule_entry *entry) |
| 975 | +{ |
| 976 | + /* Ensure that the action is set and is compatible with the flags */ |
| 977 | + if (entry->action == UNKNOWN) |
| 978 | + return false; |
| 979 | + |
| 980 | + if (entry->action != MEASURE && entry->flags & IMA_PCR) |
| 981 | + return false; |
| 982 | + |
| 983 | + if (entry->action != APPRAISE && |
| 984 | + entry->flags & (IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED | IMA_CHECK_BLACKLIST)) |
| 985 | + return false; |
| 986 | + |
| 987 | + /* |
| 988 | + * The IMA_FUNC bit must be set if and only if there's a valid hook |
| 989 | + * function specified, and vice versa. Enforcing this property allows |
| 990 | + * for the NONE case below to validate a rule without an explicit hook |
| 991 | + * function. |
| 992 | + */ |
| 993 | + if (((entry->flags & IMA_FUNC) && entry->func == NONE) || |
| 994 | + (!(entry->flags & IMA_FUNC) && entry->func != NONE)) |
| 995 | + return false; |
| 996 | + |
| 997 | + /* |
| 998 | + * Ensure that the hook function is compatible with the other |
| 999 | + * components of the rule |
| 1000 | + */ |
| 1001 | + switch (entry->func) { |
| 1002 | + case NONE: |
| 1003 | + case FILE_CHECK: |
| 1004 | + case MMAP_CHECK: |
| 1005 | + case BPRM_CHECK: |
| 1006 | + case CREDS_CHECK: |
| 1007 | + case POST_SETATTR: |
| 1008 | + case FIRMWARE_CHECK: |
| 1009 | + case POLICY_CHECK: |
| 1010 | + if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC | |
| 1011 | + IMA_UID | IMA_FOWNER | IMA_FSUUID | |
| 1012 | + IMA_INMASK | IMA_EUID | IMA_PCR | |
| 1013 | + IMA_FSNAME | IMA_DIGSIG_REQUIRED | |
| 1014 | + IMA_PERMIT_DIRECTIO)) |
| 1015 | + return false; |
| 1016 | + |
| 1017 | + break; |
| 1018 | + case MODULE_CHECK: |
| 1019 | + case KEXEC_KERNEL_CHECK: |
| 1020 | + case KEXEC_INITRAMFS_CHECK: |
| 1021 | + if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC | |
| 1022 | + IMA_UID | IMA_FOWNER | IMA_FSUUID | |
| 1023 | + IMA_INMASK | IMA_EUID | IMA_PCR | |
| 1024 | + IMA_FSNAME | IMA_DIGSIG_REQUIRED | |
| 1025 | + IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED | |
| 1026 | + IMA_CHECK_BLACKLIST)) |
| 1027 | + return false; |
| 1028 | + |
| 1029 | + break; |
| 1030 | + case KEXEC_CMDLINE: |
| 1031 | + if (entry->action & ~(MEASURE | DONT_MEASURE)) |
| 1032 | + return false; |
| 1033 | + |
| 1034 | + if (entry->flags & ~(IMA_FUNC | IMA_FSMAGIC | IMA_UID | |
| 1035 | + IMA_FOWNER | IMA_FSUUID | IMA_EUID | |
| 1036 | + IMA_PCR | IMA_FSNAME)) |
| 1037 | + return false; |
| 1038 | + |
| 1039 | + break; |
| 1040 | + case KEY_CHECK: |
| 1041 | + if (entry->action & ~(MEASURE | DONT_MEASURE)) |
| 1042 | + return false; |
| 1043 | + |
| 1044 | + if (entry->flags & ~(IMA_FUNC | IMA_UID | IMA_PCR | |
| 1045 | + IMA_KEYRINGS)) |
| 1046 | + return false; |
| 1047 | + |
| 1048 | + if (ima_rule_contains_lsm_cond(entry)) |
| 1049 | + return false; |
| 1050 | + |
| 1051 | + break; |
| 1052 | + default: |
| 1053 | + return false; |
| 1054 | + } |
| 1055 | + |
| 1056 | + /* Ensure that combinations of flags are compatible with each other */ |
| 1057 | + if (entry->flags & IMA_CHECK_BLACKLIST && |
| 1058 | + !(entry->flags & IMA_MODSIG_ALLOWED)) |
| 1059 | + return false; |
| 1060 | + |
| 1061 | + return true; |
| 1062 | +} |
| 1063 | + |
| 952 | 1064 | static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) |
| 953 | 1065 | { |
| 954 | 1066 | struct audit_buffer *ab; |
| @@ -1126,8 +1238,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) · 171 unmodified lines |
| 1126 | 1238 | keyrings_len = strlen(args[0].from) + 1; |
| 1127 | 1239 | |
| 1128 | 1240 | if ((entry->keyrings) || |
| 1129 | | − (entry->action != MEASURE) || |
| 1130 | | − (entry->func != KEY_CHECK) || |
| 1131 | 1241 | (keyrings_len < 2)) { |
| 1132 | 1242 | result = -EINVAL; |
| 1133 | 1243 | break; |
| @@ -1267,15 +1377,10 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) · 133 unmodified lines |
| 1267 | 1377 | AUDIT_SUBJ_TYPE); |
| 1268 | 1378 | break; |
| 1269 | 1379 | case Opt_appraise_type: |
| 1270 | | − if (entry->action != APPRAISE) { |
| 1271 | | − result = -EINVAL; |
| 1272 | | − break; |
| 1273 | | − } |
| 1274 | | − |
| 1275 | 1380 | ima_log_string(ab, "appraise_type", args[0].from); |
| 1276 | 1381 | if ((strcmp(args[0].from, "imasig")) == 0) |
| 1277 | 1382 | entry->flags |= IMA_DIGSIG_REQUIRED; |
| 1278 | | − else if (ima_hook_supports_modsig(entry->func) && |
| 1383 | + else if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) && |
| 1279 | 1384 | strcmp(args[0].from, "imasig|modsig") == 0) |
| 1280 | 1385 | entry->flags |= IMA_DIGSIG_REQUIRED | |
| 1281 | 1386 | IMA_MODSIG_ALLOWED; |
| @@ -1284,17 +1389,16 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) · 2 unmodified lines |
| 1284 | 1389 | break; |
| 1285 | 1390 | case Opt_appraise_flag: |
| 1286 | 1391 | ima_log_string(ab, "appraise_flag", args[0].from); |
| 1287 | | − if (strstr(args[0].from, "blacklist")) |
| 1392 | + if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) && |
| 1393 | + strstr(args[0].from, "blacklist")) |
| 1288 | 1394 | entry->flags |= IMA_CHECK_BLACKLIST; |
| 1395 | + else |
| 1396 | + result = -EINVAL; |
| 1289 | 1397 | break; |
| 1290 | 1398 | case Opt_permit_directio: |
| 1291 | 1399 | entry->flags |= IMA_PERMIT_DIRECTIO; |
| 1292 | 1400 | break; |
| 1293 | 1401 | case Opt_pcr: |
| 1294 | | − if (entry->action != MEASURE) { |
| 1295 | | − result = -EINVAL; |
| 1296 | | − break; |
| 1297 | | − } |
| 1298 | 1402 | ima_log_string(ab, "pcr", args[0].from); |
| 1299 | 1403 | |
| 1300 | 1404 | result = kstrtoint(args[0].from, 10, &entry->pcr); |
| @@ -1332,7 +1436,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) · 31 unmodified lines |
| 1332 | 1436 | break; |
| 1333 | 1437 | } |
| 1334 | 1438 | } |
| 1335 | | − if (!result && (entry->action == UNKNOWN)) |
| 1439 | + if (!result && !ima_validate_rule(entry)) |
| 1336 | 1440 | result = -EINVAL; |
| 1337 | 1441 | else if (entry->action == APPRAISE) |
| 1338 | 1442 | temp_ima_appraise |= ima_appraise_flag(entry->func); |
| @@ -1381,7 +1485,7 @@ ssize_t ima_parse_add_rule(char *rule) · 42 unmodified lines |
| 1381 | 1485 | |
| 1382 | 1486 | result = ima_parse_rule(p, entry); |
| 1383 | 1487 | if (result) { |
| 1384 | | − kfree(entry); |
| 1488 | + ima_free_rule(entry); |
| 1385 | 1489 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, |
| 1386 | 1490 | NULL, op, "invalid-policy", result, |
| 1387 | 1491 | audit_info); |
| @@ -1402,15 +1506,11 @@ ssize_t ima_parse_add_rule(char *rule) · 14 unmodified lines |
| 1402 | 1506 | void ima_delete_rules(void) |
| 1403 | 1507 | { |
| 1404 | 1508 | struct ima_rule_entry *entry, *tmp; |
| 1405 | | − int i; |
| 1406 | 1509 | |
| 1407 | 1510 | temp_ima_appraise = 0; |
| 1408 | 1511 | list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) { |
| 1409 | | − for (i = 0; i < MAX_LSM_RULES; i++) |
| 1410 | | − kfree(entry->lsm[i].args_p); |
| 1411 | | − |
| 1412 | 1512 | list_del(&entry->list); |
| 1413 | | − kfree(entry); |
| 1513 | + ima_free_rule(entry); |
| 1414 | 1514 | } |
| 1415 | 1515 | } |
| 1416 | 1516 | |
| @@ -1589,27 +1689,27 @@ int ima_policy_show(struct seq_file *m, void *v) · 172 unmodified lines |
| 1589 | 1689 | switch (i) { |
| 1590 | 1690 | case LSM_OBJ_USER: |
| 1591 | 1691 | seq_printf(m, pt(Opt_obj_user), |
| 1592 | | − (char *)entry->lsm[i].args_p); |
| 1692 | + entry->lsm[i].args_p); |
| 1593 | 1693 | break; |
| 1594 | 1694 | case LSM_OBJ_ROLE: |
| 1595 | 1695 | seq_printf(m, pt(Opt_obj_role), |
| 1596 | | − (char *)entry->lsm[i].args_p); |
| 1696 | + entry->lsm[i].args_p); |
| 1597 | 1697 | break; |
| 1598 | 1698 | case LSM_OBJ_TYPE: |
| 1599 | 1699 | seq_printf(m, pt(Opt_obj_type), |
| 1600 | | − (char *)entry->lsm[i].args_p); |
| 1700 | + entry->lsm[i].args_p); |
| 1601 | 1701 | break; |
| 1602 | 1702 | case LSM_SUBJ_USER: |
| 1603 | 1703 | seq_printf(m, pt(Opt_subj_user), |
| 1604 | | − (char *)entry->lsm[i].args_p); |
| 1704 | + entry->lsm[i].args_p); |
| 1605 | 1705 | break; |
| 1606 | 1706 | case LSM_SUBJ_ROLE: |
| 1607 | 1707 | seq_printf(m, pt(Opt_subj_role), |
| 1608 | | − (char *)entry->lsm[i].args_p); |
| 1708 | + entry->lsm[i].args_p); |
| 1609 | 1709 | break; |
| 1610 | 1710 | case LSM_SUBJ_TYPE: |
| 1611 | 1711 | seq_printf(m, pt(Opt_subj_type), |
| 1612 | | − (char *)entry->lsm[i].args_p); |
| 1712 | + entry->lsm[i].args_p); |
| 1613 | 1713 | break; |
| 1614 | 1714 | } |
| 1615 | 1715 | seq_puts(m, " "); |