[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: