Subject: port-i386/944: LDT manipulation can hard-hang an i386 system
To: None <gnats-admin@NetBSD.ORG>
From: John Kohl <jtk@kolvir.blrc.ma.us>
List: netbsd-bugs
Date: 04/06/1995 21:35:04
>Number:         944
>Category:       port-i386
>Synopsis:       LDT manipulation of LDTEs for segs 0x17 can hard-hang an i386 system
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Apr  6 21:35:03 1995
>Originator:     John Kohl
>Organization:
NetBSD Kernel Hackers `R` Us
>Release:        -current
>Environment:
	
System: NetBSD kolvir 1.0A NetBSD 1.0A (KOLVIR) #187: Thu Apr 6 22:52:57 EDT 1995 jtk@kolvir:/u1/NetBSD-current/src/sys/arch/i386/compile/KOLVIR i386

>Description:
In a kernel with USER_LDT enabled, a user can hang the system hard (ddb
can't get control on the console--reset button needed).

>How-To-Repeat:

Run this program.  When the program replaces its LDT entry for
its code segment (corresponding to %cs = 0x1f),	it will get a SIGBUS
upon return to user space because the code segment descriptor will be of
type SDT_SYSNULL.  The kernel tries to deliver SIGBUS, and sets %cs to
0x1f.  The signal is started, it takes another SIGBUS, and something bad
happens (not sure what) that locks up the processor completely.

#include <signal.h>
#include <sys/types.h>
#include <machine/segments.h>
#include <machine/sysarch.h>

sigbus(int sig, int code, struct sigcontext *scp)
{
	printf("sigbus\n");
	abort();
	exit(1);
}
main()
{
    int ldte[2];
    register int i;
    register int rval;

    signal(SIGBUS,sigbus);
    for (i = 0; i < 8192; i++) {
	ldte[0] = 0;
	ldte[1] = 0xe000; /* present, DPL = 3 */
	rval = i386_set_ldt(i, (union descriptor *)ldte, 1);
	printf("entry %d: %d\n", i, rval);
	sleep(1);
    }
    exit(0);
}

>Fix:

>Audit-Trail:
>Unformatted: