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/signal_fd.h"
17
18 #include <signal.h>
19 #include <sys/signalfd.h>
20
21 #include <absl/status/status.h>
22 #include <absl/status/statusor.h>
23 #include <absl/strings/str_cat.h>
24
25 #include "host/commands/process_sandboxer/unique_fd.h"
26
27 namespace cuttlefish::process_sandboxer {
28
SignalFd(UniqueFd fd)29 SignalFd::SignalFd(UniqueFd fd) : fd_(std::move(fd)) {}
30
AllExceptSigChld()31 absl::StatusOr<SignalFd> SignalFd::AllExceptSigChld() {
32 sigset_t mask;
33 if (sigfillset(&mask) < 0) {
34 return absl::ErrnoToStatus(errno, "sigfillset failed");
35 }
36 // TODO(schuffelen): Explore interaction between catching SIGCHLD and sandbox2
37 if (sigdelset(&mask, SIGCHLD) < 0) {
38 return absl::ErrnoToStatus(errno, "sigdelset failed");
39 }
40 if (sigprocmask(SIG_SETMASK, &mask, NULL) < 0) {
41 return absl::ErrnoToStatus(errno, "sigprocmask failed");
42 }
43
44 UniqueFd fd(signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK));
45 if (fd.Get() < 0) {
46 return absl::ErrnoToStatus(errno, "signalfd failed");
47 }
48 return SignalFd(std::move(fd));
49 }
50
ReadSignal()51 absl::StatusOr<signalfd_siginfo> SignalFd::ReadSignal() {
52 signalfd_siginfo info;
53 auto read_res = read(fd_.Get(), &info, sizeof(info));
54 if (read_res < 0) {
55 return absl::ErrnoToStatus(errno, "`read(signal_fd_, ...)` failed");
56 } else if (read_res == 0) {
57 return absl::InternalError("read(signal_fd_, ...) returned EOF");
58 } else if (read_res != (ssize_t)sizeof(info)) {
59 std::string err = absl::StrCat("read(signal_fd_, ...) gave '", read_res);
60 return absl::InternalError(err);
61 }
62 return info;
63 }
64
Fd() const65 int SignalFd::Fd() const { return fd_.Get(); }
66
67 } // namespace cuttlefish::process_sandboxer
68