12 volatile int ready[2];
15 int seal_result, seal_error;
20static void* operation(
void* argument) {
22 __atomic_store_n(&
race->ready[0], 1, __ATOMIC_RELEASE);
23 if (!mf_wait(&
race->gate, 5000)) {
25 if (
race->mapping_race)
26 race->mapping = mmap(NULL,
race->page, PROT_READ | PROT_WRITE, MAP_SHARED,
race->fd, 0);
28 race->write_result = pwrite(
race->fd,
"b", 1, 0);
29 race->operation_error = errno;
31 race->operation_error = ETIMEDOUT;
32 __atomic_store_n(&
race->done[0], 1, __ATOMIC_RELEASE);
35static void* sealer(
void* argument) {
37 __atomic_store_n(&
race->ready[1], 1, __ATOMIC_RELEASE);
38 if (!mf_wait(&
race->gate, 5000)) {
40 race->seal_result = fcntl(
race->fd, F_ADD_SEALS, F_SEAL_WRITE);
41 race->seal_error = errno;
43 race->seal_error = ETIMEDOUT;
44 __atomic_store_n(&
race->done[1], 1, __ATOMIC_RELEASE);
47static int run_race(
int mapping_race,
unsigned iteration) {
48 int failed = 0, started = 0;
51 .page = sysconf(_SC_PAGESIZE),
52 .mapping_race = mapping_race,
55 .mapping = MAP_FAILED};
56 CHECK((
race.fd = mf_make(
race.page)) >= 0 && pwrite(
race.fd,
"a", 1, 0) == 1);
57 CHECK(!pthread_create(&threads[0], NULL, operation, &
race));
59 CHECK(!pthread_create(&threads[1], NULL, sealer, &
race));
61 CHECK(!mf_wait(&
race.ready[0], 5000) && !mf_wait(&
race.ready[1], 5000));
62 __atomic_store_n(&
race.gate, 1, __ATOMIC_RELEASE);
63 CHECK(!mf_wait(&
race.done[0], 5000) && !mf_wait(&
race.done[1], 5000));
65 if (
race.mapping == MAP_FAILED) {
66 CHECK(
race.operation_error == EPERM &&
race.seal_result == 0);
69 CHECK(
race.seal_result == -1 &&
race.seal_error == EBUSY);
70 CHECK(fcntl(
race.fd, F_GET_SEALS) == 0);
71 CHECK(!munmap(
race.mapping,
race.page));
72 race.mapping = MAP_FAILED;
73 CHECK(!fcntl(
race.fd, F_ADD_SEALS, F_SEAL_WRITE));
76 CHECK(
race.seal_result == 0);
77 CHECK(
race.write_result == 1 || (
race.write_result == -1 &&
race.operation_error == EPERM));
78 CHECK(!mf_contents(
race.fd, 0,
race.write_result == 1 ?
"b" :
"a", 1));
80 CHECK(fcntl(
race.fd, F_GET_SEALS) == F_SEAL_WRITE);
81 CHECK(pwrite(
race.fd,
"c", 1, 0) == -1 && errno == EPERM);
82 CHECK(mmap(NULL,
race.page, PROT_READ | PROT_WRITE, MAP_SHARED,
race.fd, 0) == MAP_FAILED &&
84 CHECK(!mf_contents(
race.fd, 0, !mapping_race &&
race.write_result == 1 ?
"b" :
"a", 1));
86 __atomic_store_n(&
race.gate, 1, __ATOMIC_RELEASE);
87 for (
int n = 0; n < started; ++n) {
88 if (mf_wait(&
race.done[n], 5000)) {
89 fprintf(stderr,
"MEMFD-CONTRACT: race worker=%d failed to finish\n", n);
92 pthread_join(threads[n], NULL);
95 fprintf(stderr,
"MEMFD-CONTRACT: race=%s iteration=%u seal=%d/%d mapping=%p write=%ld/%d\n",
96 mapping_race ?
"mmap" :
"write", iteration,
race.seal_result,
race.seal_error,
97 race.mapping, (long)
race.write_result,
race.operation_error);
98 if (
race.mapping != MAP_FAILED)
104int memfd_races(
void) {
105 for (
unsigned n = 0; n < 8; ++n)
106 if (run_race(1, n) || run_race(0, n))