summaryrefslogtreecommitdiff
path: root/packaging/0004-ExecuteHandlerOnOriginalStack-handle-case-when-it-is.patch
blob: 618206640cf408bb5164d068a6c51292160ff9b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
From a72739ab5a9c40788557dbc4084c275b5a62a657 Mon Sep 17 00:00:00 2001
From: Konstantin Baladurin <k.baladurin@partner.samsung.com>
Date: Wed, 7 Feb 2018 18:44:10 +0300
Subject: [PATCH 4/4] ExecuteHandlerOnOriginalStack: handle case when it is
 called on original stack.

If ExecuteHandlerOnOriginalStack is called on original stack (for example,
if segmentation fault occurs in native application's thread that hasn't
alternate signal stack) we should use faultSp from its frame otherwise
stackframe of the caller function will be corrupted.
---
 src/pal/src/arch/amd64/signalhandlerhelper.cpp | 20 ++++++++++++++++++--
 src/pal/src/arch/arm/signalhandlerhelper.cpp   | 18 +++++++++++++++++-
 src/pal/src/arch/arm64/signalhandlerhelper.cpp | 19 ++++++++++++++++++-
 src/pal/src/arch/i386/signalhandlerhelper.cpp  | 18 +++++++++++++++++-
 4 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/src/pal/src/arch/amd64/signalhandlerhelper.cpp b/src/pal/src/arch/amd64/signalhandlerhelper.cpp
index 8789f5a..803479c 100644
--- a/src/pal/src/arch/amd64/signalhandlerhelper.cpp
+++ b/src/pal/src/arch/amd64/signalhandlerhelper.cpp
@@ -27,7 +27,23 @@ Parameters :
 void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
 {
     ucontext_t *ucontext = (ucontext_t *)context;
-    size_t faultSp = (size_t)MCREG_Rsp(ucontext->uc_mcontext);
+    size_t faultSp;
+
+    // check whether this function is called on alternate stack or not. In the second case we already
+    // on original stack and we should use faultSp from this frame otherwise stackframe of the caller
+    // function will be corrupted.
+    char fakeStackFrame[128 /* redzone */ + 16 /* aligment */ + 4 * sizeof(size_t) /* registers */];
+    stack_t oss;
+    int st = sigaltstack(NULL, &oss);
+    if ((st == 0) && ((oss.ss_flags == SS_DISABLE) ||
+        ((size_t)oss.ss_sp > (size_t)&faultSp) || (((size_t)oss.ss_sp + oss.ss_size) < (size_t)&faultSp)))
+    {
+        faultSp = (size_t)&fakeStackFrame[sizeof(fakeStackFrame)];
+    }
+    else
+    {
+        faultSp = (size_t)MCREG_Rsp(ucontext->uc_mcontext);
+    }
 
     _ASSERTE(IS_ALIGNED(faultSp, 8));
 
@@ -58,7 +74,7 @@ void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context,
     // We don't care about the other registers state since the stack unwinding restores
     // them for the target frame directly from the signal context.
     context2.Rsp = (size_t)sp;
-    context2.Rbx = (size_t)faultSp;
+    context2.Rbx = (size_t)MCREG_Rsp(ucontext->uc_mcontext);
     context2.Rbp = (size_t)fp;
     context2.Rip = (size_t)signal_handler_worker;
     context2.Rdi = code;
diff --git a/src/pal/src/arch/arm/signalhandlerhelper.cpp b/src/pal/src/arch/arm/signalhandlerhelper.cpp
index 3936204..fbf33e3 100644
--- a/src/pal/src/arch/arm/signalhandlerhelper.cpp
+++ b/src/pal/src/arch/arm/signalhandlerhelper.cpp
@@ -27,7 +27,23 @@ Parameters :
 void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
 {
     ucontext_t *ucontext = (ucontext_t *)context;
-    size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext);
+    size_t faultSp;
+
+    // check whether this function is called on alternate stack or not. In the second case we already
+    // on original stack and we should use faultSp from this frame otherwise stackframe of the caller
+    // function will be corrupted.
+    char fakeStackFrame[8 /* redzone */ + 8 /* aligment */ + sizeof(ucontext->uc_mcontext) + 8 /* registers */];
+    stack_t oss;
+    int st = sigaltstack(NULL, &oss);
+    if ((st == 0) && ((oss.ss_flags == SS_DISABLE) ||
+        ((size_t)oss.ss_sp > (size_t)&faultSp) || (((size_t)oss.ss_sp + oss.ss_size) < (size_t)&faultSp)))
+    {
+        faultSp = (size_t)&fakeStackFrame[sizeof(fakeStackFrame)];
+    }
+    else
+    {
+        faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext);
+    }
 
     _ASSERTE(IS_ALIGNED(faultSp, 4));
 
