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 // Generic implementation that relies on guest arch-specific headers. This file must be compiled
18 // separately for each guest architecture.
19
20 #include "berberis/guest_os_primitives/guest_signal.h"
21
22 #include "berberis/base/host_signal.h"
23 #include "berberis/base/tracing.h"
24 #include "berberis/guest_abi/guest_call.h"
25 #include "berberis/guest_os_primitives/guest_signal_arch.h"
26 #include "berberis/guest_os_primitives/guest_thread.h"
27
28 #include "guest_context_arch.h"
29 #include "scoped_signal_blocker.h"
30
31 namespace berberis {
32
ProcessGuestSignal(GuestThread * thread,const Guest_sigaction * sa,Guest_siginfo_t * info)33 void ProcessGuestSignal(GuestThread* thread, const Guest_sigaction* sa, Guest_siginfo_t* info) {
34 // ATTENTION: action mask is ADDED to currently blocked signals!
35 // Should be no-op if invoked from HandleHostSignal, as it must run under guest action mask!
36 HostSigset block_mask;
37 ConvertToBigSigset(sa->sa_mask, &block_mask);
38 if ((sa->sa_flags & SA_NODEFER) == 0u) {
39 HostSigaddset(&block_mask, info->si_signo);
40 }
41 ScopedSignalBlocker signal_blocker(&block_mask);
42
43 // Save state to ucontext.
44 ThreadState* state = thread->state();
45 GuestContext ctx;
46 ctx.Save(&state->cpu);
47
48 // Switch to alternate stack.
49 if (sa->sa_flags & SA_ONSTACK) {
50 thread->SwitchToSigAltStack();
51 }
52
53 TRACE("delivering signal %d at %p", info->si_signo, ToHostAddr<void>(sa->guest_sa_sigaction));
54 // We get here only if guest set a custom signal action, default actions are handled by host.
55 CHECK_NE(sa->guest_sa_sigaction, Guest_SIG_DFL);
56 CHECK_NE(sa->guest_sa_sigaction, Guest_SIG_IGN);
57 CHECK_NE(sa->guest_sa_sigaction, Guest_SIG_ERR);
58 // Run guest signal handler. Assume this is
59 // void (*sa_sigaction)(int, siginfo_t*, void*);
60 // If this is actually
61 // void (*sa_handler)(int);
62 // then extra args will be just ignored.
63 GuestCall guest_call;
64 guest_call.AddArgInt32(info->si_signo);
65 guest_call.AddArgGuestAddr(ToGuestAddr(info));
66 guest_call.AddArgGuestAddr(ToGuestAddr(ctx.ptr()));
67 guest_call.RunVoid(sa->guest_sa_sigaction);
68 TRACE("signal %d delivered", info->si_signo);
69
70 // Restore state from ucontext, it may be updated by the handler.
71 ctx.Restore(&state->cpu);
72 }
73
74 } // namespace berberis
75