1 /*
2  * Copyright (C) 2023 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 #ifndef BERBERIS_GUEST_OS_PRIMITIVES_GUEST_SIGNAL_H_
18 #define BERBERIS_GUEST_OS_PRIMITIVES_GUEST_SIGNAL_H_
19 
20 #include <csignal>
21 #include <cstring>
22 
23 #include "berberis/base/host_signal.h"  // HostStructSigaction
24 #include "berberis/base/struct_check.h"
25 #include "berberis/guest_os_primitives/guest_thread.h"
26 #include "berberis/guest_state/guest_addr.h"
27 
28 namespace berberis {
29 
30 // Maximum number of signals for the guest kernel.
31 constexpr int Guest__KERNEL__NSIG = 64;
32 
33 const GuestAddr Guest_SIG_DFL = GuestAddr{0U};
34 const GuestAddr Guest_SIG_IGN = GuestAddr{1U};
35 const GuestAddr Guest_SIG_ERR = GuestAddr{~0U};
36 
37 // Guest siginfo_t, as expected by guest rt_sigqueueinfo syscall.
38 using Guest_siginfo_t = siginfo_t;
39 
40 // Guest sigset_t, as expected by guest rt_sigprocmask syscall.
41 #if defined(BERBERIS_GUEST_LP64)
42 struct Guest_sigset_t {
43   unsigned long __bits[1];
44 };
45 CHECK_STRUCT_LAYOUT(Guest_sigset_t, 64, 64);
46 #else
47 // TODO(b/283352810): Explicitly support ILP32 guest data model.
48 // This condition currently assumes ILP32 support.
49 struct Guest_sigset_t {
50   unsigned long __bits[2];
51 };
52 CHECK_STRUCT_LAYOUT(Guest_sigset_t, 64, 32);
53 #endif
54 
55 // TODO(b/280551353): check other SA_* flags!
56 static_assert(SA_NODEFER == 0x40000000, "Host and guest SA_NODEFER don't match");
57 
58 template <typename SmallSigset, typename BigSigset>
ConvertToSmallSigset(const BigSigset & big_sigset,SmallSigset * small_sigset)59 inline void ConvertToSmallSigset(const BigSigset& big_sigset, SmallSigset* small_sigset) {
60   static_assert(sizeof(SmallSigset) <= sizeof(BigSigset), "wrong sigset size");
61   memcpy(small_sigset, &big_sigset, sizeof(SmallSigset));
62 }
63 
64 template <typename SmallSigset, typename BigSigset>
ConvertToBigSigset(const SmallSigset & small_sigset,BigSigset * big_sigset)65 inline void ConvertToBigSigset(const SmallSigset& small_sigset, BigSigset* big_sigset) {
66   static_assert(sizeof(SmallSigset) <= sizeof(BigSigset), "wrong sigset size");
67   memset(big_sigset, 0, sizeof(BigSigset));
68   memcpy(big_sigset, &small_sigset, sizeof(SmallSigset));
69 }
70 
71 size_t GetGuest_MINSIGSTKSZ();
72 
73 struct Guest_sigaction;
74 bool SetGuestSignalHandler(int signal,
75                            const Guest_sigaction* act,
76                            Guest_sigaction* old_act,
77                            int* error);
78 
79 // Recognize canonical (kernel-provided) handlers and log a fatal message otherwise.
80 void CheckSigactionRestorer(const Guest_sigaction* guest_sa);
81 void ResetSigactionRestorer(Guest_sigaction* guest_sa);
82 
83 GuestAddr WrapHostSigactionForGuest(const HostStructSigaction& host_sa);
84 
85 void ProcessGuestSignal(GuestThread* thread, const Guest_sigaction* sa, Guest_siginfo_t* info);
86 
87 }  // namespace berberis
88 
89 #endif  // BERBERIS_GUEST_OS_PRIMITIVES_GUEST_SIGNAL_H_
90