The Pedigree Project 0.1
uts-namespace-contract-test/main.c
1#define _GNU_SOURCE
2#include <sched.h>
3#include <signal.h>
4#include <string.h>
5#include <unistd.h>
6
7#include "contract.h"
8#include <sys/utsname.h>
9
10int main(int argc, char** argv) {
11 setvbuf(stdout, NULL, _IONBF, 0);
12 ns_page = (size_t)sysconf(_SC_PAGESIZE);
13 if (argc > 1 && !strcmp(argv[1], "uts-exec"))
14 return ns_exec(argc, argv);
15 struct {
16 const char* name;
17 int (*run)(void);
18 } families[] = {{"names", ns_names},
19 {"membership", ns_membership},
20 {"proc", ns_proc},
21 {"lifetime", ns_lifetime},
22 {"admission", ns_admission}};
23 int selected = 0;
24 if (argc > 2)
25 return 2;
26 for (size_t i = 0; i < sizeof(families) / sizeof(families[0]); ++i) {
27 if (argc == 2 && strcmp(argv[1], "all") && strcmp(argv[1], families[i].name))
28 continue;
29 ++selected;
30 struct utsname before, after;
31 struct ns_identity original, final;
32 if (uname(&before) || ns_path_identity("/proc/thread-self/ns/uts", &original))
33 return 1;
34 printf("UTS-NAMESPACE-CONTRACT: BEGIN %s\n", families[i].name);
35 pid_t child = fork();
36 if (!child) {
37 alarm(40);
38 int result;
39 if (unshare(CLONE_NEWUTS)) {
40 perror("family unshare");
41 result = 1;
42 } else {
43 result = families[i].run();
44 }
45 fflush(stderr);
46 _exit(result ? 1 : 0);
47 }
48 int status = child < 0 ? -1 : ns_reap(child, 45000);
49 if (uname(&after) || memcmp(&before, &after, sizeof(before)) ||
50 ns_path_identity("/proc/thread-self/ns/uts", &final) || !ns_same(original, final)) {
51 fprintf(stderr, "supervisor namespace changed after %s\n", families[i].name);
52 status = 1;
53 }
54 printf("UTS-NAMESPACE-CONTRACT: %s %s status=%d\n", status ? "FAIL" : "PASS", families[i].name,
55 status);
56 if (status)
57 return 1;
58 }
59 if (!selected)
60 return 2;
61 puts("UTS-NAMESPACE-CONTRACT: END PASS");
62 return 0;
63}