amd64: Cleanups to setting TLS registers for Linux binaries.
- Use update_pcb_bases() when updating FS or GS base addresses to permit use of FSBASE and GSBASE in Linux processes. This also sets PCB_FULL_IRET. linux32 was setting PCB_32BIT which should be a no-op (exec sets it). - Remove write-only variables to construct unused segment descriptors for linux32. Reviewed by: kib MFC after: 1 week Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D29026
This commit is contained in:
parent
9221145868
commit
704547ce1c
@ -251,7 +251,7 @@ linux_arch_prctl(struct thread *td, struct linux_arch_prctl_args *args)
|
||||
switch (args->code) {
|
||||
case LINUX_ARCH_SET_GS:
|
||||
if (args->addr < VM_MAXUSER_ADDRESS) {
|
||||
set_pcb_flags(pcb, PCB_FULL_IRET);
|
||||
update_pcb_bases(pcb);
|
||||
pcb->pcb_gsbase = args->addr;
|
||||
td->td_frame->tf_gs = _ugssel;
|
||||
error = 0;
|
||||
@ -260,7 +260,7 @@ linux_arch_prctl(struct thread *td, struct linux_arch_prctl_args *args)
|
||||
break;
|
||||
case LINUX_ARCH_SET_FS:
|
||||
if (args->addr < VM_MAXUSER_ADDRESS) {
|
||||
set_pcb_flags(pcb, PCB_FULL_IRET);
|
||||
update_pcb_bases(pcb);
|
||||
pcb->pcb_fsbase = args->addr;
|
||||
td->td_frame->tf_fs = _ufssel;
|
||||
error = 0;
|
||||
@ -290,6 +290,7 @@ linux_set_cloned_tls(struct thread *td, void *desc)
|
||||
return (EPERM);
|
||||
|
||||
pcb = td->td_pcb;
|
||||
update_pcb_bases(pcb);
|
||||
pcb->pcb_fsbase = (register_t)desc;
|
||||
td->td_frame->tf_fs = _ufssel;
|
||||
|
||||
|
@ -394,11 +394,9 @@ linux_old_select(struct thread *td, struct linux_old_select_args *args)
|
||||
int
|
||||
linux_set_cloned_tls(struct thread *td, void *desc)
|
||||
{
|
||||
struct user_segment_descriptor sd;
|
||||
struct l_user_desc info;
|
||||
struct pcb *pcb;
|
||||
int error;
|
||||
int a[2];
|
||||
|
||||
error = copyin(desc, &info, sizeof(struct l_user_desc));
|
||||
if (error) {
|
||||
@ -410,14 +408,10 @@ linux_set_cloned_tls(struct thread *td, void *desc)
|
||||
if (error)
|
||||
linux_msg(td, "set_cloned_tls copyout info failed!");
|
||||
|
||||
a[0] = LINUX_LDT_entry_a(&info);
|
||||
a[1] = LINUX_LDT_entry_b(&info);
|
||||
|
||||
memcpy(&sd, &a, sizeof(a));
|
||||
pcb = td->td_pcb;
|
||||
update_pcb_bases(pcb);
|
||||
pcb->pcb_gsbase = (register_t)info.base_addr;
|
||||
td->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL);
|
||||
set_pcb_flags(pcb, PCB_32BIT);
|
||||
}
|
||||
|
||||
return (error);
|
||||
@ -668,9 +662,7 @@ linux_set_thread_area(struct thread *td,
|
||||
struct linux_set_thread_area_args *args)
|
||||
{
|
||||
struct l_user_desc info;
|
||||
struct user_segment_descriptor sd;
|
||||
struct pcb *pcb;
|
||||
int a[2];
|
||||
int error;
|
||||
|
||||
error = copyin(args->desc, &info, sizeof(struct l_user_desc));
|
||||
@ -721,18 +713,9 @@ linux_set_thread_area(struct thread *td,
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (LINUX_LDT_empty(&info)) {
|
||||
a[0] = 0;
|
||||
a[1] = 0;
|
||||
} else {
|
||||
a[0] = LINUX_LDT_entry_a(&info);
|
||||
a[1] = LINUX_LDT_entry_b(&info);
|
||||
}
|
||||
|
||||
memcpy(&sd, &a, sizeof(a));
|
||||
pcb = td->td_pcb;
|
||||
update_pcb_bases(pcb);
|
||||
pcb->pcb_gsbase = (register_t)info.base_addr;
|
||||
set_pcb_flags(pcb, PCB_32BIT);
|
||||
update_gdt_gsbase(td, info.base_addr);
|
||||
|
||||
return (0);
|
||||
|
Loading…
Reference in New Issue
Block a user