1 /*
2  * This is a reproducer of CVE-2011-0999, which fixed by mainline commit
3  * a7d6e4ecdb7648478ddec76d30d87d03d6e22b31:
4  *
5  * "Transparent hugepages can only be created if rmap is fully
6  * functional. So we must prevent hugepages to be created while
7  * is_vma_temporary_stack() is true."
8  *
9  * It will cause a panic something like this, if the patch didn't get
10  * applied:
11  *
12  * kernel BUG at mm/huge_memory.c:1260!
13  * invalid opcode: 0000 [#1] SMP
14  * last sysfs file: /sys/devices/system/cpu/cpu23/cache/index2/shared_cpu_map
15  * ....
16  *
17  * Copyright (C) 2011  Red Hat, Inc.
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of version 2 of the GNU General Public
20  * License as published by the Free Software Foundation.
21  *
22  * This program is distributed in the hope that it would be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25  *
26  * Further, this software is distributed without any warranty that it
27  * is free of the rightful claim of any third person regarding
28  * infringement or the like.  Any license provided herein, whether
29  * implied or otherwise, applies only to this software file.  Patent
30  * licenses, if any, provided herein do not apply to combinations of
31  * this program with other software, or any other product whatsoever.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program; if not, write the Free Software
35  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
36  * 02110-1301, USA.
37  */
38 
39 #include <sys/types.h>
40 #include <sys/resource.h>
41 #include <sys/wait.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include "test.h"
46 
47 char *TCID = "thp01";
48 int TST_TOTAL = 1;
49 
50 #define ARRAY_SZ	256
51 
52 static int ps;
53 static long length;
54 static char *array[ARRAY_SZ];
55 static char *arg;
56 static struct rlimit rl = {
57 	.rlim_cur = RLIM_INFINITY,
58 	.rlim_max = RLIM_INFINITY,
59 };
60 
61 static void setup(void);
62 static void cleanup(void);
63 
main(int argc,char ** argv)64 int main(int argc, char **argv)
65 {
66 	int i, lc, st;
67 	pid_t pid;
68 
69 	tst_parse_opts(argc, argv, NULL, NULL);
70 
71 	setup();
72 
73 	for (lc = 0; TEST_LOOPING(lc); lc++) {
74 		switch (pid = fork()) {
75 		case -1:
76 			tst_brkm(TBROK | TERRNO, cleanup, "fork");
77 		case 0:
78 			memset(arg, 'c', length - 1);
79 			arg[length - 1] = '\0';
80 			array[0] = "true";
81 			for (i = 1; i < ARRAY_SZ - 1; i++)
82 				array[i] = arg;
83 			array[ARRAY_SZ - 1] = NULL;
84 			if (setrlimit(RLIMIT_STACK, &rl) == -1) {
85 				perror("setrlimit");
86 				exit(1);
87 			}
88 			if (execvp("true", array) == -1) {
89 				perror("execvp");
90 				exit(1);
91 			}
92 		default:
93 			if (waitpid(pid, &st, 0) == -1)
94 				tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
95 			if (!WIFEXITED(st) || WEXITSTATUS(st) != 0)
96 				tst_brkm(TBROK, cleanup,
97 					 "child exited abnormally");
98 		}
99 	}
100 	tst_resm(TPASS, "system didn't crash, pass.");
101 	cleanup();
102 	tst_exit();
103 }
104 
setup(void)105 static void setup(void)
106 {
107 	ps = sysconf(_SC_PAGESIZE);
108 	length = 32 * ps;
109 	arg = malloc(length);
110 	if (arg == NULL)
111 		tst_brkm(TBROK | TERRNO, NULL, "malloc");
112 
113 	tst_sig(FORK, DEF_HANDLER, cleanup);
114 	TEST_PAUSE;
115 }
116 
cleanup(void)117 static void cleanup(void)
118 {
119 }
120