[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: systat got SIGSYS signal with -current kernel
Takao Shinohara <shin@sm.sony.co.jp> writes:
>
> 1月11日から16日にかけてthorpejさんがMIPSのsyscallやASTの辺りを変更してい
> ますが、この変更に伴って、一部のプログラムがSIGSYSを受けて異常終了するよ
> うになりました。
皆様からいただいた情報を元に絞り込んでいったところ、原因がわかりました。
sys/arch/mips/mips/syscall.c(1.2)はsystem callの処理をする部分をtrap.cか
ら切り離して書き直したファイルですが、書き直した際にenbugされています。
従来は、カーネルスタック上にsystam callの戻り値の領域を確保してそれを使っ
て実際のsystem callの処理を呼び出していたのですが、syscall.c(1.2)では別
の領域を使わずに直接trap frame(struct frame)を使うように変更されています。
system callの処理がエラーにならなければ問題ないのですが、ERESTARTになっ
た場合には、保存すべきだったレジスタ(v0, v1)を破壊します。ERESTARTの場合
はユーザプロセスは再度syscall命令を実行しますので、v0に入っていたsystem
call番号が破壊されると、存在しないsystem callを発行したことになり、異常
終了します。
system callの戻り値の処理を従来と同じになるように修正したところ、異常終
了する現象は発生しなくなりました(添付のpatchを参照)。
ご協力ありがとうございました。
篠原
Index: syscall.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/mips/syscall.c,v
retrieving revision 1.2
diff -u -r1.2 syscall.c
--- syscall.c 2001/01/18 17:48:01 1.2
+++ syscall.c 2001/01/25 13:24:06
@@ -138,7 +138,7 @@
syscall_plain(struct proc *p, u_int status, u_int cause, u_int opc)
{
struct frame *frame = (struct frame *)p->p_md.md_regs;
- mips_reg_t *args, copyargs[8];
+ mips_reg_t *args, copyargs[8], rval[2];
size_t code, numsys, nsaved, nargs;
const struct sysent *callp;
int error;
@@ -223,13 +223,16 @@
scdebug_call(p, code, args);
#endif
- frame->f_regs[V0] = 0;
+ rval[0] = 0;
+ rval[1] = frame->f_regs[V1];
/* XXX register_t vs. mips_reg_t */
- error = (*callp->sy_call)(p, args, (register_t *)&frame->f_regs[V0]);
+ error = (*callp->sy_call)(p, args, (register_t *)rval);
switch (error) {
case 0:
+ frame->f_regs[V0] = rval[0];
+ frame->f_regs[V1] = rval[1];
frame->f_regs[A3] = 0;
break;
case ERESTART:
@@ -255,7 +258,7 @@
syscall_fancy(struct proc *p, u_int status, u_int cause, u_int opc)
{
struct frame *frame = (struct frame *)p->p_md.md_regs;
- mips_reg_t *args, copyargs[8];
+ mips_reg_t *args, copyargs[8], rval[2];
size_t code, numsys, nsaved, nargs;
const struct sysent *callp;
int error;
@@ -347,13 +350,16 @@
}
#endif
- frame->f_regs[V0] = 0;
+ rval[0] = 0;
+ rval[1] = frame->f_regs[V1];
/* XXX register_t vs. mips_reg_t */
- error = (*callp->sy_call)(p, args, (register_t *)&frame->f_regs[V0]);
+ error = (*callp->sy_call)(p, args, (register_t *)rval);
switch (error) {
case 0:
+ frame->f_regs[V0] = rval[0];
+ frame->f_regs[V1] = rval[1];
frame->f_regs[A3] = 0;
break;
case ERESTART: