Skip to content

Commit c4311b4

Browse files
committed
func/cheri: probe memcpy correctness
Fling some misaligned cases at our memcpy and check the results
1 parent 2b3897e commit c4311b4

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

src/test/func/cheri/cheri.cc

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,119 @@ int main()
146146
*/
147147
}
148148

149+
/*
150+
* Verify that our memcpy implementation successfully copies capabilities
151+
* even when it is given a region that is not capability-aligned.
152+
*/
153+
message("Checking memcpy behaviors");
154+
{
155+
static constexpr size_t ncaps = 16;
156+
157+
int* icaps[ncaps];
158+
159+
for (size_t i = 0; i < ncaps; i++)
160+
{
161+
icaps[i] = (int*)&icaps[i];
162+
SNMALLOC_CHECK(__builtin_cheri_tag_get(icaps[i]));
163+
}
164+
165+
int* ocaps[ncaps];
166+
167+
/*
168+
* While it may seem trivial, check the both-aligned case, both for one
169+
* and for many capabilities.
170+
*/
171+
bzero(ocaps, sizeof(ocaps));
172+
snmalloc::memcpy<false>(ocaps, icaps, sizeof(void*));
173+
SNMALLOC_CHECK(__builtin_cheri_tag_get(ocaps[0]));
174+
SNMALLOC_CHECK(__builtin_cheri_equal_exact(icaps[0], ocaps[0]));
175+
176+
bzero(ocaps, sizeof(ocaps));
177+
snmalloc::memcpy<false>(ocaps, icaps, sizeof(icaps));
178+
for (size_t i = 0; i < ncaps; i++)
179+
{
180+
SNMALLOC_CHECK(__builtin_cheri_tag_get(ocaps[i]));
181+
SNMALLOC_CHECK(__builtin_cheri_equal_exact(icaps[i], ocaps[i]));
182+
}
183+
184+
/*
185+
* When both input and output are equally misaligned, we should preserve
186+
* caps that aren't sheared by the copy. The size of this copy is also
187+
* "unnatural", which should guarantee that any memcpy implementation that
188+
* tries the overlapping-misaligned-sizeof(long)-at-the-end dance corrupts
189+
* the penultimate capability by overwriting it with (identical) data.
190+
*
191+
* Probe a misaligned copy of bytes followed by a zero or more pointers
192+
* followed by bytes.
193+
*/
194+
for (size_t pre = 1; pre < sizeof(int*); pre++)
195+
{
196+
for (size_t post = 0; post < sizeof(int*); post++)
197+
{
198+
for (size_t ptrs = 0; ptrs < ncaps - 2; ptrs++)
199+
{
200+
bzero(ocaps, sizeof(ocaps));
201+
202+
snmalloc::memcpy<false>(
203+
pointer_offset(ocaps, pre),
204+
pointer_offset(icaps, pre),
205+
(ptrs + 1) * sizeof(int*) - pre + post);
206+
207+
/* prefix */
208+
SNMALLOC_CHECK(
209+
memcmp(
210+
pointer_offset(icaps, pre),
211+
pointer_offset(ocaps, pre),
212+
sizeof(int*) - pre) == 0);
213+
/* pointer */
214+
for (size_t p = 0; p < ptrs; p++)
215+
{
216+
SNMALLOC_CHECK(__builtin_cheri_tag_get(ocaps[1 + p]));
217+
SNMALLOC_CHECK(
218+
__builtin_cheri_equal_exact(icaps[1 + p], ocaps[1 + p]));
219+
}
220+
/* suffix */
221+
SNMALLOC_CHECK(memcmp(&icaps[1 + ptrs], &ocaps[1 + ptrs], post) == 0);
222+
}
223+
}
224+
}
225+
226+
/*
227+
* If the alignments are different, then the bytes should get copied but
228+
* the tags should be cleared.
229+
*/
230+
for (size_t sa = 0; sa < sizeof(int*); sa++)
231+
{
232+
for (size_t da = 0; da < sizeof(int*); da++)
233+
{
234+
static constexpr size_t n = 4;
235+
236+
if (sa == da)
237+
{
238+
continue;
239+
}
240+
241+
bzero(ocaps, n * sizeof(int*));
242+
243+
snmalloc::memcpy<false>(
244+
pointer_offset(ocaps, da),
245+
pointer_offset(icaps, sa),
246+
n * sizeof(int*) - da - sa);
247+
248+
for (size_t i = 0; i < n; i++)
249+
{
250+
SNMALLOC_CHECK(__builtin_cheri_tag_get(ocaps[i]) == 0);
251+
}
252+
253+
SNMALLOC_CHECK(
254+
memcmp(
255+
pointer_offset(icaps, sa),
256+
pointer_offset(ocaps, da),
257+
n * sizeof(int*) - da - sa) == 0);
258+
}
259+
}
260+
}
261+
149262
message("CHERI checks OK");
150263
return 0;
151264
}

0 commit comments

Comments
 (0)