1d8af9cfced2410afda008bd83c404836ff1834acKees Cook/* 209bfe684ba65168204569fa51072c80f025058cdKees Cook * Copyright (c) 2012 The Chromium OS Authors. 3d8af9cfced2410afda008bd83c404836ff1834acKees Cook * 4d8af9cfced2410afda008bd83c404836ff1834acKees Cook * Based on: 5d8af9cfced2410afda008bd83c404836ff1834acKees Cook * http://bazaar.launchpad.net/~ubuntu-bugcontrol/qa-regression-testing/master/view/head:/scripts/kernel-security/ptrace/thread-prctl.c 6d8af9cfced2410afda008bd83c404836ff1834acKees Cook * Copyright 2011 Canonical, Ltd 7d8af9cfced2410afda008bd83c404836ff1834acKees Cook * License: GPLv3 8d8af9cfced2410afda008bd83c404836ff1834acKees Cook * Author: Kees Cook <kees.cook@canonical.com> 9d8af9cfced2410afda008bd83c404836ff1834acKees Cook * 10d8af9cfced2410afda008bd83c404836ff1834acKees Cook * Based on reproducer written by Philippe Waroquiers in: 11d8af9cfced2410afda008bd83c404836ff1834acKees Cook * https://launchpad.net/bugs/729839 12d8af9cfced2410afda008bd83c404836ff1834acKees Cook */ 13d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <unistd.h> 14d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <stdio.h> 15d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <stdlib.h> 16d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <sys/types.h> 17d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <sys/wait.h> 18d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <signal.h> 19d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <string.h> 20d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <pthread.h> 21d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <sys/ptrace.h> 22d8af9cfced2410afda008bd83c404836ff1834acKees Cook#include <sys/prctl.h> 23d8af9cfced2410afda008bd83c404836ff1834acKees Cook#ifndef PR_SET_PTRACER 24d8af9cfced2410afda008bd83c404836ff1834acKees Cook# define PR_SET_PTRACER 0x59616d61 25d8af9cfced2410afda008bd83c404836ff1834acKees Cook#endif 26d8af9cfced2410afda008bd83c404836ff1834acKees Cook 27d8af9cfced2410afda008bd83c404836ff1834acKees Cookint tracee_method = 0; 28d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define TRACEE_FORKS_FROM_TRACER 0 29d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define TRACEE_CALLS_PRCTL_FROM_MAIN 1 30d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define TRACEE_CALLS_PRCTL_FROM_THREAD 2 31d8af9cfced2410afda008bd83c404836ff1834acKees Cook 32d8af9cfced2410afda008bd83c404836ff1834acKees Cook/* Define some distinct exit values to aid failure debugging. */ 33d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_FORK_TRACEE 1 34d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_FORK_TRACER 2 35d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_PIPE_COMMUNICATION 3 36d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_PIPE_NOTIFICATION 4 37d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_TRACEE_PIPE_READ 5 38d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_TRACEE_UNREACHABLE 6 39d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_TRACER_PIPE_READ 7 40d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_TRACER_PTRACE_ATTACH 8 41d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_TRACER_PTRACE_CONTINUE 9 42d8af9cfced2410afda008bd83c404836ff1834acKees Cook#define EXIT_TRACER_UNREACHABLE 10 43d8af9cfced2410afda008bd83c404836ff1834acKees Cook 44d8af9cfced2410afda008bd83c404836ff1834acKees Cookint main_does_ptrace = 0; 45d8af9cfced2410afda008bd83c404836ff1834acKees Cook 46d8af9cfced2410afda008bd83c404836ff1834acKees Cookint ret; 47d8af9cfced2410afda008bd83c404836ff1834acKees Cookint pipes[2]; 48d8af9cfced2410afda008bd83c404836ff1834acKees Cookint notification[2]; 49d8af9cfced2410afda008bd83c404836ff1834acKees Cookpid_t tracer, tracee; 50d8af9cfced2410afda008bd83c404836ff1834acKees Cook 51d8af9cfced2410afda008bd83c404836ff1834acKees Cookstatic void *thr_fn(void *v) 52d8af9cfced2410afda008bd83c404836ff1834acKees Cook{ 53d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee thread started\n"); 54d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (tracee_method == TRACEE_CALLS_PRCTL_FROM_THREAD) { 55d8af9cfced2410afda008bd83c404836ff1834acKees Cook ret = prctl (PR_SET_PTRACER, tracer, 0, 0, 0); 56d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee thread prtctl result: %d\n", ret); 57d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 58d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee thread finishing\n"); 59d8af9cfced2410afda008bd83c404836ff1834acKees Cook return NULL; 60d8af9cfced2410afda008bd83c404836ff1834acKees Cook} 61d8af9cfced2410afda008bd83c404836ff1834acKees Cook 62d8af9cfced2410afda008bd83c404836ff1834acKees Cookvoid start_tracee(void); 63d8af9cfced2410afda008bd83c404836ff1834acKees Cook 64d8af9cfced2410afda008bd83c404836ff1834acKees Cookvoid * tracer_main(void * data) 65d8af9cfced2410afda008bd83c404836ff1834acKees Cook{ 66d8af9cfced2410afda008bd83c404836ff1834acKees Cook long ptrace_result; 67d8af9cfced2410afda008bd83c404836ff1834acKees Cook char buf[8]; 68d8af9cfced2410afda008bd83c404836ff1834acKees Cook int saw; 69d8af9cfced2410afda008bd83c404836ff1834acKees Cook 70d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracer = getpid(); 71d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracer %d waiting\n", tracer); 72d8af9cfced2410afda008bd83c404836ff1834acKees Cook 73d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (tracee_method == TRACEE_FORKS_FROM_TRACER) { 74d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("forking tracee from tracer\n"); 75d8af9cfced2410afda008bd83c404836ff1834acKees Cook start_tracee(); 76d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 77d8af9cfced2410afda008bd83c404836ff1834acKees Cook 78d8af9cfced2410afda008bd83c404836ff1834acKees Cook close(pipes[1]); 79d8af9cfced2410afda008bd83c404836ff1834acKees Cook close(notification[0]); 80d8af9cfced2410afda008bd83c404836ff1834acKees Cook close(notification[1]); 81d8af9cfced2410afda008bd83c404836ff1834acKees Cook 82d8af9cfced2410afda008bd83c404836ff1834acKees Cook saw = read(pipes[0], buf, 3); 83d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (saw < 3) { 84d8af9cfced2410afda008bd83c404836ff1834acKees Cook perror("tracer pipe read"); 85d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_TRACER_PIPE_READ); 86d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 87d8af9cfced2410afda008bd83c404836ff1834acKees Cook 88d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracer to PTRACE_ATTACH my tracee %d\n", tracee); 89d8af9cfced2410afda008bd83c404836ff1834acKees Cook ptrace_result = ptrace(PTRACE_ATTACH, tracee, NULL, NULL); 90d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (ptrace_result != 0) { 91d8af9cfced2410afda008bd83c404836ff1834acKees Cook fflush(NULL); 92d8af9cfced2410afda008bd83c404836ff1834acKees Cook perror ("tracer ptrace attach has failed"); 93d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_TRACER_PTRACE_ATTACH); 94d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 95d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf ("tracer ptrace attach successful\n"); 96d8af9cfced2410afda008bd83c404836ff1834acKees Cook 97d8af9cfced2410afda008bd83c404836ff1834acKees Cook /* Wait for signal. */ 98d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracer waiting for tracee to SIGSTOP\n"); 99d8af9cfced2410afda008bd83c404836ff1834acKees Cook waitpid(tracee, NULL, 0); 100d8af9cfced2410afda008bd83c404836ff1834acKees Cook 101d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracer to PTRACE_CONT tracee\n"); 102d8af9cfced2410afda008bd83c404836ff1834acKees Cook ptrace_result = ptrace(PTRACE_CONT, tracee, NULL, NULL); 103d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (ptrace_result != 0) { 104d8af9cfced2410afda008bd83c404836ff1834acKees Cook fflush(NULL); 105d8af9cfced2410afda008bd83c404836ff1834acKees Cook perror ("tracer ptrace continue has failed"); 106d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_TRACER_PTRACE_CONTINUE); 107d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 108d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf ("tracer ptrace continue successful\n"); 109d8af9cfced2410afda008bd83c404836ff1834acKees Cook 110d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracer returning 0\n"); 111d8af9cfced2410afda008bd83c404836ff1834acKees Cook fflush(NULL); 112d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_SUCCESS); 113d8af9cfced2410afda008bd83c404836ff1834acKees Cook 114d8af9cfced2410afda008bd83c404836ff1834acKees Cook return NULL; 115d8af9cfced2410afda008bd83c404836ff1834acKees Cook} 116d8af9cfced2410afda008bd83c404836ff1834acKees Cook 117d8af9cfced2410afda008bd83c404836ff1834acKees Cook/* Tracee knows nothing, needs tracee and tracer pid. */ 118d8af9cfced2410afda008bd83c404836ff1834acKees Cookvoid tracee_main(void) { 119d8af9cfced2410afda008bd83c404836ff1834acKees Cook char buf[1024]; 120d8af9cfced2410afda008bd83c404836ff1834acKees Cook int saw; 121d8af9cfced2410afda008bd83c404836ff1834acKees Cook pthread_t thr; 122d8af9cfced2410afda008bd83c404836ff1834acKees Cook 123d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracee = getpid(); 124d8af9cfced2410afda008bd83c404836ff1834acKees Cook close(pipes[0]); 125d8af9cfced2410afda008bd83c404836ff1834acKees Cook 126d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee %d reading tracer pid\n", tracee); 127d8af9cfced2410afda008bd83c404836ff1834acKees Cook close(notification[1]); 128d8af9cfced2410afda008bd83c404836ff1834acKees Cook saw = read(notification[0], buf, 1024); 129d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (saw < 1) { 130d8af9cfced2410afda008bd83c404836ff1834acKees Cook perror("pipe read"); 131d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_TRACEE_PIPE_READ); 132d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 133d8af9cfced2410afda008bd83c404836ff1834acKees Cook buf[saw]='\0'; 134d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracer = atoi(buf); 135d8af9cfced2410afda008bd83c404836ff1834acKees Cook 136d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee %d started (expecting %d as tracer)\n", tracee, tracer); 137d8af9cfced2410afda008bd83c404836ff1834acKees Cook 138d8af9cfced2410afda008bd83c404836ff1834acKees Cook /* Handle setting PR_SET_PTRACER. */ 139d8af9cfced2410afda008bd83c404836ff1834acKees Cook switch (tracee_method) { 140d8af9cfced2410afda008bd83c404836ff1834acKees Cook case TRACEE_CALLS_PRCTL_FROM_MAIN: 141d8af9cfced2410afda008bd83c404836ff1834acKees Cook ret = prctl (PR_SET_PTRACER, tracer, 0, 0, 0); 142d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee main prtctl result: %d \n", ret); 143d8af9cfced2410afda008bd83c404836ff1834acKees Cook break; 144d8af9cfced2410afda008bd83c404836ff1834acKees Cook case TRACEE_CALLS_PRCTL_FROM_THREAD: 145d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee thread starting\n"); 146d8af9cfced2410afda008bd83c404836ff1834acKees Cook pthread_create(&thr, NULL, thr_fn, NULL); 147d8af9cfced2410afda008bd83c404836ff1834acKees Cook pthread_join(thr, NULL); 148d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee thread finished\n"); 149d8af9cfced2410afda008bd83c404836ff1834acKees Cook break; 150d8af9cfced2410afda008bd83c404836ff1834acKees Cook default: 151d8af9cfced2410afda008bd83c404836ff1834acKees Cook break; 152d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 153d8af9cfced2410afda008bd83c404836ff1834acKees Cook 154d8af9cfced2410afda008bd83c404836ff1834acKees Cook /* Wait for Oedipal action. */ 155d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee triggering tracer\n"); 156d8af9cfced2410afda008bd83c404836ff1834acKees Cook fflush(NULL); 157d8af9cfced2410afda008bd83c404836ff1834acKees Cook write(pipes[1], "ok\n", 3); 158d8af9cfced2410afda008bd83c404836ff1834acKees Cook 159d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee waiting for master\n"); 160d8af9cfced2410afda008bd83c404836ff1834acKees Cook saw = read(notification[0], buf, 1024); 161d8af9cfced2410afda008bd83c404836ff1834acKees Cook buf[saw] = '\0'; 162d8af9cfced2410afda008bd83c404836ff1834acKees Cook 163d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracee finished (%s)\n", buf); 164d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_SUCCESS); 165d8af9cfced2410afda008bd83c404836ff1834acKees Cook} 166d8af9cfced2410afda008bd83c404836ff1834acKees Cook 167d8af9cfced2410afda008bd83c404836ff1834acKees Cookvoid start_tracee(void) 168d8af9cfced2410afda008bd83c404836ff1834acKees Cook{ 169d8af9cfced2410afda008bd83c404836ff1834acKees Cook fflush(NULL); 170d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracee = fork(); 171d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (tracee < 0) { 172d8af9cfced2410afda008bd83c404836ff1834acKees Cook perror("fork tracee"); 173d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_FORK_TRACEE); 174d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 175d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (tracee == 0) { 176d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracee_main(); 177d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_TRACEE_UNREACHABLE); 178d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 179d8af9cfced2410afda008bd83c404836ff1834acKees Cook} 180d8af9cfced2410afda008bd83c404836ff1834acKees Cook 181d8af9cfced2410afda008bd83c404836ff1834acKees Cook/* Tracer knows tracee, needs tracer pid. */ 182d8af9cfced2410afda008bd83c404836ff1834acKees Cookint main(int argc, char*argv[]) 183d8af9cfced2410afda008bd83c404836ff1834acKees Cook{ 184d8af9cfced2410afda008bd83c404836ff1834acKees Cook int status; 185d8af9cfced2410afda008bd83c404836ff1834acKees Cook char buf[1024]; 186d8af9cfced2410afda008bd83c404836ff1834acKees Cook 187d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (argc > 1) { 188d8af9cfced2410afda008bd83c404836ff1834acKees Cook /* Operational states: 189d8af9cfced2410afda008bd83c404836ff1834acKees Cook * 0: tracer forks tracee. 190d8af9cfced2410afda008bd83c404836ff1834acKees Cook * 1: tracee calls prctl from main process. 191d8af9cfced2410afda008bd83c404836ff1834acKees Cook * 2: tracee calls prctl from non-leader thread. 192d8af9cfced2410afda008bd83c404836ff1834acKees Cook */ 193d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracee_method = atoi(argv[1]); 194d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 195d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (argc > 2) { 196d8af9cfced2410afda008bd83c404836ff1834acKees Cook /* Operational states: 197d8af9cfced2410afda008bd83c404836ff1834acKees Cook * 0: ptrace happens from non-leader thread. 198d8af9cfced2410afda008bd83c404836ff1834acKees Cook * 1: ptrace happens from main process. 199d8af9cfced2410afda008bd83c404836ff1834acKees Cook */ 200d8af9cfced2410afda008bd83c404836ff1834acKees Cook main_does_ptrace = atoi(argv[2]) != 0; 201d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 202d8af9cfced2410afda008bd83c404836ff1834acKees Cook 203d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (tracee_method != TRACEE_FORKS_FROM_TRACER) { 204d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("will issue prctl from %s\n", 205d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracee_method == TRACEE_CALLS_PRCTL_FROM_MAIN ? 206d8af9cfced2410afda008bd83c404836ff1834acKees Cook "main" : "thread"); 207d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 208d8af9cfced2410afda008bd83c404836ff1834acKees Cook else { 209d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("will fork tracee from tracer\n"); 210d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 211d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("will issue ptrace from tracer %s\n", 212d8af9cfced2410afda008bd83c404836ff1834acKees Cook main_does_ptrace ? "main" : "thread"); 213d8af9cfced2410afda008bd83c404836ff1834acKees Cook 214d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("master is %d\n", getpid()); 215d8af9cfced2410afda008bd83c404836ff1834acKees Cook 216d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (pipe(notification)<0) { 217d8af9cfced2410afda008bd83c404836ff1834acKees Cook perror("pipe"); 218d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_PIPE_NOTIFICATION); 219d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 220d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (pipe(pipes)<0) { 221d8af9cfced2410afda008bd83c404836ff1834acKees Cook perror("pipe"); 222d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_PIPE_COMMUNICATION); 223d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 224d8af9cfced2410afda008bd83c404836ff1834acKees Cook 225d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (tracee_method != TRACEE_FORKS_FROM_TRACER) { 226d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("forking tracee from master\n"); 227d8af9cfced2410afda008bd83c404836ff1834acKees Cook start_tracee(); 228d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 229d8af9cfced2410afda008bd83c404836ff1834acKees Cook 230d8af9cfced2410afda008bd83c404836ff1834acKees Cook fflush(NULL); 231d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracer = fork(); 232d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (tracer < 0) { 233d8af9cfced2410afda008bd83c404836ff1834acKees Cook perror("fork tracer"); 234d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_FORK_TRACER); 235d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 236d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (tracer == 0) { 237d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("tracer is %d\n", getpid()); 238d8af9cfced2410afda008bd83c404836ff1834acKees Cook if (main_does_ptrace) { 239d8af9cfced2410afda008bd83c404836ff1834acKees Cook tracer_main(NULL); 240d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 241d8af9cfced2410afda008bd83c404836ff1834acKees Cook else { 242d8af9cfced2410afda008bd83c404836ff1834acKees Cook pthread_t thread; 243d8af9cfced2410afda008bd83c404836ff1834acKees Cook pthread_create(&thread, NULL, tracer_main, NULL); 244d8af9cfced2410afda008bd83c404836ff1834acKees Cook pthread_join(thread, NULL); 245d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 246d8af9cfced2410afda008bd83c404836ff1834acKees Cook exit(EXIT_TRACER_UNREACHABLE); 247d8af9cfced2410afda008bd83c404836ff1834acKees Cook } 248d8af9cfced2410afda008bd83c404836ff1834acKees Cook 249d8af9cfced2410afda008bd83c404836ff1834acKees Cook /* Leave the pipes for the tracee and tracer. */ 250d8af9cfced2410afda008bd83c404836ff1834acKees Cook close(pipes[0]); 251d8af9cfced2410afda008bd83c404836ff1834acKees Cook close(pipes[1]); 252d8af9cfced2410afda008bd83c404836ff1834acKees Cook 253d8af9cfced2410afda008bd83c404836ff1834acKees Cook /* Close our end of pid notification. */ 254d8af9cfced2410afda008bd83c404836ff1834acKees Cook close(notification[0]); 255d8af9cfced2410afda008bd83c404836ff1834acKees Cook sprintf(buf, "%d", tracer); 256d8af9cfced2410afda008bd83c404836ff1834acKees Cook write(notification[1], buf, strlen(buf)); 257d8af9cfced2410afda008bd83c404836ff1834acKees Cook 258d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("master waiting for tracer to finish\n"); 259d8af9cfced2410afda008bd83c404836ff1834acKees Cook fflush(NULL); 260d8af9cfced2410afda008bd83c404836ff1834acKees Cook waitpid(tracer, &status, 0); 261d8af9cfced2410afda008bd83c404836ff1834acKees Cook 262d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("master waiting for tracee to finish\n"); 263d8af9cfced2410afda008bd83c404836ff1834acKees Cook fflush(NULL); 264d8af9cfced2410afda008bd83c404836ff1834acKees Cook write(notification[1], "stop", 4); 265d8af9cfced2410afda008bd83c404836ff1834acKees Cook kill(tracee, SIGCONT); // Just in case. 266d8af9cfced2410afda008bd83c404836ff1834acKees Cook waitpid(tracee, NULL, 0); 267d8af9cfced2410afda008bd83c404836ff1834acKees Cook 268d8af9cfced2410afda008bd83c404836ff1834acKees Cook status = WEXITSTATUS(status); 269d8af9cfced2410afda008bd83c404836ff1834acKees Cook printf("master saw rc %d from tracer\n", status); 270d8af9cfced2410afda008bd83c404836ff1834acKees Cook return status; 271d8af9cfced2410afda008bd83c404836ff1834acKees Cook} 272d8af9cfced2410afda008bd83c404836ff1834acKees Cook 273