Subject: Bugs in i386_get_ldt, i386_set_ldt
To: None <netbsd-bugs@NetBSD.ORG>
From: None <r_friedl@informatik.uni-kl.de>
List: netbsd-bugs
Date: 10/12/1995 16:27:13
Function i386_get_ldt contains splx(s), where s is uninitialized.
Function i386_set_ldt has a bug when reallocating the LDT. It uses
the new length to free the old LDT.
This is ficed by the following patch.
--- arch/i386/i386/sys_machdep.c.orig Sun May 7 12:05:34 1995
+++ arch/i386/i386/sys_machdep.c Sat Oct 7 02:55:16 1995
@@ -143,7 +143,6 @@
struct pcb *pcb = &p->p_addr->u_pcb;
int nldt, num;
union descriptor *lp;
- int s;
struct i386_get_ldt_args ua, *uap;
if ((error = copyin(args, &ua, sizeof(struct i386_get_ldt_args))) < 0)
@@ -166,10 +165,8 @@
nldt = NLDT;
lp = ldt;
}
- if (uap->start > nldt) {
- splx(s);
+ if (uap->start > nldt)
return (EINVAL);
- }
lp += uap->start;
num = min(uap->num, nldt - uap->start);
@@ -211,23 +208,25 @@
/* allocate user ldt */
if (!pcb->pcb_ldt || (uap->start + uap->num) > pcb->pcb_ldt_len) {
size_t oldlen, len;
- union descriptor *new_ldt;
+ union descriptor *old_ldt, *new_ldt;
- if (!pcb->pcb_ldt)
+ if (!pcb->pcb_ldt) {
pcb->pcb_ldt_len = 512;
+ oldlen = NLDT * sizeof(union descriptor);
+ old_ldt = ldt;
+ }
+ else {
+ oldlen = pcb->pcb_ldt_len * sizeof(union descriptor);
+ old_ldt = (union descriptor *)pcb->pcb_ldt;
+ }
while ((uap->start + uap->num) > pcb->pcb_ldt_len)
pcb->pcb_ldt_len *= 2;
len = pcb->pcb_ldt_len * sizeof(union descriptor);
new_ldt = (union descriptor *)kmem_alloc(kernel_map, len);
- if (!pcb->pcb_ldt) {
- oldlen = NLDT * sizeof(union descriptor);
- bcopy(ldt, new_ldt, oldlen);
- } else {
- oldlen = pcb->pcb_ldt_len * sizeof(union descriptor);
- bcopy(pcb->pcb_ldt, new_ldt, oldlen);
+ bcopy(old_ldt, new_ldt, oldlen);
+ if (pcb->pcb_ldt)
kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt,
oldlen);
- }
bzero((caddr_t)new_ldt + oldlen, len - oldlen);
pcb->pcb_ldt = (caddr_t)new_ldt;
gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt;