On 23.06.2019 05:44, Christos Zoulas wrote: > In article <272cb7c0-c171-8b87-393a-0ccdd042b84b%gmx.com@localhost>, > Kamil Rytarowski <n54%gmx.com@localhost> wrote: >> -=-=-=-=-=- >> -=-=-=-=-=- >> >> On 22.06.2019 16:38, maya%netbsd.org@localhost wrote: >>> The following kernel works with unmodified -current userland. >>> NetBSD 7.99.75 >>> >>> Reverting to the git mirror Dec 1 2018 with this list of commits also >>> works. >>> >>> 4cab1e757c7197a01b6dc268c0104fa43ab7f0aa >>> 5542798943417f4d1bdb61d0a49a9f8c1c37445c >>> ef20f297e5f1527c1b54d4b2de8280a6cca21c71 >>> 80d084c7ddc1104b2bf191ccaa8a5347e71253ef >>> >>> We don't need any changes to GDB whatsoever. I didn't even rebuild the >>> binary. >>> >>> It's a really tricky bisect because every few days changes are made to >>> re-break it. >>> >> >> My patch adds i386 to recognized osabi/bfd, but there is trash in >> registers. Something gets malformed, might it be related to these >> regressions? > > Maxv disabled 64 bit ptrace on a 32 bit tracee. The following patch > puts it back, and an unmodified gdb from head now can trace a 32 bit > binary again. > > Index: machdep.c > =================================================================== > RCS file: /cvsroot/src/sys/arch/amd64/amd64/machdep.c,v > retrieving revision 1.332 > diff -u -p -u -r1.332 machdep.c > --- machdep.c 12 Jun 2019 14:28:38 -0000 1.332 > +++ machdep.c 23 Jun 2019 03:40:54 -0000 > @@ -2095,40 +2095,46 @@ cpu_setmcontext(struct lwp *l, const mco > int > cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) > { > - struct proc *p __diagused = l->l_proc; > + struct proc *p = l->l_proc; > struct trapframe *tf = l->l_md.md_regs; > const __greg_t *gr; > uint16_t sel; > + const bool pk32 = (p->p_flag & PK_32) != 0; > > - KASSERT((p->p_flag & PK_32) == 0); > gr = mcp->__gregs; > > if (((gr[_REG_RFLAGS] ^ tf->tf_rflags) & PSL_USERSTATIC) != 0) > return EINVAL; > +#define VUD(sel) (pk32 ? VALID_USER_DSEL32(sel) : VALID_USER_DSEL(sel)) > +#define VUF(sel) (pk32 ? (VALID_USER_DSEL32(sel) || VALID_USER_FSEL32(sel)) \ > + : VALID_USER_DSEL(sel)) > +#define VUG(sel) (pk32 ? (VALID_USER_DSEL32(sel) || VALID_USER_GSEL32(sel)) \ > + : VALID_USER_DSEL(sel)) > +#define VUC(sel) (pk32 ? VALID_USER_CSEL32(sel) : VALID_USER_CSEL(sel)) > > sel = gr[_REG_ES] & 0xffff; > - if (sel != 0 && !VALID_USER_DSEL(sel)) > + if (sel != 0 && !VUD(sel)) > return EINVAL; > > sel = gr[_REG_FS] & 0xffff; > - if (sel != 0 && !VALID_USER_DSEL(sel)) > + if (sel != 0 && !VUF(sel)) > return EINVAL; > > sel = gr[_REG_GS] & 0xffff; > - if (sel != 0 && !VALID_USER_DSEL(sel)) > + if (sel != 0 && !VUG(sel)) > return EINVAL; > > sel = gr[_REG_DS] & 0xffff; > - if (!VALID_USER_DSEL(sel)) > + if (!VUD(sel)) > return EINVAL; > > #ifndef XENPV > sel = gr[_REG_SS] & 0xffff; > - if (!VALID_USER_DSEL(sel)) > + if (!VUD(sel)) > return EINVAL; > > sel = gr[_REG_CS] & 0xffff; > - if (!VALID_USER_CSEL(sel)) > + if (!VUC(sel)) > return EINVAL; > #endif > > Index: process_machdep.c > =================================================================== > RCS file: /cvsroot/src/sys/arch/amd64/amd64/process_machdep.c,v > retrieving revision 1.39 > diff -u -p -u -r1.39 process_machdep.c > --- process_machdep.c 11 Feb 2019 14:59:32 -0000 1.39 > +++ process_machdep.c 23 Jun 2019 03:40:54 -0000 > @@ -100,42 +100,48 @@ process_frame(struct lwp *l) > } > > int > -process_read_regs(struct lwp *l, struct reg *regs) > +process_read_regs(struct lwp *l, struct reg *regp) > { > struct trapframe *tf = process_frame(l); > - struct proc *p = l->l_proc; > + long *regs = regp->regs; > + const bool pk32 = (l->l_proc->p_flag & PK_32) != 0; > > - if (p->p_flag & PK_32) { > - return EINVAL; > - } > - > - regs->regs[_REG_RDI] = tf->tf_rdi; > - regs->regs[_REG_RSI] = tf->tf_rsi; > - regs->regs[_REG_RDX] = tf->tf_rdx; > - regs->regs[_REG_R10] = tf->tf_r10; > - regs->regs[_REG_R8] = tf->tf_r8; > - regs->regs[_REG_R9] = tf->tf_r9; > + regs[_REG_RDI] = tf->tf_rdi; > + regs[_REG_RSI] = tf->tf_rsi; > + regs[_REG_RDX] = tf->tf_rdx; > + regs[_REG_R10] = tf->tf_r10; > + regs[_REG_R8] = tf->tf_r8; > + regs[_REG_R9] = tf->tf_r9; > /* argX not touched */ > - regs->regs[_REG_RCX] = tf->tf_rcx; > - regs->regs[_REG_R11] = tf->tf_r11; > - regs->regs[_REG_R12] = tf->tf_r12; > - regs->regs[_REG_R13] = tf->tf_r13; > - regs->regs[_REG_R14] = tf->tf_r14; > - regs->regs[_REG_R15] = tf->tf_r15; > - regs->regs[_REG_RBP] = tf->tf_rbp; > - regs->regs[_REG_RBX] = tf->tf_rbx; > - regs->regs[_REG_RAX] = tf->tf_rax; > - regs->regs[_REG_GS] = 0; > - regs->regs[_REG_FS] = 0; > - regs->regs[_REG_ES] = GSEL(GUDATA_SEL, SEL_UPL); > - regs->regs[_REG_DS] = GSEL(GUDATA_SEL, SEL_UPL); > - regs->regs[_REG_TRAPNO] = tf->tf_trapno; > - regs->regs[_REG_ERR] = tf->tf_err; > - regs->regs[_REG_RIP] = tf->tf_rip; > - regs->regs[_REG_CS] = LSEL(LUCODE_SEL, SEL_UPL); > - regs->regs[_REG_RFLAGS] = tf->tf_rflags; > - regs->regs[_REG_RSP] = tf->tf_rsp; > - regs->regs[_REG_SS] = LSEL(LUDATA_SEL, SEL_UPL); > + regs[_REG_RCX] = tf->tf_rcx; > + regs[_REG_R11] = tf->tf_r11; > + regs[_REG_R12] = tf->tf_r12; > + regs[_REG_R13] = tf->tf_r13; > + regs[_REG_R14] = tf->tf_r14; > + regs[_REG_R15] = tf->tf_r15; > + regs[_REG_RBP] = tf->tf_rbp; > + regs[_REG_RBX] = tf->tf_rbx; > + regs[_REG_RAX] = tf->tf_rax; > + if (pk32) { > + regs[_REG_GS] = tf->tf_gs & 0xffff; > + regs[_REG_FS] = tf->tf_fs & 0xffff; > + regs[_REG_ES] = tf->tf_es & 0xffff; > + regs[_REG_DS] = tf->tf_ds & 0xffff; > + regs[_REG_CS] = tf->tf_cs & 0xffff; > + regs[_REG_SS] = tf->tf_ss & 0xffff; > + } else { > + regs[_REG_GS] = 0; > + regs[_REG_FS] = 0; > + regs[_REG_ES] = GSEL(GUDATA_SEL, SEL_UPL); > + regs[_REG_DS] = GSEL(GUDATA_SEL, SEL_UPL); > + regs[_REG_CS] = LSEL(LUCODE_SEL, SEL_UPL); > + regs[_REG_SS] = LSEL(LUDATA_SEL, SEL_UPL); > + } > + regs[_REG_TRAPNO] = tf->tf_trapno; > + regs[_REG_ERR] = tf->tf_err; > + regs[_REG_RIP] = tf->tf_rip; > + regs[_REG_RFLAGS] = tf->tf_rflags; > + regs[_REG_RSP] = tf->tf_rsp; > > return 0; > } > @@ -143,11 +149,6 @@ process_read_regs(struct lwp *l, struct > int > process_read_fpregs(struct lwp *l, struct fpreg *regs, size_t *sz) > { > - struct proc *p = l->l_proc; > - > - if (p->p_flag & PK_32) { > - return EINVAL; > - } > > process_read_fpregs_xmm(l, ®s->fxstate); > > @@ -157,11 +158,6 @@ process_read_fpregs(struct lwp *l, struc > int > process_read_dbregs(struct lwp *l, struct dbreg *regs, size_t *sz) > { > - struct proc *p = l->l_proc; > - > - if (p->p_flag & PK_32) { > - return EINVAL; > - } > > x86_dbregs_read(l, regs); > > @@ -172,13 +168,9 @@ int > process_write_regs(struct lwp *l, const struct reg *regp) > { > struct trapframe *tf = process_frame(l); > - struct proc *p = l->l_proc; > int error; > const long *regs = regp->regs; > - > - if (p->p_flag & PK_32) { > - return EINVAL; > - } > + const bool pk32 = (l->l_proc->p_flag & PK_32) != 0; > > /* > * Check for security violations. Note that struct regs is compatible > @@ -204,16 +196,25 @@ process_write_regs(struct lwp *l, const > tf->tf_rbp = regs[_REG_RBP]; > tf->tf_rbx = regs[_REG_RBX]; > tf->tf_rax = regs[_REG_RAX]; > - tf->tf_gs = 0; > - tf->tf_fs = 0; > - tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); > - tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); > + if (pk32) { > + tf->tf_gs = regs[_REG_GS] & 0xffff; > + tf->tf_fs = regs[_REG_FS] & 0xffff; > + tf->tf_es = regs[_REG_ES] & 0xffff; > + tf->tf_ds = regs[_REG_DS] & 0xffff; > + tf->tf_cs = regs[_REG_CS] & 0xffff; > + tf->tf_ss = regs[_REG_SS] & 0xffff; > + } else { > + tf->tf_gs = 0; > + tf->tf_fs = 0; > + tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); > + tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); > + tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL); > + tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL); > + } > /* trapno, err not touched */ > tf->tf_rip = regs[_REG_RIP]; > - tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL); > tf->tf_rflags = regs[_REG_RFLAGS]; > tf->tf_rsp = regs[_REG_RSP]; > - tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL); > > #ifdef XENPV > /* see comment in cpu_setmcontext */ > @@ -227,11 +228,6 @@ process_write_regs(struct lwp *l, const > int > process_write_fpregs(struct lwp *l, const struct fpreg *regs, size_t sz) > { > - struct proc *p = l->l_proc; > - > - if (p->p_flag & PK_32) { > - return EINVAL; > - } > > process_write_fpregs_xmm(l, ®s->fxstate); > return 0; > @@ -240,13 +236,8 @@ process_write_fpregs(struct lwp *l, cons > int > process_write_dbregs(struct lwp *l, const struct dbreg *regs, size_t sz) > { > - struct proc *p = l->l_proc; > int error; > > - if (p->p_flag & PK_32) { > - return EINVAL; > - } > - > /* > * Check for security violations. > */ > @@ -276,11 +267,6 @@ int > process_set_pc(struct lwp *l, void *addr) > { > struct trapframe *tf = process_frame(l); > - struct proc *p = l->l_proc; > - > - if (p->p_flag & PK_32) { > - return EINVAL; > - } > > if ((uint64_t)addr >= VM_MAXUSER_ADDRESS) > return EINVAL; > We still want to pass FS/GS to userland through ptrace(2). For PK_32 we could keep check for VM_MAXUSER_ADDRESS32.
Attachment:
signature.asc
Description: OpenPGP digital signature