Received: by 2002:a25:c593:0:0:0:0:0 with SMTP id v141csp619797ybe; Fri, 6 Sep 2019 04:54:16 -0700 (PDT) X-Google-Smtp-Source: APXvYqzMhPXRnLobFKPPAtCozpZ3rwan8YgFinn8s9I1YxQ3qNNNJJC9QEyzkaarRupe9V4SmZfp X-Received: by 2002:a17:90a:a78b:: with SMTP id f11mr9471894pjq.16.1567770856435; Fri, 06 Sep 2019 04:54:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1567770856; cv=none; d=google.com; s=arc-20160816; b=MQNJjCIdV6cwF0smxZEVSsDNmoUZUJ2coKtWGqv1DWjzsMvhriNmHHS2/fdgve2oB1 zCJ2twZCyOZEdNNb+2bX7dqTkaEv8jZVD8u7C7+lDSk7CGXkpzU7BOnXQ68rSV/Dx3U3 m4JgMeeg0ndh1swlTllCWqjcU3ngy9FJR3BbKwhmjk+NWL+cJ8BI5KZMtFC9JSCS5c87 jL6J3HmStV0dtIxu4pGfGTGOcFGfz+pGInepsAceCv7XRIHt0FSTLr+nMjTtVflSHDw4 tVUO4FLnlYvOANLmvet0D2Y7Fd5pFXuDirhu9J+dtrq54Vws+TuukTwuyw3XcIWThh+w 5AXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature; bh=rASns3U+6Oa/LoIG4M+RXQqZmudbbKPab+NbWJxo+g0=; b=DBaBJ8BuyCsCJi7dXStbSGWe9pV8BwbS1tpTKwkONqXH4NmZ1e+y+exEKsiptLGFYZ lv5IEVfDNF8qOpBRdLVBzaUWBaUnvWHrYT3J2BGnlm+Nk9H+GwexmJbJsASLczmf+vVe r/HGp5qd0nnv0KtUVTkKMRgzMuwIv0XMDPOh/RqEyBT1i0qUb7En053bd5IRhrLUcZ5I +saytgi2ubkvEc4bXasrsIL0hfW7VcmBds3BbriWJx9IjaoOcYrLO5Sn8/BcgH/3C8jm 9fD6SpheY1+vZ9cehBLiA8TvjKR8j/oGOunGaBurSLtqUanFn83UkTRl5OUG7f0NwMEm ISnA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail (test mode) header.i=@codeweavers.com header.s=6377696661 header.b="TjzIp1x/"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=codeweavers.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a1si4040852pgh.570.2019.09.06.04.54.00; Fri, 06 Sep 2019 04:54:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail (test mode) header.i=@codeweavers.com header.s=6377696661 header.b="TjzIp1x/"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=codeweavers.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389271AbfIEXoF (ORCPT + 99 others); Thu, 5 Sep 2019 19:44:05 -0400 Received: from mail.codeweavers.com ([50.203.203.244]:33980 "EHLO mail.codeweavers.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725921AbfIEXoF (ORCPT ); Thu, 5 Sep 2019 19:44:05 -0400 X-Greylist: delayed 964 seconds by postgrey-1.27 at vger.kernel.org; Thu, 05 Sep 2019 19:44:05 EDT DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=codeweavers.com; s=6377696661; h=Message-Id:Date:Subject:Cc:To:From:Sender: Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=rASns3U+6Oa/LoIG4M+RXQqZmudbbKPab+NbWJxo+g0=; b=TjzIp1x/oChw/7uIFnctLEQNYP 29PS6hDMe4HNArik8U+9zc2IChTbjg4v1emSxDQZGgVhPh/go6t1DcUVc7gnOg2zNK5WbQpUOjLpq 0MKbE0eYl3+hfF/RIgR+0FOS+dZX2RxoErfR0yYxunUupCclVkfFI8y8DbKLUTrCVj4k=; Received: from cpe-107-184-2-226.socal.res.rr.com ([107.184.2.226] helo=brendan-dell.bslabs.net) by mail.codeweavers.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1i61AR-0004DI-Re; Thu, 05 Sep 2019 18:27:57 -0500 From: Brendan Shanks To: linux-kernel@vger.kernel.org Cc: Ricardo Neri , Brendan Shanks , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" , x86@kernel.org, "Eric W. Biederman" Subject: [PATCH] x86/umip: Add emulation for 64-bit processes Date: Thu, 5 Sep 2019 16:22:21 -0700 Message-Id: <20190905232222.14900-1-bshanks@codeweavers.com> X-Mailer: git-send-email 2.17.1 X-Spam-Score: -106.0 X-Spam-Report: Spam detection software, running on the system "mail.codeweavers.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Add emulation of the sgdt, sidt, and smsw instructions for 64-bit processes. Wine users have encountered a number of 64-bit Windows games that use these instructions (particularly sgdt), and were crashing when run on UMIP-enabled systems. Content analysis details: (-106.0 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -100 USER_IN_WHITELIST From: address is in the user's white-list -6.0 ALL_TRUSTED Passed through trusted hosts only via SMTP Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add emulation of the sgdt, sidt, and smsw instructions for 64-bit processes. Wine users have encountered a number of 64-bit Windows games that use these instructions (particularly sgdt), and were crashing when run on UMIP-enabled systems. Originally-by: Ricardo Neri Signed-off-by: Brendan Shanks --- arch/x86/kernel/umip.c | 55 +++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c index 5b345add550f..1812e95d2f55 100644 --- a/arch/x86/kernel/umip.c +++ b/arch/x86/kernel/umip.c @@ -51,9 +51,7 @@ * The instruction smsw is emulated to return the value that the register CR0 * has at boot time as set in the head_32. * - * Also, emulation is provided only for 32-bit processes; 64-bit processes - * that attempt to use the instructions that UMIP protects will receive the - * SIGSEGV signal issued as a consequence of the general protection fault. + * Emulation is provided for both 32-bit and 64-bit processes. * * Care is taken to appropriately emulate the results when segmentation is * used. That is, rather than relying on USER_DS and USER_CS, the function @@ -63,17 +61,18 @@ * application uses a local descriptor table. */ -#define UMIP_DUMMY_GDT_BASE 0xfffe0000 -#define UMIP_DUMMY_IDT_BASE 0xffff0000 +#define UMIP_DUMMY_GDT_BASE 0xfffffffffffe0000ULL +#define UMIP_DUMMY_IDT_BASE 0xffffffffffff0000ULL /* * The SGDT and SIDT instructions store the contents of the global descriptor * table and interrupt table registers, respectively. The destination is a * memory operand of X+2 bytes. X bytes are used to store the base address of - * the table and 2 bytes are used to store the limit. In 32-bit processes, the - * only processes for which emulation is provided, X has a value of 4. + * the table and 2 bytes are used to store the limit. In 32-bit processes X + * has a value of 4, in 64-bit processes X has a value of 8. */ -#define UMIP_GDT_IDT_BASE_SIZE 4 +#define UMIP_GDT_IDT_BASE_SIZE_64BIT 8 +#define UMIP_GDT_IDT_BASE_SIZE_32BIT 4 #define UMIP_GDT_IDT_LIMIT_SIZE 2 #define UMIP_INST_SGDT 0 /* 0F 01 /0 */ @@ -189,6 +188,7 @@ static int identify_insn(struct insn *insn) * @umip_inst: A constant indicating the instruction to emulate * @data: Buffer into which the dummy result is stored * @data_size: Size of the emulated result + * @x86_64: true if process is 64-bit, false otherwise * * Emulate an instruction protected by UMIP and provide a dummy result. The * result of the emulation is saved in @data. The size of the results depends @@ -202,11 +202,8 @@ static int identify_insn(struct insn *insn) * 0 on success, -EINVAL on error while emulating. */ static int emulate_umip_insn(struct insn *insn, int umip_inst, - unsigned char *data, int *data_size) + unsigned char *data, int *data_size, bool x86_64) { - unsigned long dummy_base_addr, dummy_value; - unsigned short dummy_limit = 0; - if (!data || !data_size || !insn) return -EINVAL; /* @@ -219,6 +216,9 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst, * is always returned irrespective of the operand size. */ if (umip_inst == UMIP_INST_SGDT || umip_inst == UMIP_INST_SIDT) { + u64 dummy_base_addr; + u16 dummy_limit = 0; + /* SGDT and SIDT do not use registers operands. */ if (X86_MODRM_MOD(insn->modrm.value) == 3) return -EINVAL; @@ -228,13 +228,24 @@ static int emulate_umip_insn(struct insn *insn, int umip_inst, else dummy_base_addr = UMIP_DUMMY_IDT_BASE; - *data_size = UMIP_GDT_IDT_LIMIT_SIZE + UMIP_GDT_IDT_BASE_SIZE; + /* + * 64-bit processes use the entire dummy base address. + * 32-bit processes use the lower 32 bits of the base address. + * dummy_base_addr is always 64 bits, but we memcpy the correct + * number of bytes from it to the destination. + */ + if (x86_64) + *data_size = UMIP_GDT_IDT_BASE_SIZE_64BIT; + else + *data_size = UMIP_GDT_IDT_BASE_SIZE_32BIT; + + memcpy(data + 2, &dummy_base_addr, *data_size); - memcpy(data + 2, &dummy_base_addr, UMIP_GDT_IDT_BASE_SIZE); + *data_size += UMIP_GDT_IDT_LIMIT_SIZE; memcpy(data, &dummy_limit, UMIP_GDT_IDT_LIMIT_SIZE); } else if (umip_inst == UMIP_INST_SMSW) { - dummy_value = CR0_STATE; + unsigned long dummy_value = CR0_STATE; /* * Even though the CR0 register has 4 bytes, the number @@ -291,10 +302,9 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs) * @regs: Registers as saved when entering the #GP handler * * The instructions sgdt, sidt, str, smsw, sldt cause a general protection - * fault if executed with CPL > 0 (i.e., from user space). If the offending - * user-space process is not in long mode, this function fixes the exception - * up and provides dummy results for sgdt, sidt and smsw; str and sldt are not - * fixed up. Also long mode user-space processes are not fixed up. + * fault if executed with CPL > 0 (i.e., from user space). This function fixes + * the exception up and provides dummy results for sgdt, sidt and smsw; str + * and sldt are not fixed up. * * If operands are memory addresses, results are copied to user-space memory as * indicated by the instruction pointed by eIP using the registers indicated in @@ -373,13 +383,14 @@ bool fixup_umip_exception(struct pt_regs *regs) umip_pr_warning(regs, "%s instruction cannot be used by applications.\n", umip_insns[umip_inst]); - /* Do not emulate SLDT, STR or user long mode processes. */ - if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs)) + /* Do not emulate SLDT or STR. */ + if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT) return false; umip_pr_warning(regs, "For now, expensive software emulation returns the result.\n"); - if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size)) + if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size, + user_64bit_mode(regs))) return false; /* -- 2.17.1