• 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 #if defined(__i386__) || defined(__x86_64__)
26 static short watchpoint;
27 static pid_t child_pid;
28 
child_main(void)29 static int child_main(void)
30 {
31 	SAFE_PTRACE(PTRACE_TRACEME, 0, NULL, NULL);
32 	raise(SIGSTOP);
33 	/* wait for SIGCONT from parent */
34 
35 	asm volatile(
36 		"mov %%ss, %0\n"
37 		"mov %0, %%ss\n"
38 		"int $3\n"
39 		: "+m" (watchpoint)
40 	);
41 
42 	return 0;
43 }
44 
run(void)45 static void run(void)
46 {
47 	int status;
48 
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 
64 	while (1) {
65 		if (SAFE_WAITPID(child_pid, &status, 0) != child_pid)
66 			tst_brk(TBROK, "Received event from unexpected PID");
67 
68 		if (WIFEXITED(status)) {
69 			child_pid = 0;
70 			break;
71 		}
72 
73 		if (WIFSTOPPED(status)) {
74 			SAFE_PTRACE(PTRACE_CONT, child_pid, NULL, NULL);
75 			continue;
76 		}
77 
78 		tst_brk(TBROK, "Unexpected event from child");
79 	}
80 
81 	tst_res(TPASS, "We're still here. Nothing bad happened, probably.");
82 }
83 
cleanup(void)84 static void cleanup(void)
85 {
86 	/* Main process terminated by tst_brk() with child still paused */
87 	if (child_pid)
88 		SAFE_KILL(child_pid, SIGKILL);
89 }
90 
91 static struct tst_test test = {
92 	.test_all = run,
93 	.cleanup = cleanup,
94 	.forks_child = 1,
95 	.tags = (const struct tst_tag[]) {
96 		{"linux-git", "d8ba61ba58c8"},
97 		{"CVE", "2018-8897"},
98 		{}
99 	}
100 };
101 #else
102 TST_TEST_TCONF("This test is only supported on x86 systems");
103 #endif
104