blob: b05665896fcdc5b6faa64e77e27ec95a744c1a81 [file] [log] [blame]
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +00001/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00002 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00003 * honggfuzz - architecture dependent code (LINUX)
4 * -----------------------------------------
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00005 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00006 * Author: Robert Swiecki <swiecki@google.com>
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00007 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00008 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00009 *
10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
11 * not use this file except in compliance with the License. You may obtain
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000012 * a copy of the License at
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000013 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000014 * http://www.apache.org/licenses/LICENSE-2.0
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000015 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000016 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
19 * implied. See the License for the specific language governing
20 * permissions and limitations under the License.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000021 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000022 */
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000023
24#include "common.h"
25#include "arch.h"
26
27#include <ctype.h>
28#include <errno.h>
29#include <signal.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <inttypes.h>
34#include <sys/cdefs.h>
35#include <sys/personality.h>
36#include <sys/ptrace.h>
37#include <sys/prctl.h>
38#include <sys/resource.h>
39#include <sys/stat.h>
40#include <sys/time.h>
41#include <sys/types.h>
42#include <sys/user.h>
43#include <sys/wait.h>
44#include <time.h>
45#include <unistd.h>
46
robert.swiecki@gmail.com6310b112015-02-17 23:30:45 +000047#include "linux/perf.h"
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000048#include "linux/ptrace.h"
49#include "log.h"
50#include "util.h"
51
52bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
53{
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000054 /*
55 * Kill a process which corrupts its own heap (with ABRT)
56 */
57 if (setenv("MALLOC_CHECK_", "3", 1) == -1) {
58 LOGMSG_P(l_ERROR, "setenv(MALLOC_CHECK_=3) failed");
59 return false;
60 }
61
62 /*
63 * Tell asan to ignore SEGVs
64 */
robert.swiecki@gmail.com03770092015-02-20 13:48:31 +000065 if (setenv
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +000066 ("ASAN_OPTIONS",
67 "allow_user_segv_handler=1:handle_segv=0:abort_on_error=1:allocator_may_return_null=1",
68 1) == -1) {
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000069 LOGMSG_P(l_ERROR, "setenv(ASAN_OPTIONS) failed");
70 return false;
71 }
72
73 /*
74 * Kill the children when fuzzer dies (e.g. due to Ctrl+C)
75 */
76 if (prctl(PR_SET_PDEATHSIG, (long)SIGKILL, 0L, 0L, 0L) == -1) {
77 LOGMSG_P(l_ERROR, "prctl(PR_SET_PDEATHSIG, SIGKILL) failed");
78 return false;
79 }
80
81 /*
82 * Disable ASLR
83 */
84 if (personality(ADDR_NO_RANDOMIZE) == -1) {
85 LOGMSG_P(l_ERROR, "personality(ADDR_NO_RANDOMIZE) failed");
86 return false;
87 }
88#define ARGS_MAX 512
89 char *args[ARGS_MAX + 2];
90
91 int x;
92
93 for (x = 0; x < ARGS_MAX && hfuzz->cmdline[x]; x++) {
94 if (!hfuzz->fuzzStdin && strcmp(hfuzz->cmdline[x], _HF_FILE_PLACEHOLDER) == 0) {
95 args[x] = fileName;
96 } else {
97 args[x] = hfuzz->cmdline[x];
98 }
99 }
100
101 args[x++] = NULL;
102
103 LOGMSG(l_DEBUG, "Launching '%s' on file '%s'", args[0], fileName);
104
105 /*
106 * Set timeout (prof), real timeout (2*prof), and rlimit_cpu (2*prof)
107 */
108 if (hfuzz->tmOut) {
109 /*
110 * The hfuzz->tmOut is real CPU usage time...
111 */
112 struct itimerval it_prof = {
113 .it_interval = {.tv_sec = hfuzz->tmOut,.tv_usec = 0},
114 .it_value = {.tv_sec = 0,.tv_usec = 0}
115 };
116 if (setitimer(ITIMER_PROF, &it_prof, NULL) == -1) {
117 LOGMSG_P(l_ERROR, "Couldn't set the ITIMER_PROF timer");
118 return false;
119 }
120
121 /*
122 * ...so, if a process sleeps, this one should
123 * trigger a signal...
124 */
125 struct itimerval it_real = {
126 .it_interval = {.tv_sec = hfuzz->tmOut * 2UL,.tv_usec = 0},
127 .it_value = {.tv_sec = 0,.tv_usec = 0}
128 };
129 if (setitimer(ITIMER_REAL, &it_real, NULL) == -1) {
130 LOGMSG_P(l_ERROR, "Couldn't set the ITIMER_REAL timer");
131 return false;
132 }
133
134 /*
135 * ..if a process sleeps and catches SIGPROF/SIGALRM
136 * rlimits won't help either
137 */
138 struct rlimit rl = {
139 .rlim_cur = hfuzz->tmOut * 2,
140 .rlim_max = hfuzz->tmOut * 2,
141 };
142 if (setrlimit(RLIMIT_CPU, &rl) == -1) {
143 LOGMSG_P(l_ERROR, "Couldn't enforce the RLIMIT_CPU resource limit");
144 return false;
145 }
146 }
147
148 /*
149 * The address space limit. If big enough - roughly the size of RAM used
150 */
151 if (hfuzz->asLimit) {
152 struct rlimit rl = {
153 .rlim_cur = hfuzz->asLimit * 1024UL * 1024UL,
154 .rlim_max = hfuzz->asLimit * 1024UL * 1024UL,
155 };
156 if (setrlimit(RLIMIT_AS, &rl) == -1) {
157 LOGMSG_P(l_DEBUG, "Couldn't encforce the RLIMIT_AS resource limit, ignoring");
158 }
159 }
160
161 if (hfuzz->nullifyStdio) {
162 util_nullifyStdio();
163 }
164
165 if (hfuzz->fuzzStdin) {
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000166 /*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +0000167 * Uglyyyyyy ;)
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000168 */
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000169 if (!util_redirectStdin(fileName)) {
170 return false;
171 }
172 }
173
robert.swiecki@gmail.comda8396c2015-03-04 01:42:09 +0000174 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs) && hfuzz->envs[i]; i++) {
robert.swiecki@gmail.com15eca6f2015-03-04 03:31:36 +0000175 putenv(hfuzz->envs[i]);
robert.swiecki@gmail.comda8396c2015-03-04 01:42:09 +0000176 }
177
robert.swiecki@gmail.com1fc28672015-02-18 00:08:01 +0000178 if (!arch_ptraceEnable(hfuzz)) {
179 return false;
180 }
181
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000182 execvp(args[0], args);
183
184 util_recoverStdio();
185 LOGMSG(l_FATAL, "Failed to create new '%s' process", args[0]);
186 return false;
187}
188
189void arch_reapChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
190{
191 int status;
robert.swiecki@gmail.comf987e552015-02-25 01:47:07 +0000192 pid_t pid = wait3(&status, __WNOTHREAD | __WALL | WUNTRACED, NULL);
193 if (pid == -1) {
194 LOGMSG(l_FATAL, "wait3() pid=-1");
robert.swiecki@gmail.comd7818972015-02-24 23:37:59 +0000195 }
robert.swiecki@gmail.com23b3a2f2015-03-01 03:40:12 +0000196 if (!WIFSTOPPED(status)) {
197 LOGMSG(l_FATAL, "PID '%d' is not in a stopped state");
198 }
robert.swiecki@gmail.com627c1932015-02-25 02:35:00 +0000199
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +0000200 int perfFd[3];
201 if (arch_perfEnable(pid, hfuzz, perfFd) == false) {
robert.swiecki@gmail.com627c1932015-02-25 02:35:00 +0000202 return;
203 }
robert.swiecki@gmail.comf987e552015-02-25 01:47:07 +0000204 arch_ptraceAnalyze(hfuzz, status, pid, fuzzer);
robert.swiecki@gmail.comd7818972015-02-24 23:37:59 +0000205
206 for (;;) {
robert.swiecki@gmail.comc471a9f2015-02-25 17:28:06 +0000207 pid_t pid = wait3(&status, __WNOTHREAD | __WALL | WUNTRACED, NULL);
robert.swiecki@gmail.com6e3d04c2015-02-25 02:04:15 +0000208
robert.swiecki@gmail.com004ddfe2015-02-25 02:57:39 +0000209 LOGMSG(l_DEBUG, "PID '%d' returned with status '%d'", pid, status);
robert.swiecki@gmail.comd7818972015-02-24 23:37:59 +0000210
robert.swiecki@gmail.com004ddfe2015-02-25 02:57:39 +0000211 if (pid == -1 && errno == EINTR) {
212 continue;
213 }
214 if (pid == -1 && errno == ECHILD) {
215 arch_perfAnalyze(hfuzz, fuzzer, perfFd);
216 LOGMSG(l_DEBUG, "No more processes to track");
217 return;
218 }
219 if (pid == -1) {
220 LOGMSG_P(l_FATAL, "wait3() failed");
221 return;
222 }
223
224 arch_ptraceAnalyze(hfuzz, status, pid, fuzzer);
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000225 }
226}
227
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000228bool arch_archInit(honggfuzz_t * hfuzz)
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000229{
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000230 return arch_ptracePrepare(hfuzz);
231}