From owner-svn-src-stable-12@freebsd.org Sun Aug 23 19:19:01 2020 Return-Path: Delivered-To: svn-src-stable-12@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id B20DD3C5456; Sun, 23 Aug 2020 19:19:01 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BZQ6F4H67z40hB; Sun, 23 Aug 2020 19:19:01 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 76090C318; Sun, 23 Aug 2020 19:19:01 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 07NJJ15c056256; Sun, 23 Aug 2020 19:19:01 GMT (envelope-from trasz@FreeBSD.org) Received: (from trasz@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 07NJJ17O056255; Sun, 23 Aug 2020 19:19:01 GMT (envelope-from trasz@FreeBSD.org) Message-Id: <202008231919.07NJJ17O056255@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: trasz set sender to trasz@FreeBSD.org using -f From: Edward Tomasz Napierala Date: Sun, 23 Aug 2020 19:19:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r364503 - stable/12/sys/amd64/linux X-SVN-Group: stable-12 X-SVN-Commit-Author: trasz X-SVN-Commit-Paths: stable/12/sys/amd64/linux X-SVN-Commit-Revision: 364503 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-12@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for only the 12-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Aug 2020 19:19:01 -0000 Author: trasz Date: Sun Aug 23 19:19:00 2020 New Revision: 364503 URL: https://svnweb.freebsd.org/changeset/base/364503 Log: MFC r347231: Support PTRACE_GETREGSET w/ NT_PRSTATUS in Linux ptrace(2). While Linux strace(1) doesn't strictly require it - it has a fallback to PTRACE_GETREGS - it's a newer interface, so we better support it before the old one is deprecated. Sponsored by: The FreeBSD Foundation Modified: stable/12/sys/amd64/linux/linux_ptrace.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/amd64/linux/linux_ptrace.c ============================================================================== --- stable/12/sys/amd64/linux/linux_ptrace.c Sun Aug 23 17:46:10 2020 (r364502) +++ stable/12/sys/amd64/linux/linux_ptrace.c Sun Aug 23 19:19:00 2020 (r364503) @@ -131,6 +131,36 @@ struct linux_pt_reg { l_ulong ss; }; +struct linux_pt_regset { + l_ulong r15; + l_ulong r14; + l_ulong r13; + l_ulong r12; + l_ulong rbp; + l_ulong rbx; + l_ulong r11; + l_ulong r10; + l_ulong r9; + l_ulong r8; + l_ulong rax; + l_ulong rcx; + l_ulong rdx; + l_ulong rsi; + l_ulong rdi; + l_ulong orig_rax; + l_ulong rip; + l_ulong cs; + l_ulong eflags; + l_ulong rsp; + l_ulong ss; + l_ulong fs_base; + l_ulong gs_base; + l_ulong ds; + l_ulong es; + l_ulong fs; + l_ulong gs; +}; + /* * Translate amd64 ptrace registers between Linux and FreeBSD formats. * The translation is pretty straighforward, for all registers but @@ -164,6 +194,40 @@ map_regs_to_linux(struct reg *b_reg, struct linux_pt_r } static void +map_regs_to_linux_regset(struct reg *b_reg, unsigned long fs_base, + unsigned long gs_base, struct linux_pt_regset *l_regset) +{ + + l_regset->r15 = b_reg->r_r15; + l_regset->r14 = b_reg->r_r14; + l_regset->r13 = b_reg->r_r13; + l_regset->r12 = b_reg->r_r12; + l_regset->rbp = b_reg->r_rbp; + l_regset->rbx = b_reg->r_rbx; + l_regset->r11 = b_reg->r_r11; + l_regset->r10 = b_reg->r_r10; + l_regset->r9 = b_reg->r_r9; + l_regset->r8 = b_reg->r_r8; + l_regset->rax = b_reg->r_rax; + l_regset->rcx = b_reg->r_rcx; + l_regset->rdx = b_reg->r_rdx; + l_regset->rsi = b_reg->r_rsi; + l_regset->rdi = b_reg->r_rdi; + l_regset->orig_rax = b_reg->r_rax; + l_regset->rip = b_reg->r_rip; + l_regset->cs = b_reg->r_cs; + l_regset->eflags = b_reg->r_rflags; + l_regset->rsp = b_reg->r_rsp; + l_regset->ss = b_reg->r_ss; + l_regset->fs_base = fs_base; + l_regset->gs_base = gs_base; + l_regset->ds = b_reg->r_ds; + l_regset->es = b_reg->r_es; + l_regset->fs = b_reg->r_fs; + l_regset->gs = b_reg->r_gs; +} + +static void map_regs_from_linux(struct reg *b_reg, struct linux_pt_reg *l_reg) { b_reg->r_r15 = l_reg->r15; @@ -306,14 +370,75 @@ linux_ptrace_setregs(struct thread *td, pid_t pid, voi } static int +linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data) +{ + struct ptrace_lwpinfo lwpinfo; + struct reg b_reg; + struct linux_pt_regset l_regset; + struct iovec iov; + struct pcb *pcb; + unsigned long fsbase, gsbase; + size_t len; + int error; + + error = copyin((const void *)data, &iov, sizeof(iov)); + if (error != 0) { + printf("%s: copyin error %d\n", __func__, error); + return (error); + } + + error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); + if (error != 0) + return (error); + + pcb = td->td_pcb; + if (td == curthread) + update_pcb_bases(pcb); + fsbase = pcb->pcb_fsbase; + gsbase = pcb->pcb_gsbase; + + map_regs_to_linux_regset(&b_reg, fsbase, gsbase, &l_regset); + + /* + * The strace(1) utility depends on RAX being set to -ENOSYS + * on syscall entry; otherwise it loops printing those: + * + * [ Process PID=928 runs in 64 bit mode. ] + * [ Process PID=928 runs in x32 mode. ] + */ + error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); + if (error != 0) { + printf("%s: PT_LWPINFO failed with error %d\n", + __func__, error); + return (error); + } + if (lwpinfo.pl_flags & PL_FLAG_SCE) + l_regset.rax = -38; // XXX: Don't hardcode? + + len = MIN(iov.iov_len, sizeof(l_regset)); + error = copyout(&l_regset, (void *)iov.iov_base, len); + if (error != 0) { + printf("%s: copyout error %d\n", __func__, error); + return (error); + } + + iov.iov_len -= len; + error = copyout(&iov, (void *)data, sizeof(iov)); + if (error != 0) { + printf("%s: iov copyout error %d\n", __func__, error); + return (error); + } + + return (error); +} + +static int linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data) { switch (addr) { case LINUX_NT_PRSTATUS: - printf("%s: NT_PRSTATUS not implemented; returning EINVAL\n", - __func__); - return (EINVAL); + return (linux_ptrace_getregset_prstatus(td, pid, data)); default: printf("%s: PTRACE_GETREGSET request %ld not implemented; " "returning EINVAL\n", __func__, addr);