From 2a1d58ed22faca0ce84c76bc84fbcdc33fe26c8d Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Tue, 11 Dec 2018 21:28:51 +0100 Subject: [PATCH] Check data device offset if it fits data device size in luksFormat. --- lib/internal.h | 3 +++ lib/luks2/luks2_disk_metadata.c | 29 ++--------------------------- lib/setup.c | 8 ++++++++ lib/utils_device.c | 26 ++++++++++++++++++++++++++ tests/api-test.c | 2 +- tests/compat-test | 1 + 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/lib/internal.h b/lib/internal.h index 22680ffb..69ba57eb 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -112,6 +112,9 @@ size_t device_alignment(struct device *device); int device_direct_io(const struct device *device); int device_fallocate(struct device *device, uint64_t size); void device_sync(struct crypt_device *cd, struct device *device, int devfd); +int device_check_size(struct crypt_device *cd, + struct device *device, + uint64_t req_offset, int falloc); int device_open_locked(struct crypt_device *cd, struct device *device, int flags); int device_read_lock(struct crypt_device *cd, struct device *device); diff --git a/lib/luks2/luks2_disk_metadata.c b/lib/luks2/luks2_disk_metadata.c index d7211081..77c55caf 100644 --- a/lib/luks2/luks2_disk_metadata.c +++ b/lib/luks2/luks2_disk_metadata.c @@ -359,31 +359,6 @@ static int hdr_write_disk(struct crypt_device *cd, return r; } -static int LUKS2_check_device_size(struct crypt_device *cd, struct device *device, - uint64_t hdr_size, int falloc) -{ - uint64_t dev_size; - - if (device_size(device, &dev_size)) { - log_dbg(cd, "Cannot get device size for device %s.", device_path(device)); - return -EIO; - } - - log_dbg(cd, "Device size %" PRIu64 ", header size %" PRIu64 ".", dev_size, hdr_size); - - if (hdr_size > dev_size) { - /* If it is header file, increase its size */ - if (falloc && !device_fallocate(device, hdr_size)) - return 0; - - log_err(cd, _("Device %s is too small. (LUKS2 requires at least %" PRIu64 " bytes.)"), - device_path(device), hdr_size); - return -EINVAL; - } - - return 0; -} - /* * Convert in-memory LUKS2 header and write it to disk. * This will increase sequence id, write both header copies and calculate checksum. @@ -400,7 +375,7 @@ int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct return -EINVAL; } - r = LUKS2_check_device_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr->jobj), 1); + r = device_check_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr->jobj), 1); if (r) return r; @@ -665,7 +640,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, goto err; } - r = LUKS2_check_device_size(cd, device, hdr_size, 0); + r = device_check_size(cd, device, hdr_size, 0); if (r) goto err; diff --git a/lib/setup.c b/lib/setup.c index 0094ca97..20d5bb32 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -1519,6 +1519,10 @@ static int _crypt_format_luks1(struct crypt_device *cd, if (r < 0) return r; + r = device_check_size(cd, crypt_data_device(cd), crypt_get_data_offset(cd) * SECTOR_SIZE, 0); + if (r < 0) + return r; + r = LUKS_wipe_header_areas(&cd->u.luks1.hdr, cd); if (r < 0) { log_err(cd, _("Cannot wipe header on device %s."), @@ -1676,6 +1680,10 @@ static int _crypt_format_luks2(struct crypt_device *cd, if (r < 0) goto out; + r = device_check_size(cd, crypt_data_device(cd), crypt_get_data_offset(cd) * SECTOR_SIZE, 0); + if (r < 0) + return r; + if (!integrity && sector_size > SECTOR_SIZE && !device_size(crypt_data_device(cd), &dev_size)) { dev_size -= (crypt_get_data_offset(cd) * SECTOR_SIZE); if (dev_size % sector_size) { diff --git a/lib/utils_device.c b/lib/utils_device.c index 21139d93..ff57a910 100644 --- a/lib/utils_device.c +++ b/lib/utils_device.c @@ -539,6 +539,32 @@ int device_fallocate(struct device *device, uint64_t size) return r; } +int device_check_size(struct crypt_device *cd, + struct device *device, + uint64_t req_offset, int falloc) +{ + uint64_t dev_size; + + if (device_size(device, &dev_size)) { + log_dbg(cd, "Cannot get device size for device %s.", device_path(device)); + return -EIO; + } + + log_dbg(cd, "Device size %" PRIu64 ", offset %" PRIu64 ".", dev_size, req_offset); + + if (req_offset > dev_size) { + /* If it is header file, increase its size */ + if (falloc && !device_fallocate(device, req_offset)) + return 0; + + log_err(cd, _("Device %s is too small. Need at least %" PRIu64 " bytes."), + device_path(device), req_offset); + return -EINVAL; + } + + return 0; +} + static int device_info(struct crypt_device *cd, struct device *device, enum devcheck device_check, diff --git a/tests/api-test.c b/tests/api-test.c index 2b3ed97a..12302deb 100644 --- a/tests/api-test.c +++ b/tests/api-test.c @@ -263,7 +263,7 @@ static int _setup(void) fd = loop_attach(&DEVICE_1, IMAGE1, 0, 0, &ro); close(fd); - _system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=4 2>/dev/null", 1); + _system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=10 2>/dev/null", 1); fd = loop_attach(&DEVICE_2, IMAGE_EMPTY, 0, 0, &ro); close(fd); diff --git a/tests/compat-test b/tests/compat-test index ba64bc93..81b8d471 100755 --- a/tests/compat-test +++ b/tests/compat-test @@ -679,6 +679,7 @@ echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --head echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 8192 || fail echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 0 || fail echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 8192 --offset 8192 >/dev/null 2>&1 && fail +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --offset 80000 2>/dev/null && fail echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --offset 8192 || fail echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --offset 0 || fail echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail