1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <sys/socket.h>
19 #include <sys/un.h>
20
21 #include <algorithm>
22 #include <cerrno>
23 #include <cstddef>
24 #include <cstring>
25 #include <iostream>
26 #include <string>
27 #include <string_view>
28
29 #include <absl/status/status.h>
30 #include <absl/status/statusor.h>
31 #include <absl/strings/numbers.h>
32
33 #include "host/commands/process_sandboxer/proxy_common.h"
34
35 namespace cuttlefish::process_sandboxer {
36 namespace {
37
38 template <typename T>
UnwrapStatusOr(absl::StatusOr<T> status_or)39 T UnwrapStatusOr(absl::StatusOr<T> status_or) {
40 if (!status_or.ok()) {
41 std::cerr << status_or.status().ToString() << '\n';
42 abort();
43 }
44 return std::move(*status_or);
45 }
46
47 template <typename T>
AtoiOr(std::string_view str)48 absl::StatusOr<T> AtoiOr(std::string_view str) {
49 T out;
50 if (!absl::SimpleAtoi(str, &out)) {
51 return absl::InvalidArgumentError("Not an integer");
52 }
53 return out;
54 }
55
OpenSandboxManagerSocket()56 absl::StatusOr<int> OpenSandboxManagerSocket() {
57 int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
58 if (sock < 0) {
59 return absl::ErrnoToStatus(errno, "`socket` failed");
60 }
61
62 sockaddr_un addr = sockaddr_un{
63 .sun_family = AF_UNIX,
64 };
65 size_t size = std::min(sizeof(addr.sun_path), kManagerSocketPath.size());
66 strncpy(addr.sun_path, kManagerSocketPath.data(), size);
67
68 if (connect(sock, (sockaddr*)&addr, sizeof(addr)) < 0) {
69 return absl::ErrnoToStatus(errno, "`connect` failed");
70 }
71
72 return sock;
73 }
74
ProcessSandboxerMain()75 int ProcessSandboxerMain() {
76 int sock = UnwrapStatusOr(OpenSandboxManagerSocket());
77 UnwrapStatusOr(SendStringMsg(sock, kHandshakeBegin));
78 UnwrapStatusOr(SendStringMsg(sock, std::to_string(sock)));
79 Message pingback = UnwrapStatusOr(Message::RecvFrom(sock));
80 UnwrapStatusOr(SendStringMsg(sock, pingback.Data()));
81
82 // If signals other than SIGKILL become relevant, this should `poll` to check
83 // both `sock` and a `signalfd`.
84 while (true) {
85 Message command = UnwrapStatusOr(Message::RecvFrom(sock));
86 if (command.Data() == "exit") {
87 Message message = UnwrapStatusOr(Message::RecvFrom(sock));
88 return UnwrapStatusOr(AtoiOr<int>(message.Data()));
89 }
90 std::cerr << "Unexpected message: '" << command.Data() << "'\n";
91 return 1;
92 }
93
94 return 0;
95 }
96
97 } // namespace
98 } // namespace cuttlefish::process_sandboxer
99
main()100 int main() { return cuttlefish::process_sandboxer::ProcessSandboxerMain(); }
101