Require only up to last keyslot area for header device (ignore data offset).
authorMilan Broz <gmazyland@gmail.com>
Mon, 11 Jun 2012 10:20:19 +0000 (12:20 +0200)
committerMilan Broz <gmazyland@gmail.com>
Mon, 11 Jun 2012 10:20:19 +0000 (12:20 +0200)
Fix header backup and restore to work on files with large data offset.

ChangeLog
lib/luks1/keymanage.c
lib/setup.c
tests/api-test.c
tests/evil_hdr-small_luks_device.bz2

index b8d2e04..9c5e6d4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,8 @@
 2012-06-10  Milan Broz  <gmazyland@gmail.com>
        * Both data and header device can now be a file.
        * Loop is automatically allocated in crypt_set_data_device().
+       * Require only up to last keyslot area for header device (ignore data offset).
+       * Fix header backup and restore to work on files with large data offset.
 
 2012-05-27  Milan Broz  <gmazyland@gmail.com>
        * Fix readonly activation if underlying device is readonly (1.4.0).
index 44230b0..d0ba869 100644 (file)
@@ -47,12 +47,12 @@ static inline int round_up_modulo(int x, int m) {
 }
 
 /* Get size of struct luks_phrd with all keyslots material space */
-static uint64_t LUKS_device_sectors(size_t keyLen, unsigned int stripes)
+static uint64_t LUKS_device_sectors(size_t keyLen)
 {
        uint64_t keyslot_sectors, sector;
        int i;
 
-       keyslot_sectors = div_round_up(keyLen * stripes, SECTOR_SIZE);
+       keyslot_sectors = div_round_up(keyLen * LUKS_STRIPES, SECTOR_SIZE);
        sector = round_up_modulo(LUKS_PHDR_SIZE, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
 
        for (i = 0; i < LUKS_NUMKEYS; i++) {
@@ -63,22 +63,22 @@ static uint64_t LUKS_device_sectors(size_t keyLen, unsigned int stripes)
        return sector;
 }
 
-static int LUKS_check_device_size(const char *device,
-                                 uint64_t min_sectors,
+static int LUKS_check_device_size(struct crypt_device *ctx, const char *device,
                                  size_t keyLength)
 {
-       uint64_t dev_size, req_sectors;
-
-       req_sectors = LUKS_device_sectors(keyLength, LUKS_STRIPES);
-       if (min_sectors > req_sectors)
-               req_sectors = min_sectors;
+       uint64_t dev_size;
 
        if(device_size(device, &dev_size)) {
                log_dbg("Cannot get device size for device %s.", device);
                return -EIO;
        }
 
-       return (req_sectors > (dev_size >> SECTOR_SHIFT));
+       if (LUKS_device_sectors(keyLength) > (dev_size >> SECTOR_SHIFT)) {
+               log_err(ctx, _("Device %s is too small.\n"), device);
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 /* Check keyslot to prevent access outside of header and keyslot area */
@@ -154,7 +154,7 @@ int LUKS_hdr_backup(
        if (r)
                return r;
 
-       buffer_size = hdr->payloadOffset << SECTOR_SHIFT;
+       buffer_size = LUKS_device_sectors(hdr->keyBytes) << SECTOR_SHIFT;
        buffer = crypt_safe_alloc(buffer_size);
        if (!buffer || buffer_size < LUKS_ALIGN_KEYSLOTS) {
                r = -ENOMEM;
@@ -219,7 +219,7 @@ int LUKS_hdr_restore(
 
        r = LUKS_read_phdr_backup(backup_file, device, &hdr_file, 0, ctx);
        if (!r)
-               buffer_size = hdr_file.payloadOffset << SECTOR_SHIFT;
+               buffer_size = LUKS_device_sectors(hdr_file.keyBytes) << SECTOR_SHIFT;
 
        if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) {
                log_err(ctx, _("Backup file doesn't contain valid LUKS header.\n"));
@@ -512,6 +512,9 @@ int LUKS_read_phdr(const char *device,
                r = _check_and_convert_hdr(device, hdr, require_luks_device,
                                           repair, ctx);
 
+       if (!r)
+               r = LUKS_check_device_size(ctx, device, hdr->keyBytes);
+
        close(devfd);
        return r;
 }
@@ -529,10 +532,9 @@ int LUKS_write_phdr(const char *device,
        log_dbg("Updating LUKS header of size %d on device %s",
                sizeof(struct luks_phdr), device);
 
-       if (LUKS_check_device_size(device, hdr->payloadOffset, hdr->keyBytes)) {
-               log_err(ctx, _("Device %s is too small.\n"), device);
-               return -EINVAL;
-       }
+       r = LUKS_check_device_size(ctx, device, hdr->keyBytes);
+       if (r)
+               return r;
 
        devfd = open(device,O_RDWR | O_DIRECT | O_SYNC);
        if(-1 == devfd) {
index e7190eb..024e2ba 100644 (file)
@@ -598,7 +598,7 @@ static int crypt_check_data_device_size(struct crypt_device *cd)
                return r;
 
        if (size < size_min) {
-               log_err(cd, _("LUKS header detected but device %s is too small.\n"),
+               log_err(cd, _("Header detected but device %s is too small.\n"),
                        crypt_get_device_name(cd));
                return -EINVAL;
        }
@@ -1224,16 +1224,6 @@ int crypt_load(struct crypt_device *cd,
        } else
                return -EINVAL;
 
-       if (r < 0)
-               return r;
-
-       /* cd->type and header must be set in context */
-       r = crypt_check_data_device_size(cd);
-       if (r < 0) {
-               free(cd->type);
-               cd->type = NULL;
-       }
-
        return r;
 }
 
index d39a9bb..bcbd301 100644 (file)
@@ -986,7 +986,8 @@ static void AddDeviceLuks(void)
        OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
        OK_(create_dmdevice_over_loop(L_DEVICE_0S, r_payload_offset));
        OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
-       OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1));
+       //OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1));
+       OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, 2050 - 1)); //FIXME last keyslot - 1 sector
 
        // 1 sector less than required
        OK_(crypt_init(&cd, DMDIR L_DEVICE_WRONG));
@@ -1298,8 +1299,10 @@ static void LuksHeaderLoad(void)
        // external header device
        OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
        // prepared header on a device too small to contain header and payload
-       OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_payload_offset - 1));
-       snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, r_payload_offset - 1);
+       //OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_payload_offset - 1));
+       OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, 2050 - 1)); //FIXME
+       //snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, r_payload_offset - 1);
+       snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, 2050ULL - 1);
        OK_(_system(cmd, 1));
        // some device
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
@@ -1342,7 +1345,7 @@ static void LuksHeaderLoad(void)
        crypt_free(cd);
 
        // damaged header
-       OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_0S "bs=512 count=8", 1));
+       OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 count=8", 1));
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
        FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "Header not found");
        crypt_free(cd);
index 4a2ae3a..4d77530 100644 (file)
Binary files a/tests/evil_hdr-small_luks_device.bz2 and b/tests/evil_hdr-small_luks_device.bz2 differ