Simplify memory manager

This commit is contained in:
Justine Tunney 2024-07-04 10:52:16 -07:00
parent 5a9a08d1cf
commit 01587de761
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
40 changed files with 451 additions and 311 deletions

View file

@ -46,7 +46,7 @@ void SetUpOnce(void) {
exit(0);
}
testlib_enable_tmp_setup_teardown();
pagesize = (size_t)getauxval(AT_PAGESZ);
pagesize = (size_t)getpagesize();
// ASSERT_SYS(0, 0, pledge("stdio rpath wpath cpath", 0));
}

View file

@ -65,8 +65,8 @@ TEST(madvise, subPages) {
ASSERT_NE(MAP_FAILED, (p = mmap(0, __granularity(), PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)));
ASSERT_SYS(0, 0,
madvise(p + getauxval(AT_PAGESZ),
__granularity() - getauxval(AT_PAGESZ), MADV_WILLNEED));
madvise(p + getpagesize(), __granularity() - getpagesize(),
MADV_WILLNEED));
ASSERT_SYS(0, 0, munmap(p, __granularity()));
}

View file

@ -136,8 +136,8 @@ TEST(setrlimit, testMemoryLimit) {
ASSERT_NE(-1, (wstatus = xspawn(0)));
if (wstatus == -2) {
ASSERT_EQ(0, SetKernelEnforcedMemoryLimit(MEM));
for (gotsome = false, i = 0; i < (MEM * 2) / getauxval(AT_PAGESZ); ++i) {
p = mmap(0, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE,
for (gotsome = false, i = 0; i < (MEM * 2) / __granularity(); ++i) {
p = mmap(0, __granularity(), PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_POPULATE, -1, 0);
if (p != MAP_FAILED) {
gotsome = true;
@ -149,7 +149,7 @@ TEST(setrlimit, testMemoryLimit) {
ASSERT_EQ(ENOMEM, errno);
_Exit(0);
}
rngset(p, getauxval(AT_PAGESZ), _rand64, -1);
rngset(p, __granularity(), _rand64, -1);
}
_Exit(1);
}
@ -162,24 +162,18 @@ TEST(setrlimit, testMemoryLimit) {
TEST(setrlimit, testVirtualMemoryLimit) {
char *p;
int i, wstatus;
if (IsXnu())
return; /* doesn't work on darwin */
if (IsOpenbsd())
return; /* unavailable on openbsd */
if (IsWindows())
return; /* of course it doesn't work on windows */
ASSERT_NE(-1, (wstatus = xspawn(0)));
if (wstatus == -2) {
ASSERT_EQ(0, setrlimit(RLIMIT_AS, &(struct rlimit){MEM, MEM}));
for (i = 0; i < (MEM * 2) / getauxval(AT_PAGESZ); ++i) {
p = sys_mmap(0, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE,
for (i = 0; i < (MEM * 2) / __granularity(); ++i) {
p = sys_mmap(0, __granularity(), PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_POPULATE, -1, 0)
.addr;
if (p == MAP_FAILED) {
ASSERT_EQ(ENOMEM, errno);
_Exit(0);
}
rngset(p, getauxval(AT_PAGESZ), _rand64, -1);
rngset(p, __granularity(), _rand64, -1);
}
_Exit(1);
}
@ -205,15 +199,15 @@ TEST(setrlimit, testDataMemoryLimit) {
ASSERT_NE(-1, (wstatus = xspawn(0)));
if (wstatus == -2) {
ASSERT_EQ(0, setrlimit(RLIMIT_DATA, &(struct rlimit){MEM, MEM}));
for (i = 0; i < (MEM * 2) / getauxval(AT_PAGESZ); ++i) {
p = sys_mmap(0, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE,
for (i = 0; i < (MEM * 2) / __granularity(); ++i) {
p = sys_mmap(0, __granularity(), PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_POPULATE, -1, 0)
.addr;
if (p == MAP_FAILED) {
ASSERT_EQ(ENOMEM, errno);
_Exit(0);
}
rngset(p, getauxval(AT_PAGESZ), _rand64, -1);
rngset(p, __granularity(), _rand64, -1);
}
_Exit(1);
}

View file

@ -75,7 +75,7 @@ TEST(sigbus, test) {
// map two pages of the file into memory
char *map;
long pagesz = getauxval(AT_PAGESZ);
long pagesz = getpagesize();
ASSERT_NE(MAP_FAILED,
(map = mmap(0, pagesz * 2, PROT_READ, MAP_PRIVATE, 3, 0)));

View file

@ -228,7 +228,7 @@ TEST(ksnprintf, fuzzTheUnbreakable) {
char *f, b[32];
_Alignas(65536) static const char weasel[65535];
f = (void *)__veil("r", weasel);
EXPECT_SYS(0, 0, mprotect(f, __granularity(), PROT_READ | PROT_WRITE));
EXPECT_SYS(0, 0, mprotect(f, getpagesize(), PROT_READ | PROT_WRITE));
strcpy(f, "hello %s\n");
EXPECT_EQ(12, ksnprintf(b, sizeof(b), f, "world"));
EXPECT_STREQ("hello world\n", b);
@ -240,7 +240,7 @@ TEST(ksnprintf, fuzzTheUnbreakable) {
f[Rando() & 15] = '%';
ksnprintf(b, sizeof(b), f, lemur64(), lemur64(), lemur64());
}
EXPECT_SYS(0, 0, mprotect(f, __granularity(), PROT_READ));
EXPECT_SYS(0, 0, mprotect(f, getpagesize(), PROT_READ));
}
TEST(kprintf, testFailure_wontClobberErrnoAndBypassesSystemCallSupport) {

View file

@ -60,9 +60,11 @@
__static_yoink("zipos");
int pagesz;
int granularity;
void SetUpOnce(void) {
pagesz = getpagesize();
granularity = __granularity();
testlib_enable_tmp_setup_teardown();
// ASSERT_SYS(0, 0, pledge("stdio rpath wpath cpath proc", 0));
@ -84,27 +86,41 @@ TEST(mmap, overflow) {
TEST(mmap, noreplaceImage) {
ASSERT_SYS(EEXIST, MAP_FAILED,
mmap(__executable_start, granularity, PROT_READ,
mmap(__executable_start, 1, PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0));
}
TEST(mmap, noreplaceExistingMap) {
char *p;
ASSERT_NE(MAP_FAILED, (p = mmap(0, granularity, PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
ASSERT_NE(MAP_FAILED,
(p = mmap(0, 1, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
ASSERT_SYS(EEXIST, MAP_FAILED,
mmap(p, granularity, PROT_READ,
mmap(p, 1, PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0));
EXPECT_SYS(0, 0, munmap(p, granularity));
EXPECT_SYS(0, 0, munmap(p, 1));
}
TEST(mmap, pageBeyondGone) {
int pagesz = getpagesize();
char *p = mmap(0, pagesz * 2, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
ASSERT_EQ(0, munmap(p, pagesz * 2));
p = mmap(p, 1, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
ASSERT_NE(MAP_FAILED, p);
EXPECT_TRUE(testlib_memoryexists(p));
EXPECT_TRUE(testlib_memoryexists(p + pagesz - 1));
EXPECT_FALSE(testlib_memoryexists(p + pagesz));
ASSERT_EQ(0, munmap(p, 1));
}
TEST(mmap, fixedTaken) {
char *p;
ASSERT_NE(MAP_FAILED, (p = mmap(0, granularity, PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
ASSERT_NE(MAP_FAILED, mmap(p, granularity, PROT_READ,
ASSERT_NE(MAP_FAILED,
(p = mmap(0, 1, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
ASSERT_NE(MAP_FAILED, mmap(p, 1, PROT_READ,
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
EXPECT_SYS(0, 0, munmap(p, granularity));
EXPECT_SYS(0, 0, munmap(p, 1));
}
TEST(mmap, hint) {
@ -181,7 +197,7 @@ TEST(mmap, testMapFile_fdGetsClosed_makesNoDifference) {
EXPECT_NE(-1, close(fd));
EXPECT_STREQN("hello", p, 5);
p[1] = 'a';
EXPECT_NE(-1, msync(p, getauxval(AT_PAGESZ), MS_SYNC));
EXPECT_NE(-1, msync(p, getpagesize(), MS_SYNC));
ASSERT_NE(-1, (fd = open(path, O_RDONLY)));
EXPECT_EQ(5, read(fd, buf, 5));
EXPECT_STREQN("hallo", buf, 5);
@ -193,7 +209,7 @@ TEST(mmap, testMapFile_fdGetsClosed_makesNoDifference) {
TEST(mmap, fileOffset) {
int fd;
char *map;
int offset_align = IsWindows() ? granularity : getauxval(AT_PAGESZ);
int offset_align = IsWindows() ? granularity : getpagesize();
ASSERT_NE(-1, (fd = open("foo", O_CREAT | O_RDWR, 0644)));
EXPECT_NE(-1, ftruncate(fd, offset_align * 2));
EXPECT_NE(-1, pwrite(fd, "hello", 5, offset_align * 0));
@ -433,15 +449,15 @@ void *ptrs[N];
void BenchMmapPrivate(void) {
void *p;
p = mmap(0, granularity, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE,
-1, 0);
p = mmap(0, granularity * 10, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
__builtin_trap();
ptrs[count++] = p;
}
void BenchUnmap(void) {
if (munmap(ptrs[--count], granularity))
if (munmap(ptrs[--count], granularity * 10))
__builtin_trap();
}

View file

@ -120,9 +120,9 @@ void TearDown(void) {
}
TEST(mprotect, testOkMemory) {
char *p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
char *p = gc(memalign(getpagesize(), getpagesize()));
p[0] = 0;
ASSERT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
ASSERT_NE(-1, mprotect(p, getpagesize(), PROT_READ | PROT_WRITE));
p[0] = 1;
EXPECT_EQ(1, p[0]);
EXPECT_FALSE(gotsegv);
@ -131,20 +131,19 @@ TEST(mprotect, testOkMemory) {
TEST(mprotect, testSegfault_writeToReadOnlyAnonymous) {
volatile char *p;
p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
p = gc(memalign(getpagesize(), getpagesize()));
EXPECT_FALSE(gotsegv);
p[0] = 1;
EXPECT_FALSE(gotsegv);
EXPECT_FALSE(gotbusted);
EXPECT_NE(-1, mprotect((void *)p, getauxval(AT_PAGESZ), PROT_READ));
EXPECT_NE(-1, mprotect((void *)p, getpagesize(), PROT_READ));
__expropriate(p[0]);
EXPECT_FALSE(gotsegv);
EXPECT_FALSE(gotbusted);
p[0] = 2;
EXPECT_TRUE(gotsegv | gotbusted);
EXPECT_EQ(1, p[0]);
EXPECT_NE(-1,
mprotect((void *)p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
EXPECT_NE(-1, mprotect((void *)p, getpagesize(), PROT_READ | PROT_WRITE));
}
TEST(mprotect, testExecOnly_canExecute) {
@ -164,22 +163,21 @@ TEST(mprotect, testExecOnly_canExecute) {
TEST(mprotect, testProtNone_cantEvenRead) {
volatile char *p;
p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
EXPECT_NE(-1, mprotect((void *)p, getauxval(AT_PAGESZ), PROT_NONE));
p = gc(memalign(getpagesize(), getpagesize()));
EXPECT_NE(-1, mprotect((void *)p, getpagesize(), PROT_NONE));
__expropriate(p[0]);
EXPECT_TRUE(gotsegv | gotbusted);
EXPECT_NE(-1,
mprotect((void *)p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
EXPECT_NE(-1, mprotect((void *)p, getpagesize(), PROT_READ | PROT_WRITE));
}
TEST(mprotect, testExecJit_actuallyWorks) {
int (*p)(void) = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
int (*p)(void) = gc(memalign(getpagesize(), getpagesize()));
memcpy(p, kRet31337, sizeof(kRet31337));
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_EXEC));
EXPECT_NE(-1, mprotect(p, getpagesize(), PROT_EXEC));
EXPECT_EQ(31337, p());
EXPECT_FALSE(gotsegv);
EXPECT_FALSE(gotbusted);
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
EXPECT_NE(-1, mprotect(p, getpagesize(), PROT_READ | PROT_WRITE));
}
TEST(mprotect, testRwxMap_vonNeumannRules) {
@ -187,14 +185,13 @@ TEST(mprotect, testRwxMap_vonNeumannRules) {
return; // boo
if (IsXnuSilicon())
return; // boo
int (*p)(void) = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
int (*p)(void) = gc(memalign(getpagesize(), getpagesize()));
memcpy(p, kRet31337, sizeof(kRet31337));
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ),
PROT_READ | PROT_WRITE | PROT_EXEC));
EXPECT_NE(-1, mprotect(p, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC));
EXPECT_EQ(31337, p());
EXPECT_FALSE(gotsegv);
EXPECT_FALSE(gotbusted);
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
EXPECT_NE(-1, mprotect(p, getpagesize(), PROT_READ | PROT_WRITE));
}
TEST(mprotect, testExecuteFlatFileMapOpenedAsReadonly) {
@ -231,13 +228,13 @@ TEST(mprotect, testFileMap_canChangeToExecWhileOpenInRdwrMode) {
}
TEST(mprotect, testBadProt_failsEinval) {
volatile char *p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
volatile char *p = gc(memalign(getpagesize(), getpagesize()));
EXPECT_EQ(-1, mprotect((void *)p, 9999, -1));
EXPECT_EQ(EINVAL, errno);
}
TEST(mprotect, testZeroSize_doesNothing) {
volatile char *p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
volatile char *p = gc(memalign(getpagesize(), getpagesize()));
EXPECT_NE(-1, mprotect((void *)p, 0, PROT_READ));
p[0] = 1;
EXPECT_FALSE(gotsegv);