xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/util_test.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "sandboxed_api/sandbox2/util.h"
16 
17 #include <sched.h>
18 #include <sys/mman.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 
22 #include <cstdint>
23 #include <cstdlib>
24 #include <cstring>
25 #include <string>
26 #include <vector>
27 
28 #include "gmock/gmock.h"
29 #include "gtest/gtest.h"
30 #include "absl/cleanup/cleanup.h"
31 #include "absl/status/statusor.h"
32 #include "absl/strings/str_cat.h"
33 #include "absl/strings/string_view.h"
34 #include "sandboxed_api/util/status_matchers.h"
35 
36 namespace sandbox2::util {
37 namespace {
38 
39 using ::sapi::IsOk;
40 using ::testing::ElementsAre;
41 using ::testing::Eq;
42 using ::testing::Gt;
43 using ::testing::IsEmpty;
44 using ::testing::IsTrue;
45 using ::testing::Ne;
46 using ::testing::Not;
47 using ::testing::StrEq;
48 
49 constexpr absl::string_view kTestString = "This is a test string";
50 
TEST(UtilTest,TestCreateMemFd)51 TEST(UtilTest, TestCreateMemFd) {
52   int fd = 0;
53   ASSERT_THAT(CreateMemFd(&fd), IsTrue());
54   EXPECT_THAT(fd, Gt(1));
55   close(fd);
56 }
57 
TEST(CharPtrArrayTest,FromStringVector)58 TEST(CharPtrArrayTest, FromStringVector) {
59   std::vector<std::string> strings = {"a", "b", "c"};
60   CharPtrArray array = CharPtrArray::FromStringVector(strings);
61   EXPECT_THAT(array.ToStringVector(), Eq(strings));
62   EXPECT_THAT(array.array(),
63               ElementsAre(StrEq("a"), StrEq("b"), StrEq("c"), nullptr));
64   EXPECT_THAT(array.data(), Eq(array.array().data()));
65 }
66 
TEST(CharPtrArrayTest,FromCharPtrArray)67 TEST(CharPtrArrayTest, FromCharPtrArray) {
68   std::vector<std::string> strings = {"a", "b", "c"};
69   std::vector<char*> string_arr;
70   for (std::string& s : strings) {
71     string_arr.push_back(s.data());
72   }
73   string_arr.push_back(nullptr);
74   CharPtrArray array(string_arr.data());
75   EXPECT_THAT(array.ToStringVector(), Eq(strings));
76   EXPECT_THAT(array.array(),
77               ElementsAre(StrEq("a"), StrEq("b"), StrEq("c"), nullptr));
78   EXPECT_THAT(array.data(), Eq(array.array().data()));
79 }
80 
TEST(GetProcStatusLineTest,Pid)81 TEST(GetProcStatusLineTest, Pid) {
82   std::string line = GetProcStatusLine(getpid(), "Pid");
83   EXPECT_THAT(line, Eq(absl::StrCat(getpid())));
84 }
85 
TEST(GetProcStatusLineTest,NonExisting)86 TEST(GetProcStatusLineTest, NonExisting) {
87   std::string line =
88       GetProcStatusLine(getpid(), "__N_o_n_ExistingStatusSetting");
89   EXPECT_THAT(line, IsEmpty());
90 }
91 
TEST(ForkWithFlagsTest,DoesForkNormally)92 TEST(ForkWithFlagsTest, DoesForkNormally) {
93   int pfds[2];
94   ASSERT_THAT(pipe(pfds), Eq(0));
95   pid_t child = ForkWithFlags(SIGCHLD);
96   ASSERT_THAT(child, Ne(-1));
97   if (child == 0) {
98     char c = 'a';
99     if (!write(pfds[1], &c, 1)) {
100       exit(EXIT_FAILURE);
101     }
102     exit(EXIT_SUCCESS);
103   }
104   close(pfds[1]);
105   char c = ' ';
106   EXPECT_THAT(read(pfds[0], &c, 1), Eq(1));
107   close(pfds[0]);
108   EXPECT_THAT(c, Eq('a'));
109   int status;
110   ASSERT_THAT(TEMP_FAILURE_RETRY(waitpid(child, &status, 0)), Eq(child));
111   EXPECT_TRUE(WIFEXITED(status));
112   EXPECT_THAT(WEXITSTATUS(status), Eq(0));
113 }
114 
TEST(ForkWithFlagsTest,UnsupportedFlag)115 TEST(ForkWithFlagsTest, UnsupportedFlag) {
116   EXPECT_THAT(ForkWithFlags(CLONE_CHILD_CLEARTID), Eq(-1));
117 }
118 
TEST(ReadCPathFromPidSplitPageTest,Normal)119 TEST(ReadCPathFromPidSplitPageTest, Normal) {
120   std::string test_str(kTestString);
121   absl::StatusOr<std::string> read =
122       ReadCPathFromPid(getpid(), reinterpret_cast<uintptr_t>(test_str.data()));
123   ASSERT_THAT(read, IsOk());
124   EXPECT_THAT(*read, Eq(kTestString));
125 }
126 
TEST(ReadCPathFromPidSplitPageTest,Overlong)127 TEST(ReadCPathFromPidSplitPageTest, Overlong) {
128   std::string test_str(PATH_MAX + 1, 'a');
129   absl::StatusOr<std::string> read =
130       ReadCPathFromPid(getpid(), reinterpret_cast<uintptr_t>(test_str.data()));
131   EXPECT_THAT(read, Not(IsOk()));
132 }
133 
TEST(ReadCPathFromPidSplitPageTest,SplitPage)134 TEST(ReadCPathFromPidSplitPageTest, SplitPage) {
135   const uintptr_t page_size = getpagesize();
136   char* res = reinterpret_cast<char*>(mmap(nullptr, 2 * page_size,
137                                            PROT_READ | PROT_WRITE,
138                                            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0));
139   ASSERT_THAT(res, Ne(MAP_FAILED));
140   absl::Cleanup cleanup = [res, page_size]() {
141     ASSERT_THAT(munmap(res, 2 * page_size), Eq(0));
142   };
143   char* str = &res[page_size - kTestString.size() / 2];
144   memcpy(str, kTestString.data(), kTestString.size());
145   absl::StatusOr<std::string> read =
146       ReadCPathFromPid(getpid(), reinterpret_cast<uintptr_t>(str));
147   ASSERT_THAT(read, IsOk());
148   EXPECT_THAT(*read, Eq(kTestString));
149 }
150 
TEST(ReadCPathFromPidSplitPageTest,NearUnreadableMemory)151 TEST(ReadCPathFromPidSplitPageTest, NearUnreadableMemory) {
152   const uintptr_t page_size = getpagesize();
153   char* res = reinterpret_cast<char*>(mmap(nullptr, 2 * page_size,
154                                            PROT_READ | PROT_WRITE,
155                                            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0));
156   ASSERT_THAT(res, Ne(MAP_FAILED));
157   absl::Cleanup cleanup = [res, page_size]() {
158     ASSERT_THAT(munmap(res, 2 * page_size), Eq(0));
159   };
160   ASSERT_THAT(mprotect(&res[page_size], page_size, PROT_NONE), Eq(0));
161   char* str = &res[page_size - kTestString.size() - 1];
162   memcpy(str, kTestString.data(), kTestString.size());
163   absl::StatusOr<std::string> read =
164       ReadCPathFromPid(getpid(), reinterpret_cast<uintptr_t>(str));
165   ASSERT_THAT(read, IsOk());
166   EXPECT_THAT(*read, Eq(kTestString));
167 }
168 
169 }  // namespace
170 }  // namespace sandbox2::util
171