• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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