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 <sys/socket.h>
18 #include <sys/un.h>
19 
20 #include <iostream>
21 
22 #include <absl/status/status.h>
23 #include <absl/status/statusor.h>
24 #include <absl/strings/numbers.h>
25 
26 #include "proxy_common.h"
27 
28 namespace cuttlefish::process_sandboxer {
29 namespace {
30 
31 template <typename T>
UnwrapStatusOr(absl::StatusOr<T> status_or)32 T UnwrapStatusOr(absl::StatusOr<T> status_or) {
33   if (!status_or.ok()) {
34     std::cerr << status_or.status().ToString() << '\n';
35     abort();
36   }
37   return std::move(*status_or);
38 }
39 
40 template <typename T>
AtoiOr(std::string_view str)41 absl::StatusOr<T> AtoiOr(std::string_view str) {
42   T out;
43   if (!absl::SimpleAtoi(str, &out)) {
44     return absl::InvalidArgumentError("Not an integer");
45   }
46   return out;
47 }
48 
OpenSandboxManagerSocket()49 absl::StatusOr<int> OpenSandboxManagerSocket() {
50   int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
51   if (sock < 0) {
52     return absl::ErrnoToStatus(errno, "`socket` failed");
53   }
54 
55   sockaddr_un addr = sockaddr_un{
56       .sun_family = AF_UNIX,
57   };
58   size_t size = std::min(sizeof(addr.sun_path), kManagerSocketPath.size());
59   strncpy(addr.sun_path, kManagerSocketPath.data(), size);
60 
61   if (connect(sock, (sockaddr*)&addr, sizeof(addr)) < 0) {
62     return absl::ErrnoToStatus(errno, "`connect` failed");
63   }
64 
65   return sock;
66 }
67 
ProcessSandboxerMain()68 int ProcessSandboxerMain() {
69   int sock = UnwrapStatusOr(OpenSandboxManagerSocket());
70   UnwrapStatusOr(SendStringMsg(sock, kHandshakeBegin));
71   UnwrapStatusOr(SendStringMsg(sock, std::to_string(sock)));
72   Message pingback = UnwrapStatusOr(Message::RecvFrom(sock));
73   UnwrapStatusOr(SendStringMsg(sock, pingback.Data()));
74 
75   // If signals other than SIGKILL become relevant, this should `poll` to check
76   // both `sock` and a `signalfd`.
77   while (true) {
78     Message command = UnwrapStatusOr(Message::RecvFrom(sock));
79     if (command.Data() == "exit") {
80       Message message = UnwrapStatusOr(Message::RecvFrom(sock));
81       return UnwrapStatusOr(AtoiOr<int>(message.Data()));
82     }
83     std::cerr << "Unexpected message: '" << command.Data() << "'\n";
84     return 1;
85   }
86 
87   return 0;
88 }
89 
90 }  // namespace
91 }  // namespace cuttlefish::process_sandboxer
92 
main()93 int main() { return cuttlefish::process_sandboxer::ProcessSandboxerMain(); }
94