summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/ima_policy6
-rw-r--r--security/integrity/ima/ima_policy.c74
2 files changed, 75 insertions, 5 deletions
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 070779e8d836..b0e3d278e799 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -27,7 +27,7 @@ Description:
lsm: [[subj_user=] [subj_role=] [subj_type=]
[obj_user=] [obj_role=] [obj_type=]]
option: [[appraise_type=]] [template=] [permit_directio]
- [appraise_flag=] [keyrings=]
+ [appraise_flag=] [appraise_algos=] [keyrings=]
base:
func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
@@ -55,6 +55,10 @@ Description:
label:= [selinux]|[kernel_info]|[data_label]
data_label:= a unique string used for grouping and limiting critical data.
For example, "selinux" to measure critical data for SELinux.
+ appraise_algos:= comma-separated list of hash algorithms
+ For example, "sha256,sha512" to only accept to appraise
+ files where the security.ima xattr was hashed with one
+ of these two algorithms.
default policy:
# PROC_SUPER_MAGIC
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 1536e6f5eb22..cb86da0e562b 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -960,7 +960,7 @@ enum {
Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq,
Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt,
Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
- Opt_appraise_type, Opt_appraise_flag,
+ Opt_appraise_type, Opt_appraise_flag, Opt_appraise_algos,
Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings,
Opt_label, Opt_err
};
@@ -995,6 +995,7 @@ static const match_table_t policy_tokens = {
{Opt_fowner_lt, "fowner<%s"},
{Opt_appraise_type, "appraise_type=%s"},
{Opt_appraise_flag, "appraise_flag=%s"},
+ {Opt_appraise_algos, "appraise_algos=%s"},
{Opt_permit_directio, "permit_directio"},
{Opt_pcr, "pcr=%s"},
{Opt_template, "template=%s"},
@@ -1095,7 +1096,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
return false;
if (entry->action != APPRAISE &&
- entry->flags & (IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED | IMA_CHECK_BLACKLIST))
+ entry->flags & (IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED |
+ IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS))
return false;
/*
@@ -1125,7 +1127,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
IMA_UID | IMA_FOWNER | IMA_FSUUID |
IMA_INMASK | IMA_EUID | IMA_PCR |
IMA_FSNAME | IMA_DIGSIG_REQUIRED |
- IMA_PERMIT_DIRECTIO))
+ IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS))
return false;
break;
@@ -1137,7 +1139,7 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
IMA_INMASK | IMA_EUID | IMA_PCR |
IMA_FSNAME | IMA_DIGSIG_REQUIRED |
IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED |
- IMA_CHECK_BLACKLIST))
+ IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS))
return false;
break;
@@ -1187,6 +1189,28 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
return true;
}
+static unsigned int ima_parse_appraise_algos(char *arg)
+{
+ unsigned int res = 0;
+ int idx;
+ char *token;
+
+ while ((token = strsep(&arg, ",")) != NULL) {
+ idx = match_string(hash_algo_name, HASH_ALGO__LAST, token);
+
+ if (idx < 0) {
+ pr_err("unknown hash algorithm \"%s\"",
+ token);
+ return 0;
+ }
+
+ /* Add the hash algorithm to the 'allowed' bitfield */
+ res |= (1U << idx);
+ }
+
+ return res;
+}
+
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
{
struct audit_buffer *ab;
@@ -1522,6 +1546,25 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
else
result = -EINVAL;
break;
+ case Opt_appraise_algos:
+ ima_log_string(ab, "appraise_algos", args[0].from);
+
+ if (entry->allowed_algos) {
+ result = -EINVAL;
+ break;
+ }
+
+ entry->allowed_algos =
+ ima_parse_appraise_algos(args[0].from);
+ /* invalid or empty list of algorithms */
+ if (!entry->allowed_algos) {
+ result = -EINVAL;
+ break;
+ }
+
+ entry->flags |= IMA_VALIDATE_ALGOS;
+
+ break;
case Opt_permit_directio:
entry->flags |= IMA_PERMIT_DIRECTIO;
break;
@@ -1714,6 +1757,23 @@ static void ima_show_rule_opt_list(struct seq_file *m,
seq_printf(m, "%s%s", i ? "|" : "", opt_list->items[i]);
}
+static void ima_policy_show_appraise_algos(struct seq_file *m,
+ unsigned int allowed_hashes)
+{
+ int idx, list_size = 0;
+
+ for (idx = 0; idx < HASH_ALGO__LAST; idx++) {
+ if (!(allowed_hashes & (1U << idx)))
+ continue;
+
+ /* only add commas if the list contains multiple entries */
+ if (list_size++)
+ seq_puts(m, ",");
+
+ seq_puts(m, hash_algo_name[idx]);
+ }
+}
+
int ima_policy_show(struct seq_file *m, void *v)
{
struct ima_rule_entry *entry = v;
@@ -1825,6 +1885,12 @@ int ima_policy_show(struct seq_file *m, void *v)
seq_puts(m, " ");
}
+ if (entry->flags & IMA_VALIDATE_ALGOS) {
+ seq_puts(m, "appraise_algos=");
+ ima_policy_show_appraise_algos(m, entry->allowed_algos);
+ seq_puts(m, " ");
+ }
+
for (i = 0; i < MAX_LSM_RULES; i++) {
if (entry->lsm[i].rule) {
switch (i) {