mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Lock memory in crypt_safe alloc functions.
This patch locks all memory ranges in safe allocations. While crypto backend can have some secure memory calls, it is usually limited by intitial config. For our use is enough to keep keys in memory and prevent swapping it out. If the lock fails (because of limits) we quietly stay with plain malloc.
This commit is contained in:
@@ -179,7 +179,7 @@ int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
|
||||
key_size = DEFAULT_KEYFILE_SIZE_MAXKB * 1024 + 1;
|
||||
unlimited_read = 1;
|
||||
/* use 4k for buffer (page divisor but avoid huge pages) */
|
||||
buflen = 4096 - sizeof(size_t); // sizeof(struct safe_allocation);
|
||||
buflen = 4096 - 16; /* sizeof(struct safe_allocation); */
|
||||
} else
|
||||
buflen = key_size;
|
||||
|
||||
|
||||
@@ -20,13 +20,17 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include "libcryptsetup.h"
|
||||
|
||||
struct safe_allocation {
|
||||
size_t size;
|
||||
char data[0];
|
||||
size_t size;
|
||||
bool locked;
|
||||
char data[0] __attribute__((aligned(8)));
|
||||
};
|
||||
#define OVERHEAD offsetof(struct safe_allocation, data)
|
||||
|
||||
/*
|
||||
* Replacement for memset(s, 0, n) on stack that can be optimized out
|
||||
@@ -49,15 +53,19 @@ void *crypt_safe_alloc(size_t size)
|
||||
{
|
||||
struct safe_allocation *alloc;
|
||||
|
||||
if (!size || size > (SIZE_MAX - offsetof(struct safe_allocation, data)))
|
||||
if (!size || size > (SIZE_MAX - OVERHEAD))
|
||||
return NULL;
|
||||
|
||||
alloc = malloc(size + offsetof(struct safe_allocation, data));
|
||||
alloc = malloc(size + OVERHEAD);
|
||||
if (!alloc)
|
||||
return NULL;
|
||||
|
||||
crypt_safe_memzero(alloc, size + OVERHEAD);
|
||||
alloc->size = size;
|
||||
crypt_safe_memzero(&alloc->data, size);
|
||||
|
||||
/* Ignore failure if it is over limit. */
|
||||
if (!mlock(alloc, size + OVERHEAD))
|
||||
alloc->locked = true;
|
||||
|
||||
/* coverity[leaked_storage] */
|
||||
return &alloc->data;
|
||||
@@ -72,11 +80,16 @@ void crypt_safe_free(void *data)
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
p = (char *)data - offsetof(struct safe_allocation, data);
|
||||
p = (char *)data - OVERHEAD;
|
||||
alloc = (struct safe_allocation *)p;
|
||||
|
||||
crypt_safe_memzero(data, alloc->size);
|
||||
|
||||
if (alloc->locked) {
|
||||
munlock(alloc, alloc->size + OVERHEAD);
|
||||
alloc->locked = false;
|
||||
}
|
||||
|
||||
s = (volatile size_t *)&alloc->size;
|
||||
*s = 0x55aa55aa;
|
||||
free(alloc);
|
||||
@@ -92,7 +105,7 @@ void *crypt_safe_realloc(void *data, size_t size)
|
||||
|
||||
if (new_data && data) {
|
||||
|
||||
p = (char *)data - offsetof(struct safe_allocation, data);
|
||||
p = (char *)data - OVERHEAD;
|
||||
alloc = (struct safe_allocation *)p;
|
||||
|
||||
if (size > alloc->size)
|
||||
|
||||
Reference in New Issue
Block a user