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