Skip to content

Commit 3fe0cda

Browse files
committed
add memtarget rollback tests
1 parent 04aa67b commit 3fe0cda

3 files changed

Lines changed: 484 additions & 4 deletions

File tree

temp/asan_memspace_filter_uaf.c

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/*
2+
* Reproduce a UAF in umfMemspaceFilterHelper() rollback.
3+
*
4+
* Build UMF with sanitizers, then compile this file with:
5+
*
6+
* clang -O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer \
7+
* -Iinclude -Isrc -Isrc/base_alloc -Isrc/utils -Isrc/coarse \
8+
* temp/asan_memspace_filter_uaf.c \
9+
* -Wl,--start-group \
10+
* build-asan/lib/libumf.a \
11+
* build-asan/lib/libumf_coarse.a \
12+
* build-asan/lib/libumf_ba.a \
13+
* build-asan/lib/libumf_utils.a \
14+
* -Wl,--end-group \
15+
* $(pkg-config --libs hwloc numa tbb 2>/dev/null || echo "-lhwloc -lnuma -ltbb") \
16+
* -ldl -lrt -pthread \
17+
* -o temp/asan_memspace_filter_uaf
18+
*
19+
* ASAN_OPTIONS="symbolize=1:halt_on_error=1:abort_on_error=1:detect_leaks=0" \
20+
* UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" \
21+
* temp/asan_memspace_filter_uaf
22+
*/
23+
24+
#include <stdio.h>
25+
#include <stdlib.h>
26+
27+
#include <umf/base.h>
28+
#include <umf/experimental/memspace.h>
29+
#include <umf/experimental/memtarget.h>
30+
31+
#include "memtarget_internal.h"
32+
#include "memtarget_ops.h"
33+
34+
typedef struct fake_target_t {
35+
unsigned id;
36+
} fake_target_t;
37+
38+
static int g_finalize_count;
39+
40+
static umf_result_t fake_initialize(void *params, void **memoryTarget) {
41+
if (!params || !memoryTarget) {
42+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
43+
}
44+
45+
fake_target_t *target = malloc(sizeof(*target));
46+
if (!target) {
47+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
48+
}
49+
50+
target->id = *(unsigned *)params;
51+
*memoryTarget = target;
52+
return UMF_RESULT_SUCCESS;
53+
}
54+
55+
static void fake_finalize(void *memoryTarget) {
56+
fake_target_t *target = memoryTarget;
57+
fprintf(stderr, "[ops] finalize(id=%u)\n", target->id);
58+
g_finalize_count++;
59+
free(memoryTarget);
60+
}
61+
62+
static umf_result_t fake_clone(void *memoryTarget, void **outMemoryTarget) {
63+
if (!memoryTarget || !outMemoryTarget) {
64+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
65+
}
66+
67+
fake_target_t *src = memoryTarget;
68+
fake_target_t *dst = malloc(sizeof(*dst));
69+
if (!dst) {
70+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
71+
}
72+
73+
dst->id = src->id;
74+
*outMemoryTarget = dst;
75+
return UMF_RESULT_SUCCESS;
76+
}
77+
78+
static umf_result_t
79+
fake_pool_create_from_memspace(umf_const_memspace_handle_t memspace,
80+
void **memoryTargets, size_t numTargets,
81+
umf_const_mempolicy_handle_t policy,
82+
umf_memory_pool_handle_t *pool) {
83+
(void)memspace;
84+
(void)memoryTargets;
85+
(void)numTargets;
86+
(void)policy;
87+
(void)pool;
88+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
89+
}
90+
91+
static umf_result_t fake_memory_provider_create_from_memspace(
92+
umf_const_memspace_handle_t memspace, void **memoryTargets,
93+
size_t numTargets, umf_const_mempolicy_handle_t policy,
94+
umf_memory_provider_handle_t *provider) {
95+
(void)memspace;
96+
(void)memoryTargets;
97+
(void)numTargets;
98+
(void)policy;
99+
(void)provider;
100+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
101+
}
102+
103+
static umf_result_t fake_get_capacity(void *memoryTarget, size_t *capacity) {
104+
(void)memoryTarget;
105+
*capacity = 4096;
106+
return UMF_RESULT_SUCCESS;
107+
}
108+
109+
static umf_result_t fake_get_bandwidth(void *srcMemoryTarget,
110+
void *dstMemoryTarget,
111+
size_t *bandwidth) {
112+
(void)srcMemoryTarget;
113+
(void)dstMemoryTarget;
114+
*bandwidth = 1;
115+
return UMF_RESULT_SUCCESS;
116+
}
117+
118+
static umf_result_t fake_get_latency(void *srcMemoryTarget,
119+
void *dstMemoryTarget, size_t *latency) {
120+
(void)srcMemoryTarget;
121+
(void)dstMemoryTarget;
122+
*latency = 1;
123+
return UMF_RESULT_SUCCESS;
124+
}
125+
126+
static umf_result_t fake_get_type(void *memoryTarget,
127+
umf_memtarget_type_t *type) {
128+
(void)memoryTarget;
129+
*type = UMF_MEMTARGET_TYPE_NUMA;
130+
return UMF_RESULT_SUCCESS;
131+
}
132+
133+
static umf_result_t fake_get_id(void *memoryTarget, unsigned *id) {
134+
*id = ((fake_target_t *)memoryTarget)->id;
135+
return UMF_RESULT_SUCCESS;
136+
}
137+
138+
static umf_result_t fake_compare(void *memTarget, void *otherMemTarget,
139+
int *result) {
140+
fake_target_t *left = memTarget;
141+
fake_target_t *right = otherMemTarget;
142+
143+
fprintf(stderr, "[ops] compare(a=%u, b=%u, finalize_count=%d)\n", left->id,
144+
right->id, g_finalize_count);
145+
146+
if (g_finalize_count > 0 && left->id == 2 && right->id == 2) {
147+
fprintf(stderr, "[ops] injected removal failure for id=2\n");
148+
return UMF_RESULT_ERROR_UNKNOWN;
149+
}
150+
151+
*result = left->id == right->id ? 0 : 1;
152+
return UMF_RESULT_SUCCESS;
153+
}
154+
155+
static const umf_memtarget_ops_t FAKE_OPS = {
156+
.version = UMF_MEMTARGET_OPS_VERSION_CURRENT,
157+
.initialize = fake_initialize,
158+
.finalize = fake_finalize,
159+
.clone = fake_clone,
160+
.pool_create_from_memspace = fake_pool_create_from_memspace,
161+
.memory_provider_create_from_memspace =
162+
fake_memory_provider_create_from_memspace,
163+
.get_capacity = fake_get_capacity,
164+
.get_bandwidth = fake_get_bandwidth,
165+
.get_latency = fake_get_latency,
166+
.get_type = fake_get_type,
167+
.get_id = fake_get_id,
168+
.compare = fake_compare,
169+
};
170+
171+
static int remove_everything(umf_const_memspace_handle_t memspace,
172+
umf_const_memtarget_handle_t target, void *args) {
173+
(void)memspace;
174+
(void)target;
175+
(void)args;
176+
return 0;
177+
}
178+
179+
static void check_success(const char *name, umf_result_t result) {
180+
if (result != UMF_RESULT_SUCCESS) {
181+
fprintf(stderr, "%s failed: %d\n", name, result);
182+
exit(1);
183+
}
184+
}
185+
186+
int main(void) {
187+
setbuf(stderr, NULL);
188+
189+
umf_memspace_handle_t memspace = NULL;
190+
check_success("umfMemspaceNew", umfMemspaceNew(&memspace));
191+
192+
umf_memtarget_handle_t target1 = NULL;
193+
umf_memtarget_handle_t target2 = NULL;
194+
umf_memtarget_handle_t target3 = NULL;
195+
unsigned id1 = 1;
196+
unsigned id2 = 2;
197+
unsigned id3 = 3;
198+
199+
check_success("umfMemtargetCreate(1)",
200+
umfMemtargetCreate(&FAKE_OPS, &id1, &target1));
201+
check_success("umfMemtargetCreate(2)",
202+
umfMemtargetCreate(&FAKE_OPS, &id2, &target2));
203+
check_success("umfMemtargetCreate(3)",
204+
umfMemtargetCreate(&FAKE_OPS, &id3, &target3));
205+
206+
check_success("umfMemspaceMemtargetAdd(1)",
207+
umfMemspaceMemtargetAdd(memspace, target1));
208+
check_success("umfMemspaceMemtargetAdd(2)",
209+
umfMemspaceMemtargetAdd(memspace, target2));
210+
check_success("umfMemspaceMemtargetAdd(3)",
211+
umfMemspaceMemtargetAdd(memspace, target3));
212+
213+
fprintf(stderr, "[*] filtering %zu targets\n",
214+
umfMemspaceMemtargetNum(memspace));
215+
umf_result_t result =
216+
umfMemspaceUserFilter(memspace, remove_everything, NULL);
217+
218+
fprintf(stderr, "[*] umfMemspaceUserFilter returned %d\n", result);
219+
fprintf(stderr, "[!] no sanitizer failure was observed\n");
220+
return result == UMF_RESULT_SUCCESS ? 0 : 1;
221+
}

test/CMakeLists.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022-2025 Intel Corporation
1+
# Copyright (C) 2022-2026 Intel Corporation
22
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
33
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

@@ -377,8 +377,10 @@ if(LINUX) # OS-specific functions are implemented
377377
LIBS ${LIBNUMA_LIBRARIES})
378378
add_umf_test(
379379
NAME memtarget
380-
SRCS memspaces/memtarget.cpp
381-
LIBS ${LIBNUMA_LIBRARIES} ${UMF_HWLOC_NAME})
380+
SRCS memspaces/memtarget.cpp ${UMF_SRC_DIR}/memtarget.c
381+
${UMF_SRC_DIR}/libumf_linux.c
382+
LIBS ${UMF_UTILS_FOR_TEST} ${UMF_BA_FOR_TEST} ${LIBNUMA_LIBRARIES}
383+
${UMF_HWLOC_NAME})
382384
add_umf_test(
383385
NAME provider_devdax_memory
384386
SRCS provider_devdax_memory.cpp

0 commit comments

Comments
 (0)