From patchwork Mon Feb 1 19:40:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Vagin X-Patchwork-Id: 12059855 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,DKIM_VALID,FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1B66C433DB for ; Mon, 1 Feb 2021 19:43:22 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 874ED64EA8 for ; Mon, 1 Feb 2021 19:43:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 874ED64EA8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=f2xgYvvliYum+E9mgQIuzRqUov00OokNDvfN/woj0Xk=; b=PzvDxBDoSvMoq79SA34GkJnYm OthWTPzGTCEzNaEnqKAixUn5RwzZqWL0kHfU0lu9s7G3GyXilnI2fqFWnT/+BmNZyl+QLC96IsJ60 cT5fOZm6Odgzrv+Mefu5Gw1seQtaNRE5uItV69D+NDv6XnRXVxsiBal5Ycnb0D92x8x8hvEYWZhUv C8IcuPWDqLgBZeC+zPRHc7kjD9LEfvsYIBqizCVWMxLLQJzVarAF2lytRh/KdH2vlp5uiGHGceYyI 7w7ETPtcrydvwQztYtJIq/qZ83NOQdP0YjAKPt99SekynpMUBEUfQ01KEJvh52th56r8DYqlSVPbI kC3Vewb1A==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1l6f5R-00016l-Ig; Mon, 01 Feb 2021 19:42:13 +0000 Received: from mail-pl1-x62b.google.com ([2607:f8b0:4864:20::62b]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1l6f5I-00010R-16 for linux-arm-kernel@lists.infradead.org; Mon, 01 Feb 2021 19:42:08 +0000 Received: by mail-pl1-x62b.google.com with SMTP id u11so10584082plg.13 for ; Mon, 01 Feb 2021 11:42:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=54HaqmXpfsd5zEV3HoPbFBl5GxWxzwJ8Zfrym0Khwo8=; b=DyokyQNh+PByr5WdoEJ15eDHP6uAClVcSsLQ8bJfzh7+fb6F0petWfGhE1b3rAuRxR rn1mQWomuvuuT6ar9JJJuTmEOVpAuIPYfh+gL2YOFHqV7rF6KK0JhQE4dC7ZzNMu9iFs PAd8op3ZxMXLDcBS7VvG4BSq5Kvl5/+7zFFQpMaQeJITXQXKdBxIuOFAn3YOOGzHZc0Y WUc/8air7gZV6G4ruIthZlHHhhKmTEbNrzqQ9v9TLa47mfTNKeBJXMJ8ODkKUMsfdQNq 9chTAtxh1A+ZzQkZOekFDQFt9WedIlOVbNAwAGsgOoqk1qmLBwho0B62/G4h9DMdHOKP 2+8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=54HaqmXpfsd5zEV3HoPbFBl5GxWxzwJ8Zfrym0Khwo8=; b=aiyrf4JAoRDhmlRZyygEz4ZbDD2lSULFwNNohCIefXbxgScKPzCBxK+EdWJ1ls2qnD SaqY9Kstu9ANey2v8rSQA5K2kUNgIIN9Sx3gM2k8k9vGiMMtq9eJ2G7j+Jrzb6VsI2CE o5HVosdf0ZZH48hx/x/ZTUR17sxUOLWZKCOmk+We1diCu3awe2TWyvGjCA/z+pqzKxNu yxj87WCjo2TfKFxj1Qq7Grtl5KTw6gWgjuAmxk1yHOI+yd7pkOzEcIMKuBQE2hmmdr84 aC4EXS9Hrt9BxWg6dNq+LmpdXiaZfep/c/Mfu1OxsbC/ANty8LungfECRRd8TaUHFpOw 4OsQ== X-Gm-Message-State: AOAM531Xph6yD7hy+t0DAzYqEEWAGr0ql/MMgpJMnzfCVDjEB1eJHSW+ EhEOcAc/AKNdLp76c3ezMzo= X-Google-Smtp-Source: ABdhPJwfWrhxZkDE5l0bwgoiSOHOseDRKOL8wG7innfO3wgvBgOKr7r36RB2BQhqZUrDBbueiCpj5Q== X-Received: by 2002:a17:90b:4b86:: with SMTP id lr6mr444008pjb.107.1612208521215; Mon, 01 Feb 2021 11:42:01 -0800 (PST) Received: from laptop.hsd1.wa.comcast.net ([2601:600:9b7f:872e:a655:30fb:7373:c762]) by smtp.gmail.com with ESMTPSA id i4sm18213155pfo.40.2021.02.01.11.41.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Feb 2021 11:42:00 -0800 (PST) From: Andrei Vagin To: Will Deacon , Catalin Marinas Subject: [PATCH 2/3] arm64/ptrace: introduce PTRACE_O_ARM64_RAW_REGS Date: Mon, 1 Feb 2021 11:40:11 -0800 Message-Id: <20210201194012.524831-3-avagin@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210201194012.524831-1-avagin@gmail.com> References: <20210201194012.524831-1-avagin@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210201_144204_182418_ABAF97D1 X-CRM114-Status: GOOD ( 19.10 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anthony Steinhauser , linux-api@vger.kernel.org, Oleg Nesterov , linux-kernel@vger.kernel.org, Keno Fischer , Andrei Vagin , Dave Martin , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org We have some ABI weirdness in the way that we handle syscall exit stops because we indicate whether or not the stop has been signalled from syscall entry or syscall exit by clobbering a general purpose register (ip/r12 for AArch32, x7 for AArch64) in the tracee and restoring its old value after the stop. This behavior was inherited from ARM and it isn't common for other architectures. Now, we have PTRACE_GET_SYSCALL_INFO that gives all required information about system calls, so the hack with clobbering registers isn't needed anymore. This change adds the new ptrace option PTRACE_O_ARM64_RAW_REGS. If it is set, PTRACE_GETREGSET returns values of all registers without clobbering r12 or x7 and PTRACE_SETREGSE sets all registers even if a process has been stopped in syscall-enter or syscall-exit. Signed-off-by: Andrei Vagin --- arch/arm64/include/uapi/asm/ptrace.h | 4 ++ arch/arm64/kernel/ptrace.c | 70 ++++++++++++++++------------ include/linux/ptrace.h | 1 + include/uapi/linux/ptrace.h | 9 +++- 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h index 758ae984ff97..465cc9713895 100644 --- a/arch/arm64/include/uapi/asm/ptrace.h +++ b/arch/arm64/include/uapi/asm/ptrace.h @@ -109,6 +109,10 @@ struct user_hwdebug_state { } dbg_regs[16]; }; +#define PTRACE_O_ARM64_RAW_REGS (1 << 28) + +#define _PTRACE_O_ARCH_OPTIONS PTRACE_O_ARM64_RAW_REGS + /* SVE/FP/SIMD state (NT_ARM_SVE) */ struct user_sve_header { diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 39da03104528..591a4478ad76 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -565,21 +565,23 @@ static int gpr_get(struct task_struct *target, unsigned long saved_reg; int ret; - /* - * We have some ABI weirdness here in the way that we handle syscall - * exit stops because we indicate whether or not the stop has been - * signalled from syscall entry or syscall exit by clobbering the general - * purpose register x7. - */ saved_reg = uregs->regs[7]; - switch (target->ptrace_message) { - case PTRACE_EVENTMSG_SYSCALL_ENTRY: - uregs->regs[7] = PTRACE_SYSCALL_ENTER; - break; - case PTRACE_EVENTMSG_SYSCALL_EXIT: - uregs->regs[7] = PTRACE_SYSCALL_EXIT; - break; + if (!(target->ptrace & PT_ARM64_RAW_REGS)) { + /* + * We have some ABI weirdness here in the way that we handle + * syscall exit stops because we indicate whether or not the + * stop has been signalled from syscall entry or syscall exit + * by clobbering the general purpose register x7. + */ + switch (target->ptrace_message) { + case PTRACE_EVENTMSG_SYSCALL_ENTRY: + uregs->regs[7] = PTRACE_SYSCALL_ENTER; + break; + case PTRACE_EVENTMSG_SYSCALL_EXIT: + uregs->regs[7] = PTRACE_SYSCALL_EXIT; + break; + } } ret = membuf_write(&to, uregs, sizeof(*uregs)); @@ -600,15 +602,17 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset, if (ret) return ret; - /* - * Historically, x7 can't be changed if the stop has been signalled - * from syscall-enter of syscall-exit. - */ - switch (target->ptrace_message) { - case PTRACE_EVENTMSG_SYSCALL_ENTRY: - case PTRACE_EVENTMSG_SYSCALL_EXIT: - newregs.regs[7] = task_pt_regs(target)->regs[7]; - break; + if (!(target->ptrace & PT_ARM64_RAW_REGS)) { + /* + * Historically, x7 can't be changed if the stop has been + * signalled from syscall-enter of syscall-exit. + */ + switch (target->ptrace_message) { + case PTRACE_EVENTMSG_SYSCALL_ENTRY: + case PTRACE_EVENTMSG_SYSCALL_EXIT: + newregs.regs[7] = task_pt_regs(target)->regs[7]; + break; + } } if (!valid_user_regs(&newregs, target)) @@ -1243,6 +1247,8 @@ static inline compat_ulong_t compat_get_user_reg(struct task_struct *task, int i switch (idx) { case 12: + if (task->ptrace & PT_ARM64_RAW_REGS) + return regs->regs[idx]; /* * We have some ABI weirdness here in the way that we handle * syscall exit stops because we indicate whether or not the @@ -1332,15 +1338,17 @@ static int compat_gpr_set(struct task_struct *target, } - /* - * Historically, x12 can't be changed if the stop has been signalled - * from syscall-enter of syscall-exit. - */ - switch (target->ptrace_message) { - case PTRACE_EVENTMSG_SYSCALL_ENTRY: - case PTRACE_EVENTMSG_SYSCALL_EXIT: - newregs.regs[12] = task_pt_regs(target)->regs[12]; - break; + if (!(target->ptrace & PT_ARM64_RAW_REGS)) { + /* + * Historically, r12 can't be changed if the stop has been + * signalled from syscall-enter of syscall-exit. + */ + switch (target->ptrace_message) { + case PTRACE_EVENTMSG_SYSCALL_ENTRY: + case PTRACE_EVENTMSG_SYSCALL_EXIT: + newregs.regs[12] = task_pt_regs(target)->regs[12]; + break; + } } if (valid_user_regs(&newregs.user_regs, target)) diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 2a9df80ea887..987d6ec5f0ce 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -46,6 +46,7 @@ extern int ptrace_access_vm(struct task_struct *tsk, unsigned long addr, #define PT_EXITKILL (PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT) #define PT_SUSPEND_SECCOMP (PTRACE_O_SUSPEND_SECCOMP << PT_OPT_FLAG_SHIFT) +#define PT_ARM64_RAW_REGS (PTRACE_O_ARM64_RAW_REGS << PT_OPT_FLAG_SHIFT) /* single stepping state bits (used on ARM and PA-RISC) */ #define PT_SINGLESTEP_BIT 31 diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h index 83ee45fa634b..bcc8c362ddd9 100644 --- a/include/uapi/linux/ptrace.h +++ b/include/uapi/linux/ptrace.h @@ -7,6 +7,7 @@ /* has the defines to get at the registers. */ #include +#include #define PTRACE_TRACEME 0 #define PTRACE_PEEKTEXT 1 @@ -137,8 +138,14 @@ struct ptrace_syscall_info { #define PTRACE_O_EXITKILL (1 << 20) #define PTRACE_O_SUSPEND_SECCOMP (1 << 21) +/* (1<<28) is reserved for arch specific options. */ +#ifndef _PTRACE_O_ARCH_OPTIONS +#define _PTRACE_O_ARCH_OPTIONS 0 +#endif + #define PTRACE_O_MASK (\ - 0x000000ff | PTRACE_O_EXITKILL | PTRACE_O_SUSPEND_SECCOMP) + 0x000000ff | PTRACE_O_EXITKILL | \ + PTRACE_O_SUSPEND_SECCOMP | _PTRACE_O_ARCH_OPTIONS) #include