#include <stddef.h>
#include <sys/types.h>
#include <sys/mman.h>
+#include <stdint.h>
/*
* rseq/mempool.h: rseq memory pool allocator.
int rseq_mempool_attr_set_max_nr_ranges(struct rseq_mempool_attr *attr,
unsigned long max_nr_ranges);
+/*
+ * rseq_mempool_attr_set_poison: Set pool poison value.
+ *
+ * Set a poison value to be set over freed pool entries. This can be
+ * used to anonymize freed memory, and for memory corruption checks
+ * with the robust attribute.
+ *
+ * Returns 0 on success, -1 with errno=EINVAL if arguments are invalid.
+ */
+int rseq_mempool_attr_set_poison(struct rseq_mempool_attr *attr,
+ uintptr_t poison);
+
/*
* rseq_mempool_range_init_numa: NUMA initialization helper for memory range.
*
int max_nr_cpus;
unsigned long max_nr_ranges;
+
+ bool poison_set;
+ uintptr_t poison;
};
struct rseq_mempool_range;
}
}
+static
+void rseq_percpu_poison_item(struct rseq_mempool *pool,
+ struct rseq_mempool_range *range, uintptr_t item_offset)
+{
+ uintptr_t poison = pool->attr.poison;
+ int i;
+
+ for (i = 0; i < pool->attr.max_nr_cpus; i++) {
+ char *p = __rseq_pool_range_percpu_ptr(range, i,
+ item_offset, pool->attr.stride);
+ size_t offset;
+
+ for (offset = 0; offset < pool->item_len; offset += sizeof(uintptr_t))
+ *((uintptr_t *) p) = poison;
+ }
+}
+
#ifdef HAVE_LIBNUMA
int rseq_mempool_range_init_numa(void *addr, size_t len, int cpu, int numa_flags)
{
clear_alloc_slot(pool, range, item_offset);
/* Add ptr to head of free list */
head = pool->free_list_head;
+ if (pool->attr.poison_set)
+ rseq_percpu_poison_item(pool, range, item_offset);
/* Free-list is in CPU 0 range. */
item = (struct free_list_node *) ptr;
+ /*
+ * Setting the next pointer will overwrite the first uintptr_t
+ * poison for CPU 0.
+ */
item->next = head;
pool->free_list_head = item;
pthread_mutex_unlock(&pool->lock);
return 0;
}
+int rseq_mempool_attr_set_poison(struct rseq_mempool_attr *attr,
+ uintptr_t poison)
+{
+ if (!attr) {
+ errno = EINVAL;
+ return -1;
+ }
+ attr->poison_set = true;
+ attr->poison = poison;
+ return 0;
+}
+
int rseq_mempool_get_max_nr_cpus(struct rseq_mempool *mempool)
{
if (!mempool || mempool->attr.type != MEMPOOL_TYPE_PERCPU) {
#include "list.h"
#include "tap.h"
+#if RSEQ_BITS_PER_LONG == 64
+# define POISON_VALUE 0xABCDABCDABCDABCDULL
+#else
+# define POISON_VALUE 0xABCDABCDUL
+#endif
+
struct test_data {
uintptr_t value;
struct test_data __rseq_percpu *backref;
ok(ret == 0, "Setting mempool percpu type");
ret = rseq_mempool_attr_set_max_nr_ranges(attr, max_nr_ranges);
ok(ret == 0, "Setting mempool max_nr_ranges=%lu", max_nr_ranges);
+ ret = rseq_mempool_attr_set_poison(attr, POISON_VALUE);
+ ok(ret == 0, "Setting mempool poison");
mempool = rseq_mempool_create("test_data",
sizeof(struct test_data), attr);
ok(mempool, "Create mempool of size %zu", stride);