/** * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include <../includes/common.h> volatile char *mem = 0; // child int check_zero_page() { char *temp = (char *)mmap(0, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); int zeropage = *(int *)temp; munmap(temp, 4096); return zeropage; } // child int do_child(int val) { // enable tracing and wait until parent is finished unlocking zero page ptrace(PTRACE_TRACEME, 0, 0, 0); sleep(2); mprotect((void *)mem, 4096, PROT_READ | PROT_WRITE); // try to corrupt zero page mem[0] = val; int zeropage = check_zero_page(); return zeropage ? EXIT_VULNERABLE : 0; } // parent int do_trace(pid_t child) { int status = 0; sleep(1); // wait until child is set up kill(child, SIGSTOP); // pause child waitpid(child, &status, 0); // unlock zero page status = ptrace(PTRACE_PEEKDATA, child, mem, 0); // stop tracing so child can continue ptrace(PTRACE_DETACH, child, 0, 0); kill(child, SIGCONT); return status; } int main(void) { char value = 0xAA; mem = (volatile char *)mmap(0, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); mprotect((void *)mem, 4096, PROT_NONE); pid_t child = fork(); if (child == 0) { return do_child(value); } else { do_trace(child); } int status = 0; waitpid(child, &status, 0); // wait for child to exit naturally int exit = WEXITSTATUS(status); // get child exit status munmap((void *)mem, 4096); return exit; }