diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c index b28fb95ccfd..1e4ee722f20 100644 --- a/src/basic/alloc-util.c +++ b/src/basic/alloc-util.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include #include #include @@ -27,6 +28,9 @@ void* memdup_suffix0(const void *p, size_t l) { /* The same as memdup() but place a safety NUL byte after the allocated memory */ + if (_unlikely_(l == SIZE_MAX)) /* prevent overflow */ + return NULL; + ret = malloc(l + 1); if (!ret) return NULL; @@ -45,19 +49,23 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { if (*allocated >= need) return *p; - newalloc = MAX(need * 2, 64u / size); - a = newalloc * size; - - /* check for overflows */ - if (a < size * need) + if (_unlikely_(need > SIZE_MAX/2)) /* Overflow check */ return NULL; + newalloc = need * 2; + if (size_multiply_overflow(newalloc, size)) + return NULL; + + a = newalloc * size; + if (a < 64) /* Allocate at least 64 bytes */ + a = 64; + q = realloc(*p, a); if (!q) return NULL; *p = q; - *allocated = newalloc; + *allocated = _unlikely_(size == 0) ? newalloc : malloc_usable_size(q) / size; return q; } diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h index 78ee34bb714..9b20be4773e 100644 --- a/src/basic/alloc-util.h +++ b/src/basic/alloc-util.h @@ -156,8 +156,8 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); (void*)memset(_new_, 0, _xsize_); \ }) -/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to - * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ +/* Takes inspiration from Rust's Option::take() method: reads and returns a pointer, but at the same time + * resets it to NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ #define TAKE_PTR(ptr) \ ({ \ typeof(ptr) _ptr_ = (ptr); \ diff --git a/src/basic/memory-util.h b/src/basic/memory-util.h index e1e6624d3b0..915c24a5dde 100644 --- a/src/basic/memory-util.h +++ b/src/basic/memory-util.h @@ -77,3 +77,8 @@ static inline void* explicit_bzero_safe(void *p, size_t l) { #else void *explicit_bzero_safe(void *p, size_t l); #endif + +/* Use with _cleanup_ to erase a single 'char' when leaving scope */ +static inline void erase_char(char *p) { + explicit_bzero_safe(p, sizeof(char)); +} diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 87e0cefbab5..1f0e34b0389 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -612,6 +612,24 @@ static int help(void) { return 0; } +static uint32_t determine_flags(void) { + uint32_t flags = 0; + + if (arg_readonly) + flags |= CRYPT_ACTIVATE_READONLY; + + if (arg_discards) + flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; + + if (arg_same_cpu_crypt) + flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT; + + if (arg_submit_from_crypt_cpus) + flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS; + + return flags; +} + static int run(int argc, char *argv[]) { _cleanup_(crypt_freep) struct crypt_device *cd = NULL; int r; @@ -676,17 +694,7 @@ static int run(int argc, char *argv[]) { return 0; } - if (arg_readonly) - flags |= CRYPT_ACTIVATE_READONLY; - - if (arg_discards) - flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; - - if (arg_same_cpu_crypt) - flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT; - - if (arg_submit_from_crypt_cpus) - flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS; + flags = determine_flags(); if (arg_timeout == USEC_INFINITY) until = 0; diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 4122362b3c0..ab0c34692f1 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -77,13 +77,18 @@ static int retrieve_key(key_serial_t serial, char ***ret) { n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0); if (n < 0) return -errno; - if (n < m) break; explicit_bzero_safe(p, n); - free(p); + + if (m > LONG_MAX / 2) /* overflow check */ + return -ENOMEM; m *= 2; + if ((long) (size_t) m != m) /* make sure that this still fits if converted to size_t */ + return -ENOMEM; + + free(p); } l = strv_parse_nulstr(p, n); @@ -306,9 +311,9 @@ int ask_password_tty( }; for (;;) { + _cleanup_(erase_char) char c; int sleep_for = -1, k; ssize_t n; - char c; if (until > 0) { usec_t y; @@ -452,9 +457,6 @@ int ask_password_tty( dirty = true; } - - /* Let's forget this char, just to not keep needlessly copies of key material around */ - c = 'x'; } x = strndup(passphrase, p);