Fix a nasty bug that got exposed when the sendsig() and sigreturn()
functions switched to using {g|s}et_mcontext(). The problem is that sigreturn(), being a syscall, can be given an async. context (i.e. one corresponding to an interrupt or trap). When this happens, we try to return to user mode via epc_syscall_return with a trapframe that can only be used to return to user mode via exception_restore. To fix this, we check the frame's flags immediately prior to epc_syscall_return and branch to exception_restore for non-syscall frames. Modify the assertion in set_mcontext() to check that if there's a mismatch, it's because of sigreturn().
This commit is contained in:
parent
a5896914f0
commit
9d52656a5a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=122479
@ -55,6 +55,7 @@
|
||||
#include <sys/random.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/uuid.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <net/netisr.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_kern.h>
|
||||
@ -1114,7 +1115,15 @@ set_mcontext(struct thread *td, const mcontext_t *mc)
|
||||
/* We don't have any dirty registers of the new context. */
|
||||
s.ndirty = 0;
|
||||
if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) {
|
||||
KASSERT((tf->tf_flags & FRAME_SYSCALL) == 0, ("foo"));
|
||||
/*
|
||||
* We can get an async context passed to us while we
|
||||
* entered the kernel through a syscall: sigreturn(2).
|
||||
* Hence, we cannot assert that the trapframe is not
|
||||
* a syscall frame, but we can assert that if it is
|
||||
* the syscall is sigreturn(2).
|
||||
*/
|
||||
if (tf->tf_flags & FRAME_SYSCALL)
|
||||
KASSERT(tf->tf_scratch.gr15 == SYS_sigreturn, ("foo"));
|
||||
tf->tf_scratch = mc->mc_scratch;
|
||||
tf->tf_scratch_fp = mc->mc_scratch_fp;
|
||||
/* XXX High FP */
|
||||
|
@ -371,7 +371,7 @@ ENTRY(epc_syscall, 8)
|
||||
movl gp=__gp
|
||||
;;
|
||||
}
|
||||
epc_syscall_restart:
|
||||
1:
|
||||
{ .mib
|
||||
srlz.d
|
||||
add out0=16,sp
|
||||
@ -384,12 +384,25 @@ epc_syscall_restart:
|
||||
br.call.sptk rp=do_ast
|
||||
;;
|
||||
}
|
||||
{ .mfb
|
||||
{ .mib
|
||||
cmp4.eq p15,p0=ERESTART,r8
|
||||
nop 0
|
||||
(p15) br.spnt epc_syscall_restart
|
||||
add r14=24,sp
|
||||
(p15) br.spnt 1b // restart syscall
|
||||
;;
|
||||
}
|
||||
{ .mfb
|
||||
ld8 r14=[r14] // tf_flags
|
||||
nop 0
|
||||
nop 0
|
||||
;;
|
||||
}
|
||||
{ .mib
|
||||
nop 0
|
||||
tbit.z p15,p0=r14,0
|
||||
(p15) br.spnt exception_restore
|
||||
;;
|
||||
}
|
||||
|
||||
.global epc_syscall_return
|
||||
epc_syscall_return:
|
||||
{ .mmi
|
||||
|
Loading…
Reference in New Issue
Block a user