The Pedigree Project 0.1
private.c
1#define _GNU_SOURCE
2#include <signal.h>
3#include <unistd.h>
4
5#include "contract.h"
6#include <sys/mman.h>
7
8static int private_child(int fd, unsigned char* private, unsigned char* borrowed, int ready,
9 int gate) {
10 int failed = 0;
11 const size_t page = fr_page, length = 4 * page, cut = page + 137;
12 unsigned char* independent = mmap(NULL, 3 * page, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page);
13 CHECK(independent != MAP_FAILED && private[23] == 0xc1 && private[2 * page + 19] == 0xc2);
14 private[23] = 0xd1;
15 private[2 * page + 19] = 0xd2;
16 CHECK(fr_matches(independent, page, 3 * page, 0) && fr_matches(borrowed, page, 3 * page, 0));
17 CHECK(!fr_resident(private, 4, 15, "child private before shrink") &&
18 !fr_resident(independent, 3, 7, "independent child alias before shrink"));
19 CHECK(!fr_send(ready, 'r') && !fr_receive(gate, 's'));
20
21 CHECK(!fr_resident(private, 4, 3, "child private after shrink") &&
22 !fr_resident(borrowed, 3, 1, "inherited child alias after shrink") &&
23 !fr_resident(independent, 3, 1, "independent child alias after shrink"));
24 CHECK(private[23] == 0xd1 && fr_matches(private, 0, 23, 0) &&
25 fr_matches(private + 24, 24, cut - 24, 0));
26 CHECK(fr_matches(private + cut, cut, 2 * page - cut, 1));
27 CHECK(fr_matches(independent, page, 137, 0) && fr_matches(independent + 137, cut, page - 137, 1));
28 CHECK(fr_matches(borrowed, page, 137, 0) && fr_matches(borrowed + 137, cut, page - 137, 1));
29 CHECK(!fr_fault(private + 2 * page) && !fr_fault(independent + page));
30 CHECK(!fr_send(ready, 's') && !fr_receive(gate, 'g'));
31
32 CHECK(!fr_resident(private, 2, 3, "child private prefix after regrowth") &&
33 !fr_resident(independent, 1, 1, "independent child prefix after regrowth"));
34 CHECK(private[23] == 0xd1 && fr_matches(private + cut, cut, length - cut, 1));
35 CHECK(fr_matches(independent + 137, cut, length - cut, 1) &&
36 fr_matches(borrowed + 137, cut, length - cut, 1));
37 independent[257] = 0xe7;
38 CHECK(private[page + 257] == 0xe7 && borrowed[257] == 0xe7);
39 CHECK(!fr_send(ready, 'g'));
40out:
41 if (independent != MAP_FAILED)
42 munmap(independent, 3 * page);
43 return failed;
44}
45
46int fr_private(int backend) {
47 int failed = 0, ready[2] = {-1, -1}, gate[2] = {-1, -1};
48 struct fr_file file = {.fd = -1};
49 const size_t page = fr_page, length = 4 * page, cut = page + 137;
50 pid_t child = -1;
51 unsigned char *private = MAP_FAILED, *borrowed = MAP_FAILED;
52 unsigned char byte;
53 CHECK(!fr_create(&file, backend));
54 private = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, file.fd, 0);
55 borrowed = mmap(NULL, 3 * page, PROT_READ, MAP_PRIVATE, file.fd, page);
56 CHECK(private != MAP_FAILED && borrowed != MAP_FAILED);
57 CHECK(fr_matches(private, 0, length, 0) && fr_matches(borrowed, page, 3 * page, 0));
58 private[23] = 0xc1;
59 private[2 * page + 19] = 0xc2;
60 CHECK(!fr_contents(file.fd, 0, length, 0));
61 CHECK(!pipe(ready) && !pipe(gate) && (child = fork()) >= 0);
62 if (!child) {
63 alarm(15);
64 close(ready[0]);
65 close(gate[1]);
66 int result = private_child(file.fd, private, borrowed, ready[1], gate[0]);
67 fflush(stderr);
68 _exit(result ? 1 : 0);
69 }
70 CHECK(!close(ready[1]) && !close(gate[0]));
71 ready[1] = gate[0] = -1;
72 CHECK(!fr_receive(ready[0], 'r'));
73 CHECK(private[23] == 0xc1 && private[2 * page + 19] == 0xc2);
74 CHECK(!fr_resident(private, 4, 15, "parent private before shrink"));
75 CHECK(!ftruncate(file.fd, cut));
76 CHECK(!fr_resident(private, 4, 3, "parent private after shrink") &&
77 !fr_resident(borrowed, 3, 1, "parent borrowed after shrink"));
78 CHECK(private[23] == 0xc1 && fr_matches(private, 0, 23, 0) &&
79 fr_matches(private + 24, 24, cut - 24, 0));
80 CHECK(fr_matches(private + cut, cut, 2 * page - cut, 1) &&
81 fr_matches(borrowed + 137, cut, page - 137, 1));
82 CHECK(!fr_send(gate[1], 's') && !fr_receive(ready[0], 's'));
83 CHECK(!fr_fault(private + 2 * page));
84 CHECK(!ftruncate(file.fd, length));
85 CHECK(!fr_resident(private, 2, 3, "parent private prefix after regrowth"));
86 CHECK(private[23] == 0xc1 && fr_matches(private + cut, cut, length - cut, 1));
87 CHECK(!fr_send(gate[1], 'g') && !fr_receive(ready[0], 'g'));
88 CHECK(private[23] == 0xc1 && private[page + 257] == 0xe7 && borrowed[257] == 0xe7);
89 CHECK(pread(file.fd, &byte, 1, page + 257) == 1 && byte == 0xe7);
90 int status = fr_reap(child, 5000);
91 child = -1;
92 CHECK(status == 0);
93out:
94 if (child > 0) {
95 kill(child, SIGKILL);
96 fr_reap(child, 1000);
97 }
98 for (int n = 0; n < 2; ++n) {
99 if (ready[n] >= 0)
100 close(ready[n]);
101 if (gate[n] >= 0)
102 close(gate[n]);
103 }
104 if (borrowed != MAP_FAILED)
105 munmap(borrowed, 3 * page);
106 if (private != MAP_FAILED)
107 munmap(private, length);
108 fr_close(&file);
109 return failed;
110}