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:
Marcel Moolenaar 2003-11-11 09:25:19 +00:00
parent a5896914f0
commit 9d52656a5a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=122479
2 changed files with 27 additions and 5 deletions

View File

@ -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 */

View File

@ -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