mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
integrity-v6.2
-----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQQdXVVFGN5XqKr1Hj7LwZzRsCrn5QUCY5ekGxQcem9oYXJAbGlu dXguaWJtLmNvbQAKCRDLwZzRsCrn5QLyAQC+olx4ImpAgFXoeYaZOiZr08ziAIlb hQ8rae6hFWecCgD/SZmDtOQ39UGobWbpj+GqwZvx8iJwKPCu9YzQ7Rjo7QE= =MywK -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
717e6eb49b
8 changed files with 59 additions and 26 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
* 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,
|
||||||
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,
|
||||||
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;
|
||||||
}
|
}
|
||||||
return true;
|
}
|
||||||
|
if (!rc) {
|
||||||
|
result = false;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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[] = {
|
||||||
{ 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,
|
||||||
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,7 +791,7 @@ 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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue