The Pedigree Project 0.1
file-resize-contract-test/seals.c
1#define _GNU_SOURCE
2#include <fcntl.h>
3#include <unistd.h>
4
5#include "contract.h"
6#include <sys/mman.h>
7
8int fr_seals(void) {
9 int failed = 0, duplicate = -1;
10 struct fr_file file = {.fd = -1};
11 const size_t page = fr_page, length = 4 * page;
12 unsigned char *shared = MAP_FAILED, *private = MAP_FAILED;
13 CHECK(!fr_create(&file, FR_MEMFD) && (duplicate = dup(file.fd)) >= 0);
14 shared = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, file.fd, 0);
15 private = mmap(NULL, 3 * page, PROT_READ | PROT_WRITE, MAP_PRIVATE, duplicate, page);
16 CHECK(shared != MAP_FAILED && private != MAP_FAILED);
17 CHECK(fr_matches(shared, 0, length, 0) && fr_matches(private, page, 3 * page, 0));
18 private[23] = 0xa1;
19 CHECK(!fr_resident(shared, 4, 15, "sealed shared before rejection") &&
20 !fr_resident(private, 3, 7, "sealed private before rejection"));
21 CHECK(!fcntl(file.fd, F_ADD_SEALS, F_SEAL_SHRINK));
22 const off_t position = 3 * page + 91;
23 CHECK(lseek(duplicate, position, SEEK_SET) == position);
24 const size_t sizes[] = {page + 137, 0};
25 for (unsigned n = 0; n < sizeof(sizes) / sizeof(sizes[0]); ++n) {
26 CHECK(ftruncate(duplicate, sizes[n]) == -1 && errno == EPERM);
27 CHECK(!fr_resident(shared, 4, 15, "sealed shared after rejection") &&
28 !fr_resident(private, 3, 7, "sealed private after rejection"));
29 CHECK(!fr_size(file.fd, length) && !fr_size(duplicate, length));
30 CHECK(fcntl(file.fd, F_GET_SEALS) == F_SEAL_SHRINK);
31 CHECK(lseek(file.fd, 0, SEEK_CUR) == position);
32 CHECK(fr_matches(shared, 0, length, 0) && private[23] == 0xa1 &&
33 fr_matches(private, page, 23, 0) &&
34 fr_matches(private + 24, page + 24, 3 * page - 24, 0));
35 CHECK(!fr_contents(file.fd, 0, length, 0));
36 }
37out:
38 if (private != MAP_FAILED)
39 munmap(private, 3 * page);
40 if (shared != MAP_FAILED)
41 munmap(shared, length);
42 if (duplicate >= 0)
43 close(duplicate);
44 fr_close(&file);
45 return failed;
46}