]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
alloc-util: introduce MALLOC_SIZEOF_SAFE() helper
authorLennart Poettering <lennart@poettering.net>
Tue, 18 May 2021 20:27:24 +0000 (22:27 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 19 May 2021 14:42:00 +0000 (16:42 +0200)
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
src/basic/alloc-util.h
src/basic/fileio.c
src/basic/memory-util.h
src/basic/string-util.c

index 698a6583c5cd2507ff2783b9b4a3080bd9c42315..66bee6cb8712796f492dfe05bf5ea0af940539cc 100644 (file)
@@ -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))
index dabdf5b5170a9ab6e6c05dc90e05b62ed9a6acf4..4afab84ed3e22e5c4c109402d05c4b51817e4f44 100644 (file)
@@ -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);
index 179edd247bf63bbd0f5046e1227b918fec00b70c..e3f7980d12fd0f5151b1128dcfd20087e401a080 100644 (file)
@@ -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);
 }
index c1f368dbd89b333e2e19082d6cec63dac377fdaa..f4b6515a4377f54f82dd446523b2624123ce7c67 100644 (file)
@@ -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 */