diff --git a/src/pal/src/arch/arm64/signalhandlerhelper.cpp b/src/pal/src/arch/arm64/signalhandlerhelper.cpp
index c35c629..958b8af 100644
--- a/src/pal/src/arch/arm64/signalhandlerhelper.cpp
+++ b/src/pal/src/arch/arm64/signalhandlerhelper.cpp
@@ -27,7 +27,24 @@ Parameters :
 void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
 {
     ucontext_t *ucontext = (ucontext_t *)context;
-    size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext);
+    size_t faultSp;
+
+    // check whether this function is called on alternate stack or not. In the second case we already
+    // on original stack and we should use faultSp from this frame otherwise stackframe of the caller
+    // function will be corrupted.
+    char fakeStackFrame[128 /* redzone */ + 16 /* aligment */ + 3 * sizeof(size_t) /* registers */];
+    stack_t oss;
+    int st = sigaltstack(NULL, &oss);
+    if ((st == 0) && ((oss.ss_flags == SS_DISABLE) ||
+        ((size_t)oss.ss_sp > (size_t)&faultSp) || (((size_t)oss.ss_sp + oss.ss_size) < (size_t)&faultSp)))
+    {
+        faultSp = (size_t)&fakeStackFrame[sizeof(fakeStackFrame)];
+    }
+    else
+    {
+        faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext);
+    }
+
     _ASSERTE(IS_ALIGNED(faultSp, 8));
 
     size_t fakeFrameReturnAddress;
diff --git a/src/pal/src/arch/i386/signalhandlerhelper.cpp b/src/pal/src/arch/i386/signalhandlerhelper.cpp
index a7d418a..d534f96 100644
--- a/src/pal/src/arch/i386/signalhandlerhelper.cpp
+++ b/src/pal/src/arch/i386/signalhandlerhelper.cpp
@@ -27,7 +27,23 @@ Parameters :
 void ExecuteHandlerOnOriginalStack(int code, siginfo_t *siginfo, void *context, SignalHandlerWorkerReturnPoint* returnPoint)
 {
     ucontext_t *ucontext = (ucontext_t *)context;
-    size_t faultSp = (size_t)MCREG_Esp(ucontext->uc_mcontext);
+    size_t faultSp;
+
+    // check whether this function is called on alternate stack or not. In the second case we already
+    // on original stack and we should use faultSp from this frame otherwise stackframe of the caller
+    // function will be corrupted.
+    char fakeStackFrame[16 /* aligment */ + 10 * sizeof(size_t) /* registers */];
+    stack_t oss;
+    int st = sigaltstack(NULL, &oss);
+    if ((st == 0) && ((oss.ss_flags == SS_DISABLE) ||
+        ((size_t)oss.ss_sp > (size_t)&faultSp) || (((size_t)oss.ss_sp + oss.ss_size) < (size_t)&faultSp)))
+    {
+        faultSp = (size_t)&fakeStackFrame[sizeof(fakeStackFrame)];
+    }
+    else
+    {
+        faultSp = (size_t)MCREG_Esp(ucontext->uc_mcontext);
+    }
 
     _ASSERTE(IS_ALIGNED(faultSp, 4));
 
-- 
2.7.4