Commit 717e6eb4 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 8fa37a68 b6018af4
...@@ -350,7 +350,8 @@ Load an encrypted key "evm" from saved blob:: ...@@ -350,7 +350,8 @@ Load an encrypted key "evm" from saved blob::
Instantiate an encrypted key "evm" using user-provided decrypted data:: 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 794890253
$ keyctl print 794890253 $ keyctl print 794890253
......
...@@ -126,6 +126,7 @@ int __init integrity_init_keyring(const unsigned int id) ...@@ -126,6 +126,7 @@ int __init integrity_init_keyring(const unsigned int id)
{ {
struct key_restriction *restriction; struct key_restriction *restriction;
key_perm_t perm; key_perm_t perm;
int ret;
perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
| KEY_USR_READ | KEY_USR_SEARCH; | KEY_USR_READ | KEY_USR_SEARCH;
...@@ -154,7 +155,10 @@ int __init integrity_init_keyring(const unsigned int id) ...@@ -154,7 +155,10 @@ int __init integrity_init_keyring(const unsigned int id)
perm |= KEY_USR_WRITE; perm |= KEY_USR_WRITE;
out: 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, static int __init integrity_add_key(const unsigned int id, const void *data,
......
...@@ -112,7 +112,7 @@ choice ...@@ -112,7 +112,7 @@ choice
config IMA_DEFAULT_HASH_SM3 config IMA_DEFAULT_HASH_SM3
bool "SM3" bool "SM3"
depends on CRYPTO_SM3=y depends on CRYPTO_SM3_GENERIC=y
endchoice endchoice
config IMA_DEFAULT_HASH config IMA_DEFAULT_HASH
......
...@@ -544,8 +544,13 @@ static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, ...@@ -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, rc = ima_collect_measurement(&tmp_iint, file, NULL, 0,
ima_hash_algo, NULL); 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; return -EOPNOTSUPP;
}
iint = &tmp_iint; iint = &tmp_iint;
mutex_lock(&iint->mutex); mutex_lock(&iint->mutex);
......
...@@ -398,12 +398,6 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) ...@@ -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].type = entry->lsm[i].type;
nentry->lsm[i].args_p = entry->lsm[i].args_p; 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, ima_filter_rule_init(nentry->lsm[i].type, Audit_equal,
nentry->lsm[i].args_p, nentry->lsm[i].args_p,
...@@ -417,6 +411,7 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) ...@@ -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) static int ima_lsm_update_rule(struct ima_rule_entry *entry)
{ {
int i;
struct ima_rule_entry *nentry; struct ima_rule_entry *nentry;
nentry = ima_lsm_copy_rule(entry); nentry = ima_lsm_copy_rule(entry);
...@@ -431,7 +426,8 @@ static int ima_lsm_update_rule(struct ima_rule_entry *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 * references and the entry itself. All other memory references will now
* be owned by nentry. * 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); kfree(entry);
return 0; return 0;
...@@ -549,6 +545,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, ...@@ -549,6 +545,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
const char *func_data) const char *func_data)
{ {
int i; int i;
bool result = false;
struct ima_rule_entry *lsm_rule = rule;
bool rule_reinitialized = false;
if ((rule->flags & IMA_FUNC) && if ((rule->flags & IMA_FUNC) &&
(rule->func != func && func != POST_SETATTR)) (rule->func != func && func != POST_SETATTR))
...@@ -612,35 +611,55 @@ static bool ima_match_rules(struct ima_rule_entry *rule, ...@@ -612,35 +611,55 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
int rc = 0; int rc = 0;
u32 osid; u32 osid;
if (!rule->lsm[i].rule) { if (!lsm_rule->lsm[i].rule) {
if (!rule->lsm[i].args_p) if (!lsm_rule->lsm[i].args_p)
continue; continue;
else else
return false; return false;
} }
retry:
switch (i) { switch (i) {
case LSM_OBJ_USER: case LSM_OBJ_USER:
case LSM_OBJ_ROLE: case LSM_OBJ_ROLE:
case LSM_OBJ_TYPE: case LSM_OBJ_TYPE:
security_inode_getsecid(inode, &osid); 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, Audit_equal,
rule->lsm[i].rule); lsm_rule->lsm[i].rule);
break; break;
case LSM_SUBJ_USER: case LSM_SUBJ_USER:
case LSM_SUBJ_ROLE: case LSM_SUBJ_ROLE:
case LSM_SUBJ_TYPE: 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, Audit_equal,
rule->lsm[i].rule); lsm_rule->lsm[i].rule);
break; break;
default: default:
break; 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;
} }
/* /*
......
...@@ -245,11 +245,11 @@ int template_desc_init_fields(const char *template_fmt, ...@@ -245,11 +245,11 @@ int template_desc_init_fields(const char *template_fmt,
} }
if (fields && num_fields) { if (fields && num_fields) {
*fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL); *fields = kmalloc_array(i, sizeof(**fields), GFP_KERNEL);
if (*fields == NULL) if (*fields == NULL)
return -ENOMEM; return -ENOMEM;
memcpy(*fields, found_fields, i * sizeof(*fields)); memcpy(*fields, found_fields, i * sizeof(**fields));
*num_fields = i; *num_fields = i;
} }
...@@ -340,8 +340,11 @@ static struct ima_template_desc *restore_template_fmt(char *template_name) ...@@ -340,8 +340,11 @@ static struct ima_template_desc *restore_template_fmt(char *template_name)
template_desc->name = ""; template_desc->name = "";
template_desc->fmt = kstrdup(template_name, GFP_KERNEL); template_desc->fmt = kstrdup(template_name, GFP_KERNEL);
if (!template_desc->fmt) if (!template_desc->fmt) {
kfree(template_desc);
template_desc = NULL;
goto out; goto out;
}
spin_lock(&template_list); spin_lock(&template_list);
list_add_tail_rcu(&template_desc->list, &defined_templates); list_add_tail_rcu(&template_desc->list, &defined_templates);
......
...@@ -35,6 +35,7 @@ static const struct dmi_system_id uefi_skip_cert[] = { ...@@ -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.", "MacPro7,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") }, { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") }, { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMacPro1,1") },
{ } { }
}; };
......
...@@ -627,7 +627,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, ...@@ -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"); 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); 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"); pr_err("encrypted key: decrypted data provided does not match decrypted data length provided\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -791,8 +791,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, ...@@ -791,8 +791,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload,
ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv); ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv);
} else if (decrypted_data) { } else if (decrypted_data) {
get_random_bytes(epayload->iv, ivsize); get_random_bytes(epayload->iv, ivsize);
memcpy(epayload->decrypted_data, decrypted_data, ret = hex2bin(epayload->decrypted_data, decrypted_data,
epayload->decrypted_datalen); epayload->decrypted_datalen);
} else { } else {
get_random_bytes(epayload->iv, ivsize); get_random_bytes(epayload->iv, ivsize);
get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen); get_random_bytes(epayload->decrypted_data, epayload->decrypted_datalen);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment