1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2018 Michael Moese <mmoese@suse.com> 4 */ 5/* 6 * Test for CVE-2017-17052, original reproducer taken from kernel commit: 7 * 2b7e8665b4ff51c034c55df3cff76518d1a9ee3a 8 * 9 * CAUTION!! 10 * This test will crash unpatched kernels! 11 * Use at your own risk! 12 * 13 */ 14 15#include <unistd.h> 16#include <pthread.h> 17#include <sys/wait.h> 18#include <sys/syscall.h> 19#include <sys/types.h> 20#include <stdlib.h> 21 22#include "tst_test.h" 23#include "tst_safe_pthread.h" 24#include "lapi/syscalls.h" 25 26#define RUNS 4 27#define EXEC_USEC 400000 28 29static int *do_exit; 30 31static void setup(void) 32{ 33 do_exit = SAFE_MMAP(NULL, sizeof(*do_exit), PROT_READ|PROT_WRITE, 34 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 35 36 *do_exit = 0; 37} 38 39static void cleanup(void) 40{ 41 SAFE_MUNMAP(do_exit, sizeof(*do_exit)); 42} 43 44static void *mmap_thread(void *arg) 45{ 46 for (;;) { 47 SAFE_MMAP(NULL, 0x1000000, PROT_READ, 48 MAP_POPULATE|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 49 } 50 51 return arg; 52} 53 54static void *fork_thread(void *arg) 55{ 56 usleep(rand() % 10000); 57 SAFE_FORK(); 58 59 return arg; 60} 61 62static void do_test_fork(void) 63{ 64 int status; 65 66 SAFE_FORK(); 67 SAFE_FORK(); 68 SAFE_FORK(); 69 70 for(;;) { 71 if (SAFE_FORK() == 0) { 72 pthread_t t; 73 74 SAFE_PTHREAD_CREATE(&t, NULL, mmap_thread, NULL); 75 SAFE_PTHREAD_CREATE(&t, NULL, fork_thread, NULL); 76 usleep(rand() % 10000); 77 syscall(__NR_exit_group, 0); 78 } 79 SAFE_WAIT(&status); 80 if (*do_exit) 81 exit(0); 82 } 83} 84 85static void run(void) 86{ 87 pid_t pid; 88 int status; 89 volatile int run = 0; 90 91 while (run < RUNS) { 92 *do_exit = 0; 93 pid = SAFE_FORK(); 94 95 if (pid == 0) { 96 do_test_fork(); 97 } else { 98 usleep(EXEC_USEC); 99 *do_exit = 1; 100 } 101 102 SAFE_WAIT(&status); 103 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 104 tst_res(TINFO, "run %d passed", run); 105 } else { 106 tst_res(TFAIL, "child %s", tst_strstatus(status)); 107 } 108 109 run++; 110 } 111 112 if (run == RUNS) 113 tst_res(TPASS, "kernel survived %d runs", run); 114 else 115 tst_res(TFAIL, "something strange happened"); 116} 117 118static struct tst_test test = { 119 .forks_child = 1, 120 .cleanup = cleanup, 121 .setup = setup, 122 .test_all = run, 123 .tags = (const struct tst_tag[]) { 124 {"linux-git", "2b7e8665b4ff"}, 125 {"CVE", "2017-17052"}, 126 {} 127 } 128}; 129