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