Subject: lib/34210: bus error in getdents() on 4.0_BETA with 3.0 binary
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <nakayama@NetBSD.org>
List: netbsd-bugs
Date: 08/16/2006 02:55:00
>Number: 34210
>Category: lib
>Synopsis: bus error in getdents() on 4.0_BETA with 3.0 binary
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Aug 16 02:55:00 +0000 2006
>Originator: Takeshi Nakayama
>Release: NetBSD 4.0_BETA
>Organization:
>Environment:
System: NetBSD eos 4.0_BETA NetBSD 4.0_BETA (EOS) #0: Tue Aug 15 08:35:41 JST 2006 takeshi@eos:/work/netbsd-4/src/sys/arch/sparc64/compile/EOS sparc64
Architecture: sparc64
Machine: sparc64
>Description:
Running 3.0 binary on 4.0_BETA (or -current) causes bus error as
below.
% uname -r
4.0_BETA
% file /usr/pkg/bin/zsh
/usr/pkg/bin/zsh: ELF 64-bit MSB executable, SPARC V9, version 1 (SYSV), for NetBSD 3.0, dynamically linked (uses shared libs), for NetBSD 3.0, stripped
% /usr/pkg/bin/zsh
zsh%
(do command completion or filename expansion on directory which has many files)
Bus error /usr/pkg/bin/zsh
Debugger traces are here. It seems that the cause is 64-bit load on
non 8-bytes aligned address.
(gdb) run
Starting program: /usr/pkg/bin/zsh
:
Program received signal SIGBUS, Bus error.
0x00000000404dbef0 in getdents () from /lib/libc.so.12.145
(gdb) where
#0 0x00000000404dbef0 in getdents () from /lib/libc.so.12.145
#1 0x00000000404dcb90 in __opendir2 () from /lib/libc.so.12.145
#2 0x000000004160a610 in getcpat () from /usr/pkg/lib/zsh/4.2.6/zsh/compctl.so
#3 0x000000004160dfd0 in getcpat () from /usr/pkg/lib/zsh/4.2.6/zsh/compctl.so
:
(gdb) disassemble 0x404dbee8 0x404dbef8
Dump of assembler code from 0x404dbee8 to 0x404dbef8:
0x404dbee8 <getdents+72>: lduh [ %g4 + 0xa ], %g1
0x404dbeec <getdents+76>: cmp %g3, 0x100
0x404dbef0 <getdents+80>: ldx [ %g4 ], %g2
0x404dbef4 <getdents+84>: movcc %icc, %l1, %g1
End of assembler dump.
(gdb) print/x $g4
$1 = 0x24178c
>How-To-Repeat:
Run binaries which contain opendir()/getdents() and compiled on 3.0
on 4.0_BETA/sparc64.
>Fix:
A quick and dirty fix is the following. This patch avoid 64-bit load.
Another candidate is that return value of getdents() always align to
8-bytes to avoid an unaligned buffer address in the next call.
Index: compat_getdents.c
===================================================================
RCS file: /cvsroot/src/lib/libc/compat/sys/compat_getdents.c,v
retrieving revision 1.1
diff -u -d -r1.1 compat_getdents.c
--- compat_getdents.c 13 Sep 2005 01:44:09 -0000 1.1
+++ compat_getdents.c 15 Aug 2006 05:45:49 -0000
@@ -73,7 +73,7 @@
*/
for (; ndp < endp; ndp = nndp) {
nndp = _DIRENT_NEXT(ndp);
- odp->d_ino = (u_int32_t)ndp->d_ino;
+ odp->d_ino = ((u_int32_t *)(void *)&ndp->d_ino)[_QUAD_LOWWORD];
if (ndp->d_namlen >= sizeof(odp->d_name))
odp->d_namlen = sizeof(odp->d_name) - 1;
else