The Pedigree Project 0.1
remap-file-pages-contract-test/offsets.c
1#define _GNU_SOURCE
2#include <fcntl.h>
3#include <signal.h>
4#include <unistd.h>
5
6#include "contract.h"
7#include <sys/mman.h>
8
9static int nonlinear(int backend) {
10 int failed = 0;
11 struct rp_file file = {.fd = -1};
12 const size_t page = rp_page;
13 unsigned char *mapping = MAP_FAILED, *alias = MAP_FAILED, byte;
14 CHECK(!rp_create(&file, backend));
15 mapping = mmap(NULL, 4 * page, PROT_READ | PROT_WRITE, MAP_SHARED, file.fd, 2 * page);
16 alias = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_SHARED, file.fd, 0);
17 CHECK(mapping != MAP_FAILED && alias != MAP_FAILED);
18 CHECK(rp_matches(mapping, 2 * page, 4 * page, 0));
19 CHECK(lseek(file.fd, 79, SEEK_SET) == 79);
20 CHECK(!remap_file_pages(mapping + page, page, 0, 0, 0));
21 CHECK(!remap_file_pages(mapping + 2 * page, page, 0, 0, MAP_NONBLOCK));
22 CHECK(rp_matches(mapping, 2 * page, page, 0) && rp_matches(mapping + page, 0, page, 0) &&
23 rp_matches(mapping + 2 * page, 0, page, 0) &&
24 rp_matches(mapping + 3 * page, 5 * page, page, 0));
25 mapping[page + 137] = 0xab;
26 CHECK(mapping[2 * page + 137] == 0xab && alias[137] == 0xab &&
27 pread(file.fd, &byte, 1, 137) == 1 && byte == 0xab);
28 alias[137] = rp_pattern(137);
29 CHECK(!msync(mapping + page, page, MS_SYNC));
30
31 /* Prior calls created differing-offset fragments of the same open mapping. */
32 CHECK(!remap_file_pages(mapping, 4 * page, 0, 3,
33 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | (int)0x80000000u));
34 CHECK(rp_matches(mapping, 3 * page, 4 * page, 0));
35 CHECK(!remap_file_pages(mapping + 17, page + 37, 0, 1, 0));
36 CHECK(rp_matches(mapping, page, page, 0) && rp_matches(mapping + page, 4 * page, 3 * page, 0));
37 CHECK(!remap_file_pages(mapping + 3 * page, page, 0, 8, 0));
38 CHECK(!remap_file_pages(mapping + 3 * page, page, 0, 8, MAP_NONBLOCK));
39 CHECK(!rp_fault(mapping + 3 * page, SIGBUS, 0));
40 CHECK(rp_matches(mapping, page, page, 0) && rp_matches(mapping + page, 4 * page, 2 * page, 0));
41 CHECK(!remap_file_pages(mapping + 3 * page, page, 0, 2, 0));
42 CHECK(rp_matches(mapping + 3 * page, 2 * page, page, 0));
43 CHECK(lseek(file.fd, 0, SEEK_CUR) == 79 && !rp_size(file.fd, 8 * page));
44out:
45 if (alias != MAP_FAILED)
46 munmap(alias, page);
47 if (mapping != MAP_FAILED)
48 munmap(mapping, 4 * page);
49 rp_close(&file);
50 if (failed)
51 fprintf(stderr, "REMAP-FILE-PAGES-CONTRACT: offsets backend=%d\n", backend);
52 return failed;
53}
54
55static int adjacent_open(void) {
56 int failed = 0, duplicate = -1;
57 struct rp_file file = {.fd = -1};
58 const size_t page = rp_page;
59 unsigned char* area = MAP_FAILED;
60 CHECK(!rp_create(&file, RP_MEMFD));
61 CHECK((duplicate = dup(file.fd)) >= 0);
62 area = mmap(NULL, 4 * page, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
63 CHECK(area != MAP_FAILED);
64 CHECK(mmap(area + page, page, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, file.fd,
65 5 * page) == area + page);
66 CHECK(mmap(area + 2 * page, page, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, duplicate,
67 page) == area + 2 * page);
68 CHECK(!remap_file_pages(area + page, 2 * page, 0, 2, 0));
69 CHECK(rp_matches(area + page, 2 * page, 2 * page, 0));
70 CHECK(!mprotect(area + 2 * page, page, PROT_READ));
71 CHECK(!mprotect(area + 2 * page, page, PROT_READ | PROT_WRITE));
72 CHECK(!remap_file_pages(area + 2 * page, page, 0, 7, MAP_NONBLOCK));
73 CHECK(!remap_file_pages(area + page, 2 * page, 0, 0, 0));
74 CHECK(rp_matches(area + page, 0, 2 * page, 0));
75out:
76 if (area != MAP_FAILED)
77 munmap(area, 4 * page);
78 if (duplicate >= 0)
79 close(duplicate);
80 rp_close(&file);
81 return failed;
82}
83
84int rp_offsets(void) {
85 for (int backend = RP_MEMFD; backend <= RP_EXT2; ++backend) {
86 if (nonlinear(backend))
87 return 1;
88 }
89 return adjacent_open();
90}