svn commit: r324310 - head/sys/amd64/amd64
Konstantin Belousov
kib at FreeBSD.org
Thu Oct 5 12:29:36 UTC 2017
Author: kib
Date: Thu Oct 5 12:29:34 2017
New Revision: 324310
URL: https://svnweb.freebsd.org/changeset/base/324310
Log:
Improve amd64_get_ldt().
Provide consistent snapshot of the requested descriptors by preventing
other threads from modifying LDT while we fetch the data, lock dt_lock
around the read. Copy the data into intermediate buffer, which is
copied out after the lock is dropped.
Use guaranteed atomic (aligned volatile) reads of the descriptors to
use same-size atomic as CPU update to set A bit in the descriptor type
field.
Improve overflow checking for the descriptors range calculations and
remove unneeded casts.
Reviewed by: bde
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Modified:
head/sys/amd64/amd64/sys_machdep.c
Modified: head/sys/amd64/amd64/sys_machdep.c
==============================================================================
--- head/sys/amd64/amd64/sys_machdep.c Thu Oct 5 12:25:18 2017 (r324309)
+++ head/sys/amd64/amd64/sys_machdep.c Thu Oct 5 12:29:34 2017 (r324310)
@@ -550,34 +550,36 @@ user_ldt_deref(struct proc_ldt *pldt)
int
amd64_get_ldt(struct thread *td, struct i386_ldt_args *uap)
{
- int error = 0;
struct proc_ldt *pldt;
- int num;
struct user_segment_descriptor *lp;
+ uint64_t *data;
+ u_int i, num;
+ int error;
#ifdef DEBUG
printf("amd64_get_ldt: start=%u num=%u descs=%p\n",
uap->start, uap->num, (void *)uap->descs);
#endif
- if ((pldt = td->td_proc->p_md.md_ldt) != NULL) {
- lp = &((struct user_segment_descriptor *)(pldt->ldt_base))
- [uap->start];
- num = min(uap->num, max_ldt_segment);
- } else
+ if (uap->start >= max_ldt_segment)
return (EINVAL);
-
- if ((uap->start > (unsigned int)max_ldt_segment) ||
- ((unsigned int)num > (unsigned int)max_ldt_segment) ||
- ((unsigned int)(uap->start + num) > (unsigned int)max_ldt_segment))
- return(EINVAL);
-
- error = copyout(lp, uap->descs, num *
+ num = min(uap->num, max_ldt_segment - uap->start);
+ pldt = td->td_proc->p_md.md_ldt;
+ if (pldt == NULL)
+ return (EINVAL);
+ lp = &((struct user_segment_descriptor *)(pldt->ldt_base))[uap->start];
+ data = malloc(num * sizeof(struct user_segment_descriptor), M_TEMP,
+ M_WAITOK);
+ mtx_lock(&dt_lock);
+ for (i = 0; i < num; i++)
+ data[i] = ((volatile uint64_t *)lp)[i];
+ mtx_unlock(&dt_lock);
+ error = copyout(data, uap->descs, num *
sizeof(struct user_segment_descriptor));
- if (!error)
+ free(data, M_TEMP);
+ if (error == 0)
td->td_retval[0] = num;
-
- return(error);
+ return (error);
}
int
More information about the svn-src-head
mailing list