The Pedigree Project 0.1
selectors.c
1#define _GNU_SOURCE
2#include <limits.h>
3#include <string.h>
4#include <unistd.h>
5
6#include "contract.h"
7
8int cw_selectors(void) {
9 int failed = 0;
10 struct cw_child leader = CW_CHILD_INIT, member = CW_CHILD_INIT, own = CW_CHILD_INIT;
11 struct cw_child any = CW_CHILD_INIT, numeric = CW_CHILD_INIT;
12 siginfo_t info;
13 const uid_t uid = getuid();
14 CHECK(setpgid(0, 0) == 0 && getpgrp() == getpid());
15 CHECK(cw_spawn(&leader, 0, (uid_t)-1, 21) == 0);
16 CHECK(cw_spawn(&member, leader.pid, (uid_t)-1, 22) == 0);
17 CHECK(cw_spawn(&own, -1, (uid_t)-1, 23) == 0);
18 CHECK(getpgid(leader.pid) == leader.pid && getpgid(member.pid) == leader.pid);
19 CHECK(getpgid(own.pid) == getpgrp());
20 const pid_t other_group = leader.pid;
21
22 memset(&info, 0xa5, sizeof(info));
23 CHECK(waitid(P_PID, own.pid, &info, WEXITED | WNOHANG) == 0 && !cw_empty_info(&info));
24 CHECK(cw_send(leader.command, 'E') == 0);
25 CHECK(waitid(P_PID, leader.pid, &info, WEXITED | WNOWAIT) == 0);
26 CHECK(cw_info(&info, leader.pid, uid, CLD_EXITED, 21) == 0);
27 CHECK(waitid(P_PGID, leader.pid, &info, WEXITED) == 0);
28 CHECK(cw_info(&info, leader.pid, uid, CLD_EXITED, 21) == 0);
29 leader.pid = -1;
30 CHECK(cw_send(member.command, 'E') == 0);
31 CHECK(waitid(P_PGID, other_group, &info, WEXITED) == 0);
32 CHECK(cw_info(&info, member.pid, uid, CLD_EXITED, 22) == 0);
33 member.pid = -1;
34 CHECK(cw_send(own.command, 'E') == 0);
35 CHECK(waitid(P_PGID, 0, &info, WEXITED) == 0);
36 CHECK(cw_info(&info, own.pid, uid, CLD_EXITED, 23) == 0);
37 own.pid = -1;
38
39 CHECK(cw_spawn(&any, -1, (uid_t)-1, 0x1ab) == 0 && cw_send(any.command, 'E') == 0);
40 CHECK(waitid(P_ALL, (id_t)UINT_MAX, &info, WEXITED) == 0);
41 CHECK(cw_info(&info, any.pid, uid, CLD_EXITED, 0xab) == 0);
42 any.pid = -1;
43
44 if (geteuid() == 0) {
45 CHECK(cw_spawn(&numeric, -1, 17001, 31) == 0);
46 CHECK(cw_send(numeric.command, 'E') == 0);
47 CHECK(waitid(P_PID, numeric.pid, &info, WEXITED) == 0);
48 CHECK(cw_info(&info, numeric.pid, 17001, CLD_EXITED, 31) == 0);
49 numeric.pid = -1;
50 } else {
51 puts("CHILD-WAIT-CONTRACT: SKIP distinct numeric real UID (requires root)");
52 }
53out:
54 cw_cleanup(&numeric);
55 cw_cleanup(&any);
56 cw_cleanup(&own);
57 cw_cleanup(&member);
58 cw_cleanup(&leader);
59 return failed;
60}