Skip to content

Commit 2102768

Browse files
modify test
1 parent 0261ef6 commit 2102768

File tree

1 file changed

+50
-34
lines changed

1 file changed

+50
-34
lines changed

tests/unit-tests/memory_tests/deterministic/munmap_adjacent_shm.c

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,24 @@
22
//
33
// Regression test for the bug fixed in PR #1075:
44
// munmap_syscall rounded `len` up to a page multiple and issued a single
5-
// mmap(MAP_FIXED|PROT_NONE) over the whole rounded range. When that
6-
// range crossed into a SharedMemory-backed vmmap entry, the host-level
7-
// PROT_NONE silently clobbered the shm page.
5+
// mmap(MAP_FIXED|PROT_NONE) over the whole rounded range. When that range
6+
// crossed into a SharedMemory-backed vmmap entry, the host-level PROT_NONE
7+
// silently clobbered the shm page.
88
//
9-
// Layout strategy (no MAP_FIXED, no shmat hint):
10-
// lind's allocator places NULL-addr shmat / mmap at the top of a free
11-
// gap, and empirically leaves a 1-page stride between consecutive
12-
// NULL-addr allocations. So:
13-
//
14-
// shmat(NULL) -> shm at top page T
15-
// mmap (NULL) -> anon at T - 2*PAGE
16-
// page at T - PAGE -> unmapped gap
9+
// Layout strategy:
10+
// 1. shmat(NULL) -> shm lands at some address T (allocator decides)
11+
// 2. mmap(T - 2*PAGE, ..., MAP_FIXED) -> anon forced to exactly T - 2*PAGE
12+
// 3. Gap page at T - PAGE is unmapped
1713
//
1814
// [ anon @ T-2P ][ gap @ T-P ][ shm @ T ]
1915
//
20-
// munmap(anon, 2*PAGE+1) rounds up to 3*PAGE and targets [T-2P .. T+P),
21-
// covering {anon, gap, shm}. The shm entry's backing is SharedMemory, so:
16+
// munmap(anon, 2*PAGE+1) rounds up to 3*PAGE and targets [T-2P .. T+P),
17+
// covering {anon, gap, shm}.
2218
//
2319
// Buggy path: one mmap(PROT_NONE, MAP_FIXED) over the full 3*PAGE range
2420
// clobbers shm's host memory -> reading shm[0] faults.
2521
// Fixed path: the overlap loop filters out the SharedMemory entry;
26-
// only the anon page gets PROT_NONE'd. shm stays readable.
27-
//
28-
// The stride is asserted explicitly — if allocator behavior ever changes
29-
// and anon doesn't land at T - 2*PAGE, the test fails loudly instead of
30-
// silently passing.
22+
// only the anon/gap pages get PROT_NONE'd. shm stays readable.
3123
#include <sys/ipc.h>
3224
#include <sys/shm.h>
3325
#include <sys/mman.h>
@@ -48,35 +40,59 @@ int main(void) {
4840
assert(((uintptr_t)shm % PAGE_SIZE) == 0 && "shm not page-aligned");
4941
memset(shm, 0xAB, PAGE_SIZE);
5042

51-
char *anon = (char *)mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
52-
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
53-
assert(anon != MAP_FAILED && "anon mmap failed");
54-
memset(anon, 0xCD, PAGE_SIZE);
43+
// Force anon exactly 2 pages below shm using MAP_FIXED.
44+
// We control anon's address; we don't need the allocator to cooperate.
45+
char *anon_target = shm - 2 * PAGE_SIZE;
46+
char *anon = (char *)mmap(anon_target, PAGE_SIZE, PROT_READ | PROT_WRITE,
47+
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
5548

56-
// Precondition on allocator layout: anon must land exactly 2 pages
57-
// below shm (one page of unmapped gap between them). If this ever
58-
// changes, fail loudly instead of passing by accident.
59-
assert(shm == anon + 2 * PAGE_SIZE &&
60-
"allocator layout changed: anon is not at shm - 2*PAGE");
49+
fprintf(stderr, " DIAG: shm @ %p\n", (void *)shm);
50+
fprintf(stderr, " DIAG: anon_target= %p\n", (void *)anon_target);
51+
fprintf(stderr, " DIAG: anon actual= %p\n", (void *)anon);
52+
fprintf(stderr, " DIAG: gap @ %p\n", (void *)(shm - PAGE_SIZE));
53+
fprintf(stderr, " DIAG: munmap range [%p, %p) — rounded len = 3 pages\n",
54+
(void *)anon, (void *)(anon + 3 * PAGE_SIZE));
6155

62-
// Unaligned munmap starting at anon, ending one byte past the gap:
63-
// len = 2*PAGE+1 -> rounded length = 3*PAGE
64-
// rounded range = [anon, anon + 3*PAGE) = [anon, shm + PAGE)
65-
// Buggy runtime PROT_NONEs the whole range (clobbering shm).
66-
// Fixed runtime skips the SharedMemory-backed page.
56+
if (anon == MAP_FAILED) {
57+
fprintf(stderr, "FAIL: MAP_FIXED mmap for anon failed\n");
58+
shmdt(shm);
59+
shmctl(shmid, IPC_RMID, NULL);
60+
return 1;
61+
}
62+
if (anon != anon_target) {
63+
fprintf(stderr,
64+
"FAIL: MAP_FIXED returned %p instead of %p — "
65+
"kernel rejected the fixed placement\n",
66+
(void *)anon, (void *)anon_target);
67+
munmap(anon, PAGE_SIZE);
68+
shmdt(shm);
69+
shmctl(shmid, IPC_RMID, NULL);
70+
return 1;
71+
}
72+
73+
memset(anon, 0xCD, PAGE_SIZE);
74+
75+
// munmap(anon, 2*PAGE+1):
76+
// rounded length = 3*PAGE
77+
// rounded range = [anon, anon+3*PAGE) = [T-2P, T+P)
78+
// Buggy runtime: PROT_NONEs the full range including shm at T.
79+
// Fixed runtime: skips the SharedMemory-backed page at T.
6780
int rc = munmap(anon, 2 * PAGE_SIZE + 1);
6881
assert(rc == 0 && "trigger munmap failed");
6982

83+
fprintf(stderr, " DIAG: munmap returned 0, checking shm integrity\n");
84+
7085
for (int i = 0; i < PAGE_SIZE; i++) {
7186
if ((unsigned char)shm[i] != 0xAB) {
72-
printf("FAIL: shm[%d] = 0x%02x, expected 0xAB\n",
73-
i, (unsigned char)shm[i]);
87+
fprintf(stderr, "FAIL: shm[%d] = 0x%02x, expected 0xAB\n",
88+
i, (unsigned char)shm[i]);
7489
shmdt(shm);
7590
shmctl(shmid, IPC_RMID, NULL);
7691
return 1;
7792
}
7893
}
7994

95+
fprintf(stderr, " DIAG: all %d shm bytes intact\n", PAGE_SIZE);
8096
printf("PASS: shm page intact after unaligned munmap of nearby anon\n");
8197
shmdt(shm);
8298
shmctl(shmid, IPC_RMID, NULL);

0 commit comments

Comments
 (0)