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 <cstring>
22 #include <string>
23
24 #include <absl/status/statusor.h>
25
26 #include "host/commands/process_sandboxer/unique_fd.h"
27
28 namespace cuttlefish::process_sandboxer {
29
CredentialedUnixServer(UniqueFd fd)30 CredentialedUnixServer::CredentialedUnixServer(UniqueFd fd)
31 : fd_(std::move(fd)) {}
32
Open(const std::string & path)33 absl::StatusOr<CredentialedUnixServer> CredentialedUnixServer::Open(
34 const std::string& path) {
35 UniqueFd fd(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
36
37 if (fd.Get() < 0) {
38 return absl::ErrnoToStatus(errno, "`socket` failed");
39 }
40 sockaddr_un socket_name = {
41 .sun_family = AF_UNIX,
42 };
43 std::snprintf(socket_name.sun_path, sizeof(socket_name.sun_path), "%s",
44 path.c_str());
45 sockaddr* sockname_ptr = reinterpret_cast<sockaddr*>(&socket_name);
46 if (bind(fd.Get(), sockname_ptr, sizeof(socket_name)) < 0) {
47 return absl::ErrnoToStatus(errno, "`bind` failed");
48 }
49
50 int enable_passcred = 1;
51 if (setsockopt(fd.Get(), SOL_SOCKET, SO_PASSCRED, &enable_passcred,
52 sizeof(enable_passcred)) < 0) {
53 static constexpr char kErr[] = "`setsockopt(..., SO_PASSCRED, ...)` failed";
54 return absl::ErrnoToStatus(errno, kErr);
55 }
56
57 if (listen(fd.Get(), 10) < 0) {
58 return absl::ErrnoToStatus(errno, "`listen` failed");
59 }
60
61 return CredentialedUnixServer(std::move(fd));
62 }
63
AcceptClient()64 absl::StatusOr<UniqueFd> CredentialedUnixServer::AcceptClient() {
65 UniqueFd client(accept4(fd_.Get(), nullptr, nullptr, SOCK_CLOEXEC));
66 if (client.Get() < 0) {
67 return absl::ErrnoToStatus(errno, "`accept` failed");
68 }
69 return client;
70 }
71
Fd() const72 int CredentialedUnixServer::Fd() const { return fd_.Get(); }
73
74 } // namespace cuttlefish::process_sandboxer
75