18static void* target_thread(
void* opaque) {
20 volatile unsigned char bytes[16] = {0x43};
22 int failed = pm_write(args->report, &address,
sizeof(address)) ||
23 pm_receive(args->command,
't') || bytes[0] != 0x54;
24 return (
void*)(uintptr_t)failed;
26static int thread_target(
int command,
int report,
void* ignored) {
28 int failed = 0, live = 0;
31 volatile unsigned char main_byte = 0x65;
32 uintptr_t main_address = (uintptr_t)&main_byte;
34 CHECK(!pm_dumpable(1) && !pm_write(report, &main_address,
sizeof(main_address)));
35 CHECK(!pthread_create(&thread, NULL, target_thread, &args));
37 CHECK(!pthread_join(thread, &result));
39 CHECK(result == NULL && !pm_send(report,
'd'));
40 CHECK(!pm_receive(command,
'q'));
48static int nonleader(
void) {
50 struct pm_peer peer = PM_PEER_INITIALIZER;
52 uintptr_t main_address;
54 CHECK(!pm_spawn(&peer, thread_target, NULL));
55 CHECK(!pm_read(peer.report, &main_address,
sizeof(main_address)));
56 CHECK(!pm_read(peer.report, &address,
sizeof(address)));
57 CHECK(address.tid > 0 && address.tid != peer.pid);
58 CHECK(pm_copy(address.tid, &
byte, (
void*)address.address, 1, 0) == 1 &&
byte == 0x43);
60 CHECK(pm_copy(address.tid, &
byte, (
void*)address.address, 1, 1) == 1);
61 CHECK(!pm_send(peer.command,
't') && !pm_receive(peer.report,
'd'));
63 CHECK(pm_copy(address.tid, &
byte, (
void*)address.address, 1, 0) == -1 && errno == ESRCH);
64 CHECK(pm_copy(peer.pid, &
byte, (
void*)main_address, 1, 0) == 1 &&
byte == 0x65);
65 CHECK(!pm_send(peer.command,
'q') && !pm_join(&peer));
70static int image_target(
int command,
int report,
void* ignored) {
73 unsigned char* bytes =
74 mmap(NULL, 3 * pm_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
75 CHECK(bytes != MAP_FAILED);
76 memset(bytes, 0x71, pm_page);
77 memset(bytes + pm_page, 0x82, pm_page);
78 memset(bytes + 2 * pm_page, 0x93, pm_page);
79 uintptr_t address = (uintptr_t)bytes;
80 CHECK(!pm_dumpable(1) && !pm_write(report, &address,
sizeof(address)));
81 CHECK(!pm_receive(command,
'u') && !munmap(bytes + pm_page, pm_page));
82 CHECK(!pm_send(report,
'u') && !pm_receive(command,
'x'));
83 char input[24], output[24];
84 snprintf(input,
sizeof(input),
"%d", command);
85 snprintf(output,
sizeof(output),
"%d", report);
86 execl(PM_APP, PM_APP,
"memory-exec", input, output, (
char*)NULL);
89 if (bytes != MAP_FAILED)
90 munmap(bytes, 3 * pm_page);
93int pm_exec(
int argc,
char** argv) {
96 int failed = 0, command = atoi(argv[2]), report = atoi(argv[3]);
97 unsigned char* bytes =
98 mmap(NULL, pm_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
99 CHECK(bytes != MAP_FAILED);
100 memset(bytes, 0xe1, pm_page);
101 uintptr_t address = (uintptr_t)bytes;
102 CHECK(!pm_write(report, &address,
sizeof(address)) && !pm_receive(command,
'q'));
103 CHECK(bytes[0] == 0xe2 && bytes[1] == 0xe1);
105 if (bytes != MAP_FAILED)
106 munmap(bytes, pm_page);
109static int images(
void) {
111 struct pm_peer peer = PM_PEER_INITIALIZER;
112 uintptr_t address, replacement;
113 unsigned char* local =
114 mmap(NULL, 3 * pm_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
115 CHECK(local != MAP_FAILED && !pm_spawn(&peer, image_target, NULL));
116 CHECK(!pm_read(peer.report, &address,
sizeof(address)));
117 CHECK(pm_copy(peer.pid, local, (
void*)address, 3 * pm_page, 0) == (ssize_t)(3 * pm_page));
118 CHECK(local[0] == 0x71 && local[pm_page] == 0x82 && local[2 * pm_page] == 0x93);
119 CHECK(!pm_send(peer.command,
'u') && !pm_receive(peer.report,
'u'));
120 memset(local, 0xa4, 3 * pm_page);
121 CHECK(pm_copy(peer.pid, local, (
void*)address, 3 * pm_page, 0) == (ssize_t)pm_page);
122 CHECK(local[0] == 0x71 && local[pm_page] == 0xa4 && local[2 * pm_page] == 0xa4);
124 CHECK(pm_copy(peer.pid, local, (
void*)(address + pm_page), 1, 1) == -1 && errno == EFAULT);
125 CHECK(pm_copy(peer.pid, local, (
void*)(address + 2 * pm_page), 1, 0) == 1 && local[0] == 0x93);
126 CHECK(!pm_send(peer.command,
'x') && !pm_read(peer.report, &replacement,
sizeof(replacement)));
127 CHECK(pm_copy(peer.pid, local, (
void*)replacement, pm_page, 0) == (ssize_t)pm_page);
128 for (
size_t n = 0; n < pm_page; ++n)
129 CHECK(local[n] == 0xe1);
131 CHECK(pm_copy(peer.pid, local, (
void*)replacement, 1, 1) == 1);
132 pid_t departed = peer.pid;
133 CHECK(!pm_send(peer.command,
'q') && !pm_join(&peer));
135 CHECK(pm_copy(departed, local, (
void*)replacement, 1, 0) == -1 && errno == ESRCH);
138 if (local != MAP_FAILED)
139 munmap(local, 3 * pm_page);
142int pm_lifetime(
void) {
143 return nonleader() || images();