1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Fujitsu Limited. All Rights Reserved. */
18 void sigbus_handler(int signal)
20 printf("Process is killed by signal: %d\n", signal);
24 void mmap_read_file(char *filename, off_t offset, size_t size)
30 fd = open(filename, O_RDWR);
31 map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, offset);
34 /* make sure page fault happens */
35 memcpy(dummy, map, size);
42 clock_gettime(CLOCK_REALTIME, &ts);
44 /* wait for injection done */
45 sem_timedwait(sem, &ts);
52 void mmap_read_file_then_poison(char *filename, off_t offset, size_t size,
53 off_t poisonOffset, size_t poisonSize)
58 /* wait for parent preparation done */
61 fd = open(filename, O_RDWR);
62 map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, offset);
65 /* make sure page fault happens */
66 memcpy(dummy, map, size);
68 printf("Inject poison...\n");
69 error = madvise(map + poisonOffset, poisonSize, MADV_HWPOISON);
71 printf("madvise() has fault: %d, errno: %d\n", error, errno);
78 int main(int argc, char *argv[])
80 char *pReadFile = NULL, *pPoisonFile = NULL;
81 size_t mmapSize, poisonSize;
82 off_t mmapOffset = 0, poisonOffset = 0;
83 long pagesize = sysconf(_SC_PAGESIZE);
88 fprintf(stderr, "sysconf(_SC_PAGESIZE): failed to get page size\n");
92 /* default mmap / poison size, in unit of System Page Size */
93 mmapSize = poisonSize = pagesize;
95 while ((c = getopt(argc, argv, "o::s::O::S::R:P:")) != -1) {
99 mmapOffset = atoi(optarg) * pagesize;
103 mmapSize = atoi(optarg) * pagesize;
107 poisonOffset = atoi(optarg) * pagesize;
111 poisonSize = atoi(optarg) * pagesize;
113 /* filename for mmap read */
117 /* filename for poison read */
119 pPoisonFile = optarg;
122 printf("Unknown option: %c\n", c);
127 if (!pReadFile || !pPoisonFile) {
129 " %s [-o mmapOffset] [-s mmapSize] [-O mmapOffset] [-S mmapSize] -R readFile -P poisonFile\n"
130 " (offset and size are both in unit of System Page Size: %ld)\n",
131 basename(argv[0]), pagesize);
134 if (poisonSize < mmapSize)
135 mmapSize = poisonSize;
137 /* fork and mmap files */
141 signal(SIGBUS, sigbus_handler);
142 sem = sem_open("sync", O_CREAT, 0666, 0);
144 /* mread & do memory failure on poison file */
145 mmap_read_file_then_poison(pPoisonFile, mmapOffset, mmapSize,
146 poisonOffset, poisonSize);
150 sem = sem_open("sync", O_CREAT, 0666, 0);
152 /* mread read file, wait for child process to be killed */
153 mmap_read_file(pReadFile, mmapOffset, mmapSize);