// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2017 Intel Corporation. */ #include #include #include #include #include #include #include #include #include #include #define MiB(a) ((a)*1024*1024) void err_exit(char *op) { fprintf(stderr, "%s: %s\n", op, strerror(errno)); exit(1); } int main(int argc, char *argv[]) { volatile int a __attribute__((__unused__)); char *buffer = "HELLO WORLD!"; char *data; int fd, err, ret = 0; if (argc < 2) { printf("Usage: %s \n", basename(argv[0])); exit(0); } fd = open(argv[1], O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); if (fd < 0) err_exit("fd"); /* * This allows us to map a huge zero page, and we do it at a non-zero * offset for a little additional testing. */ ftruncate(fd, 0); ftruncate(fd, MiB(4)); data = mmap(NULL, MiB(2), PROT_READ, MAP_SHARED, fd, MiB(2)); if (data == MAP_FAILED) err_exit("mmap"); /* * This faults in a 2MiB zero page to satisfy the read. * 'a' is volatile so this read doesn't get optimized out. */ a = data[0]; pwrite(fd, buffer, strlen(buffer), MiB(2)); /* * Try and use the mmap to read back the data we just wrote with * pwrite(). If the kernel bug is present the mapping from the 2MiB * zero page will still be intact, and we'll read back zeros instead. */ if (strncmp(buffer, data, strlen(buffer))) { fprintf(stderr, "strncmp mismatch: '%s' vs '%s'\n", buffer, data); ret = 1; } err = munmap(data, MiB(2)); if (err < 0) err_exit("munmap"); err = close(fd); if (err < 0) err_exit("close"); return ret; }