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