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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
From cb1bf2f321b45a06447133b3db00621b7300c456 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Mon, 2 Nov 2015 12:39:28 -0500
Subject: [PATCH] properly access mcontext_t program counter in cancellation
handler
using the actual mcontext_t definition rather than an overlaid pointer
array both improves correctness/readability and eliminates some ugly
hacks for archs with 64-bit registers bit 32-bit program counter.
also fix UB due to comparison of pointers not in a common array
object.
---
arch/aarch64/pthread_arch.h | 2 +-
arch/arm/pthread_arch.h | 2 +-
arch/i386/pthread_arch.h | 2 +-
arch/microblaze/pthread_arch.h | 2 +-
arch/mips/pthread_arch.h | 2 +-
arch/or1k/pthread_arch.h | 3 +--
arch/powerpc/pthread_arch.h | 3 +--
arch/sh/pthread_arch.h | 2 +-
arch/x32/pthread_arch.h | 2 +-
arch/x86_64/pthread_arch.h | 2 +-
src/thread/pthread_cancel.c | 7 ++++---
11 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/arch/aarch64/pthread_arch.h b/arch/aarch64/pthread_arch.h
index 74276f4..b2e2d8f 100644
--- a/arch/aarch64/pthread_arch.h
+++ b/arch/aarch64/pthread_arch.h
@@ -8,4 +8,4 @@ static inline struct pthread *__pthread_self()
#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 16)
-#define CANCEL_REG_IP 33
+#define MC_PC pc
diff --git a/arch/arm/pthread_arch.h b/arch/arm/pthread_arch.h
index 4a4dd09..8b8a7fb 100644
--- a/arch/arm/pthread_arch.h
+++ b/arch/arm/pthread_arch.h
@@ -27,4 +27,4 @@ static inline pthread_t __pthread_self()
#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8)
-#define CANCEL_REG_IP 18
+#define MC_PC arm_pc
diff --git a/arch/i386/pthread_arch.h b/arch/i386/pthread_arch.h
index 1c06c76..7f38a56 100644
--- a/arch/i386/pthread_arch.h
+++ b/arch/i386/pthread_arch.h
@@ -7,4 +7,4 @@ static inline struct pthread *__pthread_self()
#define TP_ADJ(p) (p)
-#define CANCEL_REG_IP 14
+#define MC_PC gregs[REG_EIP]
diff --git a/arch/microblaze/pthread_arch.h b/arch/microblaze/pthread_arch.h
index 259d3d6..08d1ba7 100644
--- a/arch/microblaze/pthread_arch.h
+++ b/arch/microblaze/pthread_arch.h
@@ -7,4 +7,4 @@ static inline struct pthread *__pthread_self()
#define TP_ADJ(p) (p)
-#define CANCEL_REG_IP 32
+#define MC_PC regs.pc
diff --git a/arch/mips/pthread_arch.h b/arch/mips/pthread_arch.h
index 93edbd4..8a49965 100644
--- a/arch/mips/pthread_arch.h
+++ b/arch/mips/pthread_arch.h
@@ -16,4 +16,4 @@ static inline struct pthread *__pthread_self()
#define DTP_OFFSET 0x8000
-#define CANCEL_REG_IP (3-(union {int __i; char __b;}){1}.__b)
+#define MC_PC pc
diff --git a/arch/or1k/pthread_arch.h b/arch/or1k/pthread_arch.h
index ad63169..7decd76 100644
--- a/arch/or1k/pthread_arch.h
+++ b/arch/or1k/pthread_arch.h
@@ -14,5 +14,4 @@ static inline struct pthread *__pthread_self()
#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
-/* word-offset to 'pc' in mcontext_t */
-#define CANCEL_REG_IP 32
+#define MC_PC regs.pc
diff --git a/arch/powerpc/pthread_arch.h b/arch/powerpc/pthread_arch.h
index bb7405d..7c5c4fa 100644
--- a/arch/powerpc/pthread_arch.h
+++ b/arch/powerpc/pthread_arch.h
@@ -15,9 +15,8 @@ static inline struct pthread *__pthread_self()
#define DTP_OFFSET 0x8000
-// offset of the PC register in mcontext_t, divided by the system wordsize
// the kernel calls the ip "nip", it's the first saved value after the 32
// GPRs.
-#define CANCEL_REG_IP 32
+#define MC_PC gregs[32]
#define CANARY canary_at_end
diff --git a/arch/sh/pthread_arch.h b/arch/sh/pthread_arch.h
index 65c389f..2756e7e 100644
--- a/arch/sh/pthread_arch.h
+++ b/arch/sh/pthread_arch.h
@@ -8,4 +8,4 @@ static inline struct pthread *__pthread_self()
#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8)
-#define CANCEL_REG_IP 17
+#define MC_PC sc_pc
diff --git a/arch/x32/pthread_arch.h b/arch/x32/pthread_arch.h
index 033bfd6..ecb0bbf 100644
--- a/arch/x32/pthread_arch.h
+++ b/arch/x32/pthread_arch.h
@@ -7,6 +7,6 @@ static inline struct pthread *__pthread_self()
#define TP_ADJ(p) (p)
-#define CANCEL_REG_IP 32
+#define MC_PC gregs[REG_RIP]
#define CANARY canary2
diff --git a/arch/x86_64/pthread_arch.h b/arch/x86_64/pthread_arch.h
index 29e4590..c61509c 100644
--- a/arch/x86_64/pthread_arch.h
+++ b/arch/x86_64/pthread_arch.h
@@ -7,4 +7,4 @@ static inline struct pthread *__pthread_self()
#define TP_ADJ(p) (p)
-#define CANCEL_REG_IP 16
+#define MC_PC gregs[REG_RIP]
diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
index 0151a1a..6eaf72c 100644
--- a/src/thread/pthread_cancel.c
+++ b/src/thread/pthread_cancel.c
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
#include <string.h>
#include "pthread_impl.h"
#include "syscall.h"
@@ -61,15 +62,15 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
{
pthread_t self = __pthread_self();
ucontext_t *uc = ctx;
- const char *ip = ((char **)&uc->uc_mcontext)[CANCEL_REG_IP];
+ uintptr_t pc = uc->uc_mcontext.MC_PC;
a_barrier();
if (!self->cancel || self->canceldisable == PTHREAD_CANCEL_DISABLE) return;
_sigaddset(&uc->uc_sigmask, SIGCANCEL);
- if (self->cancelasync || ip >= __cp_begin && ip < __cp_end) {
- ((char **)&uc->uc_mcontext)[CANCEL_REG_IP] = (char *)__cp_cancel;
+ if (self->cancelasync || pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) {
+ uc->uc_mcontext.MC_PC = (uintptr_t)__cp_cancel;
return;
}
--
2.7.0
|