xref: /aosp_15_r20/external/sandboxed-api/oss-internship-2020/libarchive/examples/sandbox.h (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1*ec63e07aSXin Li // Copyright 2020 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 #ifndef SAPI_LIBARCHIVE_EXAMPLES_SANDBOX_H
16*ec63e07aSXin Li #define SAPI_LIBARCHIVE_EXAMPLES_SANDBOX_H
17*ec63e07aSXin Li 
18*ec63e07aSXin Li #include <asm/unistd_64.h>
19*ec63e07aSXin Li #include <linux/fs.h>
20*ec63e07aSXin Li 
21*ec63e07aSXin Li #include "libarchive_sapi.sapi.h"  // NOLINT(build/include)
22*ec63e07aSXin Li #include "sandboxed_api/sandbox2/util/bpf_helper.h"
23*ec63e07aSXin Li #include "sandboxed_api/util/fileops.h"
24*ec63e07aSXin Li 
25*ec63e07aSXin Li // When creating an archive, we need read permissions on each of the
26*ec63e07aSXin Li // file/directory added in the archive. Also, in order to create the archive, we
27*ec63e07aSXin Li // map "/output" with the basename of the archive. This way, the program can
28*ec63e07aSXin Li // create the file without having access to anything else.
29*ec63e07aSXin Li class SapiLibarchiveSandboxCreate : public LibarchiveSandbox {
30*ec63e07aSXin Li  public:
SapiLibarchiveSandboxCreate(const std::vector<std::string> & files,absl::string_view archive_path)31*ec63e07aSXin Li   SapiLibarchiveSandboxCreate(const std::vector<std::string>& files,
32*ec63e07aSXin Li                               absl::string_view archive_path)
33*ec63e07aSXin Li       : files_(files), archive_path_(archive_path) {}
34*ec63e07aSXin Li 
35*ec63e07aSXin Li  private:
ModifyPolicy(sandbox2::PolicyBuilder *)36*ec63e07aSXin Li   std::unique_ptr<sandbox2::Policy> ModifyPolicy(
37*ec63e07aSXin Li       sandbox2::PolicyBuilder*) override {
38*ec63e07aSXin Li     sandbox2::PolicyBuilder policy =
39*ec63e07aSXin Li         sandbox2::PolicyBuilder()
40*ec63e07aSXin Li             .AddDirectoryAt(archive_path_, "/output", false)
41*ec63e07aSXin Li             .AllowRead()
42*ec63e07aSXin Li             .AllowWrite()
43*ec63e07aSXin Li             .AllowOpen()
44*ec63e07aSXin Li             .AllowSystemMalloc()
45*ec63e07aSXin Li             .AllowGetIDs()
46*ec63e07aSXin Li             .AllowSafeFcntl()
47*ec63e07aSXin Li             .AllowStat()
48*ec63e07aSXin Li             .AllowExit()
49*ec63e07aSXin Li             .AllowSyscall(__NR_futex)
50*ec63e07aSXin Li             .AllowSyscall(__NR_lseek)
51*ec63e07aSXin Li             .AllowSyscall(__NR_close)
52*ec63e07aSXin Li             .AllowSyscall(__NR_gettid)
53*ec63e07aSXin Li             .AllowSyscall(__NR_umask)
54*ec63e07aSXin Li             .AllowSyscall(__NR_utimensat)
55*ec63e07aSXin Li             .AllowUnlink()
56*ec63e07aSXin Li             .AllowMkdir()
57*ec63e07aSXin Li             .AllowSyscall(__NR_fstatfs)
58*ec63e07aSXin Li             .AllowSyscall(__NR_socket)
59*ec63e07aSXin Li             .AllowSyscall(__NR_connect)
60*ec63e07aSXin Li             .AllowSyscall(__NR_flistxattr)
61*ec63e07aSXin Li             .AllowSyscall(__NR_recvmsg)
62*ec63e07aSXin Li             .AllowSyscall(__NR_getdents64)
63*ec63e07aSXin Li             // Allow ioctl only for FS_IOC_GETFLAGS.
64*ec63e07aSXin Li             .AddPolicyOnSyscall(__NR_ioctl,
65*ec63e07aSXin Li                                 {ARG(1), JEQ(FS_IOC_GETFLAGS, ALLOW)});
66*ec63e07aSXin Li 
67*ec63e07aSXin Li     // We check whether the entry is a file or a directory.
68*ec63e07aSXin Li     for (const auto& i : files_) {
69*ec63e07aSXin Li       struct stat s;
70*ec63e07aSXin Li       CHECK(stat(i.c_str(), &s) == 0) << "Could not stat " << i;
71*ec63e07aSXin Li       if (S_ISDIR(s.st_mode)) {
72*ec63e07aSXin Li         policy = policy.AddDirectory(i);
73*ec63e07aSXin Li       } else {
74*ec63e07aSXin Li         policy = policy.AddFile(i);
75*ec63e07aSXin Li       }
76*ec63e07aSXin Li     }
77*ec63e07aSXin Li 
78*ec63e07aSXin Li     return policy.BuildOrDie();
79*ec63e07aSXin Li   }
80*ec63e07aSXin Li 
81*ec63e07aSXin Li   const std::vector<std::string> files_;
82*ec63e07aSXin Li   absl::string_view archive_path_;
83*ec63e07aSXin Li };
84*ec63e07aSXin Li 
85*ec63e07aSXin Li // When an archive is extracted, the generated files/directories will be placed
86*ec63e07aSXin Li // relative to the current working directory. In order to add permissions to
87*ec63e07aSXin Li // this we create a temporary directory at every extraction. Then, we change the
88*ec63e07aSXin Li // directory of the sandboxed process to that directory and map it to the
89*ec63e07aSXin Li // current "real" working directory. This way the contents of the archived will
90*ec63e07aSXin Li // pe placed correctly without offering additional permission.
91*ec63e07aSXin Li class SapiLibarchiveSandboxExtract : public LibarchiveSandbox {
92*ec63e07aSXin Li  public:
SapiLibarchiveSandboxExtract(absl::string_view archive_path,int do_extract,absl::string_view tmp_dir)93*ec63e07aSXin Li   SapiLibarchiveSandboxExtract(absl::string_view archive_path, int do_extract,
94*ec63e07aSXin Li                                absl::string_view tmp_dir)
95*ec63e07aSXin Li       : archive_path_(archive_path),
96*ec63e07aSXin Li         do_extract_(do_extract),
97*ec63e07aSXin Li         tmp_dir_(tmp_dir) {}
98*ec63e07aSXin Li 
99*ec63e07aSXin Li  private:
ModifyExecutor(sandbox2::Executor * executor)100*ec63e07aSXin Li   void ModifyExecutor(sandbox2::Executor* executor) override {
101*ec63e07aSXin Li     // If the user only wants to list the entries in the archive, we do
102*ec63e07aSXin Li     // not need to worry about changing directories;
103*ec63e07aSXin Li     if (do_extract_) {
104*ec63e07aSXin Li       executor->set_cwd(std::string(tmp_dir_));
105*ec63e07aSXin Li     }
106*ec63e07aSXin Li   }
107*ec63e07aSXin Li 
ModifyPolicy(sandbox2::PolicyBuilder *)108*ec63e07aSXin Li   std::unique_ptr<sandbox2::Policy> ModifyPolicy(
109*ec63e07aSXin Li       sandbox2::PolicyBuilder*) override {
110*ec63e07aSXin Li     sandbox2::PolicyBuilder policy = sandbox2::PolicyBuilder()
111*ec63e07aSXin Li                                          .AllowRead()
112*ec63e07aSXin Li                                          .AllowWrite()
113*ec63e07aSXin Li                                          .AllowOpen()
114*ec63e07aSXin Li                                          .AllowSystemMalloc()
115*ec63e07aSXin Li                                          .AllowGetIDs()
116*ec63e07aSXin Li                                          .AllowSafeFcntl()
117*ec63e07aSXin Li                                          .AllowStat()
118*ec63e07aSXin Li                                          .AllowExit()
119*ec63e07aSXin Li                                          .AllowSyscall(__NR_futex)
120*ec63e07aSXin Li                                          .AllowSyscall(__NR_lseek)
121*ec63e07aSXin Li                                          .AllowSyscall(__NR_close)
122*ec63e07aSXin Li                                          .AllowSyscall(__NR_gettid)
123*ec63e07aSXin Li                                          .AllowSyscall(__NR_umask)
124*ec63e07aSXin Li                                          .AllowSyscall(__NR_utimensat)
125*ec63e07aSXin Li                                          .AllowUnlink()
126*ec63e07aSXin Li                                          .AllowMkdir()
127*ec63e07aSXin Li                                          .AddFile(archive_path_);
128*ec63e07aSXin Li 
129*ec63e07aSXin Li     if (do_extract_) {
130*ec63e07aSXin Li       // Get the real cwd and map it to the temporary directory in which
131*ec63e07aSXin Li       // the sandboxed process takes place().
132*ec63e07aSXin Li       std::string cwd = sandbox2::file_util::fileops::GetCWD();
133*ec63e07aSXin Li       policy = policy.AddDirectoryAt(cwd, tmp_dir_, false);
134*ec63e07aSXin Li     }
135*ec63e07aSXin Li     return policy.BuildOrDie();
136*ec63e07aSXin Li   }
137*ec63e07aSXin Li 
138*ec63e07aSXin Li   absl::string_view archive_path_;
139*ec63e07aSXin Li   absl::string_view tmp_dir_;
140*ec63e07aSXin Li   const int do_extract_;
141*ec63e07aSXin Li };
142*ec63e07aSXin Li 
143*ec63e07aSXin Li #endif  // SAPI_LIBARCHIVE_EXAMPLES_SANDBOX_H
144