Skip to content

Commit 1b173d0

Browse files
committed
linux-user: xtensa: fix signal delivery in FDPIC
In FDPIC signal handlers are passed around as FD pointers. Actual code address and GOT pointer must be fetched from memory by the QEMU code that implements kernel signal delivery functionality. This change is equivalent to the following kernel change: 9c2cc74fb31e ("xtensa: fix signal delivery to FDPIC process") Cc: qemu-stable@nongnu.org Fixes: d2796be ("linux-user: add support for xtensa FDPIC") Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
1 parent 9c673a4 commit 1b173d0

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

linux-user/xtensa/signal.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
157157
{
158158
abi_ulong frame_addr;
159159
struct target_rt_sigframe *frame;
160+
int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
161+
abi_ulong handler = 0;
162+
abi_ulong handler_fdpic_GOT = 0;
160163
uint32_t ra;
161164
bool abi_call0;
162165
unsigned base;
@@ -165,6 +168,17 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
165168
frame_addr = get_sigframe(ka, env, sizeof(*frame));
166169
trace_user_setup_rt_frame(env, frame_addr);
167170

171+
if (is_fdpic) {
172+
abi_ulong funcdesc_ptr = ka->_sa_handler;
173+
174+
if (get_user_ual(handler, funcdesc_ptr)
175+
|| get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) {
176+
goto give_sigsegv;
177+
}
178+
} else {
179+
handler = ka->_sa_handler;
180+
}
181+
168182
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
169183
goto give_sigsegv;
170184
}
@@ -185,14 +199,21 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
185199
}
186200

187201
if (ka->sa_flags & TARGET_SA_RESTORER) {
188-
ra = ka->sa_restorer;
202+
if (is_fdpic) {
203+
if (get_user_ual(ra, ka->sa_restorer)) {
204+
unlock_user_struct(frame, frame_addr, 0);
205+
goto give_sigsegv;
206+
}
207+
} else {
208+
ra = ka->sa_restorer;
209+
}
189210
} else {
190211
/* Not used, but retain for ABI compatibility. */
191212
install_sigtramp(frame->retcode);
192213
ra = default_rt_sigreturn;
193214
}
194215
memset(env->regs, 0, sizeof(env->regs));
195-
env->pc = ka->_sa_handler;
216+
env->pc = handler;
196217
env->regs[1] = frame_addr;
197218
env->sregs[WINDOW_BASE] = 0;
198219
env->sregs[WINDOW_START] = 1;
@@ -212,6 +233,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
212233
env->regs[base + 3] = frame_addr + offsetof(struct target_rt_sigframe,
213234
info);
214235
env->regs[base + 4] = frame_addr + offsetof(struct target_rt_sigframe, uc);
236+
if (is_fdpic) {
237+
env->regs[base + 11] = handler_fdpic_GOT;
238+
}
215239
unlock_user_struct(frame, frame_addr, 1);
216240
return;
217241

0 commit comments

Comments
 (0)