Subject: kern/8945: Calling pwrite() from Linux application causes panic
To: None <gnats-bugs@gnats.netbsd.org>
From: None <dave@dtsp.co.nz>
List: netbsd-bugs
Date: 12/04/1999 00:30:49
>Number: 8945
>Category: kern
>Synopsis: Calling pwrite() from Linux application causes panic
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Dec 4 00:30:01 1999
>Last-Modified:
>Originator: Dave Sainty
>Organization:
Dynamic Technology Services and Products Ltd (NZ)
>Release: Recent current
>Environment:
i386, NetBSD-current
System: NetBSD tequila.dave.dtsp.co.nz 1.4P NetBSD 1.4P (TEQUILA) #7: Sat Dec 4 20:39:06 NZDT 1999 dave@tequila.dave.dtsp.co.nz:/vol/tequila/userB/u2/NetBSD-current/src/sys/arch/i386/compile/TEQUILA i386
>Description:
pwrite() under linux emulation simply calls the NetBSD system call
implementation. linux_sysent.c contains:
{ 4, sizeof(struct sys_pwrite_args), sys_pwrite }, /* 181 = pwrite */
Now, sizeof(struct sys_pwrite_args) == 24, which presents a problem.
See trap.c:
if (linux) {
/*
* Linux passes the args in ebx, ecx, edx, esi, edi, in
* increasing order.
*/
switch (argsize >> 2) {
case 5:
args[4] = frame.tf_edi;
case 4:
args[3] = frame.tf_esi;
case 3:
args[2] = frame.tf_edx;
case 2:
args[1] = frame.tf_ecx;
case 1:
args[0] = frame.tf_ebx;
break;
default:
panic("linux syscall bogus argument size %d",
argsize);
break;
}
}
Because 24 >> 2 == 6, we panic.
>How-To-Repeat:
In my case, run a linux netscape executable that tries to link with
NetBSD X libraries. Obviously anything that calls pwrite() will do
it, but that's reasonably rare.
>Fix:
Here is "a" patch that allowed me to get past the panic and determine the real
problem.
I'm not sure if it is right though, does Linux use %ebp for the 7th block of
32 bits? I chose it by a process of elimination (it was all that was left and
usable), but it may be that Linux simply cannot handle that much data in
arguments, in which case linux_sysent.c/syscalls.master is wrong about the
arguments.
Linux libc (from suse packages) doesn't implement it...
% nm /emul/linux.new/lib/libc.so.6 |fgrep -q pwrite;echo $?
1
So currently the problem is largely academic, except that it's a trivial
userland panic.
--- sys/arch/i386/i386/trap.c.orig Sun Nov 7 09:30:38 1999
+++ sys/arch/i386/i386/trap.c Sat Dec 4 20:38:33 1999
@@ -719,10 +719,12 @@
#ifdef COMPAT_LINUX
if (linux) {
/*
- * Linux passes the args in ebx, ecx, edx, esi, edi, in
- * increasing order.
+ * Linux passes the args in ebx, ecx, edx, esi, edi, ebp,
+ * in increasing order.
*/
switch (argsize >> 2) {
+ case 6:
+ args[5] = frame.tf_ebp;
case 5:
args[4] = frame.tf_edi;
case 4:
>Audit-Trail:
>Unformatted: