2020-01-17 21:05:03 +08:00
|
|
|
// Copyright 2019 Google LLC
|
2019-03-19 00:21:48 +08:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
2022-01-28 17:38:27 +08:00
|
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
2019-03-19 00:21:48 +08:00
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
#include "sandboxed_api/sandbox2/forkserver.h"
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <syscall.h>
|
|
|
|
#include <unistd.h>
|
2021-01-14 01:25:25 +08:00
|
|
|
|
2019-03-19 00:21:48 +08:00
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
#include "gtest/gtest.h"
|
2022-10-20 21:48:06 +08:00
|
|
|
#include "absl/log/check.h"
|
2019-03-19 00:21:48 +08:00
|
|
|
#include "absl/strings/str_cat.h"
|
|
|
|
#include "sandboxed_api/sandbox2/forkserver.pb.h"
|
|
|
|
#include "sandboxed_api/sandbox2/global_forkclient.h"
|
|
|
|
#include "sandboxed_api/sandbox2/ipc.h"
|
2021-01-14 01:25:25 +08:00
|
|
|
#include "sandboxed_api/testing.h"
|
2022-10-20 21:48:06 +08:00
|
|
|
#include "sandboxed_api/util/raw_logging.h"
|
2019-03-19 00:21:48 +08:00
|
|
|
|
|
|
|
namespace sandbox2 {
|
|
|
|
|
2021-01-14 01:25:25 +08:00
|
|
|
using ::sapi::GetTestSourcePath;
|
|
|
|
|
2019-03-19 00:21:48 +08:00
|
|
|
class IpcPeer {
|
|
|
|
public:
|
2022-10-20 21:48:06 +08:00
|
|
|
explicit IpcPeer(IPC* ipc) : ipc_(ipc) {}
|
2019-03-19 00:21:48 +08:00
|
|
|
|
|
|
|
void SetUpServerSideComms(int fd) { ipc_->SetUpServerSideComms(fd); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
IPC* ipc_;
|
|
|
|
};
|
|
|
|
|
|
|
|
int GetMinimalTestcaseFd() {
|
|
|
|
const std::string path = GetTestSourcePath("sandbox2/testcases/minimal");
|
|
|
|
return open(path.c_str(), O_RDONLY);
|
|
|
|
}
|
|
|
|
|
2023-01-19 21:44:11 +08:00
|
|
|
pid_t TestSingleRequest(Mode mode, int exec_fd) {
|
2019-03-19 00:21:48 +08:00
|
|
|
ForkRequest fork_req;
|
|
|
|
IPC ipc;
|
|
|
|
int sv[2];
|
|
|
|
// Setup IPC
|
|
|
|
PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != -1);
|
|
|
|
IpcPeer{&ipc}.SetUpServerSideComms(sv[1]);
|
|
|
|
// Setup fork_req
|
|
|
|
fork_req.set_mode(mode);
|
|
|
|
fork_req.add_args("/binary");
|
|
|
|
fork_req.add_envs("FOO=1");
|
|
|
|
|
2023-02-07 18:22:02 +08:00
|
|
|
SandboxeeProcess process =
|
|
|
|
GlobalForkClient::SendRequest(fork_req, exec_fd, sv[0]);
|
|
|
|
if (process.main_pid != -1) {
|
|
|
|
VLOG(1) << "TestSingleRequest: Waiting for pid=" << process.main_pid;
|
|
|
|
waitpid(process.main_pid, nullptr, 0);
|
2019-03-19 00:21:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
close(sv[0]);
|
2023-02-07 18:22:02 +08:00
|
|
|
return process.main_pid;
|
2019-03-19 00:21:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ForkserverTest, SimpleFork) {
|
|
|
|
// Make sure that the regular fork request works.
|
2023-01-19 21:44:11 +08:00
|
|
|
ASSERT_NE(TestSingleRequest(FORKSERVER_FORK, -1), -1);
|
2019-03-19 00:21:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ForkserverTest, SimpleForkNoZombie) {
|
|
|
|
// Make sure that we don't create zombies.
|
2023-01-19 21:44:11 +08:00
|
|
|
pid_t child = TestSingleRequest(FORKSERVER_FORK, -1);
|
2019-03-19 00:21:48 +08:00
|
|
|
ASSERT_NE(child, -1);
|
|
|
|
std::string proc = absl::StrCat("/proc/", child, "/cmdline");
|
|
|
|
|
|
|
|
// Give the kernel some time to clean up.
|
|
|
|
// Poll every 10ms up to 500 times (5s)
|
|
|
|
bool process_reaped = false;
|
|
|
|
for (int i = 0; i < 500; i++) {
|
|
|
|
if (access(proc.c_str(), F_OK) == -1) {
|
|
|
|
process_reaped = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
usleep(10 * 1000); // 10 ms
|
|
|
|
}
|
|
|
|
EXPECT_TRUE(process_reaped);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ForkserverTest, ForkExecveWorks) {
|
|
|
|
// Run a test binary through the FORK_EXECVE request.
|
|
|
|
int exec_fd = GetMinimalTestcaseFd();
|
|
|
|
PCHECK(exec_fd != -1) << "Could not open test binary";
|
2023-01-19 21:44:11 +08:00
|
|
|
ASSERT_NE(TestSingleRequest(FORKSERVER_FORK_EXECVE, exec_fd), -1);
|
2019-03-19 00:21:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ForkserverTest, ForkExecveSandboxWithoutPolicy) {
|
|
|
|
// Run a test binary through the FORKSERVER_FORK_EXECVE_SANDBOX request.
|
|
|
|
int exec_fd = GetMinimalTestcaseFd();
|
|
|
|
PCHECK(exec_fd != -1) << "Could not open test binary";
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace sandbox2
|