16char ef_directory[PATH_MAX];
17char ef_self[PATH_MAX];
20int ef_create(
const char* name,
char path[PATH_MAX]) {
21 snprintf(path, PATH_MAX,
"%s/%s", ef_directory, name);
22 int fd = open(path, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0700);
25 unsigned char* bytes = malloc(3 * ef_page);
27 memset(bytes, 0x31, 3 * ef_page);
28 if (!bytes || write(fd, bytes, 3 * ef_page) != (ssize_t)(3 * ef_page)) {
38int ef_copy(
const char* source,
const char* destination) {
40 int input = open(source, O_RDONLY | O_CLOEXEC);
41 int output = open(destination, O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC, 0700);
42 CHECK(input >= 0 && output >= 0);
45 while ((count = read(input, bytes,
sizeof(bytes))) > 0) {
47 while (done < count) {
48 ssize_t amount = write(output, bytes + done, count - done);
62int ef_receive(
int fd,
char expected) {
63 struct pollfd item = {.fd = fd, .events = POLLIN};
66 result = poll(&item, 1, 5000);
67 }
while (result < 0 && errno == EINTR);
69 return result > 0 && read(fd, &
byte, 1) == 1 &&
byte == expected ? 0 : -1;
72int ef_send(
int fd,
char value) {
73 return write(fd, &value, 1) == 1 ? 0 : -1;
76int ef_reap(pid_t child) {
77 for (
int n = 0; n < 1000; ++n) {
79 pid_t result = waitpid(child, &status, WNOHANG);
81 return WIFEXITED(status) ? WEXITSTATUS(status) : 128 + WTERMSIG(status);
82 if (result < 0 && errno != EINTR)
84 struct timespec pause = {0, 5000000};
85 nanosleep(&pause, NULL);
88 while (waitpid(child, NULL, 0) < 0 && errno == EINTR) {
93int main(
int argc,
char** argv) {
94 setvbuf(stdout, NULL, _IONBF, 0);
96 if (argc == 4 && !strcmp(argv[1],
"--load"))
97 return ef_load(argv[2], atoi(argv[3]));
99 fprintf(stderr,
"usage: %s [/tmp|/]\n", argv[0]);
103 const char* base = argc == 2 ? argv[1] :
"/tmp";
104 ef_ext2 = strcmp(base,
"/tmp") != 0;
105 long page = sysconf(_SC_PAGESIZE);
107 ef_page = (size_t)page;
108 ssize_t count = readlink(
"/proc/self/exe", ef_self,
sizeof(ef_self) - 1);
109 CHECK(count > 0 && (
size_t)count <
sizeof(ef_self) - 1);
111 snprintf(ef_directory,
sizeof(ef_directory),
"%s/executable-files-XXXXXX", base);
112 CHECK(mkdtemp(ef_directory));
113 printf(
"EXECUTABLE-FILE-CONTRACT: BEGIN %s\n", base);
114 CHECK(!ef_mutations());
115 puts(
"EXECUTABLE-FILE-CONTRACT: PASS mutation-denial");
116 CHECK(!ef_lifetime());
117 puts(
"EXECUTABLE-FILE-CONTRACT: PASS fork-split-lifetime");
118 CHECK(!ef_conflicts());
119 puts(
"EXECUTABLE-FILE-CONTRACT: PASS shared-conflicts");
120 CHECK(!ef_ordinary());
121 puts(
"EXECUTABLE-FILE-CONTRACT: PASS ordinary-private");
122 CHECK(!ef_library());
123 puts(
"EXECUTABLE-FILE-CONTRACT: PASS library-replacement");
127 puts(failed ?
"EXECUTABLE-FILE-CONTRACT: END FAIL" :
"EXECUTABLE-FILE-CONTRACT: END PASS");