mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-12 11:20:10 +01:00
Prevent double free with invalid verity partition.
It is possible to trigger a double free with an invalid verity partition. All it takes is an unknown hash algorithm, which makes it a bit more likely than a completely broken partition header. But all it takes is an error return value of VERITY_read_sb() or strdup(). If crypt_load fails before setting cd->type, crypt_free will handle the union as if it was of type "none", which means it will call free() for "active_name", a field which is only properly set up when the type was actually "none". In all other cases, "active_name" contains the first 4 or 8 bytes of the actually used header structure. Fortunately it can be only a pointer or NULL, so an attacker has no direct control of the value. Nonetheless it can easily trigger a double free. Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
This commit is contained in:
committed by
Milan Broz
parent
3f9346836e
commit
44d5269c0a
12
lib/setup.c
12
lib/setup.c
@@ -603,6 +603,15 @@ static int _crypt_load_verity(struct crypt_device *cd, struct crypt_params_verit
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
//FIXME: use crypt_free
|
||||||
|
if (!cd->type && !(cd->type = strdup(CRYPT_VERITY))) {
|
||||||
|
free(CONST_CAST(void*)cd->u.verity.hdr.hash_name);
|
||||||
|
free(CONST_CAST(void*)cd->u.verity.hdr.salt);
|
||||||
|
free(cd->u.verity.uuid);
|
||||||
|
crypt_memzero(&cd->u.verity.hdr, sizeof(cd->u.verity.hdr));
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
if (params)
|
if (params)
|
||||||
cd->u.verity.hdr.flags = params->flags;
|
cd->u.verity.hdr.flags = params->flags;
|
||||||
|
|
||||||
@@ -611,9 +620,6 @@ static int _crypt_load_verity(struct crypt_device *cd, struct crypt_params_verit
|
|||||||
if (cd->u.verity.root_hash_size > 4096)
|
if (cd->u.verity.root_hash_size > 4096)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!cd->type && !(cd->type = strdup(CRYPT_VERITY)))
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
if (params && params->data_device &&
|
if (params && params->data_device &&
|
||||||
(r = crypt_set_data_device(cd, params->data_device)) < 0)
|
(r = crypt_set_data_device(cd, params->data_device)) < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ int VERITY_read_sb(struct crypt_device *cd,
|
|||||||
log_err(cd, _("Hash algorithm %s not supported.\n"),
|
log_err(cd, _("Hash algorithm %s not supported.\n"),
|
||||||
params->hash_name);
|
params->hash_name);
|
||||||
free(CONST_CAST(char*)params->hash_name);
|
free(CONST_CAST(char*)params->hash_name);
|
||||||
|
params->hash_name = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,11 +131,13 @@ int VERITY_read_sb(struct crypt_device *cd,
|
|||||||
if (params->salt_size > sizeof(sb.salt)) {
|
if (params->salt_size > sizeof(sb.salt)) {
|
||||||
log_err(cd, _("VERITY header corrupted.\n"));
|
log_err(cd, _("VERITY header corrupted.\n"));
|
||||||
free(CONST_CAST(char*)params->hash_name);
|
free(CONST_CAST(char*)params->hash_name);
|
||||||
|
params->hash_name = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
params->salt = malloc(params->salt_size);
|
params->salt = malloc(params->salt_size);
|
||||||
if (!params->salt) {
|
if (!params->salt) {
|
||||||
free(CONST_CAST(char*)params->hash_name);
|
free(CONST_CAST(char*)params->hash_name);
|
||||||
|
params->hash_name = NULL;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size);
|
memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size);
|
||||||
|
|||||||
Reference in New Issue
Block a user