• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2018 SUSE LLC <nstange@suse.de>
4  * Copyright (C) 2020 SUSE LLC <mdoucha@suse.cz>
5  *
6  * CVE-2018-8897
7  *
8  * Test that the MOV SS instruction touching a ptrace watchpoint followed by
9  * INT3 breakpoint is handled correctly by the kernel. Kernel crash fixed in:
10  *
11  *  commit d8ba61ba58c88d5207c1ba2f7d9a2280e7d03be9
12  *  Author: Andy Lutomirski <luto@kernel.org>
13  *  Date:   Thu Jul 23 15:37:48 2015 -0700
14  *
15  *  x86/entry/64: Don't use IST entry for #BP stack
16  */
17 
18 #include <stdlib.h>
19 #include <stddef.h>
20 #include <sys/ptrace.h>
21 #include <sys/user.h>
22 #include <signal.h>
23 #include "tst_test.h"
24 
25 static short watchpoint;
26 static pid_t child_pid;
27 
child_main(void)28 static int child_main(void)
29 {
30 	SAFE_PTRACE(PTRACE_TRACEME, 0, NULL, NULL);
31 	raise(SIGSTOP);
32 	/* wait for SIGCONT from parent */
33 
34 	asm volatile(
35 		"mov %%ss, %0\n"
36 		"mov %0, %%ss\n"
37 		"int $3\n"
38 		: "+m" (watchpoint)
39 	);
40 
41 	return 0;
42 }
43 
run(void)44 static void run(void)
45 {
46 	int status;
47 
48 #if defined(__i386__) || defined(__x86_64__)
49 	child_pid = SAFE_FORK();
50 
51 	if (!child_pid) {
52 		exit(child_main());
53 	}
54 
55 	if (SAFE_WAITPID(child_pid, &status, 0) != child_pid)
56 		tst_brk(TBROK, "Received event from unexpected PID");
57 
58 	SAFE_PTRACE(PTRACE_POKEUSER, child_pid,
59 		(void *)offsetof(struct user, u_debugreg[0]), &watchpoint);
60 	SAFE_PTRACE(PTRACE_POKEUSER, child_pid,
61 		(void *)offsetof(struct user, u_debugreg[7]), (void *)0x30001);
62 	SAFE_PTRACE(PTRACE_CONT, child_pid, NULL, NULL);
63 #endif
64 
65 	while (1) {
66 		if (SAFE_WAITPID(child_pid, &status, 0) != child_pid)
67 			tst_brk(TBROK, "Received event from unexpected PID");
68 
69 		if (WIFEXITED(status)) {
70 			child_pid = 0;
71 			break;
72 		}
73 
74 		if (WIFSTOPPED(status)) {
75 			SAFE_PTRACE(PTRACE_CONT, child_pid, NULL, NULL);
76 			continue;
77 		}
78 
79 		tst_brk(TBROK, "Unexpected event from child");
80 	}
81 
82 	tst_res(TPASS, "We're still here. Nothing bad happened, probably.");
83 }
84 
cleanup(void)85 static void cleanup(void)
86 {
87 	/* Main process terminated by tst_brk() with child still paused */
88 	if (child_pid)
89 		SAFE_KILL(child_pid, SIGKILL);
90 }
91 
92 static struct tst_test test = {
93 	.test_all = run,
94 	.cleanup = cleanup,
95 	.forks_child = 1,
96 	.supported_archs = (const char *const []) {
97 		"x86",
98 		"x86_64",
99 		NULL
100 	},
101 	.tags = (const struct tst_tag[]) {
102 		{"linux-git", "d8ba61ba58c8"},
103 		{"CVE", "2018-8897"},
104 		{}
105 	}
106 };
107