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 default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
73 if (default_eng) {
74 GTEST_LOG_INFO << LLK_ENABLE_PROPERTY " defaults to "
75 << (default_enable ? "true" : "false") << "\n";
76 }
77 // Hail Mary hope is unconfigured.
78 if ((GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, LLK_TIMEOUT_MS_DEFAULT) !=
79 duration_cast<milliseconds>(120s)) ||
80 (GetUintProperty(LLK_CHECK_MS_PROPERTY,
81 LLK_TIMEOUT_MS_DEFAULT / LLK_CHECKS_PER_TIMEOUT_DEFAULT) !=
82 duration_cast<milliseconds>(10s))) {
83 execute("stop llkd-0");
84 execute("stop llkd-1");
85 rest();
86 std::string setprop("setprop ");
87 // Manually check that SyS_openat is _added_ to the list when restarted
88 // 4.19+ kernels report __arm64_sys_openat b/147486902
89 execute((setprop + LLK_CHECK_STACK_PROPERTY + " ,SyS_openat,__arm64_sys_openat").c_str());
90 rest();
91 execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " false").c_str());
92 rest();
93 execute((setprop + LLK_TIMEOUT_MS_PROPERTY + " 120000").c_str());
94 rest();
95 execute((setprop + KHT_TIMEOUT_PROPERTY + " 130").c_str());
96 rest();
97 execute((setprop + LLK_CHECK_MS_PROPERTY + " 10000").c_str());
98 rest();
99 if (!default_enable) {
100 execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
101 rest();
102 }
103 execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " true").c_str());
104 rest();
105 }
106 default_enable = LLK_ENABLE_DEFAULT;
107 default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
108 if (default_enable) {
109 execute("start llkd-1");
110 rest();
111 GTEST_LOG_INFO << "llkd enabled\n";
112 } else {
113 GTEST_LOG_WARNING << "llkd disabled\n";
114 }
115
116 /* KISS follows llk_init() */
117 milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;
118 seconds khtTimeout = duration_cast<seconds>(
119 llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) / LLK_CHECKS_PER_TIMEOUT_DEFAULT);
120 khtTimeout = GetUintProperty(KHT_TIMEOUT_PROPERTY, khtTimeout);
121 llkTimeoutMs =
122 khtTimeout * LLK_CHECKS_PER_TIMEOUT_DEFAULT / (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT);
123 llkTimeoutMs = GetUintProperty(LLK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
124 if (llkTimeoutMs < LLK_TIMEOUT_MS_MINIMUM) {
125 llkTimeoutMs = LLK_TIMEOUT_MS_MINIMUM;
126 }
127 milliseconds llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
128 auto timeout = GetUintProperty((state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY
129 : (state == 'S') ? LLK_STACK_TIMEOUT_MS_PROPERTY
130 : LLK_D_TIMEOUT_MS_PROPERTY,
131 llkTimeoutMs);
132 if (timeout < LLK_TIMEOUT_MS_MINIMUM) {
133 timeout = LLK_TIMEOUT_MS_MINIMUM;
134 }
135
136 if (llkCheckMs > timeout) {
137 llkCheckMs = timeout;
138 }
139 llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
140 timeout += llkCheckMs;
141 auto sec = duration_cast<seconds>(timeout);
142 if (sec == 0s) {
143 ++sec;
144 } else if (sec > 59s) {
145 GTEST_LOG_WARNING << "llkd is configured for about " << duration_cast<minutes>(sec).count()
146 << " minutes to react\n";
147 }
148
149 // 33% margin for the test to naturally timeout waiting for llkd to respond
150 return (sec * 4 + 2s) / 3;
151 }
152
waitForPid(pid_t child_pid)153 inline void waitForPid(pid_t child_pid) {
154 int wstatus;
155 ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
156 EXPECT_FALSE(WIFEXITED(wstatus)) << "[ INFO ] exit=" << WEXITSTATUS(wstatus);
157 ASSERT_TRUE(WIFSIGNALED(wstatus));
158 ASSERT_EQ(WTERMSIG(wstatus), SIGKILL);
159 }
160
checkKill(const char * reason)161 bool checkKill(const char* reason) {
162 if (android::base::GetBoolProperty(LLK_KILLTEST_PROPERTY, LLK_KILLTEST_DEFAULT)) {
163 return false;
164 }
165 auto bootreason = android::base::GetProperty("sys.boot.reason", "nothing");
166 if (bootreason == reason) {
167 GTEST_LOG_INFO << "Expected test result confirmed " << reason << "\n";
168 return true;
169 }
170 GTEST_LOG_WARNING << "Expected test result is " << reason << "\n";
171
172 // apct adjustment if needed (set LLK_KILLTEST_PROPERTY to "off" to allow test)
173 //
174 // if (android::base::GetProperty(LLK_KILLTEST_PROPERTY, "") == "false") {
175 // GTEST_LOG_WARNING << "Bypassing test\n";
176 // return true;
177 // }
178
179 return false;
180 }
181
182 } // namespace
183
184 // The tests that use this helper are to simulate processes stuck in 'D'
185 // state that are experiencing forward scheduled progress. As such the
186 // expectation is that llkd will _not_ perform any mitigations. The sleepfor
187 // argument helps us set the amount of forward scheduler progress.
llkd_driver_ABA(const microseconds sleepfor)188 static void llkd_driver_ABA(const microseconds sleepfor) {
189 const auto period = llkdSleepPeriod('D');
190 if (period <= sleepfor) {
191 GTEST_LOG_WARNING << "llkd configuration too short for "
192 << duration_cast<milliseconds>(sleepfor).count() << "ms work cycle\n";
193 return;
194 }
195
196 auto child_pid = fork();
197 ASSERT_LE(0, child_pid);
198 int wstatus;
199 if (!child_pid) {
200 auto ratio = period / sleepfor;
201 ASSERT_LT(0, ratio);
202 // vfork() parent is uninterruptable D state waiting for child to exec()
203 while (--ratio > 0) {
204 auto driver_pid = vfork();
205 ASSERT_LE(0, driver_pid);
206 if (driver_pid) { // parent
207 waitpid(driver_pid, &wstatus, 0);
208 if (!WIFEXITED(wstatus)) {
209 exit(42);
210 }
211 if (WEXITSTATUS(wstatus) != 42) {
212 exit(42);
213 }
214 } else {
215 usleep(sleepfor.count());
216 exit(42);
217 }
218 }
219 exit(0);
220 }
221 ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
222 EXPECT_TRUE(WIFEXITED(wstatus));
223 if (WIFEXITED(wstatus)) {
224 EXPECT_EQ(0, WEXITSTATUS(wstatus));
225 }
226 ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[ INFO ] signo=" << WTERMSIG(wstatus);
227 }
228
TEST(llkd,driver_ABA_fast)229 TEST(llkd, driver_ABA_fast) {
230 llkd_driver_ABA(5ms);
231 }
232
TEST(llkd,driver_ABA_slow)233 TEST(llkd, driver_ABA_slow) {
234 llkd_driver_ABA(1s);
235 }
236
TEST(llkd,driver_ABA_glacial)237 TEST(llkd, driver_ABA_glacial) {
238 llkd_driver_ABA(1min);
239 }
240
241 // Following tests must be last in this file to capture possible errant
242 // kernel_panic mitigation failure.
243
244 // The following tests simulate processes stick in 'Z' or 'D' state with
245 // no forward scheduling progress, but interruptible. As such the expectation
246 // is that llkd will perform kill mitigation and not progress to kernel_panic.
247
TEST(llkd,zombie)248 TEST(llkd, zombie) {
249 if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
250 return;
251 }
252
253 const auto period = llkdSleepPeriod('Z');
254
255 /* Create a Persistent Zombie Process */
256 pid_t child_pid = fork();
257 ASSERT_LE(0, child_pid);
258 if (!child_pid) {
259 auto zombie_pid = fork();
260 ASSERT_LE(0, zombie_pid);
261 if (!zombie_pid) {
262 sleep(1);
263 exit(0);
264 }
265 sleep(period.count());
266 exit(42);
267 }
268
269 waitForPid(child_pid);
270 }
271
TEST(llkd,driver)272 TEST(llkd, driver) {
273 if (checkKill("kernel_panic,sysrq,livelock,driver")) {
274 return;
275 }
276
277 const auto period = llkdSleepPeriod('D');
278
279 /* Create a Persistent Device Process */
280 auto child_pid = fork();
281 ASSERT_LE(0, child_pid);
282 if (!child_pid) {
283 // vfork() parent is uninterruptable D state waiting for child to exec()
284 auto driver_pid = vfork();
285 ASSERT_LE(0, driver_pid);
286 sleep(period.count());
287 exit(driver_pid ? 42 : 0);
288 }
289
290 waitForPid(child_pid);
291 }
292
TEST(llkd,sleep)293 TEST(llkd, sleep) {
294 if (checkKill("kernel_panic,sysrq,livelock,sleeping")) {
295 return;
296 }
297 if (!android::base::GetBoolProperty("ro.debuggable", false)) {
298 GTEST_LOG_WARNING << "Features not available on user builds\n";
299 }
300
301 const auto period = llkdSleepPeriod('S');
302
303 /* Create a Persistent SyS_openat for single-ended pipe */
304 static constexpr char stack_pipe_file[] = "/dev/stack_pipe_file";
305 unlink(stack_pipe_file);
306 auto pipe_ret = mknod(stack_pipe_file, S_IFIFO | 0666, 0);
307 ASSERT_LE(0, pipe_ret);
308
309 auto child_pid = fork();
310 ASSERT_LE(0, child_pid);
311 if (!child_pid) {
312 child_pid = fork();
313 ASSERT_LE(0, child_pid);
314 if (!child_pid) {
315 sleep(period.count());
316 auto fd = open(stack_pipe_file, O_RDONLY | O_CLOEXEC);
317 close(fd);
318 exit(0);
319 } else {
320 auto fd = open(stack_pipe_file, O_WRONLY | O_CLOEXEC);
321 close(fd);
322 exit(42);
323 }
324 }
325
326 waitForPid(child_pid);
327
328 unlink(stack_pipe_file);
329 }
330
331 // b/120983740
TEST(llkd,adbd_and_setsid)332 TEST(llkd, adbd_and_setsid) {
333 if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
334 return;
335 }
336 const auto period = llkdSleepPeriod('S');
337
338 // expect llkd.zombie to trigger, but not for adbd&[setsid]
339 // Create a Persistent Zombie setsid Process
340 pid_t child_pid = fork();
341 ASSERT_LE(0, child_pid);
342 if (!child_pid) {
343 prctl(PR_SET_NAME, "adbd");
344 auto zombie_pid = fork();
345 ASSERT_LE(0, zombie_pid);
346 if (!zombie_pid) {
347 prctl(PR_SET_NAME, "setsid");
348 sleep(1);
349 exit(0);
350 }
351 sleep(period.count());
352 exit(42);
353 }
354
355 // Reverse of waitForPid, do _not_ expect kill
356 int wstatus;
357 ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
358 EXPECT_TRUE(WIFEXITED(wstatus));
359 if (WIFEXITED(wstatus)) {
360 EXPECT_EQ(42, WEXITSTATUS(wstatus));
361 }
362 ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[ INFO ] signo=" << WTERMSIG(wstatus);
363 }
364