Merge pull request #19878 from poettering/large-key-file-cryptsetup

add back support for large key files to systemd-cryptsetup
This commit is contained in:
Lennart Poettering
2021-06-10 17:10:32 +02:00
committed by GitHub
3 changed files with 27 additions and 8 deletions
+17 -8
View File
@@ -27,8 +27,17 @@
#include "string-util.h"
#include "tmpfile-util.h"
/* The maximum size of the file we'll read in one go. */
#define READ_FULL_BYTES_MAX (4U*1024U*1024U - 1)
/* The maximum size of the file we'll read in one go in read_full_file() (64M). */
#define READ_FULL_BYTES_MAX (64U*1024U*1024U - 1U)
/* The maximum size of virtual files we'll read in one go in read_virtual_file() (4M). Note that this limit
* is different (and much lower) than the READ_FULL_BYTES_MAX limit. This reflects the fact that we use
* different strategies for reading virtual and regular files: virtual files are generally size constrained:
* there we allocate the full buffer size in advance. Regular files OTOH can be much larger, and here we grow
* the allocations exponentially in a loop. In glibc large allocations are immediately backed by mmap()
* making them relatively slow (measurably so). Thus, when allocating the full buffer in advance the large
* limit is a problem. When allocating piecemeal it's not. Hence pick two distinct limits. */
#define READ_VIRTUAL_BYTES_MAX (4U*1024U*1024U - 1U)
int fopen_unlocked(const char *path, const char *options, FILE **ret) {
assert(ret);
@@ -388,7 +397,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
if (fd < 0)
return -errno;
assert(max_size <= READ_FULL_BYTES_MAX || max_size == SIZE_MAX);
assert(max_size <= READ_VIRTUAL_BYTES_MAX || max_size == SIZE_MAX);
/* Limit the number of attempts to read the number of bytes returned by fstat(). */
n_retries = 3;
@@ -403,7 +412,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
return -EBADF;
/* Be prepared for files from /proc which generally report a file size of 0. */
assert_cc(READ_FULL_BYTES_MAX < SSIZE_MAX);
assert_cc(READ_VIRTUAL_BYTES_MAX < SSIZE_MAX);
if (st.st_size > 0 && n_retries > 1) {
/* Let's use the file size if we have more than 1 attempt left. On the last attempt
* we'll ignore the file size */
@@ -417,13 +426,13 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
} else {
size = MIN((size_t) st.st_size, max_size);
if (size > READ_FULL_BYTES_MAX)
if (size > READ_VIRTUAL_BYTES_MAX)
return -EFBIG;
}
n_retries--;
} else {
size = MIN(READ_FULL_BYTES_MAX, max_size);
size = MIN(READ_VIRTUAL_BYTES_MAX, max_size);
n_retries = 0;
}
@@ -432,7 +441,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents
return -ENOMEM;
/* Use a bigger allocation if we got it anyway, but not more than the limit. */
size = MIN3(MALLOC_SIZEOF_SAFE(buf) - 1, max_size, READ_FULL_BYTES_MAX);
size = MIN3(MALLOC_SIZEOF_SAFE(buf) - 1, max_size, READ_VIRTUAL_BYTES_MAX);
for (;;) {
ssize_t k;
@@ -572,7 +581,7 @@ int read_full_stream_full(
}
memcpy_safe(t, buf, n);
explicit_bzero_safe(buf, n);
buf = mfree(buf);
free(buf);
} else {
t = realloc(buf, n_next + 1);
if (!t)
+6
View File
@@ -26,6 +26,8 @@ int find_key_file(
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
bindname,
(char**) ret_key, ret_key_size);
if (r == -E2BIG)
return log_error_errno(r, "Key file '%s' too large.", key_file);
if (r < 0)
return log_error_errno(r, "Failed to load key file '%s': %m", key_file);
@@ -46,6 +48,10 @@ int find_key_file(
(char**) ret_key, ret_key_size);
if (r >= 0)
return 1;
if (r == -E2BIG) {
log_warning_errno(r, "Key file '%s' too large, ignoring.", key_file);
continue;
}
if (r != -ENOENT)
return log_error_errno(r, "Failed to load key file '%s': %m", key_file);
}
+4
View File
@@ -1261,6 +1261,10 @@ static int attach_luks_or_plain_or_bitlk_by_key_file(
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
bindname,
&kfdata, &kfsize);
if (r == -E2BIG) {
log_error_errno(r, "Failed to activate, key file '%s' too large.", key_file);
return -EAGAIN;
}
if (r == -ENOENT) {
log_error_errno(r, "Failed to activate, key file '%s' missing.", key_file);
return -EAGAIN; /* Log actual error, but return EAGAIN */