Subject: port-i386/19724: page fault trap in i386_set_ldt()
To: None <gnats-bugs@gnats.netbsd.org>
From: None <stephenm@employees.org>
List: netbsd-bugs
Date: 01/07/2003 05:15:26
>Number:         19724
>Category:       port-i386
>Synopsis:       page fault trap in i386_set_ldt()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-i386-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jan 07 06:32:00 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Stephen Ma
>Release:        NetBSD 1.6L 2003-01-04
>Organization:
	People's Front for the correct spelling of the word "Organisation"
>Environment:
System: NetBSD whitewater.local 1.6L NetBSD 1.6L (WHITEWATER) #56: Sun Jan 5 22:02:22 PST 2003 root@whitewater.local:/v1/netbsd/obj/src/sys/arch/i386/compile/WHITEWATER i386
Architecture: i386
Machine: i386
>Description:
The kernel can crash in memcpy(), called from i386_set_ldt() when running wine.
I can only get this crash to occur when running the Windows Real Player 8 Basic
under wine-20021125nb1, although I've not tested many windows programs.

DDB traceback etc follows:

kernel: page fault trap, code=0
Stopped in pid 320 (wine) at    memcpy+0x1e:    repe movsl      (%esi),%es:(%edi)
db> trace
memcpy(cae21b4c,48632af0,cae78f78,0,cae78f80) at memcpy+0x1e
sys_sysarch(cae21b4c,cae78f80,cae78f78,cae21b4c,0) at sys_sysarch+0x75
syscall_plain(1f,4863008f,4863001f,4863001f,1007) at syscall_plain+0xa7
db> show registers
ds                0x10
es                0x10
fs                0x30
gs                0x10
edi         0xcaf35000  end+0xac33b58
esi         0xcae71000  end+0xab6fb58
ebp         0xcae78f10  end+0xab77a68
ebx             0x1000
edx             0x1000
ecx              0x400
eax         0xcaf35000  end+0xac33b58
eip         0xc027b1ba  memcpy+0x1e
cs                 0x8
eflags         0x10206
esp         0xcae78ebc  end+0xab77a14
ss                0x10
memcpy+0x1e:    repe movsl      (%esi),%es:(%edi)
db> show object 0xcaf35000
OBJECT 0xcaf35000: locked=808202288, pgops=0x30302c30, npages=807411722, refs=87
5572281
db> show object 0xcae71000
kernel: page fault trap, code=0
Faulted in DDB; continuing...

>How-To-Repeat:
Run Windows Real Player 8 Basic under wine-20021125nb1. The crash seems to
happen after about 2-3 minutes of audio playback.
>Fix:
Looks like there's a bogus call to uvm_km_free() in i386_set_idt().

sys/arch/i386/i386/sys_machdep.c:
     $NetBSD: sys_machdep.c,v 1.66 2002/10/08 20:23:27 fvdl Exp $

--- sys_machdep.c.~1.66.~	Wed Oct  9 03:03:44 2002
+++ sys_machdep.c	Sun Jan  5 21:45:41 2003
@@ -197,7 +197,7 @@ i386_set_ldt(p, args, retval)
 		goto out;
 	
 	/* Check descriptors for access violations. */
-	for (i = 0, n = ua.start; i < ua.num; i++, n++) {
+	for (i = 0; i < ua.num; i++) {
 		union descriptor *desc = &descv[i];
 
 		switch (desc->sd.sd_type) {
@@ -267,8 +267,7 @@ i386_set_ldt(p, args, retval)
 
 	/* allocate user ldt */
 	simple_lock(&pmap->pm_lock);
-	if (pmap->pm_ldt == 0 || (ua.start + ua.num) > pmap->pm_ldt_len) {
-		old_ldt = pmap->pm_ldt;
+	if (pmap->pm_ldt == NULL || (ua.start + ua.num) > pmap->pm_ldt_len) {
 		if (pmap->pm_flags & PMF_USER_LDT)
 			ldt_len = pmap->pm_ldt_len;
 		else
@@ -299,7 +298,6 @@ i386_set_ldt(p, args, retval)
 
 		if (old_ldt != NULL) {
 			old_len = pmap->pm_ldt_len * sizeof(union descriptor);
-			uvm_km_free(kernel_map, (vaddr_t)old_ldt, old_len);
 		} else {
 			old_len = NLDT * sizeof(union descriptor);
 			old_ldt = ldt;

>Release-Note:
>Audit-Trail:
>Unformatted: