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