summaryrefslogtreecommitdiffstats
path: root/lib/luks2/luks2_disk_metadata.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/luks2/luks2_disk_metadata.c')
-rw-r--r--lib/luks2/luks2_disk_metadata.c25
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;