Received: by 2002:a25:e74b:0:0:0:0:0 with SMTP id e72csp2297843ybh; Fri, 24 Jul 2020 09:14:02 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyOE9NOPwqenq9t+bI3QHjNjHxfS9Tr3KFa9IXm7ugma+n5JdBDs6git7307jZk2XKpllPg X-Received: by 2002:aa7:d049:: with SMTP id n9mr9962614edo.39.1595607241787; Fri, 24 Jul 2020 09:14:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1595607241; cv=none; d=google.com; s=arc-20160816; b=e3pxz4jUv6/dRuUOm5lz3zKgE9jQysPjL/7A7OMbH6XPxmrCIXI5wffo5rQffy+yuf Q5XFV7ireVn3Ej7OOCkfqqNvU/6qUgzWUz+oxSbbOO/fi6RQbHi5Ymy28PWMDsBQp65+ zQDVvaVwT01R+Wk43QyGy3KUwedjYNfCkV7q7CXyNhpOWAUxecgOpioTz7fMBJd5wT3t 21ISDzt+m+f2kj2kDk3jTzxeq4UAHhMEpU8ycnWSyFm6xoK7OEnnAtZOCjWax0yrpRDN Y5k6cK05W2sO647KPhFeUYDmXYmSnS1DEpSJqpgFDRidut5YGRf71SEcABb7OvCDVTsA fdew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=5GW/q4lofjMTprmmW3iwgknGSF7X8i/BDw4vv6D0LWw=; b=LMKzO5pSpMZqj0ccOHdl552n4pmc7q4XwNqSU/t6+tzBpvd8jPyZ/ssCx5T396Nqli pocJxHdncQVgE5scYGKjZZgx/U5Ydb/CFo7PvnXSg705NC+2mxMvLstV5opAlGwlc9uw W0tET+0vOPT4uDRevlxVY+Ue3dDY5Ik/XY/Mg3PgOJgMJateug+mV9Q+z0Q3McLTp5dY ox0qgCY1h6EB4WSE7jKsewGc+hMjBEajhFYiIy01SltqPmj7/GP4hgBrTRvhcFPYNKmd JtxZ9Il0VfWz42kPPHxivXSO6IiQ/KOanZkISKZ5Kd9pMHJmqrlxqhTbI7VEE3/4+Q5G qROw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=8bytes.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id b21si823959ejz.710.2020.07.24.09.13.39; Fri, 24 Jul 2020 09:14:01 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=8bytes.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728640AbgGXQLL (ORCPT + 99 others); Fri, 24 Jul 2020 12:11:11 -0400 Received: from 8bytes.org ([81.169.241.247]:59368 "EHLO theia.8bytes.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726704AbgGXQED (ORCPT ); Fri, 24 Jul 2020 12:04:03 -0400 Received: from cap.home.8bytes.org (p5b006776.dip0.t-ipconnect.de [91.0.103.118]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by theia.8bytes.org (Postfix) with ESMTPSA id D83909CE; Fri, 24 Jul 2020 18:03:59 +0200 (CEST) From: Joerg Roedel To: x86@kernel.org Cc: Joerg Roedel , Joerg Roedel , hpa@zytor.com, Andy Lutomirski , Dave Hansen , Peter Zijlstra , Jiri Slaby , Dan Williams , Tom Lendacky , Juergen Gross , Kees Cook , David Rientjes , Cfir Cohen , Erdem Aktas , Masami Hiramatsu , Mike Stunes , Sean Christopherson , Martin Radev , linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org Subject: [PATCH v5 07/75] x86/umip: Factor out instruction fetch Date: Fri, 24 Jul 2020 18:02:28 +0200 Message-Id: <20200724160336.5435-8-joro@8bytes.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200724160336.5435-1-joro@8bytes.org> References: <20200724160336.5435-1-joro@8bytes.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Joerg Roedel Factor out the code to fetch the instruction from user-space to a helper function. No functional changes. Signed-off-by: Joerg Roedel --- arch/x86/include/asm/insn-eval.h | 2 ++ arch/x86/kernel/umip.c | 26 +++++----------------- arch/x86/lib/insn-eval.c | 38 ++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/insn-eval.h b/arch/x86/include/asm/insn-eval.h index 2b6ccf2c49f1..b8b9ef1bbd06 100644 --- a/arch/x86/include/asm/insn-eval.h +++ b/arch/x86/include/asm/insn-eval.h @@ -19,5 +19,7 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs); int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs); unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx); int insn_get_code_seg_params(struct pt_regs *regs); +int insn_fetch_from_user(struct pt_regs *regs, + unsigned char buf[MAX_INSN_SIZE]); #endif /* _ASM_X86_INSN_EVAL_H */ diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c index 8d5cbe1bbb3b..c9e5345da793 100644 --- a/arch/x86/kernel/umip.c +++ b/arch/x86/kernel/umip.c @@ -317,11 +317,11 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs) */ bool fixup_umip_exception(struct pt_regs *regs) { - int not_copied, nr_copied, reg_offset, dummy_data_size, umip_inst; - unsigned long seg_base = 0, *reg_addr; + int nr_copied, reg_offset, dummy_data_size, umip_inst; /* 10 bytes is the maximum size of the result of UMIP instructions */ unsigned char dummy_data[10] = { 0 }; unsigned char buf[MAX_INSN_SIZE]; + unsigned long *reg_addr; void __user *uaddr; struct insn insn; int seg_defs; @@ -329,26 +329,12 @@ bool fixup_umip_exception(struct pt_regs *regs) if (!regs) return false; - /* - * If not in user-space long mode, a custom code segment could be in - * use. This is true in protected mode (if the process defined a local - * descriptor table), or virtual-8086 mode. In most of the cases - * seg_base will be zero as in USER_CS. - */ - if (!user_64bit_mode(regs)) - seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS); - - if (seg_base == -1L) - return false; - - not_copied = copy_from_user(buf, (void __user *)(seg_base + regs->ip), - sizeof(buf)); - nr_copied = sizeof(buf) - not_copied; + nr_copied = insn_fetch_from_user(regs, buf); /* - * The copy_from_user above could have failed if user code is protected - * by a memory protection key. Give up on emulation in such a case. - * Should we issue a page fault? + * The insn_fetch_from_user above could have failed if user code + * is protected by a memory protection key. Give up on emulation + * in such a case. Should we issue a page fault? */ if (!nr_copied) return false; diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c index 31600d851fd8..0c4f7ebc261b 100644 --- a/arch/x86/lib/insn-eval.c +++ b/arch/x86/lib/insn-eval.c @@ -1369,3 +1369,41 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) return (void __user *)-1L; } } + +/** + * insn_fetch_from_user() - Copy instruction bytes from user-space memory + * @regs: Structure with register values as seen when entering kernel mode + * @buf: Array to store the fetched instruction + * + * Gets the linear address of the instruction and copies the instruction bytes + * to the buf. + * + * Returns: + * + * Number of instruction bytes copied. + * + * 0 if nothing was copied. + */ +int insn_fetch_from_user(struct pt_regs *regs, unsigned char buf[MAX_INSN_SIZE]) +{ + unsigned long seg_base = 0; + int not_copied; + + /* + * If not in user-space long mode, a custom code segment could be in + * use. This is true in protected mode (if the process defined a local + * descriptor table), or virtual-8086 mode. In most of the cases + * seg_base will be zero as in USER_CS. + */ + if (!user_64bit_mode(regs)) { + seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS); + if (seg_base == -1L) + return 0; + } + + + not_copied = copy_from_user(buf, (void __user *)(seg_base + regs->ip), + MAX_INSN_SIZE); + + return MAX_INSN_SIZE - not_copied; +} -- 2.27.0