memtag_test: add test for MADV_DONTNEED behavior

This commit is contained in:
Dmitry Muhomor 2024-01-23 13:33:06 +02:00 committed by Daniel Micay
parent 7d2151e40c
commit 5fbbdc2ef8
3 changed files with 47 additions and 0 deletions

View File

@ -6,6 +6,7 @@ cc_test {
"-Werror", "-Werror",
"-Wextra", "-Wextra",
"-O0", "-O0",
"-march=armv9-a+memtag",
], ],
compile_multilib: "64", compile_multilib: "64",

View File

@ -6,6 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/mman.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <unistd.h> #include <unistd.h>
@ -14,6 +15,8 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "../../arm_mte.h"
using namespace std; using namespace std;
using u8 = uint8_t; using u8 = uint8_t;
@ -37,6 +40,10 @@ void *untag_pointer(void *ptr) {
return (void *) ((uintptr_t) ptr & mask); return (void *) ((uintptr_t) ptr & mask);
} }
void *set_pointer_tag(void *ptr, u8 tag) {
return (void *) (((uintptr_t) tag << 56) | (uintptr_t) untag_pointer(ptr));
}
// This test checks that slab slot allocation uses tag that is distint from tags of its neighbors // This test checks that slab slot allocation uses tag that is distint from tags of its neighbors
// and from the tag of the previous allocation that used the same slot // and from the tag of the previous allocation that used the same slot
void tag_distinctness() { void tag_distinctness() {
@ -263,6 +270,39 @@ void untagged_write() {
expect_write_segv(p[0] = 1); expect_write_segv(p[0] = 1);
} }
// checks that each of memory locations inside the buffer is tagged with expected_tag
void check_tag(void *buf, size_t len, u8 expected_tag) {
for (size_t i = 0; i < len; ++i) {
assert(get_pointer_tag(__arm_mte_get_tag((void *) ((uintptr_t) buf + i))) == expected_tag);
}
}
void madvise_dontneed() {
const size_t len = 100'000;
void *ptr = mmap(NULL, len, PROT_READ | PROT_WRITE | PROT_MTE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
assert(ptr != MAP_FAILED);
// check that 0 is the initial tag
check_tag(ptr, len, 0);
arm_mte_tag_and_clear_mem(set_pointer_tag(ptr, 1), len);
check_tag(ptr, len, 1);
memset(set_pointer_tag(ptr, 1), 1, len);
assert(madvise(ptr, len, MADV_DONTNEED) == 0);
// check that MADV_DONTNEED resets the tag
check_tag(ptr, len, 0);
// check that MADV_DONTNEED clears the memory
for (size_t i = 0; i < len; ++i) {
assert(((u8 *) ptr)[i] == 0);
}
// check that mistagged read after MADV_DONTNEED fails
expect_read_segv(*((u8 *) set_pointer_tag(ptr, 1)));
}
map<string, function<void()>> tests = { map<string, function<void()>> tests = {
#define TEST(s) { #s, s } #define TEST(s) { #s, s }
TEST(tag_distinctness), TEST(tag_distinctness),
@ -274,6 +314,7 @@ map<string, function<void()>> tests = {
TEST(underflow_write), TEST(underflow_write),
TEST(untagged_read), TEST(untagged_read),
TEST(untagged_write), TEST(untagged_write),
TEST(madvise_dontneed),
#undef TEST #undef TEST
}; };

View File

@ -71,4 +71,9 @@ public class MemtagTest extends BaseHostJUnit4Test {
public void untagged_write() throws DeviceNotAvailableException { public void untagged_write() throws DeviceNotAvailableException {
runTest("untagged_write"); runTest("untagged_write");
} }
@Test
public void madvise_dontneed() throws DeviceNotAvailableException {
runTest("madvise_dontneed");
}
} }