Skip to content

Commit

Permalink
OS-4201 need GS support in arch_prctl()
Browse files Browse the repository at this point in the history
  • Loading branch information
jjelinek committed Apr 17, 2015
1 parent a9dea39 commit ba34187
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 7 deletions.
7 changes: 5 additions & 2 deletions usr/src/uts/common/brand/lx/os/lx_brand.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,13 +549,16 @@ lx_restorecontext(ucontext_t *ucp)

#if defined(__amd64)
/*
* Override the fsbase in the context with the value provided through
* the Linux arch_prctl(2) system call.
* Override the fs/gsbase in the context with the value provided
* through the Linux arch_prctl(2) system call.
*/
if (flags & LX_UC_STACK_BRAND) {
if (lwpd->br_lx_fsbase != 0) {
ucp->uc_mcontext.gregs[REG_FSBASE] = lwpd->br_lx_fsbase;
}
if (lwpd->br_lx_gsbase != 0) {
ucp->uc_mcontext.gregs[REG_GSBASE] = lwpd->br_lx_gsbase;
}
}
#endif
}
Expand Down
8 changes: 6 additions & 2 deletions usr/src/uts/common/brand/lx/os/lx_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,11 @@ lx_exec()
*/
(void) lx_ptrace_stop_for_option(LX_PTRACE_O_TRACEEXEC, B_FALSE, 0, 0);

/* clear the fsbase values until the app. can reinitialize them */
/* clear the fs/gsbase values until the app. can reinitialize them */
lwpd->br_lx_fsbase = NULL;
lwpd->br_ntv_fsbase = NULL;
lwpd->br_lx_gsbase = NULL;
lwpd->br_ntv_gsbase = NULL;

/*
* Clear the native stack flags. This will be reinitialised by
Expand Down Expand Up @@ -341,9 +343,11 @@ lx_initlwp(klwp_t *lwp, void *lwpbd)
bcopy(plwpd->br_tls, lwpd->br_tls, sizeof (lwpd->br_tls));
lwpd->br_ppid = plwpd->br_pid;
lwpd->br_ptid = curthread->t_tid;
/* The child inherits the 2 fsbase values from the parent */
/* The child inherits the fs/gsbase values from the parent */
lwpd->br_lx_fsbase = plwpd->br_lx_fsbase;
lwpd->br_ntv_fsbase = plwpd->br_ntv_fsbase;
lwpd->br_lx_gsbase = plwpd->br_lx_gsbase;
lwpd->br_ntv_gsbase = plwpd->br_ntv_gsbase;
} else {
/*
* Oddball case: the parent thread isn't a Linux process.
Expand Down
2 changes: 2 additions & 0 deletions usr/src/uts/common/brand/lx/sys/lx_brand.h
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ struct lx_lwp_data {
/* descriptors used by libc for TLS */
ulong_t br_lx_fsbase; /* lx fsbase for 64-bit thread ptr */
ulong_t br_ntv_fsbase; /* native fsbase 64-bit thread ptr */
ulong_t br_lx_gsbase; /* lx user-land gsbase */
ulong_t br_ntv_gsbase; /* native user-land gsbase */
pid_t br_pid; /* converted pid for this thread */
pid_t br_tgid; /* thread group ID for this thread */
pid_t br_ppid; /* parent pid for this thread */
Expand Down
23 changes: 22 additions & 1 deletion usr/src/uts/common/brand/lx/syscall/lx_thread_area.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ lx_arch_prctl(int code, ulong_t addr)
lx_lwp_data_t *llwp = lwptolxlwp(lwp);
pcb_t *pcb = &lwp->lwp_pcb;

/* We currently only support [g|s]et_fs */
switch (code) {
case LX_ARCH_GET_FS:
if (copyout(&llwp->br_lx_fsbase, (void *)addr,
Expand All @@ -70,6 +69,28 @@ lx_arch_prctl(int code, ulong_t addr)
kpreempt_enable();
break;

case LX_ARCH_GET_GS:
if (copyout(&llwp->br_lx_gsbase, (void *)addr,
sizeof (llwp->br_lx_gsbase)) != 0) {
return (set_errno(EFAULT));
}
break;

case LX_ARCH_SET_GS:
llwp->br_lx_gsbase = addr;

kpreempt_disable();
if (pcb->pcb_gsbase != llwp->br_lx_gsbase) {
pcb->pcb_gsbase = llwp->br_lx_gsbase;

/*
* Ensure we go out via update_sregs.
*/
pcb->pcb_rupdate = 1;
}
kpreempt_enable();
break;

default:
return (set_errno(EINVAL));
}
Expand Down
22 changes: 20 additions & 2 deletions usr/src/uts/intel/brand/lx/lx_archdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,10 +733,11 @@ lx_runexe(klwp_t *lwp, void *ucp)
struct pcb *pcb = &lwp->lwp_pcb;

/*
* Preserve the %fsbase value for this LWP, as set and used by
* native illumos code.
* Preserve the %fs/%gsbase value for this LWP, as set and used
* by native illumos code.
*/
lwpd->br_ntv_fsbase = pcb->pcb_fsbase;
lwpd->br_ntv_gsbase = pcb->pcb_gsbase;

return (getsetcontext(SETCONTEXT, ucp));
} else {
Expand Down Expand Up @@ -820,6 +821,23 @@ lx_switch_to_native(klwp_t *lwp)
}
kpreempt_enable();
}
/*
* ... and the correct %gsbase
*/
if (lwpd->br_ntv_gsbase != 0) {
struct pcb *pcb = &lwp->lwp_pcb;

kpreempt_disable();
if (pcb->pcb_gsbase != lwpd->br_ntv_gsbase) {
pcb->pcb_gsbase = lwpd->br_ntv_gsbase;

/*
* Ensure we go out via update_sregs.
*/
pcb->pcb_rupdate = 1;
}
kpreempt_enable();
}
break;
}

Expand Down

0 comments on commit ba34187

Please sign in to comment.