Skip to content

Commit 30031b0

Browse files
tyhicksmimizohar
authored andcommitted
ima: Move comprehensive rule validation checks out of the token parser
Use ima_validate_rule(), at the end of the token parsing stage, to verify combinations of actions, hooks, and flags. This is useful to increase readability by consolidating such checks into a single function and also because rule conditionals can be specified in arbitrary order making it difficult to do comprehensive rule validation until the entire rule has been parsed. This allows for the check that ties together the "keyrings" conditional with the KEY_CHECK function hook to be moved into the final rule validation. The modsig check no longer needs to compiled conditionally because the token parser will ensure that modsig support is enabled before accepting "imasig|modsig" appraise type values. The final rule validation will ensure that appraise_type and appraise_flag options are only present in appraise rules. Finally, this allows for the check that ties together the "pcr" conditional with the measure action to be moved into the final rule validation. Signed-off-by: Tyler Hicks <[email protected]> Signed-off-by: Mimi Zohar <[email protected]>
1 parent aa0c022 commit 30031b0

File tree

3 files changed

+37
-46
lines changed

3 files changed

+37
-46
lines changed

security/integrity/ima/ima.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,6 @@ static inline int ima_read_xattr(struct dentry *dentry,
372372
#endif /* CONFIG_IMA_APPRAISE */
373373

374374
#ifdef CONFIG_IMA_APPRAISE_MODSIG
375-
bool ima_hook_supports_modsig(enum ima_hooks func);
376375
int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
377376
struct modsig **modsig);
378377
void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size);
@@ -382,11 +381,6 @@ int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
382381
u32 *data_len);
383382
void ima_free_modsig(struct modsig *modsig);
384383
#else
385-
static inline bool ima_hook_supports_modsig(enum ima_hooks func)
386-
{
387-
return false;
388-
}
389-
390384
static inline int ima_read_modsig(enum ima_hooks func, const void *buf,
391385
loff_t buf_len, struct modsig **modsig)
392386
{

security/integrity/ima/ima_modsig.c

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,6 @@ struct modsig {
3232
u8 raw_pkcs7[];
3333
};
3434

35-
/**
36-
* ima_hook_supports_modsig - can the policy allow modsig for this hook?
37-
*
38-
* modsig is only supported by hooks using ima_post_read_file(), because only
39-
* they preload the contents of the file in a buffer. FILE_CHECK does that in
40-
* some cases, but not when reached from vfs_open(). POLICY_CHECK can support
41-
* it, but it's not useful in practice because it's a text file so deny.
42-
*/
43-
bool ima_hook_supports_modsig(enum ima_hooks func)
44-
{
45-
switch (func) {
46-
case KEXEC_KERNEL_CHECK:
47-
case KEXEC_INITRAMFS_CHECK:
48-
case MODULE_CHECK:
49-
return true;
50-
default:
51-
return false;
52-
}
53-
}
54-
5535
/*
5636
* ima_read_modsig - Read modsig from buf.
5737
*

security/integrity/ima/ima_policy.c

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -984,10 +984,27 @@ static void check_template_modsig(const struct ima_template_desc *template)
984984

985985
static bool ima_validate_rule(struct ima_rule_entry *entry)
986986
{
987-
/* Ensure that the action is set */
987+
/* Ensure that the action is set and is compatible with the flags */
988988
if (entry->action == UNKNOWN)
989989
return false;
990990

991+
if (entry->action != MEASURE && entry->flags & IMA_PCR)
992+
return false;
993+
994+
if (entry->action != APPRAISE &&
995+
entry->flags & (IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED | IMA_CHECK_BLACKLIST))
996+
return false;
997+
998+
/*
999+
* The IMA_FUNC bit must be set if and only if there's a valid hook
1000+
* function specified, and vice versa. Enforcing this property allows
1001+
* for the NONE case below to validate a rule without an explicit hook
1002+
* function.
1003+
*/
1004+
if (((entry->flags & IMA_FUNC) && entry->func == NONE) ||
1005+
(!(entry->flags & IMA_FUNC) && entry->func != NONE))
1006+
return false;
1007+
9911008
/*
9921009
* Ensure that the hook function is compatible with the other
9931010
* components of the rule
@@ -999,12 +1016,27 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
9991016
case BPRM_CHECK:
10001017
case CREDS_CHECK:
10011018
case POST_SETATTR:
1002-
case MODULE_CHECK:
10031019
case FIRMWARE_CHECK:
1020+
case POLICY_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))
1026+
return false;
1027+
1028+
break;
1029+
case MODULE_CHECK:
10041030
case KEXEC_KERNEL_CHECK:
10051031
case KEXEC_INITRAMFS_CHECK:
1006-
case POLICY_CHECK:
1007-
/* Validation of these hook functions is in ima_parse_rule() */
1032+
if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
1033+
IMA_UID | IMA_FOWNER | IMA_FSUUID |
1034+
IMA_INMASK | IMA_EUID | IMA_PCR |
1035+
IMA_FSNAME | IMA_DIGSIG_REQUIRED |
1036+
IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED |
1037+
IMA_CHECK_BLACKLIST))
1038+
return false;
1039+
10081040
break;
10091041
case KEXEC_CMDLINE:
10101042
if (entry->action & ~(MEASURE | DONT_MEASURE))
@@ -1218,7 +1250,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
12181250
keyrings_len = strlen(args[0].from) + 1;
12191251

12201252
if ((entry->keyrings) ||
1221-
(entry->func != KEY_CHECK) ||
12221253
(keyrings_len < 2)) {
12231254
result = -EINVAL;
12241255
break;
@@ -1358,27 +1389,17 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
13581389
AUDIT_SUBJ_TYPE);
13591390
break;
13601391
case Opt_appraise_type:
1361-
if (entry->action != APPRAISE) {
1362-
result = -EINVAL;
1363-
break;
1364-
}
1365-
13661392
ima_log_string(ab, "appraise_type", args[0].from);
13671393
if ((strcmp(args[0].from, "imasig")) == 0)
13681394
entry->flags |= IMA_DIGSIG_REQUIRED;
1369-
else if (ima_hook_supports_modsig(entry->func) &&
1395+
else if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) &&
13701396
strcmp(args[0].from, "imasig|modsig") == 0)
13711397
entry->flags |= IMA_DIGSIG_REQUIRED |
13721398
IMA_MODSIG_ALLOWED;
13731399
else
13741400
result = -EINVAL;
13751401
break;
13761402
case Opt_appraise_flag:
1377-
if (entry->action != APPRAISE) {
1378-
result = -EINVAL;
1379-
break;
1380-
}
1381-
13821403
ima_log_string(ab, "appraise_flag", args[0].from);
13831404
if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) &&
13841405
strstr(args[0].from, "blacklist"))
@@ -1390,10 +1411,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
13901411
entry->flags |= IMA_PERMIT_DIRECTIO;
13911412
break;
13921413
case Opt_pcr:
1393-
if (entry->action != MEASURE) {
1394-
result = -EINVAL;
1395-
break;
1396-
}
13971414
ima_log_string(ab, "pcr", args[0].from);
13981415

13991416
result = kstrtoint(args[0].from, 10, &entry->pcr);

0 commit comments

Comments
 (0)