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