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