diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-05-18 22:27:24 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-05-19 16:42:00 +0200 |
commit | 6df28e1f847d68ad37ffe3f4ff47745b55233861 (patch) | |
tree | 2366ae0c63be949c236045e5f79b505021b8d0b5 /src | |
parent | 871a3a33bbb3458c97e47fc828243082014fc583 (diff) | |
download | systemd-6df28e1f847d68ad37ffe3f4ff47745b55233861.tar.gz |
alloc-util: introduce MALLOC_SIZEOF_SAFE() helper
It's a wrapper around malloc_usable_size() that is supposed to be
compatible with _FORTIFY_SOURCES=1, by taking the
__builtin_object_size() data into account, the same way as the
_FORTIFY_SOURCES=1 logic does.
Fixes: #19203
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/alloc-util.h | 12 | ||||
-rw-r--r-- | src/basic/fileio.c | 4 | ||||
-rw-r--r-- | src/basic/memory-util.h | 2 | ||||
-rw-r--r-- | src/basic/string-util.c | 4 |
4 files changed, 17 insertions, 5 deletions
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h index 698a6583c5..66bee6cb87 100644 --- a/src/basic/alloc-util.h +++ b/src/basic/alloc-util.h @@ -163,3 +163,15 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); #else # define msan_unpoison(r, s) #endif + +/* This returns the number of usable bytes in a malloc()ed region as per malloc_usable_size(), in a way that + * is compatible with _FORTIFY_SOURCES. If _FORTIFY_SOURCES is used many memory operations will take the + * object size as returned by __builtin_object_size() into account. Hence, let's return the smaller size of + * malloc_usable_size() and __builtin_object_size() here, so that we definitely operate in safe territory by + * both the compiler's and libc's standards. Note that __builtin_object_size() evaluates to SIZE_MAX if the + * size cannot be determined, hence the MIN() expression should be safe with dynamically sized memory, + * too. Moreover, when NULL is passed malloc_usable_size() is documented to return zero, and + * __builtin_object_size() returns SIZE_MAX too, hence we also return a sensible value of 0 in this corner + * case. */ +#define MALLOC_SIZEOF_SAFE(x) \ + MIN(malloc_usable_size(x), __builtin_object_size(x, 0)) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index dabdf5b517..4afab84ed3 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -424,7 +424,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents if (!buf) return -ENOMEM; /* Use a bigger allocation if we got it anyway, but not more than the limit. */ - size = MIN3(malloc_usable_size(buf) - 1, max_size, READ_FULL_BYTES_MAX); + size = MIN3(MALLOC_SIZEOF_SAFE(buf) - 1, max_size, READ_FULL_BYTES_MAX); for (;;) { ssize_t k; @@ -570,7 +570,7 @@ int read_full_stream_full( buf = t; /* Unless a size has been explicitly specified, try to read as much as fits into the memory * we allocated (minus 1, to leave one byte for the safety NUL byte) */ - n = size == SIZE_MAX ? malloc_usable_size(buf) - 1 : n_next; + n = size == SIZE_MAX ? MALLOC_SIZEOF_SAFE(buf) - 1 : n_next; errno = 0; k = fread(buf + l, 1, n - l, f); diff --git a/src/basic/memory-util.h b/src/basic/memory-util.h index 179edd247b..e3f7980d12 100644 --- a/src/basic/memory-util.h +++ b/src/basic/memory-util.h @@ -88,7 +88,7 @@ static inline void* erase_and_free(void *p) { if (!p) return NULL; - l = malloc_usable_size(p); + l = MALLOC_SIZEOF_SAFE(p); explicit_bzero_safe(p, l); return mfree(p); } diff --git a/src/basic/string-util.c b/src/basic/string-util.c index c1f368dbd8..f4b6515a43 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -805,7 +805,7 @@ int strextendf(char **x, const char *format, ...) { /* Let's try to use the allocated buffer, if there's room at the end still. Otherwise let's extend by 64 chars. */ if (*x) { m = strlen(*x); - a = malloc_usable_size(*x); + a = MALLOC_SIZEOF_SAFE(*x); assert(a >= m + 1); } else m = a = 0; @@ -821,7 +821,7 @@ int strextendf(char **x, const char *format, ...) { return -ENOMEM; *x = n; - a = malloc_usable_size(*x); + a = MALLOC_SIZEOF_SAFE(*x); } /* Now, let's try to format the string into it */ |