1 /*
2 * Copyright (C) 2017 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
17 #include "gtest/gtest.h"
18
19 #include <signal.h>
20
21 #include "berberis/guest_os_primitives/guest_signal.h"
22 #include "berberis/guest_state/guest_addr.h"
23
24 #include "guest_signal_action.h"
25
26 namespace berberis {
27
28 namespace {
29
30 class ScopedSignalHandler {
31 public:
ScopedSignalHandler(int sig,void (* handler)(int))32 ScopedSignalHandler(int sig, void (*handler)(int)) : sig_(sig) {
33 struct sigaction act {};
34 act.sa_handler = handler;
35 sigaction(sig_, &act, &old_act_);
36 }
37
ScopedSignalHandler(int sig,void (* action)(int,siginfo_t *,void *))38 ScopedSignalHandler(int sig, void (*action)(int, siginfo_t*, void*)) : sig_(sig) {
39 struct sigaction act {};
40 act.sa_sigaction = action;
41 act.sa_flags = SA_SIGINFO;
42 sigaction(sig_, &act, &old_act_);
43 }
44
~ScopedSignalHandler()45 ~ScopedSignalHandler() { sigaction(sig_, &old_act_, nullptr); }
46
47 private:
48 int sig_;
49 struct sigaction old_act_;
50 };
51
ClaimedHostSaSigaction(int,siginfo_t *,void *)52 void ClaimedHostSaSigaction(int, siginfo_t*, void*) {}
53
TEST(GuestSignalActionTest,Smoke)54 TEST(GuestSignalActionTest, Smoke) {
55 GuestSignalAction action;
56
57 // Ensure address doesn't accidentally coincide with any valid host function :)
58 int fake_guest_func;
59 const GuestAddr kGuestSaSigaction = ToGuestAddr(&fake_guest_func);
60
61 Guest_sigaction new_sa{};
62 new_sa.guest_sa_sigaction = kGuestSaSigaction;
63 Guest_sigaction old_sa{};
64 int error = 0;
65
66 EXPECT_TRUE(action.Change(SIGUSR1, &new_sa, ClaimedHostSaSigaction, &old_sa, &error));
67 EXPECT_EQ(0, error);
68 EXPECT_EQ(kGuestSaSigaction, action.GetClaimedGuestAction().guest_sa_sigaction);
69
70 EXPECT_TRUE(action.Change(SIGUSR1, &old_sa, nullptr, &old_sa, &error));
71 EXPECT_EQ(0, error);
72 EXPECT_EQ(kGuestSaSigaction, old_sa.guest_sa_sigaction);
73 }
74
CustomSignalAction(int,siginfo_t *,void *)75 void CustomSignalAction(int, siginfo_t*, void*) {}
76
TEST(GuestSignalActionTest,ShareNewAndOld)77 TEST(GuestSignalActionTest, ShareNewAndOld) {
78 // Start with custom action.
79 ScopedSignalHandler scoped_usr1_handler(SIGUSR1, CustomSignalAction);
80 const GuestAddr kOrigGuestSaSigaction = ToGuestAddr(CustomSignalAction);
81
82 GuestSignalAction action;
83
84 // Ensure address doesn't accidentally coincide with any valid host function :)
85 int fake_guest_func;
86 const GuestAddr kNewGuestSaSigaction = ToGuestAddr(&fake_guest_func);
87
88 Guest_sigaction sa{};
89 sa.guest_sa_sigaction = kNewGuestSaSigaction;
90 int error = 0;
91
92 // Set new action, use the same object for new and old sa.
93 EXPECT_TRUE(action.Change(SIGUSR1, &sa, ClaimedHostSaSigaction, &sa, &error));
94 EXPECT_EQ(0, error);
95 EXPECT_EQ(kOrigGuestSaSigaction, sa.guest_sa_sigaction);
96
97 // Check current action.
98 EXPECT_TRUE(action.Change(SIGUSR1, nullptr, nullptr, &sa, &error));
99 EXPECT_EQ(0, error);
100 EXPECT_EQ(kNewGuestSaSigaction, sa.guest_sa_sigaction);
101 }
102
TEST(GuestSignalActionTest,SetDFL)103 TEST(GuestSignalActionTest, SetDFL) {
104 // Start with custom action.
105 ScopedSignalHandler scoped_usr1_handler(SIGUSR1, CustomSignalAction);
106 const GuestAddr kOrigGuestSaSigaction = ToGuestAddr(CustomSignalAction);
107
108 GuestSignalAction action;
109
110 // Examine current action.
111
112 Guest_sigaction old_sa{};
113 int error = 0;
114
115 EXPECT_TRUE(action.Change(SIGUSR1, nullptr, nullptr, &old_sa, &error));
116 EXPECT_EQ(0, error);
117 EXPECT_EQ(kOrigGuestSaSigaction, old_sa.guest_sa_sigaction);
118
119 // Set SIG_DFL.
120
121 Guest_sigaction new_sa{};
122 new_sa.guest_sa_sigaction = Guest_SIG_DFL;
123
124 EXPECT_TRUE(action.Change(SIGUSR1, &new_sa, ClaimedHostSaSigaction, &old_sa, &error));
125 EXPECT_EQ(0, error);
126 EXPECT_EQ(kOrigGuestSaSigaction, old_sa.guest_sa_sigaction);
127
128 // Restore original action.
129
130 new_sa.guest_sa_sigaction = kOrigGuestSaSigaction;
131
132 EXPECT_TRUE(action.Change(SIGUSR1, &new_sa, ClaimedHostSaSigaction, &old_sa, &error));
133 EXPECT_EQ(0, error);
134 EXPECT_EQ(Guest_SIG_DFL, old_sa.guest_sa_sigaction);
135
136 // Examine current action.
137
138 EXPECT_TRUE(action.Change(SIGUSR1, nullptr, nullptr, &old_sa, &error));
139 EXPECT_EQ(0, error);
140 EXPECT_EQ(kOrigGuestSaSigaction, old_sa.guest_sa_sigaction);
141 }
142
TEST(GuestSignalActionTest,SetCurr)143 TEST(GuestSignalActionTest, SetCurr) {
144 // Start with custom action.
145 ScopedSignalHandler scoped_usr1_handler(SIGUSR1, CustomSignalAction);
146 const GuestAddr kOrigGuestSaSigaction = ToGuestAddr(CustomSignalAction);
147
148 GuestSignalAction action;
149
150 // Examine current action.
151
152 Guest_sigaction old_sa{};
153 int error = 0;
154
155 EXPECT_TRUE(action.Change(SIGUSR1, nullptr, nullptr, &old_sa, &error));
156 EXPECT_EQ(0, error);
157 EXPECT_EQ(kOrigGuestSaSigaction, old_sa.guest_sa_sigaction);
158
159 // Set action that is already current.
160
161 EXPECT_TRUE(action.Change(SIGUSR1, &old_sa, ClaimedHostSaSigaction, &old_sa, &error));
162 EXPECT_EQ(0, error);
163 EXPECT_EQ(kOrigGuestSaSigaction, old_sa.guest_sa_sigaction);
164 }
165
TEST(GuestSignalActionTest,SetCurrDFL)166 TEST(GuestSignalActionTest, SetCurrDFL) {
167 // Start with SIG_DFL action - ensure it is actually current!
168 ScopedSignalHandler scoped_usr1_handler(SIGUSR1, SIG_DFL);
169
170 GuestSignalAction action;
171
172 // Examine current action.
173
174 Guest_sigaction old_sa{};
175 int error = 0;
176
177 EXPECT_TRUE(action.Change(SIGUSR1, nullptr, nullptr, &old_sa, &error));
178 EXPECT_EQ(0, error);
179 EXPECT_EQ(Guest_SIG_DFL, old_sa.guest_sa_sigaction);
180
181 // Set SIG_DFL that is already current.
182
183 EXPECT_TRUE(action.Change(SIGUSR1, &old_sa, ClaimedHostSaSigaction, &old_sa, &error));
184 EXPECT_EQ(0, error);
185 EXPECT_EQ(Guest_SIG_DFL, old_sa.guest_sa_sigaction);
186 }
187
TEST(GuestSignalActionTest,SetNullAction)188 TEST(GuestSignalActionTest, SetNullAction) {
189 // Start with custom action.
190 ScopedSignalHandler scoped_usr1_handler(SIGUSR1, CustomSignalAction);
191
192 GuestSignalAction action;
193
194 // Set null sa_sigaction.
195
196 Guest_sigaction new_sa{};
197 new_sa.sa_flags = SA_SIGINFO;
198 int error = 0;
199
200 EXPECT_TRUE(action.Change(SIGUSR1, &new_sa, ClaimedHostSaSigaction, nullptr, &error));
201 EXPECT_EQ(0, error);
202
203 // Examine current action.
204
205 Guest_sigaction old_sa{};
206
207 EXPECT_TRUE(action.Change(SIGUSR1, nullptr, nullptr, &old_sa, &error));
208 EXPECT_EQ(0, error);
209 EXPECT_EQ(0u, old_sa.guest_sa_sigaction);
210 }
211
212 } // namespace
213
214 } // namespace berberis
215