Copy in segment descriptors all at once rather than one at a time.

This commit is contained in:
sommerfeld 2001-06-10 17:30:41 +00:00
parent 8561123ccf
commit b55c21bb0d

View File

@ -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 */