1 /*
2  * Copyright (C) 2011 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 "exec_utils.h"
18 
19 #include <sys/utsname.h>
20 #include <unistd.h>
21 
22 #include <csignal>
23 #include <cstdio>
24 #include <cstring>
25 #include <filesystem>
26 #include <memory>
27 #include <optional>
28 #include <tuple>
29 
30 #include "android-base/logging.h"
31 #include "android-base/result.h"
32 #include "android-base/stringprintf.h"
33 #include "base/file_utils.h"
34 #include "base/memory_tool.h"
35 #include "common_runtime_test.h"
36 #include "gmock/gmock.h"
37 #include "gtest/gtest.h"
38 
39 namespace art HIDDEN {
40 
41 using ::android::base::Result;
42 using ::testing::_;
43 using ::testing::AllOf;
44 using ::testing::Gt;
45 using ::testing::HasSubstr;
46 using ::testing::InSequence;
47 using ::testing::MockFunction;
48 using ::testing::Ne;
49 using ::testing::Return;
50 
51 std::string PrettyArguments(const char* signature);
52 std::string PrettyReturnType(const char* signature);
53 
GetBin(const std::string & name)54 std::string GetBin(const std::string& name) {
55   if (kIsTargetBuild) {
56     std::string android_root(GetAndroidRoot());
57     return android_root + "/bin/" + name;
58   } else if (std::filesystem::exists("/usr/bin/" + name)) {
59     return "/usr/bin/" + name;
60   } else {
61     return "/bin/" + name;
62   }
63 }
64 
GetKernelVersion()65 std::tuple<int, int> GetKernelVersion() {
66   std::tuple<int, int> version;
67   utsname uts;
68   CHECK_EQ(uname(&uts), 0);
69   CHECK_EQ(sscanf(uts.release, "%d.%d", &std::get<0>(version), &std::get<1>(version)), 2);
70   return version;
71 }
72 
73 class TestingExecUtils : public ExecUtils {
74  public:
75   MOCK_METHOD(std::string, GetProcStat, (pid_t pid), (const, override));
76   MOCK_METHOD(Result<int64_t>, DoGetUptimeMs, (), (const));
77   MOCK_METHOD(int64_t, GetTicksPerSec, (), (const, override));
78 
79   // A workaround to avoid MOCK_METHOD on a method with an `std::string*` parameter, which will lead
80   // to a conflict between gmock and android-base/logging.h (b/132668253).
GetUptimeMs(std::string * error_msg) const81   std::optional<int64_t> GetUptimeMs(std::string* error_msg) const override {
82     Result<int64_t> result = DoGetUptimeMs();
83     if (result.ok()) {
84       return *result;
85     }
86     *error_msg = result.error().message();
87     return std::nullopt;
88   }
89 };
90 
91 class AlwaysFallbackExecUtils : public TestingExecUtils {
92  protected:
PidfdOpen(pid_t) const93   android::base::unique_fd PidfdOpen(pid_t) const override { return android::base::unique_fd(-1); }
94 };
95 
96 class NeverFallbackExecUtils : public TestingExecUtils {
97  protected:
PidfdOpen(pid_t pid) const98   android::base::unique_fd PidfdOpen(pid_t pid) const override {
99     android::base::unique_fd pidfd = ExecUtils::PidfdOpen(pid);
100     CHECK_GE(pidfd.get(), 0) << strerror(errno);
101     return pidfd;
102   }
103 };
104 
105 class ExecUtilsTest : public CommonRuntimeTest, public testing::WithParamInterface<bool> {
106  protected:
SetUp()107   void SetUp() override {
108     CommonRuntimeTest::SetUp();
109     bool always_fallback = GetParam();
110     if (always_fallback) {
111       exec_utils_ = std::make_unique<AlwaysFallbackExecUtils>();
112     } else {
113       if (GetKernelVersion() >= std::make_tuple(5, 4)) {
114         exec_utils_ = std::make_unique<NeverFallbackExecUtils>();
115       } else {
116         GTEST_SKIP() << "Kernel version older than 5.4";
117       }
118     }
119   }
120 
121   std::unique_ptr<TestingExecUtils> exec_utils_;
122 };
123 
TEST_P(ExecUtilsTest,ExecSuccess)124 TEST_P(ExecUtilsTest, ExecSuccess) {
125   std::vector<std::string> command;
126   command.push_back(GetBin("id"));
127   std::string error_msg;
128   // Historical note: Running on Valgrind failed due to some memory
129   // that leaks in thread alternate signal stacks.
130   EXPECT_TRUE(exec_utils_->Exec(command, &error_msg));
131   EXPECT_EQ(0U, error_msg.size()) << error_msg;
132 }
133 
TEST_P(ExecUtilsTest,ExecError)134 TEST_P(ExecUtilsTest, ExecError) {
135   std::vector<std::string> command;
136   command.push_back("bogus");
137   std::string error_msg;
138   // Historical note: Running on Valgrind failed due to some memory
139   // that leaks in thread alternate signal stacks.
140   ExecResult result = exec_utils_->ExecAndReturnResult(command, /*timeout_sec=*/-1, &error_msg);
141   EXPECT_EQ(result.status, ExecResult::kSignaled);
142   EXPECT_EQ(result.signal, SIGABRT);
143   EXPECT_FALSE(error_msg.empty());
144 }
145 
TEST_P(ExecUtilsTest,EnvSnapshotAdditionsAreNotVisible)146 TEST_P(ExecUtilsTest, EnvSnapshotAdditionsAreNotVisible) {
147   static constexpr const char* kModifiedVariable = "EXEC_SHOULD_NOT_EXPORT_THIS";
148   static constexpr int kOverwrite = 1;
149   // Set an variable in the current environment.
150   EXPECT_EQ(setenv(kModifiedVariable, "NEVER", kOverwrite), 0);
151   // Test that it is not exported.
152   std::vector<std::string> command;
153   command.push_back(GetBin("printenv"));
154   command.push_back(kModifiedVariable);
155   std::string error_msg;
156   // Historical note: Running on Valgrind failed due to some memory
157   // that leaks in thread alternate signal stacks.
158   EXPECT_FALSE(exec_utils_->Exec(command, &error_msg));
159   EXPECT_NE(0U, error_msg.size()) << error_msg;
160 }
161 
TEST_P(ExecUtilsTest,EnvSnapshotDeletionsAreNotVisible)162 TEST_P(ExecUtilsTest, EnvSnapshotDeletionsAreNotVisible) {
163   static constexpr const char* kDeletedVariable = "PATH";
164   static constexpr int kOverwrite = 1;
165   // Save the variable's value.
166   const char* save_value = getenv(kDeletedVariable);
167   EXPECT_NE(save_value, nullptr);
168   // Delete the variable.
169   EXPECT_EQ(unsetenv(kDeletedVariable), 0);
170   // Test that it is not exported.
171   std::vector<std::string> command;
172   command.push_back(GetBin("printenv"));
173   command.push_back(kDeletedVariable);
174   std::string error_msg;
175   // Historical note: Running on Valgrind failed due to some memory
176   // that leaks in thread alternate signal stacks.
177   EXPECT_TRUE(exec_utils_->Exec(command, &error_msg));
178   EXPECT_EQ(0U, error_msg.size()) << error_msg;
179   // Restore the variable's value.
180   EXPECT_EQ(setenv(kDeletedVariable, save_value, kOverwrite), 0);
181 }
182 
SleepCommand(int sleep_seconds)183 static std::vector<std::string> SleepCommand(int sleep_seconds) {
184   std::vector<std::string> command;
185   command.push_back(GetBin("sleep"));
186   command.push_back(android::base::StringPrintf("%d", sleep_seconds));
187   return command;
188 }
189 
TEST_P(ExecUtilsTest,ExecTimeout)190 TEST_P(ExecUtilsTest, ExecTimeout) {
191   static constexpr int kSleepSeconds = 5;
192   static constexpr int kWaitSeconds = 1;
193   std::vector<std::string> command = SleepCommand(kSleepSeconds);
194   std::string error_msg;
195   EXPECT_EQ(exec_utils_->ExecAndReturnResult(command, kWaitSeconds, &error_msg).status,
196             ExecResult::kTimedOut)
197       << error_msg;
198   EXPECT_THAT(error_msg, HasSubstr("timed out"));
199 }
200 
TEST_P(ExecUtilsTest,ExecNoTimeout)201 TEST_P(ExecUtilsTest, ExecNoTimeout) {
202   static constexpr int kSleepSeconds = 1;
203   static constexpr int kWaitSeconds = 5;
204   std::vector<std::string> command = SleepCommand(kSleepSeconds);
205   std::string error_msg;
206   EXPECT_EQ(exec_utils_->ExecAndReturnResult(command, kWaitSeconds, &error_msg).status,
207             ExecResult::kExited)
208       << error_msg;
209 }
210 
TEST_P(ExecUtilsTest,ExecStat)211 TEST_P(ExecUtilsTest, ExecStat) {
212   std::vector<std::string> command;
213   command.push_back(GetBin("id"));
214 
215   std::string error_msg;
216   ProcessStat stat;
217 
218   // The process filename is "a) b".
219   EXPECT_CALL(*exec_utils_, GetProcStat(_))
220       .WillOnce(Return(
221           "14963 (a) b) Z 6067 14963 1 0 -1 4228108 105 0 0 0 94 5 0 0 39 19 1 0 162034388 0 0 "
222           "18446744073709551615 0 0 0 0 0 0 20999 0 0 1 0 0 17 71 0 0 0 0 0 0 0 0 0 0 0 0 9"));
223   EXPECT_CALL(*exec_utils_, DoGetUptimeMs()).WillOnce(Return(1620344887ll));
224   EXPECT_CALL(*exec_utils_, GetTicksPerSec()).WillOnce(Return(100));
225 
226   ASSERT_EQ(exec_utils_
227                 ->ExecAndReturnResult(command,
228                                       /*timeout_sec=*/-1,
229                                       ExecCallbacks(),
230                                       /*new_process_group=*/false,
231                                       &stat,
232                                       &error_msg)
233                 .status,
234             ExecResult::kExited)
235       << error_msg;
236 
237   EXPECT_EQ(stat.cpu_time_ms, 990);
238   EXPECT_EQ(stat.wall_time_ms, 1007);
239 }
240 
TEST_P(ExecUtilsTest,ExecStatNoStartTime)241 TEST_P(ExecUtilsTest, ExecStatNoStartTime) {
242   std::vector<std::string> command;
243   command.push_back(GetBin("id"));
244 
245   std::string error_msg;
246   ProcessStat stat;
247 
248   // The process filename is "a) b".
249   EXPECT_CALL(*exec_utils_, GetProcStat(_))
250       .WillOnce(Return(
251           "14963 (a) b) Z 6067 14963 1 0 -1 4228108 105 0 0 0 94 5 0 0 39 19 1 0 0 0 0 "
252           "18446744073709551615 0 0 0 0 0 0 20999 0 0 1 0 0 17 71 0 0 0 0 0 0 0 0 0 0 0 0 9"));
253   EXPECT_CALL(*exec_utils_, DoGetUptimeMs()).WillOnce(Return(1620344887ll));
254   EXPECT_CALL(*exec_utils_, GetTicksPerSec()).WillOnce(Return(100));
255 
256   ASSERT_EQ(exec_utils_
257                 ->ExecAndReturnResult(command,
258                                       /*timeout_sec=*/-1,
259                                       ExecCallbacks(),
260                                       /*new_process_group=*/false,
261                                       &stat,
262                                       &error_msg)
263                 .status,
264             ExecResult::kExited)
265       << error_msg;
266 
267   EXPECT_EQ(stat.cpu_time_ms, 0);
268   EXPECT_EQ(stat.wall_time_ms, 0);
269 }
270 
TEST_P(ExecUtilsTest,ExecStatNoUptime)271 TEST_P(ExecUtilsTest, ExecStatNoUptime) {
272   std::vector<std::string> command;
273   command.push_back(GetBin("id"));
274 
275   std::string error_msg;
276   ProcessStat stat;
277 
278   EXPECT_CALL(*exec_utils_, DoGetUptimeMs())
279       .WillOnce(Return(Result<int64_t>(Errorf("Failed to get uptime"))));
280 
281   ASSERT_EQ(exec_utils_
282                 ->ExecAndReturnResult(command,
283                                       /*timeout_sec=*/-1,
284                                       ExecCallbacks(),
285                                       /*new_process_group=*/false,
286                                       &stat,
287                                       &error_msg)
288                 .status,
289             ExecResult::kExited)
290       << error_msg;
291 
292   EXPECT_EQ(stat.cpu_time_ms, 0);
293   EXPECT_EQ(stat.wall_time_ms, 0);
294 }
295 
TEST_P(ExecUtilsTest,ExecStatFailed)296 TEST_P(ExecUtilsTest, ExecStatFailed) {
297   std::vector<std::string> command = SleepCommand(5);
298 
299   std::string error_msg;
300   ProcessStat stat;
301 
302   EXPECT_CALL(*exec_utils_, GetProcStat(_))
303       .WillOnce(Return(
304           "14963 (a) b) Z 6067 14963 1 0 -1 4228108 105 0 0 0 94 5 0 0 39 19 1 0 162034388 0 0 "
305           "18446744073709551615 0 0 0 0 0 0 20999 0 0 1 0 0 17 71 0 0 0 0 0 0 0 0 0 0 0 0 9"));
306   EXPECT_CALL(*exec_utils_, DoGetUptimeMs()).WillOnce(Return(1620344887ll));
307   EXPECT_CALL(*exec_utils_, GetTicksPerSec()).WillOnce(Return(100));
308 
309   // This will always time out.
310   ASSERT_EQ(exec_utils_
311                 ->ExecAndReturnResult(command,
312                                       /*timeout_sec=*/1,
313                                       ExecCallbacks(),
314                                       /*new_process_group=*/false,
315                                       &stat,
316                                       &error_msg)
317                 .status,
318             ExecResult::kTimedOut);
319 
320   EXPECT_EQ(stat.cpu_time_ms, 990);
321   EXPECT_EQ(stat.wall_time_ms, 1007);
322 }
323 
TEST_P(ExecUtilsTest,ExecCallbacks)324 TEST_P(ExecUtilsTest, ExecCallbacks) {
325   MockFunction<void(pid_t)> on_start;
326   MockFunction<void(pid_t)> on_end;
327 
328   {
329     InSequence s;
330     EXPECT_CALL(on_start, Call(AllOf(Gt(0), Ne(getpid()))));
331     EXPECT_CALL(on_end, Call(AllOf(Gt(0), Ne(getpid()))));
332   }
333 
334   std::vector<std::string> command;
335   command.push_back(GetBin("id"));
336 
337   std::string error_msg;
338   exec_utils_->ExecAndReturnResult(command,
339                                    /*timeout_sec=*/-1,
340                                    ExecCallbacks{
341                                        .on_start = on_start.AsStdFunction(),
342                                        .on_end = on_end.AsStdFunction(),
343                                    },
344                                    /*new_process_group=*/false,
345                                    /*stat=*/nullptr,
346                                    &error_msg);
347 }
348 
TEST_P(ExecUtilsTest,ExecNewProcessGroupTrue)349 TEST_P(ExecUtilsTest, ExecNewProcessGroupTrue) {
350   auto on_end = [](pid_t pid) {
351     pid_t pgid = getpgid(pid);
352     ASSERT_GE(pgid, 0) << strerror(errno);
353     ASSERT_EQ(pgid, pid);
354   };
355 
356   std::vector<std::string> command;
357   command.push_back(GetBin("id"));
358 
359   std::string error_msg;
360   exec_utils_->ExecAndReturnResult(command,
361                                    /*timeout_sec=*/-1,
362                                    ExecCallbacks{
363                                        .on_end = on_end,
364                                    },
365                                    /*new_process_group=*/true,
366                                    /*stat=*/nullptr,
367                                    &error_msg);
368 }
369 
TEST_P(ExecUtilsTest,ExecNewProcessGroupFalse)370 TEST_P(ExecUtilsTest, ExecNewProcessGroupFalse) {
371   auto on_end = [](pid_t pid) {
372     pid_t pgid = getpgid(pid);
373     ASSERT_GE(pgid, 0) << strerror(errno);
374     pid_t parent_pgid = getpgid(0);
375     ASSERT_GE(parent_pgid, 0) << strerror(errno);
376     ASSERT_EQ(pgid, parent_pgid);
377   };
378 
379   std::vector<std::string> command;
380   command.push_back(GetBin("id"));
381 
382   std::string error_msg;
383   exec_utils_->ExecAndReturnResult(command,
384                                    /*timeout_sec=*/-1,
385                                    ExecCallbacks{
386                                        .on_end = on_end,
387                                    },
388                                    /*new_process_group=*/false,
389                                    /*stat=*/nullptr,
390                                    &error_msg);
391 }
392 
393 INSTANTIATE_TEST_SUITE_P(AlwaysOrNeverFallback, ExecUtilsTest, testing::Values(true, false));
394 
395 }  // namespace art
396