11static int attachment_move(
void) {
12 int failed = 0,
id = -1;
13 const size_t p = vm_page;
15 unsigned char *view = (
void*)-1, *alias = (
void*)-1, *target = MAP_FAILED;
16 struct shmid_ds status;
17 CHECK((
id = shmget(IPC_PRIVATE, 3 * p, 0600)) >= 0);
18 CHECK((view = shmat(
id, NULL, 0)) != (
void*)-1 &&
19 (alias = shmat(
id, NULL, SHM_RDONLY)) != (
void*)-1);
20 for (
int n = 0; n < 3; ++n)
21 memset(view + n * p, 0xa1 + n, p);
22 CHECK(shmctl(
id, IPC_RMID, NULL) == 0);
23 CHECK((target = mmap(NULL, 3 * p, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED);
25 CHECK(mremap(view, 3 * p, 3 * p, MREMAP_MAYMOVE | MREMAP_FIXED, target) == target);
28 CHECK(shmdt(old) == -1 && errno == EINVAL);
29 CHECK(shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == 2 && status.shm_segsz == 3 * p);
30 CHECK(vm_uniform(view, p, 0xa1) && vm_uniform(alias + 2 * p, p, 0xa3));
32 CHECK(alias[0] == 0xa4 && (child = fork()) >= 0);
35 if (shmctl(
id, IPC_STAT, &status) || status.shm_nattch != 4 || view[0] != 0xa4 || shmdt(view) ||
36 shmctl(
id, IPC_STAT, &status) || status.shm_nattch != 3)
40 int result = vm_reap(child, 3000);
42 CHECK(result == 0 && shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == 2);
43 CHECK(mremap(view, 3 * p, 2 * p, 0) == view);
44 CHECK(view[0] == 0xa4 && view[p] == 0xa2 && alias[2 * p] == 0xa3);
45 CHECK(shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == 2 && status.shm_segsz == 3 * p);
46 CHECK(shmdt(view) == 0);
48 CHECK(shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == 1);
49 CHECK(shmdt(alias) == 0);
51 CHECK(shmctl(
id, IPC_STAT, &status) == -1 && errno == EINVAL);
58 if (target != MAP_FAILED)
59 munmap(target, 3 * p);
60 if (view != (
void*)-1)
62 if (alias != (
void*)-1)
65 shmctl(
id, IPC_RMID, NULL);
69static int rejected_attachment_forms(
void) {
70 int failed = 0,
id = -1;
71 const size_t p = vm_page;
72 unsigned char* view = (
void*)-1;
73 struct shmid_ds status;
74 CHECK((
id = shmget(IPC_PRIVATE, 3 * p, 0600)) >= 0 && (view = shmat(
id, NULL, 0)) != (
void*)-1);
75 memset(view, 0xb1, 3 * p);
76 CHECK(mremap(view + p, p, p, MREMAP_MAYMOVE) == MAP_FAILED && errno == EOPNOTSUPP);
77 CHECK(mremap(view, 3 * p, 4 * p, MREMAP_MAYMOVE) == MAP_FAILED && errno == EOPNOTSUPP);
78 CHECK(shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == 1 &&
79 vm_uniform(view, 3 * p, 0xb1));
80 CHECK(munmap(view + p, p) == 0);
81 CHECK(mremap(view, p, p, MREMAP_MAYMOVE) == MAP_FAILED && errno == EOPNOTSUPP);
82 CHECK(shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == 1 && vm_uniform(view, p, 0xb1) &&
83 vm_uniform(view + 2 * p, p, 0xb1));
84 CHECK(shmdt(view) == 0);
86 CHECK(shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == 0);
88 if (view != (
void*)-1)
91 shmctl(
id, IPC_RMID, NULL);
95static int attachment_victims(
void) {
96 int failed = 0,
id = -1, attached = 0;
97 const size_t p = vm_page;
98 unsigned char *view = (
void*)-1, *alias = (
void*)-1, *source = MAP_FAILED;
99 struct shmid_ds status;
100 CHECK((
id = shmget(IPC_PRIVATE, 3 * p, 0600)) >= 0);
101 CHECK((view = shmat(
id, NULL, 0)) != (
void*)-1);
103 CHECK((alias = shmat(
id, NULL, 0)) != (
void*)-1);
104 memset(view, 0xc1, 3 * p);
105 const int order[3] = {1, 0, 2};
106 for (
int n = 0; n < 3; ++n) {
107 CHECK((source = mmap(NULL, p, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) !=
109 memset(source, 0xd1 + n, p);
110 unsigned char* victim = view + order[n] * p;
111 CHECK(mremap(source, p, p, MREMAP_MAYMOVE | MREMAP_FIXED, victim) == victim);
115 CHECK(shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == (n == 2 ? 1U : 2U));
116 CHECK(vm_uniform(victim, p, 0xd1 + n) && vm_uniform(alias, 3 * p, 0xc1));
118 CHECK(shmdt(view) == -1 && errno == EINVAL);
119 CHECK(vm_uniform(view, p, 0xd2) && vm_uniform(view + p, p, 0xd1) &&
120 vm_uniform(view + 2 * p, p, 0xd3));
122 if (source != MAP_FAILED)
126 if (view != (
void*)-1)
128 if (alias != (
void*)-1)
131 shmctl(
id, IPC_RMID, NULL);
135int vm_test_remap_shm(
void) {
136 return attachment_move() || rejected_attachment_forms() || attachment_victims();