1 /*
2 ** Licensed under the Apache License, Version 2.0 (the "License");
3 ** you may not use this file except in compliance with the License.
4 ** You may obtain a copy of the License at
5 **
6 ** http://www.apache.org/licenses/LICENSE-2.0
7 **
8 ** Unless required by applicable law or agreed to in writing, software
9 ** distributed under the License is distributed on an "AS IS" BASIS,
10 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 ** See the License for the specific language governing permissions and
12 ** limitations under the License.
13 **
14 ** Copyright 2021 NXP
15 **
16 */
17
18 #define LOG_TAG "OmapiTransport_SignalHandler"
19
20 #include <android-base/logging.h>
21 #include <log/log.h>
22 #include <signal.h>
23 #include <iomanip>
24 #include <vector>
25
26 #include <AppletConnection.h>
27 #include <SignalHandler.h>
28
29 keymint::javacard::AppletConnection* g_AppClient = nullptr;
30
31 #define NUM_OF_SIGNALS 6
32 int handledSignals[] = {SIGTRAP, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGTERM};
33 struct sigaction old_action[NUM_OF_SIGNALS] = {};
34
35 namespace keymint::javacard {
36
37 /* Handle Fatal signals to close opened Logical channel before
38 * the process dies
39 */
customSignalHandler(int sig,siginfo_t * info,void * ucontext)40 void customSignalHandler(int sig, siginfo_t* info, void* ucontext) {
41 LOG(WARNING) << "received signal " << sig;
42 if (g_AppClient != nullptr) g_AppClient->close();
43 // default handling of the received signal
44 for (int i = 0; i < NUM_OF_SIGNALS; i++) {
45 if (handledSignals[i] == sig) {
46 if (old_action[i].sa_sigaction != nullptr) {
47 LOG(INFO) << "execute originally installed handler" << sig;
48 (*(old_action[i].sa_sigaction))(sig, info, ucontext);
49 } else if (old_action[i].sa_handler == SIG_DFL || old_action[i].sa_handler == SIG_IGN) {
50 signal(sig, old_action[i].sa_handler); // reset to old handler
51 raise(sig);
52 }
53 break;
54 }
55 }
56 }
57
58 /**
59 * Register signal Handler.
60 * Use mPtrC to pass handle/data which might be required in signal Handler context
61 * marks registration OK if at least one of signal is registered successfully
62 */
63
installHandler(void * mPtr)64 void SignalHandler::installHandler(void* mPtr) {
65 mContext = mPtr;
66 g_AppClient = (keymint::javacard::AppletConnection*)mContext;
67 int reg_signals = 0;
68 for (int i = 0; i < NUM_OF_SIGNALS; i++) {
69 struct sigaction enable_act = {};
70 enable_act.sa_sigaction = customSignalHandler;
71 enable_act.sa_flags = SA_RESTART | SA_SIGINFO;
72 if (sigaction(handledSignals[i], &enable_act, &(old_action[i])) != 0) {
73 LOG(ERROR) << "Unable to set up signal handler for signal " << handledSignals[i]
74 << "errno " << errno;
75 } else {
76 reg_signals++;
77 }
78 }
79 if (reg_signals > 0) isRegistered = true;
80 }
81
SignalHandler()82 SignalHandler::SignalHandler() {
83 sigemptyset(&blockedSignals);
84 sigemptyset(&oldMask);
85 mContext = nullptr;
86 isRegistered = false;
87 }
88
89 SignalHandler* SignalHandler::instance = nullptr;
90
getInstance()91 SignalHandler* SignalHandler::getInstance() {
92 if (!instance) {
93 instance = new SignalHandler();
94 }
95 return instance;
96 }
97
isHandlerRegistered()98 bool SignalHandler::isHandlerRegistered() {
99 return isRegistered;
100 }
101
102 /**
103 * block Signals to prevent interrupts during critical parts of code
104 */
105
blockSignals()106 void SignalHandler::blockSignals() {
107 if (!isRegistered) return;
108 sigemptyset(&blockedSignals);
109 sigemptyset(&oldMask);
110
111 for (int i = 0; i < NUM_OF_SIGNALS; i++) {
112 sigaddset(&blockedSignals, handledSignals[i]);
113 }
114 if (sigprocmask(SIG_BLOCK, &blockedSignals, &oldMask) < 0) {
115 LOG(ERROR) << "failed to block signal " << errno;
116 }
117 }
118
119 /**
120 * Unblock signal previously blocked using blockSignals()
121 * Pending signals are delivered after they are unblocked.
122 */
123
unblockSignals()124 void SignalHandler::unblockSignals() {
125 if (!isRegistered) return;
126 if (sigprocmask(SIG_SETMASK, &oldMask, NULL) < 0) {
127 LOG(ERROR) << "failed to set sigmask " << errno;
128 }
129 }
130
131 } // namespace keymint::javacard
132