xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/monitor_unotify.h (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 #ifndef SANDBOXED_API_SANDBOX2_MONITOR_UNOTIFY_H_
2 #define SANDBOXED_API_SANDBOX2_MONITOR_UNOTIFY_H_
3 
4 #include <linux/seccomp.h>
5 #include <sys/sysinfo.h>
6 #include <sys/types.h>
7 
8 #include <atomic>
9 #include <cstdint>
10 #include <cstdlib>
11 #include <memory>
12 #include <thread>
13 #include <string>
14 #include <vector>
15 
16 #include "absl/log/log.h"
17 #include "absl/status/statusor.h"
18 #include "absl/synchronization/mutex.h"
19 #include "absl/synchronization/notification.h"
20 #include "absl/time/clock.h"
21 #include "absl/time/time.h"
22 #include "sandboxed_api/sandbox2/executor.h"
23 #include "sandboxed_api/sandbox2/monitor_base.h"
24 #include "sandboxed_api/sandbox2/notify.h"
25 #include "sandboxed_api/sandbox2/policy.h"
26 #include "sandboxed_api/sandbox2/result.h"
27 #include "sandboxed_api/util/fileops.h"
28 #include "sandboxed_api/util/raw_logging.h"
29 
30 namespace sandbox2 {
31 
32 #ifndef SECCOMP_IOCTL_NOTIF_RECV
33 struct seccomp_notif {
34   __u64 id;
35   __u32 pid;
36   __u32 flags;
37   struct seccomp_data data;
38 };
39 #endif
40 
41 class UnotifyMonitor : public MonitorBase {
42  public:
43   UnotifyMonitor(Executor* executor, Policy* policy, Notify* notify);
~UnotifyMonitor()44   ~UnotifyMonitor() { Join(); }
45 
Kill()46   void Kill() override {
47     external_kill_request_flag_.clear(std::memory_order_relaxed);
48     NotifyMonitor();
49   }
50 
DumpStackTrace()51   void DumpStackTrace() override {
52     dump_stack_request_flag_.clear(std::memory_order_relaxed);
53     NotifyMonitor();
54   }
55 
SetWallTimeLimit(absl::Duration limit)56   void SetWallTimeLimit(absl::Duration limit) override {
57     if (limit == absl::ZeroDuration()) {
58       VLOG(1) << "Disarming walltime timer to ";
59       deadline_millis_.store(0, std::memory_order_relaxed);
60     } else {
61       VLOG(1) << "Will set the walltime timer to " << limit;
62       absl::Time deadline = absl::Now() + limit;
63       deadline_millis_.store(absl::ToUnixMillis(deadline),
64                              std::memory_order_relaxed);
65       NotifyMonitor();
66     }
67   }
68 
69  private:
70   // Waits for events from monitored clients and signals from the main process.
71   void RunInternal() override;
72   void Join() override;
73   void Run();
74 
75   bool InitSetupUnotify();
76   bool InitSetupNotifyEventFd();
77   // Kills the main traced PID with SIGKILL.
78   // Returns false if an error occured and process could not be killed.
79   bool KillSandboxee();
80   void KillInit();
81 
82   void HandleUnotify();
83   void SetExitStatusFromStatusPipe();
84 
85   void MaybeGetStackTrace(pid_t pid, Result::StatusEnum status);
86   absl::StatusOr<std::vector<std::string>> GetStackTrace(pid_t pid);
87 
88   // Notifies monitor about a state change
89   void NotifyMonitor();
90 
91   absl::Notification setup_notification_;
92   sapi::file_util::fileops::FDCloser seccomp_notify_fd_;
93   sapi::file_util::fileops::FDCloser monitor_notify_fd_;
94   // Deadline in Unix millis
95   std::atomic<int64_t> deadline_millis_{0};
96   // False iff external kill is requested
97   std::atomic_flag external_kill_request_flag_ = ATOMIC_FLAG_INIT;
98   // False iff dump stack is requested
99   std::atomic_flag dump_stack_request_flag_ = ATOMIC_FLAG_INIT;
100 
101   // Was external kill sent to the sandboxee
102   bool external_kill_ = false;
103   // Network violation occurred and process of killing sandboxee started
104   bool network_violation_ = false;
105   // Is the sandboxee timed out
106   bool timed_out_ = false;
107 
108   // Monitor thread object.
109   std::unique_ptr<std::thread> thread_;
110 
111   // Synchronizes monitor thread deletion and notifying the monitor.
112   absl::Mutex notify_mutex_;
113 
114   size_t req_size_;
115   std::unique_ptr<seccomp_notif, decltype(std::free)*> req_{nullptr, std::free};
116 };
117 
118 }  // namespace sandbox2
119 
120 #endif  // SANDBOXED_API_SANDBOX2_MONITOR_UNOTIFY_H_
121