} else {
req = malloc(sizeof(*req));
}
+ kr_asan_unpoison(req, sizeof(*req));
return req;
}
static inline void ioreq_release(struct worker_ctx *worker, struct ioreq *req)
{
+ kr_asan_poison(req, sizeof(*req));
if (!req || worker->ioreqs.len < 4 * MP_FREELIST_SIZE) {
array_push(worker->ioreqs, req);
} else {
}
}
+static inline struct mempool *pool_take(struct worker_ctx *worker)
+{
+ /* Recycle available mempool if possible */
+ struct mempool *mp = NULL;
+ if (worker->pools.len > 0) {
+ mp = array_tail(worker->pools);
+ array_pop(worker->pools);
+ } else { /* No mempool on the freelist, create new one */
+ mp = mp_new (4 * CPU_PAGE_SIZE);
+ }
+ kr_asan_unpoison(mp, sizeof(*mp));
+ return mp;
+}
+
+static inline void pool_release(struct worker_ctx *worker, struct mempool *mp)
+{
+ /* Return mempool to ring or free it if it's full */
+ if (worker->pools.len < MP_FREELIST_SIZE) {
+ mp_flush(mp);
+ array_push(worker->pools, mp);
+ kr_asan_poison(mp, sizeof(*mp));
+ } else {
+ mp_delete(mp);
+ }
+}
+
/** @internal Query resolution task. */
struct qr_task
{
/* Recycle available mempool if possible */
mm_ctx_t pool = {
- .ctx = NULL,
+ .ctx = pool_take(worker),
.alloc = (mm_alloc_t) mp_alloc
};
- if (worker->pools.len > 0) {
- pool.ctx = array_tail(worker->pools);
- array_pop(worker->pools);
- } else { /* No mempool on the freelist, create new one */
- pool.ctx = mp_new (4 * CPU_PAGE_SIZE);
- }
/* Create resolution task */
struct qr_task *task = mm_alloc(&pool, sizeof(*task));
{
/* Return mempool to ring or free it if it's full */
struct worker_ctx *worker = task->worker;
- void *mp_context = task->req.pool.ctx;
- if (worker->pools.len < MP_FREELIST_SIZE) {
- mp_flush(mp_context);
- array_push(worker->pools, mp_context);
- } else {
- mp_delete(mp_context);
- }
+ pool_release(worker, task->req.pool.ctx);
+ /* @note The 'task' is invalidated from now on. */
/* Decommit memory every once in a while */
static int mp_delete_count = 0;
if (++mp_delete_count == 100000) {
return kr_ok();
}
-#define reclaim_freelist(list, cb) \
+#define reclaim_freelist(list, type, cb) \
for (unsigned i = 0; i < list.len; ++i) { \
- cb(list.at[i]); \
+ type *elm = list.at[i]; \
+ kr_asan_unpoison(elm, sizeof(type)); \
+ cb(elm); \
} \
array_clear(list)
void worker_reclaim(struct worker_ctx *worker)
{
- reclaim_freelist(worker->pools, mp_delete);
- reclaim_freelist(worker->ioreqs, free);
+ reclaim_freelist(worker->pools, struct mempool, mp_delete);
+ reclaim_freelist(worker->ioreqs, struct ioreq, free);
mp_delete(worker->pkt_pool.ctx);
worker->pkt_pool.ctx = NULL;
}
#define KR_DNS_PORT 53
#define KR_EDNS_VERSION 0
#define KR_EDNS_PAYLOAD 4096 /* Default UDP payload (max unfragmented UDP is 1452B) */
-/* @endcond */
+
+/*
+ * Address sanitizer hints.
+ */
+#if !defined(__SANITIZE_ADDRESS__) && defined(__has_feature)
+# if __has_feature(address_sanitizer)
+# define __SANITIZE_ADDRESS__ 1
+# endif
+#endif
+#if defined(__SANITIZE_ADDRESS__)
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#define kr_asan_poison(addr, size) __asan_poison_memory_region((addr), (size))
+#define kr_asan_unpoison(addr, size) __asan_unpoison_memory_region((addr), (size))
+#else
+#define kr_asan_poison(addr, size)
+#define kr_asan_unpoison(addr, size)
+#endif
+/* @endcond */
\ No newline at end of file