Copy in segment descriptors all at once rather than one at a time.
This commit is contained in:
parent
8561123ccf
commit
b55c21bb0d
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: sys_machdep.c,v 1.57 2001/06/02 18:09:13 chs Exp $ */
|
/* $NetBSD: sys_machdep.c,v 1.58 2001/06/10 17:30:41 sommerfeld Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
@ -51,6 +51,7 @@
|
|||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/buf.h>
|
#include <sys/buf.h>
|
||||||
#include <sys/signal.h>
|
#include <sys/signal.h>
|
||||||
|
#include <sys/malloc.h>
|
||||||
|
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/syscallargs.h>
|
#include <sys/syscallargs.h>
|
||||||
@ -139,7 +140,7 @@ i386_set_ldt(p, args, retval)
|
|||||||
pmap_t pmap = p->p_vmspace->vm_map.pmap;
|
pmap_t pmap = p->p_vmspace->vm_map.pmap;
|
||||||
int fsslot, gsslot;
|
int fsslot, gsslot;
|
||||||
struct i386_set_ldt_args ua;
|
struct i386_set_ldt_args ua;
|
||||||
union descriptor desc;
|
union descriptor *descv;
|
||||||
|
|
||||||
if ((error = copyin(args, &ua, sizeof(ua))) != 0)
|
if ((error = copyin(args, &ua, sizeof(ua))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
@ -154,6 +155,13 @@ i386_set_ldt(p, args, retval)
|
|||||||
if (ua.start > 8192 || (ua.start + ua.num) > 8192)
|
if (ua.start > 8192 || (ua.start + ua.num) > 8192)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
|
descv = malloc(sizeof (*descv) * ua.num, M_TEMP, M_NOWAIT);
|
||||||
|
if (descv == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
if ((error = copyin(ua.desc, descv, sizeof (*descv) * ua.num)) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX LOCKING
|
* XXX LOCKING
|
||||||
*/
|
*/
|
||||||
@ -209,12 +217,11 @@ i386_set_ldt(p, args, retval)
|
|||||||
|
|
||||||
/* Check descriptors for access violations. */
|
/* Check descriptors for access violations. */
|
||||||
for (i = 0, n = ua.start; i < ua.num; i++, n++) {
|
for (i = 0, n = ua.start; i < ua.num; i++, n++) {
|
||||||
if ((error = copyin(&ua.desc[i], &desc, sizeof(desc))) != 0)
|
union descriptor *desc = &descv[i];
|
||||||
return (error);
|
|
||||||
|
|
||||||
switch (desc.sd.sd_type) {
|
switch (desc->sd.sd_type) {
|
||||||
case SDT_SYSNULL:
|
case SDT_SYSNULL:
|
||||||
desc.sd.sd_p = 0;
|
desc->sd.sd_p = 0;
|
||||||
break;
|
break;
|
||||||
case SDT_SYS286CGT:
|
case SDT_SYS286CGT:
|
||||||
case SDT_SYS386CGT:
|
case SDT_SYS386CGT:
|
||||||
@ -224,22 +231,29 @@ i386_set_ldt(p, args, retval)
|
|||||||
* part of the gdt. Segments in the LDT are
|
* part of the gdt. Segments in the LDT are
|
||||||
* constrained (below) to be user segments.
|
* constrained (below) to be user segments.
|
||||||
*/
|
*/
|
||||||
if (desc.gd.gd_p != 0 && !ISLDT(desc.gd.gd_selector) &&
|
if (desc->gd.gd_p != 0 &&
|
||||||
((IDXSEL(desc.gd.gd_selector) >= NGDT) ||
|
!ISLDT(desc->gd.gd_selector) &&
|
||||||
(gdt[IDXSEL(desc.gd.gd_selector)].sd.sd_dpl !=
|
((IDXSEL(desc->gd.gd_selector) >= NGDT) ||
|
||||||
SEL_UPL)))
|
(gdt[IDXSEL(desc->gd.gd_selector)].sd.sd_dpl !=
|
||||||
return (EACCES);
|
SEL_UPL))) {
|
||||||
|
error = EACCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/* Can't replace in use descriptor with gate. */
|
/* Can't replace in use descriptor with gate. */
|
||||||
if (n == fsslot || n == gsslot)
|
if (n == fsslot || n == gsslot) {
|
||||||
return (EBUSY);
|
error = EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SDT_MEMEC:
|
case SDT_MEMEC:
|
||||||
case SDT_MEMEAC:
|
case SDT_MEMEAC:
|
||||||
case SDT_MEMERC:
|
case SDT_MEMERC:
|
||||||
case SDT_MEMERAC:
|
case SDT_MEMERAC:
|
||||||
/* Must be "present" if executable and conforming. */
|
/* Must be "present" if executable and conforming. */
|
||||||
if (desc.sd.sd_p == 0)
|
if (desc->sd.sd_p == 0) {
|
||||||
return (EACCES);
|
error = EACCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SDT_MEMRO:
|
case SDT_MEMRO:
|
||||||
case SDT_MEMROA:
|
case SDT_MEMROA:
|
||||||
@ -255,34 +269,40 @@ i386_set_ldt(p, args, retval)
|
|||||||
case SDT_MEMERA:
|
case SDT_MEMERA:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Only care if it's present. */
|
/*
|
||||||
if (desc.sd.sd_p != 0)
|
* Make sure that unknown descriptor types are
|
||||||
return (EACCES);
|
* not marked present.
|
||||||
|
*/
|
||||||
|
if (desc->sd.sd_p != 0) {
|
||||||
|
error = EACCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc.sd.sd_p != 0) {
|
if (desc->sd.sd_p != 0) {
|
||||||
/* Only user (ring-3) descriptors may be present. */
|
/* Only user (ring-3) descriptors may be present. */
|
||||||
if (desc.sd.sd_dpl != SEL_UPL)
|
if (desc->sd.sd_dpl != SEL_UPL) {
|
||||||
return (EACCES);
|
error = EACCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Must be "present" if in use. */
|
/* Must be "present" if in use. */
|
||||||
if (n == fsslot || n == gsslot)
|
if (n == fsslot || n == gsslot) {
|
||||||
return (EBUSY);
|
error = EACCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now actually replace the descriptors. */
|
/* Now actually replace the descriptors. */
|
||||||
for (i = 0, n = ua.start; i < ua.num; i++, n++) {
|
for (i = 0, n = ua.start; i < ua.num; i++, n++)
|
||||||
if ((error = copyin(&ua.desc[i], &desc, sizeof(desc))) != 0)
|
pmap->pm_ldt[n] = descv[i];
|
||||||
goto out;
|
|
||||||
|
|
||||||
pmap->pm_ldt[n] = desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
*retval = ua.start;
|
*retval = ua.start;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
free(descv, M_TEMP);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
#endif /* USER_LDT */
|
#endif /* USER_LDT */
|
||||||
|
Loading…
Reference in New Issue
Block a user