test code v1

This commit is contained in:
2026-08-13 10:44:59 +02:00
commit f3b1165f19
301 changed files with 37885 additions and 0 deletions
+200
View File
@@ -0,0 +1,200 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void
pread_all(int fd, unsigned char *buf, size_t len)
{
size_t done;
ssize_t nr;
for (done = 0; done < len; done += nr) {
nr = pread(fd, buf + done, len - done, done);
if (nr < 0)
err(1, "pread");
if (nr == 0)
errx(1, "unexpected EOF at %zu", done);
}
}
static uint64_t
fnv1a64(const unsigned char *buf, size_t len)
{
uint64_t hash;
hash = UINT64_C(14695981039346656037);
for (size_t i = 0; i < len; i++) {
hash ^= buf[i];
hash *= UINT64_C(1099511628211);
}
return (hash);
}
static uint32_t
xorshift32(uint32_t *state)
{
uint32_t value;
value = *state;
value ^= value << 13;
value ^= value >> 17;
value ^= value << 5;
*state = value;
return (value);
}
static void
verify_random_faults(const unsigned char *map, const unsigned char *expected,
size_t size, size_t pagesize)
{
size_t *order;
size_t npages, page, span;
uint32_t state;
npages = (size + pagesize - 1) / pagesize;
order = calloc(npages, sizeof(*order));
if (order == NULL)
err(1, "calloc page order");
for (size_t i = 0; i < npages; i++)
order[i] = i;
state = UINT32_C(0x5eed22);
for (size_t i = npages; i > 1; i--) {
size_t other;
other = xorshift32(&state) % i;
page = order[i - 1];
order[i - 1] = order[other];
order[other] = page;
}
for (size_t i = 0; i < npages; i++) {
page = order[i] * pagesize;
span = size - page < pagesize ? size - page : pagesize;
if (memcmp(map + page, expected + page, span) != 0)
errx(1, "random page mismatch at offset %zu", page);
}
free(order);
}
static void
verify_sigbus(const unsigned char *map, size_t eof_page)
{
pid_t child;
int status;
child = fork();
if (child < 0)
err(1, "fork");
if (child == 0) {
volatile unsigned char value;
value = map[eof_page];
_exit(value == 0 ? 0 : 1);
}
if (waitpid(child, &status, 0) != child)
err(1, "waitpid");
if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS)
errx(1, "full page beyond EOF did not raise SIGBUS (status=%#x)",
status);
}
int
main(int argc, char **argv)
{
unsigned char *expected, *map, *private_map, byte;
struct stat sb;
size_t eof_page, map_len, pagesize, private_offset;
uint64_t hash;
int fd, rwfd, shared_errno;
if (argc != 2)
errx(2, "usage: mmap_fault file");
pagesize = (size_t)getpagesize();
fd = open(argv[1], O_RDONLY);
if (fd < 0)
err(1, "open %s", argv[1]);
if (fstat(fd, &sb) != 0)
err(1, "fstat %s", argv[1]);
if (sb.st_size <= (off_t)(pagesize * 3))
errx(1, "fixture must exceed three VM pages");
if ((uintmax_t)sb.st_size > SIZE_MAX - pagesize * 2)
errx(1, "fixture is too large");
eof_page = ((size_t)sb.st_size + pagesize - 1) / pagesize * pagesize;
map_len = eof_page + pagesize;
expected = malloc((size_t)sb.st_size);
if (expected == NULL)
err(1, "malloc expected data");
pread_all(fd, expected, (size_t)sb.st_size);
map = mmap(NULL, map_len, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED)
err(1, "mmap read-only private");
if (madvise(map, map_len, MADV_DONTNEED) != 0)
err(1, "madvise MADV_DONTNEED");
verify_random_faults(map, expected, (size_t)sb.st_size, pagesize);
if (memcmp(map, expected, (size_t)sb.st_size) != 0)
errx(1, "sequential mmap data differs from pread");
for (size_t i = (size_t)sb.st_size; i < eof_page; i++) {
if (map[i] != 0)
errx(1, "non-zero byte in partial EOF page at %zu", i);
}
verify_sigbus(map, eof_page);
hash = fnv1a64(map, (size_t)sb.st_size);
errno = 0;
private_map = mmap(NULL, eof_page, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0);
shared_errno = errno;
if (private_map != MAP_FAILED) {
munmap(private_map, eof_page);
errx(1, "writable MAP_SHARED unexpectedly succeeded");
}
if (shared_errno != EACCES)
errx(1, "writable MAP_SHARED returned %s, expected Permission denied",
strerror(shared_errno));
private_map = mmap(NULL, eof_page, PROT_READ | PROT_WRITE, MAP_PRIVATE,
fd, 0);
if (private_map == MAP_FAILED)
err(1, "mmap writable private");
private_offset = (size_t)sb.st_size / 2;
byte = expected[private_offset];
private_map[private_offset] ^= UINT8_C(0xff);
if (private_map[private_offset] == byte)
errx(1, "private mapping did not change");
if (pread(fd, &byte, 1, private_offset) != 1)
err(1, "pread private verification");
if (byte != expected[private_offset])
errx(1, "MAP_PRIVATE modified the EROFS file");
errno = 0;
rwfd = open(argv[1], O_RDWR);
if (rwfd >= 0) {
close(rwfd);
errx(1, "O_RDWR unexpectedly succeeded");
}
if (errno != EROFS)
errx(1, "O_RDWR returned %s, expected Read-only file system",
strerror(errno));
if (munmap(private_map, eof_page) != 0 || munmap(map, map_len) != 0)
err(1, "munmap");
free(expected);
if (close(fd) != 0)
err(1, "close");
printf("PASS size=%jd pages=%zu fnv1a64=%016" PRIx64
" random-faults=%zu eof-zero=PASS sigbus=PASS private-cow=PASS\n",
(intmax_t)sb.st_size, eof_page / pagesize, hash,
((size_t)sb.st_size + pagesize - 1) / pagesize);
return (0);
}