xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/testcases/namespace.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 // Checks various things related to namespaces, depending on the first argument:
16 // ./binary 0 <file1> <file2> ... <fileN>:
17 //    Make sure all provided files exist and are RO, return 0 on OK.
18 //    Returns the index of the first non-existing file on failure.
19 // ./binary 1 <file1> <file2> ... <fileN>:
20 //    Make sure all provided files exist and are RW, return 0 on OK.
21 //    Returns the index of the first non-existing file on failure.
22 // ./binary 2
23 //    Make sure that we run in a PID namespace (this implies getpid() == 1)
24 //    Returns 0 on OK.
25 // ./binary 3 <uid> <gid>
26 //    Make sure getuid()/getgid() returns the provided uid/gid (User namespace).
27 //    Returns 0 on OK.
28 // ./binary 4 <file1> <file2> ... <fileN>:
29 //    Create provided files, return 0 on OK.
30 //    Returns the index of the first non-creatable file on failure.
31 #include <fcntl.h>
32 #include <ifaddrs.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 
36 #include <cstdlib>
37 #include <string>
38 #include <vector>
39 
40 #include "absl/container/flat_hash_set.h"
41 #include "absl/log/check.h"
42 #include "absl/strings/str_cat.h"
43 #include "sandboxed_api/sandbox2/comms.h"
44 #include "sandboxed_api/util/fileops.h"
45 #include "sandboxed_api/util/path.h"
46 
47 namespace {
48 
49 using sapi::file::JoinPath;
50 using sapi::file_util::fileops::ListDirectoryEntries;
51 
IsDirectory(const std::string & path)52 bool IsDirectory(const std::string& path) {
53   struct stat statbuf;
54   PCHECK(lstat(path.c_str(), &statbuf) == 0) << "Failed to stat " << path;
55   return statbuf.st_mode & S_IFDIR;
56 }
57 
ListDirectoriesRecursively(const std::string & path,std::vector<std::string> & files)58 void ListDirectoriesRecursively(const std::string& path,
59                                 std::vector<std::string>& files) {
60   std::string error;
61   std::vector<std::string> entries;
62   CHECK(ListDirectoryEntries(path, &entries, &error)) << error;
63   for (const std::string& entry : entries) {
64     std::string new_path = JoinPath(path, entry);
65     // Don't descent into /sys or /proc, just mark their existence
66     if (new_path == "/sys" || new_path == "/proc") {
67       files.push_back(new_path);
68       continue;
69     }
70     if (IsDirectory(new_path)) {
71       ListDirectoriesRecursively(new_path, files);
72     } else {
73       files.push_back(new_path);
74     }
75   }
76 }
77 
78 }  // namespace
79 
main(int argc,char * argv[])80 int main(int argc, char* argv[]) {
81   if (argc < 2) {
82     return 0;
83   }
84 
85   int mode = atoi(argv[1]);  // NOLINT(runtime/deprecated_fn)
86   std::vector<std::string> result;
87 
88   sandbox2::Comms comms(sandbox2::Comms::kDefaultConnection);
89 
90   switch (mode) {
91     case 0:
92       // Make sure file exist
93       for (int i = 2; i < argc; i++) {
94         if (access(argv[i], R_OK) == 0) {
95           result.push_back(argv[i]);
96         }
97       }
98       break;
99 
100     case 1:
101       for (int i = 2; i < argc; i++) {
102         if (access(argv[i], W_OK) == 0) {
103           result.push_back(argv[i]);
104         }
105       }
106       break;
107 
108     case 2:
109       result.push_back(absl::StrCat(getpid()));
110       break;
111 
112     case 3:
113       result.push_back(absl::StrCat(getuid()));
114       result.push_back(absl::StrCat(getgid()));
115       break;
116 
117     case 4:
118       for (int i = 2; i < argc; ++i) {
119         if (open(argv[i], O_CREAT | O_WRONLY, 0644) != -1) {
120           result.push_back(argv[i]);
121         }
122       }
123       break;
124 
125     case 5: {
126       absl::flat_hash_set<std::string> ifnames;
127       struct ifaddrs* addrs;
128       if (getifaddrs(&addrs)) {
129         return -1;
130       }
131       for (struct ifaddrs* cur = addrs; cur; cur = cur->ifa_next) {
132         ifnames.insert(cur->ifa_name);
133       }
134       result.insert(result.end(), ifnames.begin(), ifnames.end());
135       freeifaddrs(addrs);
136       break;
137     }
138 
139     case 6:
140       ListDirectoriesRecursively(argv[2], result);
141       break;
142     case 7: {
143       char hostname[1000];
144       if (gethostname(hostname, sizeof(hostname)) == -1) {
145         return -1;
146       }
147       result.push_back(hostname);
148       break;
149     }
150 
151     default:
152       return 1;
153   }
154 
155   CHECK(comms.SendUint64(result.size()));
156   for (const std::string& entry : result) {
157     CHECK(comms.SendString(entry));
158   }
159   return 0;
160 }
161