• 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/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