]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
talloc: Add talloc aligned array
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 4 Jun 2020 02:59:14 +0000 (21:59 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 4 Jun 2020 03:03:03 +0000 (22:03 -0500)
src/lib/util/talloc.c
src/lib/util/talloc.h

index 3042beefb09a62abadcd3bac927edc6c4ec98eb3..37bc89211f5778abb68845a0e10daaaa598af858 100644 (file)
 RCSID("$Id$")
 
 #include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/dlist.h>
+#include <freeradius-devel/util/misc.h>
 #include <freeradius-devel/util/strerror.h>
 #include <freeradius-devel/util/talloc.h>
-#include <freeradius-devel/util/dlist.h>
 
 #include <string.h>
 #include <unistd.h>
@@ -156,6 +157,51 @@ int talloc_link_ctx(TALLOC_CTX *parent, TALLOC_CTX *child)
        return 0;
 }
 
+/** Return a page aligned talloc memory array
+ *
+ * Because we can't intercept talloc's malloc() calls, we need to do some tricks
+ * in order to get the first allocation in the array page aligned, and to limit
+ * the size of the array to a multiple of the page size.
+ *
+ * The reason for wanting a page aligned talloc array, is it allows us to
+ * mprotect() the pages that belong to the array.
+ *
+ * Talloc chunks appear to be allocated within the protected region, so this should
+ * catch frees too.
+ *
+ * @param[in] ctx      to allocate array memory in.
+ * @param[out] start   The first aligned address in the array.
+ * @param[in] alignment        What alignment the memory chunk should have.
+ * @param[in] size     How big to make the array.  Will be corrected to a multiple
+ *                     of the page size.  The actual array size will be size
+ *                     rounded to a multiple of the (page_size), + page_size
+ * @return
+ *     - A talloc chunk on success.
+ *     - NULL on failure.
+ */
+TALLOC_CTX *talloc_aligned_array(TALLOC_CTX *ctx, void **start, size_t alignment, size_t size)
+{
+       size_t          rounded;
+       size_t          array_size;
+       void            *next;
+       TALLOC_CTX      *array;
+
+       rounded = ROUND_UP(size, alignment);            /* Round up to a multiple of the page size */
+       if (rounded == 0) rounded = alignment;
+
+       array_size = rounded + alignment;
+       array = talloc_array(ctx, uint8_t, array_size);         /* Over allocate */
+       if (!array) {
+               fr_strerror_printf("Out of memory");
+               return NULL;
+       }
+
+       next = (void *)ROUND_UP((uintptr_t)array, alignment);           /* Round up address to the next multiple */
+       *start = next;
+
+       return array;
+}
+
 /** Return a page aligned talloc memory pool
  *
  * Because we can't intercept talloc's malloc() calls, we need to do some tricks
@@ -183,8 +229,6 @@ TALLOC_CTX *talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, void **end,
        void            *next, *chunk;
        TALLOC_CTX      *pool;
 
-#define ROUND_UP(_num, _mul) (((((_num) + ((_mul) - 1))) / (_mul)) * (_mul))
-
        rounded = ROUND_UP(size, page_size);                    /* Round up to a multiple of the page size */
        if (rounded == 0) rounded = page_size;
 
index 11310c564dbe595c44a22230d44cdb1475b963a9..47d2991b16f3ea131555c9947c4e7a340613887a 100644 (file)
@@ -94,6 +94,7 @@ fr_talloc_destructor_t *talloc_add_destructor(TALLOC_CTX *chunk, fr_talloc_free_
 void           talloc_disarm_destructor(fr_talloc_destructor_t *d);
 
 TALLOC_CTX     *talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, void **end, size_t size);
+TALLOC_CTX     *talloc_aligned_array(TALLOC_CTX *ctx, void **start, size_t alignment, size_t size);
 
 /*
  *     Add variant that zeroes out newly allocated memory