1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <fcntl.h>
18 #include <signal.h>
19 #include <stdint.h>
20 #include <sys/prctl.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/wait.h>
24 #include <unistd.h>
25
26 #include <chrono>
27 #include <iostream>
28 #include <string>
29
30 #include <android-base/properties.h>
31 #include <gtest/gtest.h>
32 #include <log/log_time.h> // for MS_PER_SEC and US_PER_SEC
33
34 #include "llkd.h"
35
36 using namespace std::chrono;
37 using namespace std::chrono_literals;
38
39 namespace {
40
GetUintProperty(const std::string & key,milliseconds def)41 milliseconds GetUintProperty(const std::string& key, milliseconds def) {
42 return milliseconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
43 static_cast<uint64_t>(def.max().count())));
44 }
45
GetUintProperty(const std::string & key,seconds def)46 seconds GetUintProperty(const std::string& key, seconds def) {
47 return seconds(android::base::GetUintProperty(key, static_cast<uint64_t>(def.count()),
48 static_cast<uint64_t>(def.max().count())));
49 }
50
51 // GTEST_LOG_(WARNING) output is fugly, this has much less noise
52 // ToDo: look into fixing googletest to produce output that matches style of
53 // all the other status messages, and can switch off __line__ and
54 // __function__ noise
55 #define GTEST_LOG_WARNING std::cerr << "[ WARNING ] "
56 #define GTEST_LOG_INFO std::cerr << "[ INFO ] "
57
58 // Properties is _not_ a high performance ABI!
rest()59 void rest() {
60 usleep(200000);
61 }
62
execute(const char * command)63 void execute(const char* command) {
64 if (getuid() || system(command)) {
65 system((std::string("su root ") + command).c_str());
66 }
67 }
68
llkdSleepPeriod(char state)69 seconds llkdSleepPeriod(char state) {
70 auto default_eng = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
71 auto default_enable = LLK_ENABLE_DEFAULT;
72 if (!LLK_ENABLE_DEFAULT && default_eng &&
73 android::base::GetBoolProperty("ro.debuggable", false)) {
74 default_enable = true;
75 }
76 default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
77 if (default_eng) {
78 GTEST_LOG_INFO << LLK_ENABLE_PROPERTY " defaults to \"eng\" thus "
79 << (default_enable ? "true" : "false") << "\n";
80 }
81 // Hail Mary hope is unconfigured.
82 if ((GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, LLK_TIMEOUT_MS_DEFAULT) !=
83 duration_cast<milliseconds>(120s)) ||
84 (GetUintProperty(LLK_CHECK_MS_PROPERTY,
85 LLK_TIMEOUT_MS_DEFAULT / LLK_CHECKS_PER_TIMEOUT_DEFAULT) !=
86 duration_cast<milliseconds>(10s))) {
87 execute("stop llkd-0");
88 execute("stop llkd-1");
89 rest();
90 std::string setprop("setprop ");
91 // Manually check that SyS_openat is _added_ to the list when restarted
92 execute((setprop + LLK_CHECK_STACK_PROPERTY + " ,SyS_openat").c_str());
93 rest();
94 execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " false").c_str());
95 rest();
96 execute((setprop + LLK_TIMEOUT_MS_PROPERTY + " 120000").c_str());
97 rest();
98 execute((setprop + KHT_TIMEOUT_PROPERTY + " 130").c_str());
99 rest();
100 execute((setprop + LLK_CHECK_MS_PROPERTY + " 10000").c_str());
101 rest();
102 if (!default_enable) {
103 execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
104 rest();
105 }
106 execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " true").c_str());
107 rest();
108 }
109 default_enable = LLK_ENABLE_DEFAULT;
110 if (!LLK_ENABLE_DEFAULT && (android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng") &&
111 android::base::GetBoolProperty("ro.debuggable", false)) {
112 default_enable = true;
113 }
114 default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
115 if (default_enable) {
116 execute("start llkd-1");
117 rest();
118 GTEST_LOG_INFO << "llkd enabled\n";
119 } else {
120 GTEST_LOG_WARNING << "llkd disabled\n";
121 }
122
123 /* KISS follows llk_init() */
124 milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;
125 seconds khtTimeout = duration_cast<seconds>(
126 llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) / LLK_CHECKS_PER_TIMEOUT_DEFAULT);
127 khtTimeout = GetUintProperty(KHT_TIMEOUT_PROPERTY, khtTimeout);
128 llkTimeoutMs =
129 khtTimeout * LLK_CHECKS_PER_TIMEOUT_DEFAULT / (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT);
130 llkTimeoutMs = GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
131 if (llkTimeoutMs < LLK_TIMEOUT_MS_MINIMUM) {
132 llkTimeoutMs = LLK_TIMEOUT_MS_MINIMUM;
133 }
134 milliseconds llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
135 auto timeout = GetUintProperty((state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY
136 : (state == 'S') ? LLK_STACK_TIMEOUT_MS_PROPERTY
137 : LLK_D_TIMEOUT_MS_PROPERTY,
138 llkTimeoutMs);
139 if (timeout < LLK_TIMEOUT_MS_MINIMUM) {
140 timeout = LLK_TIMEOUT_MS_MINIMUM;
141 }
142
143 if (llkCheckMs > timeout) {
144 llkCheckMs = timeout;
145 }
146 llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
147 timeout += llkCheckMs;
148 auto sec = duration_cast<seconds>(timeout);
149 if (sec == 0s) {
150 ++sec;
151 } else if (sec > 59s) {
152 GTEST_LOG_WARNING << "llkd is configured for about " << duration_cast<minutes>(sec).count()
153 << " minutes to react\n";
154 }
155
156 // 33% margin for the test to naturally timeout waiting for llkd to respond
157 return (sec * 4 + 2s) / 3;
158 }
159
waitForPid(pid_t child_pid)160 inline void waitForPid(pid_t child_pid) {
161 int wstatus;
162 ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
163 EXPECT_FALSE(WIFEXITED(wstatus)) << "[ INFO ] exit=" << WEXITSTATUS(wstatus);
164 ASSERT_TRUE(WIFSIGNALED(wstatus));
165 ASSERT_EQ(WTERMSIG(wstatus), SIGKILL);
166 }
167
checkKill(const char * reason)168 bool checkKill(const char* reason) {
169 if (android::base::GetBoolProperty(LLK_KILLTEST_PROPERTY, LLK_KILLTEST_DEFAULT)) {
170 return false;
171 }
172 auto bootreason = android::base::GetProperty("sys.boot.reason", "nothing");
173 if (bootreason == reason) {
174 GTEST_LOG_INFO << "Expected test result confirmed " << reason << "\n";
175 return true;
176 }
177 GTEST_LOG_WARNING << "Expected test result is " << reason << "\n";
178
179 // apct adjustment if needed (set LLK_KILLTEST_PROPERTY to "off" to allow test)
180 //
181 // if (android::base::GetProperty(LLK_KILLTEST_PROPERTY, "") == "false") {
182 // GTEST_LOG_WARNING << "Bypassing test\n";
183 // return true;
184 // }
185
186 return false;
187 }
188
189 } // namespace
190
191 // The tests that use this helper are to simulate processes stuck in 'D'
192 // state that are experiencing forward scheduled progress. As such the
193 // expectation is that llkd will _not_ perform any mitigations. The sleepfor
194 // argument helps us set the amount of forward scheduler progress.
llkd_driver_ABA(const microseconds sleepfor)195 static void llkd_driver_ABA(const microseconds sleepfor) {
196 const auto period = llkdSleepPeriod('D');
197 if (period <= sleepfor) {
198 GTEST_LOG_WARNING << "llkd configuration too short for "
199 << duration_cast<milliseconds>(sleepfor).count() << "ms work cycle\n";
200 return;
201 }
202
203 auto child_pid = fork();
204 ASSERT_LE(0, child_pid);
205 int wstatus;
206 if (!child_pid) {
207 auto ratio = period / sleepfor;
208 ASSERT_LT(0, ratio);
209 // vfork() parent is uninterruptable D state waiting for child to exec()
210 while (--ratio > 0) {
211 auto driver_pid = vfork();
212 ASSERT_LE(0, driver_pid);
213 if (driver_pid) { // parent
214 waitpid(driver_pid, &wstatus, 0);
215 if (!WIFEXITED(wstatus)) {
216 exit(42);
217 }
218 if (WEXITSTATUS(wstatus) != 42) {
219 exit(42);
220 }
221 } else {
222 usleep(sleepfor.count());
223 exit(42);
224 }
225 }
226 exit(0);
227 }
228 ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
229 EXPECT_TRUE(WIFEXITED(wstatus));
230 if (WIFEXITED(wstatus)) {
231 EXPECT_EQ(0, WEXITSTATUS(wstatus));
232 }
233 ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[ INFO ] signo=" << WTERMSIG(wstatus);
234 }
235
TEST(llkd,driver_ABA_fast)236 TEST(llkd, driver_ABA_fast) {
237 llkd_driver_ABA(5ms);
238 }
239
TEST(llkd,driver_ABA_slow)240 TEST(llkd, driver_ABA_slow) {
241 llkd_driver_ABA(1s);
242 }
243
TEST(llkd,driver_ABA_glacial)244 TEST(llkd, driver_ABA_glacial) {
245 llkd_driver_ABA(1min);
246 }
247
248 // Following tests must be last in this file to capture possible errant
249 // kernel_panic mitigation failure.
250
251 // The following tests simulate processes stick in 'Z' or 'D' state with
252 // no forward scheduling progress, but interruptible. As such the expectation
253 // is that llkd will perform kill mitigation and not progress to kernel_panic.
254
TEST(llkd,zombie)255 TEST(llkd, zombie) {
256 if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
257 return;
258 }
259
260 const auto period = llkdSleepPeriod('Z');
261
262 /* Create a Persistent Zombie Process */
263 pid_t child_pid = fork();
264 ASSERT_LE(0, child_pid);
265 if (!child_pid) {
266 auto zombie_pid = fork();
267 ASSERT_LE(0, zombie_pid);
268 if (!zombie_pid) {
269 sleep(1);
270 exit(0);
271 }
272 sleep(period.count());
273 exit(42);
274 }
275
276 waitForPid(child_pid);
277 }
278
TEST(llkd,driver)279 TEST(llkd, driver) {
280 if (checkKill("kernel_panic,sysrq,livelock,driver")) {
281 return;
282 }
283
284 const auto period = llkdSleepPeriod('D');
285
286 /* Create a Persistent Device Process */
287 auto child_pid = fork();
288 ASSERT_LE(0, child_pid);
289 if (!child_pid) {
290 // vfork() parent is uninterruptable D state waiting for child to exec()
291 auto driver_pid = vfork();
292 ASSERT_LE(0, driver_pid);
293 sleep(period.count());
294 exit(driver_pid ? 42 : 0);
295 }
296
297 waitForPid(child_pid);
298 }
299
TEST(llkd,sleep)300 TEST(llkd, sleep) {
301 if (checkKill("kernel_panic,sysrq,livelock,sleeping")) {
302 return;
303 }
304 if (!android::base::GetBoolProperty("ro.debuggable", false)) {
305 GTEST_LOG_WARNING << "Features not available on user builds\n";
306 }
307
308 const auto period = llkdSleepPeriod('S');
309
310 /* Create a Persistent SyS_openat for single-ended pipe */
311 static constexpr char stack_pipe_file[] = "/dev/stack_pipe_file";
312 unlink(stack_pipe_file);
313 auto pipe_ret = mknod(stack_pipe_file, S_IFIFO | 0666, 0);
314 ASSERT_LE(0, pipe_ret);
315
316 auto child_pid = fork();
317 ASSERT_LE(0, child_pid);
318 if (!child_pid) {
319 child_pid = fork();
320 ASSERT_LE(0, child_pid);
321 if (!child_pid) {
322 sleep(period.count());
323 auto fd = open(stack_pipe_file, O_RDONLY | O_CLOEXEC);
324 close(fd);
325 exit(0);
326 } else {
327 auto fd = open(stack_pipe_file, O_WRONLY | O_CLOEXEC);
328 close(fd);
329 exit(42);
330 }
331 }
332
333 waitForPid(child_pid);
334
335 unlink(stack_pipe_file);
336 }
337
338 // b/120983740
TEST(llkd,adbd_and_setsid)339 TEST(llkd, adbd_and_setsid) {
340 if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
341 return;
342 }
343 const auto period = llkdSleepPeriod('S');
344
345 // expect llkd.zombie to trigger, but not for adbd&[setsid]
346 // Create a Persistent Zombie setsid Process
347 pid_t child_pid = fork();
348 ASSERT_LE(0, child_pid);
349 if (!child_pid) {
350 prctl(PR_SET_NAME, "adbd");
351 auto zombie_pid = fork();
352 ASSERT_LE(0, zombie_pid);
353 if (!zombie_pid) {
354 prctl(PR_SET_NAME, "setsid");
355 sleep(1);
356 exit(0);
357 }
358 sleep(period.count());
359 exit(42);
360 }
361
362 // Reverse of waitForPid, do _not_ expect kill
363 int wstatus;
364 ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
365 EXPECT_TRUE(WIFEXITED(wstatus));
366 if (WIFEXITED(wstatus)) {
367 EXPECT_EQ(42, WEXITSTATUS(wstatus));
368 }
369 ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[ INFO ] signo=" << WTERMSIG(wstatus);
370 }
371