summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-12-13 14:22:50 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2022-12-13 14:22:50 -0800
commit717e6eb49bdd98357d14c90d60a3409196b33cfc (patch)
treed524e136a8ffab9036fc1b2bfdfb02eeeb4ad327
parent8fa37a68359d2d5dc16deeb5b09d64c9833c0674 (diff)
parentb6018af440a07bd0d74b58c4e18045f4a8dbfe6b (diff)
Merge tag 'integrity-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity updates from Mimi Zohar: "Aside from the one cleanup, the other changes are bug fixes: Cleanup: - Include missing iMac Pro 2017 in list of Macs with T2 security chip Bug fixes: - Improper instantiation of "encrypted" keys with user provided data - Not handling delay in updating LSM label based IMA policy rules (-ESTALE) - IMA and integrity memory leaks on error paths - CONFIG_IMA_DEFAULT_HASH_SM3 hash algorithm renamed" * tag 'integrity-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: ima: Fix hash dependency to correct algorithm ima: Fix misuse of dereference of pointer in template_desc_init_fields() integrity: Fix memory leakage in keyring allocation error path ima: Fix memory leak in __ima_inode_hash() ima: Handle -ESTALE returned by ima_filter_rule_match() ima: Simplify ima_lsm_copy_rule ima: Fix a potential NULL pointer access in ima_restore_measurement_list efi: Add iMac Pro 2017 to uefi skip cert quirk KEYS: encrypted: fix key instantiation with user-provided data
-rw-r--r--Documentation/security/keys/trusted-encrypted.rst3
-rw-r--r--security/integrity/digsig.c6
-rw-r--r--security/integrity/ima/Kconfig2
-rw-r--r--security/integrity/ima/ima_main.c7
-rw-r--r--security/integrity/ima/ima_policy.c51
-rw-r--r--security/integrity/ima/ima_template.c9
-rw-r--r--security/integrity/platform_certs/load_uefi.c1
-rw-r--r--security/keys/encrypted-keys/encrypted.c6
8 files changed, 59 insertions, 26 deletions
diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst
index 0bfb4c339748..9bc9db8ec651 100644
--- a/Documentation/security/keys/trusted-encrypted.rst
+++ b/Documentation/security/keys/trusted-encrypted.rst
@@ -350,7 +350,8 @@ Load an encrypted key "evm" from saved blob::
Instantiate an encrypted key "evm" using user-provided decrypted data::
- $ keyctl add encrypted evm "new default user:kmk 32 `cat evm_decrypted_data.blob`" @u
+ $ evmkey=$(dd if=/dev/urandom bs=1 count=32 | xxd -c32 -p)
+ $ keyctl add encrypted evm "new default user:kmk 32 $evmkey" @u
794890253
$ keyctl print 794890253
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 8a82a6c7f48a..f2193c531f4a 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -126,6 +126,7 @@ int __init integrity_init_keyring(const unsigned int id)
{
struct key_restriction *restriction;
key_perm_t perm;
+ int ret;
perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
| KEY_USR_READ | KEY_USR_SEARCH;
@@ -154,7 +155,10 @@ int __init integrity_init_keyring(const unsigned int id)
perm |= KEY_USR_WRITE;
out:
- return __integrity_init_keyring(id, perm, restriction);
+ ret = __integrity_init_keyring(id, perm, restriction);
+ if (ret)
+ kfree(restriction);
+ return ret;
}
static int __init integrity_add_key(const unsigned int id, const void *data,
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 7249f16257c7..39caeca47444 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -112,7 +112,7 @@ choice
config IMA_DEFAULT_HASH_SM3
bool "SM3"
- depends on CRYPTO_SM3=y
+ depends on CRYPTO_SM3_GENERIC=y
endchoice
config IMA_DEFAULT_HASH
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 0226899947d6..377300973e6c 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -544,8 +544,13 @@ static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
rc = ima_collect_measurement(&tmp_iint, file, NULL, 0,
ima_hash_algo, NULL);
- if (rc < 0)
+ if (rc < 0) {
+ /* ima_hash could be allocated in case of failure. */
+ if (rc != -ENOMEM)
+ kfree(tmp_iint.ima_hash);
+
return -EOPNOTSUPP;
+ }
iint = &tmp_iint;
mutex_lock(&iint->mutex);
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 54c475f98ce1..20cffd32dc9e 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -398,12 +398,6 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
nentry->lsm[i].type = entry->lsm[i].type;
nentry->lsm[i].args_p = entry->lsm[i].args_p;
- /*
- * Remove the reference from entry so that the associated
- * memory will not be freed during a later call to
- * ima_lsm_free_rule(entry).
- */
- entry->lsm[i].args_p = NULL;
ima_filter_rule_init(nentry->lsm[i].type, Audit_equal,
nentry->lsm[i].args_p,
@@ -417,6 +411,7 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
static int ima_lsm_update_rule(struct ima_rule_entry *entry)
{
+ int i;
struct ima_rule_entry *nentry;
nentry = ima_lsm_copy_rule(entry);
@@ -431,7 +426,8 @@ static int ima_lsm_update_rule(struct ima_rule_entry *entry)
* references and the entry itself. All other memory references will now
* be owned by nentry.
*/
- ima_lsm_free_rule(entry);
+ for (i = 0; i < MAX_LSM_RULES; i++)
+ ima_filter_rule_free(entry->lsm[i].rule);
kfree(entry);
return 0;
@@ -549,6 +545,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
const char *func_data)
{
int i;
+ bool result = false;
+ struct ima_rule_entry *lsm_rule = rule;
+ bool rule_reinitialized = false;
if ((rule->flags & IMA_FUNC) &&
(rule->func != func && func != POST_SETATTR))
@@ -612,35 +611,55 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
int rc = 0;
u32 osid;
- if (!rule->lsm[i].rule) {
- if (!rule->lsm[i].args_p)
+ if (!lsm_rule->lsm[i].rule) {
+ if (!lsm_rule->lsm[i].args_p)
continue;
else
return false;
}
+
+retry:
switch (i) {
case LSM_OBJ_USER:
case LSM_OBJ_ROLE:
case LSM_OBJ_TYPE:
security_inode_getsecid(inode, &osid);
- rc = ima_filter_rule_match(osid, rule->lsm[i].type,
+ rc = ima_filter_rule_match(osid, lsm_rule->lsm[i].type,
Audit_equal,
- rule->lsm[i].rule);
+ lsm_rule->lsm[i].rule);
break;
case LSM_SUBJ_USER:
case LSM_SUBJ_ROLE:
case LSM_SUBJ_TYPE:
- rc = ima_filter_rule_match(secid, rule->lsm[i].type,
+ rc = ima_filter_rule_match(secid, lsm_rule->lsm[i].type,
Audit_equal,
- rule->lsm[i].rule);
+ lsm_rule->lsm[i].rule);
break;
default:
break;
}
- if (!rc)
- return false;
+
+ if (rc == -ESTALE && !rule_reinitialized) {
+ lsm_rule = ima_lsm_copy_rule(rule);
+ if (lsm_rule) {
+ rule_reinitialized = true;
+ goto retry;
+ }
+ }
+ if (!rc) {
+ result = false;
+ goto out;
+ }
}
- return true;
+ result = true;
+
+out:
+ if (rule_reinitialized) {
+ for (i = 0; i < MAX_LSM_RULES; i++)
+ ima_filter_rule_free(lsm_rule->lsm[i].rule);
+ kfree(lsm_rule);
+ }
+ return result;
}
/*
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index c25079faa208..04c49f05cb74 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -245,11 +245,11 @@ int template_desc_init_fields(const char *template_fmt,
}
if (fields && num_fields) {
- *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL);
+ *fields = kmalloc_array(i, sizeof(**fields), GFP_KERNEL);
if (*fields == NULL)
return -ENOMEM;
- memcpy(*fields, found_fields, i * sizeof(*fields));
+ memcpy(*fields, found_fields, i * sizeof(**fields));
*num_fields = i;
}
@@ -340,8 +340,11 @@ static struct ima_template_desc *restore_template_fmt(char *template_name)
template_desc->name = "";
template_desc->fmt = kstrdup(template_name, GFP_KERNEL);
- if (!template_desc->fmt)
+ if (!template_desc->fmt) {
+ kfree(template_desc);
+ template_desc = NULL;
goto out;
+ }
spin_lock(&template_list);
list_add_tail_rcu(&template_desc->list, &defined_templates);
diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
index b78753d27d8e..d1fdd113450a 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -35,6 +35,7 @@ static const struct dmi_system_id uefi_skip_cert[] = {
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacPro7,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") },
+ { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMacPro1,1") },
{ }
};
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index e05cfc2e49ae..1e313982af02 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -627,7 +627,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
pr_err("encrypted key: instantiation of keys using provided decrypted data is disabled since CONFIG_USER_DECRYPTED_DATA is set to false\n");
return ERR_PTR(-EINVAL);
}
- if (strlen(decrypted_data) != decrypted_datalen) {
+ if (strlen(decrypted_data) != decrypted_datalen * 2) {
pr_err("encrypted key: decrypted data provided does not match decrypted data length provided\n");
return ERR_PTR(-EINVAL);
}
@@ -791,8 +791,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload,
ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv);
} else if (decrypted_data) {
get_random_bytes(epayload->iv, ivsize);
- memcpy(epayload->decrypted_data, decrypted_data,
- epayload->decrypted_datalen);
+ ret = hex2bin(epayload->decrypted_data, decrypted_data,
+ epayload->decrypted_datalen);
} else {
get_random_bytes(epayload->iv, ivsize);
get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen);