7#include <sys/syscall.h>
9static int exited(
struct cw_child* child,
int status,
struct rusage*
usage, siginfo_t* info) {
11 return cw_spawn(child, -1, (uid_t)-1, status) || cw_send(child->command,
'B') ||
12 cw_receive(child->report,
'B') || cw_send(child->command,
'E') ||
13 cw_raw_waitid(P_PID, child->pid, info, WEXITED | WNOWAIT,
usage)
18static int fault_case(
int use_wait4,
int first_output,
int no_wait) {
19 int failed = 0, status = 0x7777;
20 struct cw_child child = CW_CHILD_INIT;
21 struct rusage
usage, expected;
23 void* bad = mmap(NULL, cw_page, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
24 CHECK(bad != MAP_FAILED);
25 CHECK(exited(&child, 67, &expected, &info) == 0 && !cw_usage(&expected));
26 memset(&info, 0xa5,
sizeof(info));
32 syscall(SYS_wait4, child.pid, first_output ? bad : &status, 0, first_output ? &
usage : bad);
34 result = cw_raw_waitid(P_PID, child.pid, first_output ? &info : bad,
35 WEXITED | (no_wait ? WNOWAIT : 0), first_output ? bad : &
usage);
37 CHECK(result == -1 && errno == EFAULT);
40 CHECK(cw_bytes(&
usage,
sizeof(
usage), 0xa5) == 0);
42 CHECK(WIFEXITED(status) && WEXITSTATUS(status) == 67);
43 }
else if (first_output) {
44 CHECK(cw_bytes(&info,
sizeof(info), 0xa5) == 0);
46 CHECK(memcmp(&
usage, &expected, CW_RUSAGE_BYTES) == 0 && !cw_usage(&
usage));
49 CHECK(waitid(P_PID, child.pid, &info, WEXITED | WNOWAIT) == 0);
50 CHECK(cw_info(&info, child.pid, getuid(), CLD_EXITED, 67) == 0);
51 CHECK(wait4(child.pid, &status, 0, NULL) == child.pid && WEXITSTATUS(status) == 67);
53 CHECK(waitid(P_PID, child.pid, &info, WEXITED | WNOHANG) == -1 && errno == ECHILD);
54 CHECK(!cw_empty_info(&info));
59 if (bad != MAP_FAILED)
64static int optional_and_overlap(
void) {
66 struct cw_child child = CW_CHILD_INIT;
67 struct rusage
usage, expected_usage;
68 siginfo_t info, expected_info;
74 CHECK(exited(&child, 73, &expected_usage, &info) == 0);
75 CHECK(!cw_usage(&expected_usage));
76 CHECK(cw_info(&info, child.pid, getuid(), CLD_EXITED, 73) == 0);
78 CHECK(cw_raw_waitid(P_PID, child.pid, NULL, WEXITED | WNOWAIT, &
usage) == 0);
79 CHECK(memcmp(&
usage, &expected_usage, CW_RUSAGE_BYTES) == 0 && !cw_usage(&
usage));
81 memset(&info, 0xa5,
sizeof(info));
83 expected_info.si_signo = SIGCHLD;
84 expected_info.si_errno = 0;
85 expected_info.si_code = CLD_EXITED;
86 expected_info.si_pid = child.pid;
87 expected_info.si_uid = getuid();
88 expected_info.si_status = 73;
89 CHECK(waitid(P_PID, child.pid, &info, WEXITED | WNOWAIT) == 0);
90 CHECK(memcmp(&info, &expected_info,
sizeof(info)) == 0);
92 memset(&overlap, 0xa5,
sizeof(overlap));
93 memset(&expected, 0xa5,
sizeof(expected));
94 memcpy(&expected, &expected_usage, CW_RUSAGE_BYTES);
95 expected.info.si_signo = SIGCHLD;
96 expected.info.si_errno = 0;
97 expected.info.si_code = CLD_EXITED;
98 expected.info.si_pid = child.pid;
99 expected.info.si_uid = getuid();
100 expected.info.si_status = 73;
101 CHECK(cw_raw_waitid(P_PID, child.pid, &overlap.info, WEXITED | WNOWAIT, &overlap.usage) == 0);
102 CHECK(memcmp(&overlap, &expected, CW_RUSAGE_BYTES) == 0);
103 CHECK(cw_bytes((
const unsigned char*)&overlap + CW_RUSAGE_BYTES,
104 sizeof(overlap) - CW_RUSAGE_BYTES, 0xa5) == 0);
107 CHECK(syscall(SYS_wait4, child.pid, &overlap.status, 0, &overlap.usage) == child.pid);
108 CHECK(memcmp(&overlap.usage, &expected_usage, CW_RUSAGE_BYTES) == 0 && !cw_usage(&overlap.usage));
111 CHECK(exited(&child, 74, &
usage, &info) == 0);
112 CHECK(cw_raw_waitid(P_PID, child.pid, NULL, WEXITED, NULL) == 0);
113 CHECK(waitpid(child.pid, NULL, WNOHANG) == -1 && errno == ECHILD);
120int cw_copyout(
void) {
121 for (
int no_wait = 0; no_wait < 2; ++no_wait)
122 for (
int first = 0; first < 2; ++first)
123 if (fault_case(0, first, no_wait))
125 for (
int first = 0; first < 2; ++first)
126 if (fault_case(1, first, 0))
128 return optional_and_overlap();