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 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include <cerrno>
24 #include <cstddef>
25 #include <string>
26 #include <utility>
27
28 #include <absl/status/status.h>
29 #include <absl/status/statusor.h>
30 #include <absl/strings/str_cat.h>
31 #include <sandboxed_api/util/fileops.h>
32
33 namespace cuttlefish::process_sandboxer {
34
35 using sapi::file_util::fileops::FDCloser;
36
SignalFd(FDCloser fd)37 SignalFd::SignalFd(FDCloser fd) : fd_(std::move(fd)) {}
38
AllExceptSigChld()39 absl::StatusOr<SignalFd> SignalFd::AllExceptSigChld() {
40 sigset_t mask;
41 if (sigfillset(&mask) < 0) {
42 return absl::ErrnoToStatus(errno, "sigfillset failed");
43 }
44 // TODO(schuffelen): Explore interaction between catching SIGCHLD and sandbox2
45 if (sigdelset(&mask, SIGCHLD) < 0) {
46 return absl::ErrnoToStatus(errno, "sigdelset failed");
47 }
48 if (sigprocmask(SIG_SETMASK, &mask, NULL) < 0) {
49 return absl::ErrnoToStatus(errno, "sigprocmask failed");
50 }
51
52 FDCloser fd(signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK));
53 if (fd.get() < 0) {
54 return absl::ErrnoToStatus(errno, "signalfd failed");
55 }
56 return SignalFd(std::move(fd));
57 }
58
ReadSignal()59 absl::StatusOr<signalfd_siginfo> SignalFd::ReadSignal() {
60 signalfd_siginfo info;
61 auto read_res = read(fd_.get(), &info, sizeof(info));
62 if (read_res < 0) {
63 return absl::ErrnoToStatus(errno, "`read(signal_fd_, ...)` failed");
64 } else if (read_res == 0) {
65 return absl::InternalError("read(signal_fd_, ...) returned EOF");
66 } else if (read_res != (ssize_t)sizeof(info)) {
67 std::string err = absl::StrCat("read(signal_fd_, ...) gave '", read_res);
68 return absl::InternalError(err);
69 }
70 return info;
71 }
72
Fd() const73 int SignalFd::Fd() const { return fd_.get(); }
74
75 } // namespace cuttlefish::process_sandboxer
76