• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "sandboxed_api/sandbox2/util/deadline_manager.h"
16 
17 #include <sys/syscall.h>
18 
19 #include <csignal>
20 #include <ctime>
21 
22 #include "gtest/gtest.h"
23 #include "absl/flags/flag.h"
24 #include "absl/log/check.h"
25 #include "absl/time/clock.h"
26 #include "absl/time/time.h"
27 #include "sandboxed_api/util/thread.h"
28 
29 namespace sandbox2 {
30 namespace {
31 
TEST(DeadlineManagerTest,Basic)32 TEST(DeadlineManagerTest, Basic) {
33   DeadlineManager manager("test");
34   DeadlineRegistration registration(manager);
35   absl::Time start_time = absl::Now();
36   struct timespec ts = absl::ToTimespec(absl::Seconds(1));
37   registration.SetDeadline(start_time + absl::Milliseconds(100));
38   registration.ExecuteBlockingSyscall(
39       [&] { ASSERT_EQ(nanosleep(&ts, nullptr), -1); });
40   absl::Duration elapsed = absl::Now() - start_time;
41   EXPECT_GE(elapsed, absl::Milliseconds(100));
42   EXPECT_LE(elapsed, absl::Milliseconds(200));
43 }
44 
TEST(DeadlineManagerTest,NotifiesUntilFunctionReturns)45 TEST(DeadlineManagerTest, NotifiesUntilFunctionReturns) {
46   DeadlineManager manager("test");
47   DeadlineRegistration registration(manager);
48   absl::Time start_time = absl::Now();
49   struct timespec ts = absl::ToTimespec(absl::Seconds(1));
50   registration.SetDeadline(start_time + absl::Milliseconds(100));
51   registration.ExecuteBlockingSyscall([&] {
52     // Double so that it needs to be notified twice.
53     ASSERT_EQ(nanosleep(&ts, nullptr), -1);
54     ASSERT_EQ(nanosleep(&ts, nullptr), -1);
55   });
56   absl::Duration elapsed = absl::Now() - start_time;
57   EXPECT_GE(elapsed, absl::Milliseconds(100));
58   EXPECT_LE(elapsed, absl::Milliseconds(200));
59 }
60 
TEST(DeadlineManagerTest,DeadlineInThePast)61 TEST(DeadlineManagerTest, DeadlineInThePast) {
62   DeadlineManager manager("test");
63   DeadlineRegistration registration(manager);
64   registration.SetDeadline(absl::InfinitePast());
65   registration.ExecuteBlockingSyscall(
66       [&] { FAIL() << "Function should not be executed"; });
67 }
68 
TEST(DeadlineManagerTest,DeadlineSetConcurrently)69 TEST(DeadlineManagerTest, DeadlineSetConcurrently) {
70   DeadlineManager manager("test");
71   DeadlineRegistration registration(manager);
72   absl::Time start_time = absl::Now();
73   struct timespec ts = absl::ToTimespec(absl::Seconds(1));
74   registration.ExecuteBlockingSyscall([&] {
75     sapi::Thread thread([&] {
76       absl::SleepFor(absl::Milliseconds(10));
77       registration.SetDeadline(start_time + absl::Milliseconds(100));
78     });
79     ASSERT_EQ(nanosleep(&ts, nullptr), -1);
80     thread.Join();
81   });
82   absl::Duration elapsed = absl::Now() - start_time;
83   EXPECT_GE(elapsed, absl::Milliseconds(100));
84   EXPECT_LE(elapsed, absl::Milliseconds(200));
85 }
86 
TEST(DeadlineManagerTest,DeadlineInPastSetConcurrently)87 TEST(DeadlineManagerTest, DeadlineInPastSetConcurrently) {
88   DeadlineManager manager("test");
89   DeadlineRegistration registration(manager);
90   absl::Time start_time = absl::Now();
91   struct timespec ts = absl::ToTimespec(absl::Seconds(1));
92   registration.ExecuteBlockingSyscall([&] {
93     sapi::Thread thread([&] {
94       absl::SleepFor(absl::Milliseconds(100));
95       registration.SetDeadline(absl::InfinitePast());
96     });
97     ASSERT_EQ(nanosleep(&ts, nullptr), -1);
98     thread.Join();
99   });
100   absl::Duration elapsed = absl::Now() - start_time;
101   EXPECT_GE(elapsed, absl::Milliseconds(100));
102   EXPECT_LE(elapsed, absl::Milliseconds(200));
103 }
104 
TEST(DeadlineManagerTest,DeadlineReset)105 TEST(DeadlineManagerTest, DeadlineReset) {
106   DeadlineManager manager("test");
107   DeadlineRegistration registration(manager);
108   absl::Time start_time = absl::Now();
109   struct timespec ts = absl::ToTimespec(absl::Milliseconds(200));
110   registration.ExecuteBlockingSyscall([&] {
111     registration.SetDeadline(absl::InfiniteFuture());
112     ASSERT_EQ(nanosleep(&ts, nullptr), 0);
113   });
114   absl::Duration elapsed = absl::Now() - start_time;
115   EXPECT_GE(elapsed, absl::Milliseconds(200));
116 }
117 
TEST(DeadlineManagerTest,CanBeReusedAfterExpiration)118 TEST(DeadlineManagerTest, CanBeReusedAfterExpiration) {
119   DeadlineManager manager("test");
120   DeadlineRegistration registration(manager);
121   for (int i = 0; i < 3; ++i) {
122     absl::Time start_time = absl::Now();
123     struct timespec ts = absl::ToTimespec(absl::Seconds(1));
124     registration.SetDeadline(start_time + absl::Milliseconds(100));
125     registration.ExecuteBlockingSyscall(
126         [&] { ASSERT_EQ(nanosleep(&ts, nullptr), -1); });
127     absl::Duration elapsed = absl::Now() - start_time;
128     EXPECT_GE(elapsed, absl::Milliseconds(100));
129     EXPECT_LE(elapsed, absl::Milliseconds(200));
130   }
131 }
132 
TEST(DeadlineManagerTest,WorksInAThread)133 TEST(DeadlineManagerTest, WorksInAThread) {
134   DeadlineManager manager("test");
135   DeadlineRegistration registration(manager);
136   sapi::Thread thread([&] {
137     absl::Time start_time = absl::Now();
138     struct timespec ts = absl::ToTimespec(absl::Seconds(1));
139     registration.SetDeadline(start_time + absl::Milliseconds(100));
140     registration.ExecuteBlockingSyscall(
141         [&] { ASSERT_EQ(nanosleep(&ts, nullptr), -1); });
142     absl::Duration elapsed = absl::Now() - start_time;
143     EXPECT_GE(elapsed, absl::Milliseconds(100));
144     EXPECT_LE(elapsed, absl::Milliseconds(200));
145   });
146   thread.Join();
147 }
148 
TEST(DeadlineManagerTest,DetectsOverridenHandler)149 TEST(DeadlineManagerTest, DetectsOverridenHandler) {
150   DeadlineManager manager("test");
151   DeadlineRegistration registration(manager);
152   EXPECT_DEATH(
153       {
154         struct sigaction sa = {};
155         CHECK_EQ(
156             sigaction(absl::GetFlag(FLAGS_sandbox2_deadline_manager_signal),
157                       nullptr, &sa),
158             0);
159         sa.sa_handler = SIG_IGN;
160         CHECK_EQ(
161             sigaction(absl::GetFlag(FLAGS_sandbox2_deadline_manager_signal),
162                       &sa, nullptr),
163             0);
164         absl::Time start_time = absl::Now();
165         absl::Time sleep_until = start_time + absl::Seconds(5);
166         registration.SetDeadline(start_time + absl::Milliseconds(100));
167         registration.ExecuteBlockingSyscall([sleep_until] {
168           absl::Duration remaining = sleep_until - absl::Now();
169           while (remaining > absl::ZeroDuration()) {
170             struct timespec ts = absl::ToTimespec(remaining);
171             CHECK_EQ(nanosleep(&ts, nullptr), -1);
172             remaining = sleep_until - absl::Now();
173           }
174         });
175       },
176       "Signal handler was overriden");
177 }
178 
TEST(DeadlineManagerTest,DetectsOverridenHandlerFlags)179 TEST(DeadlineManagerTest, DetectsOverridenHandlerFlags) {
180   DeadlineManager manager("test");
181   DeadlineRegistration registration(manager);
182   EXPECT_DEATH(
183       {
184         struct sigaction sa = {};
185         CHECK_EQ(
186             sigaction(absl::GetFlag(FLAGS_sandbox2_deadline_manager_signal),
187                       nullptr, &sa),
188             0);
189         sa.sa_flags = SA_RESTART;
190         CHECK_EQ(
191             sigaction(absl::GetFlag(FLAGS_sandbox2_deadline_manager_signal),
192                       &sa, nullptr),
193             0);
194         absl::Time start_time = absl::Now();
195         absl::Time sleep_until = start_time + absl::Seconds(5);
196         registration.SetDeadline(start_time + absl::Milliseconds(100));
197         registration.ExecuteBlockingSyscall([sleep_until] {
198           absl::Duration remaining = sleep_until - absl::Now();
199           while (remaining > absl::ZeroDuration()) {
200             struct timespec ts = absl::ToTimespec(remaining);
201             CHECK_EQ(nanosleep(&ts, nullptr), -1);
202             remaining = sleep_until - absl::Now();
203           }
204         });
205       },
206       "SA_RESTART signal handler flag was overriden");
207 }
208 
209 }  // namespace
210 }  // namespace sandbox2
211