• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "host/commands/process_sandboxer/credentialed_unix_server.h"
17 
18 #include <sys/socket.h>
19 #include <sys/un.h>
20 
21 #include <cerrno>
22 #include <cstdio>
23 #include <string>
24 #include <utility>
25 
26 #include <absl/status/status.h>
27 #include <absl/status/statusor.h>
28 #include <sandboxed_api/util/fileops.h>
29 
30 namespace cuttlefish::process_sandboxer {
31 
32 using sapi::file_util::fileops::FDCloser;
33 
CredentialedUnixServer(FDCloser fd)34 CredentialedUnixServer::CredentialedUnixServer(FDCloser fd)
35     : fd_(std::move(fd)) {}
36 
Open(const std::string & path)37 absl::StatusOr<CredentialedUnixServer> CredentialedUnixServer::Open(
38     const std::string& path) {
39   FDCloser fd(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
40 
41   if (fd.get() < 0) {
42     return absl::ErrnoToStatus(errno, "`socket` failed");
43   }
44   sockaddr_un socket_name = {
45       .sun_family = AF_UNIX,
46   };
47   std::snprintf(socket_name.sun_path, sizeof(socket_name.sun_path), "%s",
48                 path.c_str());
49   sockaddr* sockname_ptr = reinterpret_cast<sockaddr*>(&socket_name);
50   if (bind(fd.get(), sockname_ptr, sizeof(socket_name)) < 0) {
51     return absl::ErrnoToStatus(errno, "`bind` failed");
52   }
53 
54   int enable_passcred = 1;
55   if (setsockopt(fd.get(), SOL_SOCKET, SO_PASSCRED, &enable_passcred,
56                  sizeof(enable_passcred)) < 0) {
57     static constexpr char kErr[] = "`setsockopt(..., SO_PASSCRED, ...)` failed";
58     return absl::ErrnoToStatus(errno, kErr);
59   }
60 
61   if (listen(fd.get(), 10) < 0) {
62     return absl::ErrnoToStatus(errno, "`listen` failed");
63   }
64 
65   return CredentialedUnixServer(std::move(fd));
66 }
67 
AcceptClient()68 absl::StatusOr<FDCloser> CredentialedUnixServer::AcceptClient() {
69   FDCloser client(accept4(fd_.get(), nullptr, nullptr, SOCK_CLOEXEC));
70   if (client.get() < 0) {
71     return absl::ErrnoToStatus(errno, "`accept` failed");
72   }
73   return client;
74 }
75 
Fd() const76 int CredentialedUnixServer::Fd() const { return fd_.get(); }
77 
78 }  // namespace cuttlefish::process_sandboxer
79