Commit d5e48fcb authored by Milan Broz's avatar Milan Broz

Enhance check of device size before writing LUKS header.

(Thanks to okozina@redhat.com)

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@607 36d66b0a-2a48-0410-832c-cd162a569da5
parent 4d997730
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Add more paranoid checks for LUKS header and keyslot attributes. * Add more paranoid checks for LUKS header and keyslot attributes.
* Fix crypt_load to properly check device size. * Fix crypt_load to properly check device size.
* Use new /dev/loop-control (kernel 3.1) if possible. * Use new /dev/loop-control (kernel 3.1) if possible.
* Enhance check of device size before writing LUKS header.
2011-07-25 Milan Broz <mbroz@redhat.com> 2011-07-25 Milan Broz <mbroz@redhat.com>
* Remove hash/hmac restart from crypto backend and make it part of hash/hmac final. * Remove hash/hmac restart from crypto backend and make it part of hash/hmac final.
......
...@@ -45,6 +45,41 @@ static inline int round_up_modulo(int x, int m) { ...@@ -45,6 +45,41 @@ static inline int round_up_modulo(int x, int m) {
return div_round_up(x, m) * m; return div_round_up(x, m) * m;
} }
/* Get size of struct luks_phrd with all keyslots material space */
static uint64_t LUKS_device_sectors(size_t keyLen, unsigned int stripes)
{
uint64_t keyslot_sectors, sector;
int i;
keyslot_sectors = div_round_up(keyLen * stripes, SECTOR_SIZE);
sector = round_up_modulo(LUKS_PHDR_SIZE, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
for (i = 0; i < LUKS_NUMKEYS; i++) {
sector = round_up_modulo(sector, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
sector += keyslot_sectors;
}
return sector;
}
static int LUKS_check_device_size(const char *device,
uint64_t min_sectors,
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;
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));
}
/* Check keyslot to prevent access outside of header and keyslot area */ /* Check keyslot to prevent access outside of header and keyslot area */
static int LUKS_check_keyslot_size(const struct luks_phdr *phdr, unsigned int keyIndex) static int LUKS_check_keyslot_size(const struct luks_phdr *phdr, unsigned int keyIndex)
{ {
...@@ -391,6 +426,11 @@ int LUKS_write_phdr(const char *device, ...@@ -391,6 +426,11 @@ int LUKS_write_phdr(const char *device,
log_dbg("Updating LUKS header of size %d on device %s", log_dbg("Updating LUKS header of size %d on device %s",
sizeof(struct luks_phdr), device); 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;
}
devfd = open(device,O_RDWR | O_DIRECT | O_SYNC); devfd = open(device,O_RDWR | O_DIRECT | O_SYNC);
if(-1 == devfd) { if(-1 == devfd) {
log_err(ctx, _("Cannot open device %s.\n"), device); log_err(ctx, _("Cannot open device %s.\n"), device);
......
...@@ -923,16 +923,16 @@ static void AddDeviceLuks(void) ...@@ -923,16 +923,16 @@ static void AddDeviceLuks(void)
OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_header_size - 1)); OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_header_size - 1));
// format // format
// OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG)); OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG));
// params.data_alignment = 0; params.data_alignment = 0;
// FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Not enough space for keyslots material"); FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Not enough space for keyslots material");
// crypt_free(cd); crypt_free(cd);
// test payload_offset = 0 for encrypted device with external header device // test payload_offset = 0 for encrypted device with external header device
// OK_(crypt_init(&cd, DMDIR H_DEVICE)); OK_(crypt_init(&cd, DMDIR H_DEVICE));
// OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params)); OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
// EQ_(crypt_get_data_offset(cd), 0); EQ_(crypt_get_data_offset(cd), 0);
// crypt_free(cd); crypt_free(cd);
params.data_alignment = 0; params.data_alignment = 0;
params.data_device = NULL; params.data_device = NULL;
...@@ -953,9 +953,9 @@ static void AddDeviceLuks(void) ...@@ -953,9 +953,9 @@ static void AddDeviceLuks(void)
OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1)); OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1));
// 1 sector less than required // 1 sector less than required
// OK_(crypt_init(&cd, DMDIR L_DEVICE_WRONG)); OK_(crypt_init(&cd, DMDIR L_DEVICE_WRONG));
// FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Device too small"); FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Device too small");
// crypt_free(cd); crypt_free(cd);
// 0 sectors for encrypted area // 0 sectors for encrypted area
OK_(crypt_init(&cd, DMDIR L_DEVICE_0S)); OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment