diff options
Diffstat (limited to 'lib/luks2/luks2_disk_metadata.c')
-rw-r--r-- | lib/luks2/luks2_disk_metadata.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/lib/luks2/luks2_disk_metadata.c b/lib/luks2/luks2_disk_metadata.c index e995959..d7f360c 100644 --- a/lib/luks2/luks2_disk_metadata.c +++ b/lib/luks2/luks2_disk_metadata.c @@ -1,8 +1,8 @@ /* * LUKS - Linux Unified Key Setup v2 * - * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2015-2023 Milan Broz + * Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2015-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -256,6 +256,7 @@ static int hdr_read_disk(struct crypt_device *cd, if (read_lseek_blockwise(devfd, device_block_size(cd, device), device_alignment(device), hdr_disk, LUKS2_HDR_BIN_LEN, offset) != LUKS2_HDR_BIN_LEN) { + memset(hdr_disk, 0, LUKS2_HDR_BIN_LEN); return -EIO; } @@ -537,11 +538,20 @@ static int validate_luks2_json_object(struct crypt_device *cd, json_object *jobj } static json_object *parse_and_validate_json(struct crypt_device *cd, - const char *json_area, uint64_t max_length) + const char *json_area, uint64_t hdr_size) { int json_len, r; - json_object *jobj = parse_json_len(cd, json_area, max_length, &json_len); + json_object *jobj; + uint64_t max_length; + + if (hdr_size <= LUKS2_HDR_BIN_LEN || hdr_size > LUKS2_HDR_OFFSET_MAX) { + log_dbg(cd, "LUKS2 header JSON has bogus size 0x%04" PRIx64 ".", hdr_size); + return NULL; + } + + max_length = hdr_size - LUKS2_HDR_BIN_LEN; + jobj = parse_json_len(cd, json_area, max_length, &json_len); if (!jobj) return NULL; @@ -635,7 +645,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, state_hdr1 = HDR_FAIL; r = hdr_read_disk(cd, device, &hdr_disk1, &json_area1, 0, 0); if (r == 0) { - jobj_hdr1 = parse_and_validate_json(cd, json_area1, be64_to_cpu(hdr_disk1.hdr_size) - LUKS2_HDR_BIN_LEN); + jobj_hdr1 = parse_and_validate_json(cd, json_area1, be64_to_cpu(hdr_disk1.hdr_size)); state_hdr1 = jobj_hdr1 ? HDR_OK : HDR_OBSOLETE; } else if (r == -EIO) state_hdr1 = HDR_FAIL_IO; @@ -647,7 +657,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, if (state_hdr1 != HDR_FAIL && state_hdr1 != HDR_FAIL_IO) { r = hdr_read_disk(cd, device, &hdr_disk2, &json_area2, be64_to_cpu(hdr_disk1.hdr_size), 1); if (r == 0) { - jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN); + jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size)); state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE; } else if (r == -EIO) state_hdr2 = HDR_FAIL_IO; @@ -655,11 +665,12 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, /* * No header size, check all known offsets. */ + hdr_disk2.hdr_size = 0; for (r = -EINVAL,i = 0; r < 0 && i < ARRAY_SIZE(hdr2_offsets); i++) r = hdr_read_disk(cd, device, &hdr_disk2, &json_area2, hdr2_offsets[i], 1); if (r == 0) { - jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN); + jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size)); state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE; } else if (r == -EIO) state_hdr2 = HDR_FAIL_IO; |