| @@ -74,7 +74,7 @@ struct ima_rule_entry { · 73 unmodified lines |
| 74 | int pcr; | 74 | int pcr; |
| 75 | struct { | 75 | struct { |
| 76 | void *rule; /* LSM file metadata specific */ | 76 | void *rule; /* LSM file metadata specific */ |
| 77 | void *args_p; /* audit value */ | 77 | char *args_p; /* audit value */ |
| 78 | int type; /* audit type */ | 78 | int type; /* audit type */ |
| 79 | } lsm[MAX_LSM_RULES]; | 79 | } lsm[MAX_LSM_RULES]; |
| 80 | char *fsname; | 80 | char *fsname; |
| @@ -258,9 +258,24 @@ static void ima_lsm_free_rule(struct ima_rule_entry *entry) · 177 unmodified lines |
| 258 | int i; | 258 | int i; |
| 259 | | 259 | |
| 260 | for (i = 0; i < MAX_LSM_RULES; i++) { | 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 | kfree(entry->lsm[i].args_p); | 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 | kfree(entry); | 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 | continue; | 300 | continue; |
| 286 | | 301 | |
| 287 | nentry->lsm[i].type = entry->lsm[i].type; | 302 | nentry->lsm[i].type = entry->lsm[i].type; |
| 288 | nentry->lsm[i].args_p = kstrdup(entry->lsm[i].args_p, | 303 | nentry->lsm[i].args_p = entry->lsm[i].args_p; |
| 289 | GFP_KERNEL); | 304 | /* |
| 290 | if (!nentry->lsm[i].args_p) | 305 | * Remove the reference from entry so that the associated |
| 291 | goto out_err; | 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 | security_filter_rule_init(nentry->lsm[i].type, | 311 | security_filter_rule_init(nentry->lsm[i].type, |
| 294 | Audit_equal, | 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 | &nentry->lsm[i].rule); | 314 | &nentry->lsm[i].rule); |
| 297 | if (!nentry->lsm[i].rule) | 315 | if (!nentry->lsm[i].rule) |
| 298 | pr_warn("rule for LSM \'%s\' is undefined\n", | 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 | return nentry; | 319 | return nentry; |
| 302 | | | |
| 303 | out_err: | | |
| 304 | ima_lsm_free_rule(nentry); | | |
| 305 | return NULL; | | |
| 306 | } | 320 | } |
| 307 | | 321 | |
| 308 | static int ima_lsm_update_rule(struct ima_rule_entry *entry) | 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 | list_replace_rcu(&entry->list, &nentry->list); | 330 | list_replace_rcu(&entry->list, &nentry->list); |
| 317 | synchronize_rcu(); | 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 | ima_lsm_free_rule(entry); | 338 | ima_lsm_free_rule(entry); |
| | 339 | kfree(entry); |
| 319 | | 340 | |
| 320 | return 0; | 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 | * The LSM policy can be reloaded, leaving the IMA LSM based rules referring | 356 | * The LSM policy can be reloaded, leaving the IMA LSM based rules referring |
| 325 | * to the old, stale LSM policy. Update the IMA LSM based rules to reflect | 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 | static void ima_lsm_update_rules(void) | 360 | static void ima_lsm_update_rules(void) |
| 329 | { | 361 | { |
| 330 | struct ima_rule_entry *entry, *e; | 362 | struct ima_rule_entry *entry, *e; |
| 331 | int i, result, needs_update; | 363 | int result; |
| 332 | | 364 | |
| 333 | list_for_each_entry_safe(entry, e, &ima_policy_rules, list) { | 365 | list_for_each_entry_safe(entry, e, &ima_policy_rules, list) { |
| 334 | needs_update = 0; | 366 | if (!ima_rule_contains_lsm_cond(entry)) |
| 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) | | |
| 342 | continue; | 367 | continue; |
| 343 | | 368 | |
| 344 | result = ima_lsm_update_rule(entry); | 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 | int i; | 444 | int i; |
| 420 | | 445 | |
| 421 | if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) { | 446 | if (func == KEY_CHECK) { |
| 422 | if ((rule->flags & IMA_FUNC) && (rule->func == func)) { | 447 | return (rule->flags & IMA_FUNC) && (rule->func == func) && |
| 423 | if (func == KEY_CHECK) | 448 | ima_match_keyring(rule, keyring, cred); |
| 424 | return ima_match_keyring(rule, keyring, cred); | | |
| 425 | return true; | | |
| 426 | } | | |
| 427 | return false; | | |
| 428 | } | 449 | } |
| 429 | if ((rule->flags & IMA_FUNC) && | 450 | if ((rule->flags & IMA_FUNC) && |
| 430 | (rule->func != func && func != POST_SETATTR)) | 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 | &entry->lsm[lsm_rule].rule); | 907 | &entry->lsm[lsm_rule].rule); |
| 887 | if (!entry->lsm[lsm_rule].rule) { | 908 | if (!entry->lsm[lsm_rule].rule) { |
| 888 | pr_warn("rule for LSM \'%s\' is undefined\n", | 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 | if (ima_rules == &ima_default_rules) { | 912 | if (ima_rules == &ima_default_rules) { |
| 892 | kfree(entry->lsm[lsm_rule].args_p); | 913 | kfree(entry->lsm[lsm_rule].args_p); |
| | 914 | entry->lsm[lsm_rule].args_p = NULL; |
| 893 | result = -EINVAL; | 915 | result = -EINVAL; |
| 894 | } else | 916 | } else |
| 895 | result = 0; | 917 | result = 0; |
| @@ -949,6 +971,96 @@ static void check_template_modsig(const struct ima_template_desc *template) · 53 unmodified lines |
| 949 | #undef MSG | 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 | static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | 1064 | static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) |
| 953 | { | 1065 | { |
| 954 | struct audit_buffer *ab; | 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 | keyrings_len = strlen(args[0].from) + 1; | 1238 | keyrings_len = strlen(args[0].from) + 1; |
| 1127 | | 1239 | |
| 1128 | if ((entry->keyrings) || | 1240 | if ((entry->keyrings) || |
| 1129 | (entry->action != MEASURE) || | | |
| 1130 | (entry->func != KEY_CHECK) || | | |
| 1131 | (keyrings_len < 2)) { | 1241 | (keyrings_len < 2)) { |
| 1132 | result = -EINVAL; | 1242 | result = -EINVAL; |
| 1133 | break; | 1243 | break; |
| @@ -1267,15 +1377,10 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) · 133 unmodified lines |
| 1267 | AUDIT_SUBJ_TYPE); | 1377 | AUDIT_SUBJ_TYPE); |
| 1268 | break; | 1378 | break; |
| 1269 | case Opt_appraise_type: | 1379 | case Opt_appraise_type: |
| 1270 | if (entry->action != APPRAISE) { | | |
| 1271 | result = -EINVAL; | | |
| 1272 | break; | | |
| 1273 | } | | |
| 1274 | | | |
| 1275 | ima_log_string(ab, "appraise_type", args[0].from); | 1380 | ima_log_string(ab, "appraise_type", args[0].from); |
| 1276 | if ((strcmp(args[0].from, "imasig")) == 0) | 1381 | if ((strcmp(args[0].from, "imasig")) == 0) |
| 1277 | entry->flags |= IMA_DIGSIG_REQUIRED; | 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 | strcmp(args[0].from, "imasig|modsig") == 0) | 1384 | strcmp(args[0].from, "imasig|modsig") == 0) |
| 1280 | entry->flags |= IMA_DIGSIG_REQUIRED | | 1385 | entry->flags |= IMA_DIGSIG_REQUIRED | |
| 1281 | IMA_MODSIG_ALLOWED; | 1386 | IMA_MODSIG_ALLOWED; |
| @@ -1284,17 +1389,16 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) · 2 unmodified lines |
| 1284 | break; | 1389 | break; |
| 1285 | case Opt_appraise_flag: | 1390 | case Opt_appraise_flag: |
| 1286 | ima_log_string(ab, "appraise_flag", args[0].from); | 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 | entry->flags |= IMA_CHECK_BLACKLIST; | 1394 | entry->flags |= IMA_CHECK_BLACKLIST; |
| | 1395 | else |
| | 1396 | result = -EINVAL; |
| 1289 | break; | 1397 | break; |
| 1290 | case Opt_permit_directio: | 1398 | case Opt_permit_directio: |
| 1291 | entry->flags |= IMA_PERMIT_DIRECTIO; | 1399 | entry->flags |= IMA_PERMIT_DIRECTIO; |
| 1292 | break; | 1400 | break; |
| 1293 | case Opt_pcr: | 1401 | case Opt_pcr: |
| 1294 | if (entry->action != MEASURE) { | | |
| 1295 | result = -EINVAL; | | |
| 1296 | break; | | |
| 1297 | } | | |
| 1298 | ima_log_string(ab, "pcr", args[0].from); | 1402 | ima_log_string(ab, "pcr", args[0].from); |
| 1299 | | 1403 | |
| 1300 | result = kstrtoint(args[0].from, 10, &entry->pcr); | 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 | break; | 1436 | break; |
| 1333 | } | 1437 | } |
| 1334 | } | 1438 | } |
| 1335 | if (!result && (entry->action == UNKNOWN)) | 1439 | if (!result && !ima_validate_rule(entry)) |
| 1336 | result = -EINVAL; | 1440 | result = -EINVAL; |
| 1337 | else if (entry->action == APPRAISE) | 1441 | else if (entry->action == APPRAISE) |
| 1338 | temp_ima_appraise |= ima_appraise_flag(entry->func); | 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 | result = ima_parse_rule(p, entry); | 1486 | result = ima_parse_rule(p, entry); |
| 1383 | if (result) { | 1487 | if (result) { |
| 1384 | kfree(entry); | 1488 | ima_free_rule(entry); |
| 1385 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, | 1489 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, |
| 1386 | NULL, op, "invalid-policy", result, | 1490 | NULL, op, "invalid-policy", result, |
| 1387 | audit_info); | 1491 | audit_info); |
| @@ -1402,15 +1506,11 @@ ssize_t ima_parse_add_rule(char *rule) · 14 unmodified lines |
| 1402 | void ima_delete_rules(void) | 1506 | void ima_delete_rules(void) |
| 1403 | { | 1507 | { |
| 1404 | struct ima_rule_entry *entry, *tmp; | 1508 | struct ima_rule_entry *entry, *tmp; |
| 1405 | int i; | | |
| 1406 | | 1509 | |
| 1407 | temp_ima_appraise = 0; | 1510 | temp_ima_appraise = 0; |
| 1408 | list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) { | 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 | list_del(&entry->list); | 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 | switch (i) { | 1689 | switch (i) { |
| 1590 | case LSM_OBJ_USER: | 1690 | case LSM_OBJ_USER: |
| 1591 | seq_printf(m, pt(Opt_obj_user), | 1691 | seq_printf(m, pt(Opt_obj_user), |
| 1592 | (char *)entry->lsm[i].args_p); | 1692 | entry->lsm[i].args_p); |
| 1593 | break; | 1693 | break; |
| 1594 | case LSM_OBJ_ROLE: | 1694 | case LSM_OBJ_ROLE: |
| 1595 | seq_printf(m, pt(Opt_obj_role), | 1695 | seq_printf(m, pt(Opt_obj_role), |
| 1596 | (char *)entry->lsm[i].args_p); | 1696 | entry->lsm[i].args_p); |
| 1597 | break; | 1697 | break; |
| 1598 | case LSM_OBJ_TYPE: | 1698 | case LSM_OBJ_TYPE: |
| 1599 | seq_printf(m, pt(Opt_obj_type), | 1699 | seq_printf(m, pt(Opt_obj_type), |
| 1600 | (char *)entry->lsm[i].args_p); | 1700 | entry->lsm[i].args_p); |
| 1601 | break; | 1701 | break; |
| 1602 | case LSM_SUBJ_USER: | 1702 | case LSM_SUBJ_USER: |
| 1603 | seq_printf(m, pt(Opt_subj_user), | 1703 | seq_printf(m, pt(Opt_subj_user), |
| 1604 | (char *)entry->lsm[i].args_p); | 1704 | entry->lsm[i].args_p); |
| 1605 | break; | 1705 | break; |
| 1606 | case LSM_SUBJ_ROLE: | 1706 | case LSM_SUBJ_ROLE: |
| 1607 | seq_printf(m, pt(Opt_subj_role), | 1707 | seq_printf(m, pt(Opt_subj_role), |
| 1608 | (char *)entry->lsm[i].args_p); | 1708 | entry->lsm[i].args_p); |
| 1609 | break; | 1709 | break; |
| 1610 | case LSM_SUBJ_TYPE: | 1710 | case LSM_SUBJ_TYPE: |
| 1611 | seq_printf(m, pt(Opt_subj_type), | 1711 | seq_printf(m, pt(Opt_subj_type), |
| 1612 | (char *)entry->lsm[i].args_p); | 1712 | entry->lsm[i].args_p); |
| 1613 | break; | 1713 | break; |
| 1614 | } | 1714 | } |
| 1615 | seq_puts(m, " "); | 1715 | seq_puts(m, " "); |