Fix some types:

* code, args, and rval should use register_t.
* argsize should be a size_t.
Small optimization to the Linux compat code, and don't blindly fail on if
the argument list size is invalid.
This commit is contained in:
mycroft 1995-03-08 07:12:28 +00:00
parent add762f71c
commit 80d817b8de

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.68 1995/02/28 23:18:03 cgd Exp $ */ /* $NetBSD: trap.c,v 1.69 1995/03/08 07:12:28 mycroft Exp $ */
#undef DEBUG #undef DEBUG
#define DEBUG #define DEBUG
@ -489,10 +489,9 @@ syscall(frame)
register caddr_t params; register caddr_t params;
register struct sysent *callp; register struct sysent *callp;
register struct proc *p; register struct proc *p;
int error, opc; int error, opc, nsys;
u_int argsize; size_t argsize;
int args[8], rval[2]; register_t code, args[8], rval[2];
int code, nsys;
u_quad_t sticks; u_quad_t sticks;
#ifdef COMPAT_SVR4 #ifdef COMPAT_SVR4
extern int nsvr4_sysent; extern int nsvr4_sysent;
@ -506,8 +505,8 @@ syscall(frame)
#ifdef COMPAT_LINUX #ifdef COMPAT_LINUX
extern int nlinux_sysent; extern int nlinux_sysent;
extern struct sysent linux_sysent[]; extern struct sysent linux_sysent[];
extern char sigcode[], esigcode[];
extern int linux_error[]; extern int linux_error[];
extern char sigcode[], esigcode[];
int fromtramp; int fromtramp;
#endif #endif
@ -519,7 +518,6 @@ syscall(frame)
p->p_md.md_regs = (int *)&frame; p->p_md.md_regs = (int *)&frame;
opc = frame.tf_eip; opc = frame.tf_eip;
code = frame.tf_eax; code = frame.tf_eax;
params = (caddr_t)frame.tf_esp + sizeof(int);
switch (p->p_emul) { switch (p->p_emul) {
case EMUL_NETBSD: case EMUL_NETBSD:
@ -530,9 +528,6 @@ syscall(frame)
case EMUL_IBCS2_ELF: case EMUL_IBCS2_ELF:
nsys = nsvr4_sysent; nsys = nsvr4_sysent;
callp = svr4_sysent; callp = svr4_sysent;
#ifdef DEBUG_SVR4
printf("svr4_syscall(%d)\n", code);
#endif
break; break;
#endif #endif
#ifdef COMPAT_IBCS2 #ifdef COMPAT_IBCS2
@ -546,19 +541,24 @@ syscall(frame)
#endif #endif
#ifdef COMPAT_LINUX #ifdef COMPAT_LINUX
case EMUL_LINUX: case EMUL_LINUX:
/* XXXX This is really horrible */ /*
if ((char *) opc > ((char *)PS_STRINGS) - (esigcode - sigcode) * XXXX
&& (char *) opc < (char *) PS_STRINGS) { * This is a kluge until Linux sendsig() and sigreturn() are
* emulated correctly, and a Linux-compatible signal trampoline
* is written.
* Note that `opc' is the value of eip when the call gate is
* entered, which is the address right *after* the instruction.
*/
if ((caddr_t)opc > (caddr_t)PS_STRINGS - (esigcode - sigcode) &&
(caddr_t)opc <= (caddr_t)PS_STRINGS) {
nsys = nsysent; nsys = nsysent;
callp = sysent; callp = sysent;
fromtramp = 1; fromtramp = 1;
} } else {
else {
nsys = nlinux_sysent; nsys = nlinux_sysent;
callp = linux_sysent; callp = linux_sysent;
fromtramp = 0; fromtramp = 0;
} }
break; break;
#endif #endif
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
@ -567,6 +567,8 @@ syscall(frame)
#endif #endif
} }
params = (caddr_t)frame.tf_esp + sizeof(int);
switch (code) { switch (code) {
case SYS_syscall: case SYS_syscall:
#ifdef COMPAT_LINUX #ifdef COMPAT_LINUX
@ -574,20 +576,23 @@ syscall(frame)
if (p->p_emul == EMUL_LINUX && !fromtramp) if (p->p_emul == EMUL_LINUX && !fromtramp)
break; break;
#endif #endif
/*
* Code is first argument, followed by actual args.
*/
code = fuword(params); code = fuword(params);
params += sizeof(int); params += sizeof(int);
break; break;
case SYS___syscall: case SYS___syscall:
if (p->p_emul != EMUL_NETBSD) /*
code = 0; * Like syscall, but code is a quad, so as to maintain
else * quad alignment for the rest of the arguments.
code = fuword(params + _QUAD_LOWWORD * sizeof(int)); */
if (callp != sysent)
break;
code = fuword(params + _QUAD_LOWWORD * sizeof(int));
params += sizeof(quad_t); params += sizeof(quad_t);
break; break;
default: default:
/* do nothing by default */
break; break;
} }
if (code < 0 || code >= nsys) if (code < 0 || code >= nsys)
@ -599,50 +604,42 @@ syscall(frame)
/* XXX extra if() for every emul type.. */ /* XXX extra if() for every emul type.. */
if (p->p_emul == EMUL_LINUX && !fromtramp) { if (p->p_emul == EMUL_LINUX && !fromtramp) {
/* /*
* Linux passes the args in ebx, ecx, edx, esi, edi, * Linux passes the args in ebx, ecx, edx, esi, edi, in
* in increasing order. * increasing order.
*/ */
switch(argsize / sizeof (register_t)) { switch (argsize) {
default: case 20:
/* No Linux syscalls with > 5 arguments */
break;
case 5:
args[4] = frame.tf_edi; args[4] = frame.tf_edi;
/*FALLTHROUGH*/ case 16:
case 4:
args[3] = frame.tf_esi; args[3] = frame.tf_esi;
/*FALLTHROUGH*/ case 12:
case 3:
args[2] = frame.tf_edx; args[2] = frame.tf_edx;
/*FALLTHROUGH*/ case 8:
case 2:
args[1] = frame.tf_ecx; args[1] = frame.tf_ecx;
/*FALLTHROUGH*/ case 4:
case 1:
args[0] = frame.tf_ebx; args[0] = frame.tf_ebx;
break; break;
default:
panic("linux syscall with weird argument size %d",
argsize);
break;
} }
} }
else else
#endif #endif
if (argsize && (error = copyin(params, (caddr_t)args, argsize))) { if (argsize)
error = copyin(params, (caddr_t)args, argsize);
else
error = 0;
#ifdef SYSCALL_DEBUG #ifdef SYSCALL_DEBUG
scdebug_call(p, code, argsize, args); scdebug_call(p, code, args);
#endif
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p->p_tracep, code, callp->sy_narg, argsize,
&args);
#endif
goto bad;
}
#ifdef SYSCALL_DEBUG
scdebug_call(p, code, argsize, args);
#endif #endif
#ifdef KTRACE #ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL)) if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p->p_tracep, code, callp->sy_narg, argsize, &args); ktrsyscall(p->p_tracep, code, callp->sy_narg, argsize, args);
#endif #endif
if (error)
goto bad;
rval[0] = 0; rval[0] = 0;
rval[1] = frame.tf_edx; rval[1] = frame.tf_edx;
error = (*callp->sy_call)(p, args, rval); error = (*callp->sy_call)(p, args, rval);
@ -657,7 +654,6 @@ syscall(frame)
frame.tf_edx = rval[1]; frame.tf_edx = rval[1];
frame.tf_eflags &= ~PSL_C; /* carry bit */ frame.tf_eflags &= ~PSL_C; /* carry bit */
break; break;
case ERESTART: case ERESTART:
/* /*
* The offset to adjust the PC by depends on whether we entered * The offset to adjust the PC by depends on whether we entered
@ -666,11 +662,9 @@ syscall(frame)
*/ */
frame.tf_eip = opc - frame.tf_err; frame.tf_eip = opc - frame.tf_err;
break; break;
case EJUSTRETURN: case EJUSTRETURN:
/* nothing to do */ /* nothing to do */
break; break;
default: default:
bad: bad:
#ifdef COMPAT_SVR4 #ifdef COMPAT_SVR4
@ -678,9 +672,8 @@ syscall(frame)
error = svr4_error[error]; error = svr4_error[error];
#endif #endif
#ifdef COMPAT_LINUX #ifdef COMPAT_LINUX
if (p->p_emul == EMUL_LINUX && !fromtramp) { if (p->p_emul == EMUL_LINUX && !fromtramp)
error = -linux_error[error]; error = -linux_error[error];
}
#endif #endif
frame.tf_eax = error; frame.tf_eax = error;
frame.tf_eflags |= PSL_C; /* carry bit */ frame.tf_eflags |= PSL_C; /* carry bit */