Message ID | 20221114164823.69555-1-hborghor@amazon.de |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2250207wru; Mon, 14 Nov 2022 08:58:05 -0800 (PST) X-Google-Smtp-Source: AA0mqf7g8dSxnVTJ4ecSmOg2RZQFbf/fdC5EOKgPVI5XvkLmzdiB6Gg3QzNonB0Gd1LDqrIq698Y X-Received: by 2002:a17:902:6a86:b0:16d:d767:1e91 with SMTP id n6-20020a1709026a8600b0016dd7671e91mr214424plk.32.1668445084763; Mon, 14 Nov 2022 08:58:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668445084; cv=none; d=google.com; s=arc-20160816; b=BaIgQ1jyeYGv4Wny/FH5CnT/conds/skK+Pz4MCizxGiULQ5ywv3KpyDl7AA6HRlHj zxgsv2yzhhLSkkmGqO4GJSd5L/Y43pnRYJHo5yRvjzTpRv+ljYutzsPS8DTLjLt3DuIf RqGCIXecWHXMMZer+3w/jHvSH5upQbFgn+peZMnIM6JOJCJMSulu3tctp94KsPuR0IXw ezODqgVkQy54xm87mTGR6kzvE6njLz/cVi7D4G6SO58HBcXjkkT5Ioz7Bmhu7cFBjIy1 vZ7rE088Poc3XZDBwBKniaHp+TaAocR2tbcDQSxmgE09H6IODbjcWSodSWOD3pNNrZev Asgw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=W/HB3Xe0IyEpEgjwwlHeRnwekQHUqIvwFTZpMp6G+lM=; b=voK0QO2WUSG1u7CtqFhjI+aRZoWDxRE0pBzOrBgmuyCoVZV4vIo4irif/3udBy97zM 5U6ZJmg5upu3OT73ypsgV/W7s9V6PSrJeYYIbdXhWJh3r+ntQ3efUdIacsblxxSF0H+L 0pSaCDYYdsMnDdEgrdFMQho0ggUrYFOtzK2JV1c8TENVjWvxCxHywS9djQcp+cLpT0Eb POM8zT0GpSv4WXGXee0kCvQBkxV3s9G8AJEtgfWZO0rMx9VjbXR9qPIFz4AeiNGJtuWp L2bpdmPsCk0tACND4GtW/J3qGmLUwb7Cdk/mh/ux83nDP5tuHn2v3tPdI9ld34IxC7Ug z8Bg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amazon.de header.s=amazon201209 header.b=MYO5uvfa; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.de Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id s4-20020a170903214400b0018873ba17ccsi8567271ple.32.2022.11.14.08.57.50; Mon, 14 Nov 2022 08:58:04 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@amazon.de header.s=amazon201209 header.b=MYO5uvfa; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238051AbiKNQuz (ORCPT <rfc822;winker.wchi@gmail.com> + 99 others); Mon, 14 Nov 2022 11:50:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59264 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236205AbiKNQua (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 14 Nov 2022 11:50:30 -0500 Received: from smtp-fw-80006.amazon.com (smtp-fw-80006.amazon.com [99.78.197.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A0B62FC03; Mon, 14 Nov 2022 08:49:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.de; i=@amazon.de; q=dns/txt; s=amazon201209; t=1668444574; x=1699980574; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=W/HB3Xe0IyEpEgjwwlHeRnwekQHUqIvwFTZpMp6G+lM=; b=MYO5uvfaSqroRvZ+kbNFu8HME5ahb2CYN+S5Aa73qb01yHrQliB4VfOW rFWfzOth9iYlZ6Z9prGPptvaK0oJeulDefCrDbROUUsLRObnNza0oShLS DGe1nad1iQ4ComO0j9L6et6ol2aHcm5Cb8cZ3/kJFRL2+LP9UJsZroAqQ E=; X-IronPort-AV: E=Sophos;i="5.96,164,1665446400"; d="scan'208";a="150552225" Received: from pdx4-co-svc-p1-lb2-vlan2.amazon.com (HELO email-inbound-relay-pdx-2b-m6i4x-26a610d2.us-west-2.amazon.com) ([10.25.36.210]) by smtp-border-fw-80006.pdx80.corp.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Nov 2022 16:49:23 +0000 Received: from EX13D06EUC001.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan2.pdx.amazon.com [10.236.137.194]) by email-inbound-relay-pdx-2b-m6i4x-26a610d2.us-west-2.amazon.com (Postfix) with ESMTPS id D197041726; Mon, 14 Nov 2022 16:49:18 +0000 (UTC) Received: from EX19D033EUC002.ant.amazon.com (10.252.61.215) by EX13D06EUC001.ant.amazon.com (10.43.164.225) with Microsoft SMTP Server (TLS) id 15.0.1497.42; Mon, 14 Nov 2022 16:49:17 +0000 Received: from dev-dsk-hborghor-1a-30381df9.eu-west-1.amazon.com (10.43.162.178) by EX19D033EUC002.ant.amazon.com (10.252.61.215) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.1118.20; Mon, 14 Nov 2022 16:49:13 +0000 From: Hendrik Borghorst <hborghor@amazon.de> To: <hborghor@amazon.de> CC: <graf@amazon.de>, Sean Christopherson <seanjc@google.com>, Paolo Bonzini <pbonzini@redhat.com>, Thomas Gleixner <tglx@linutronix.de>, Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>, Dave Hansen <dave.hansen@linux.intel.com>, <x86@kernel.org>, "H. Peter Anvin" <hpa@zytor.com>, <kvm@vger.kernel.org>, <linux-kernel@vger.kernel.org> Subject: [PATCH] KVM: x86/vmx: Do not skip segment attributes if unusable bit is set Date: Mon, 14 Nov 2022 16:48:23 +0000 Message-ID: <20221114164823.69555-1-hborghor@amazon.de> X-Mailer: git-send-email 2.37.1 MIME-Version: 1.0 X-Originating-IP: [10.43.162.178] X-ClientProxiedBy: EX13D21UWB001.ant.amazon.com (10.43.161.108) To EX19D033EUC002.ant.amazon.com (10.252.61.215) Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749491473440996642?= X-GMAIL-MSGID: =?utf-8?q?1749491473440996642?= |
Series |
KVM: x86/vmx: Do not skip segment attributes if unusable bit is set
|
|
Commit Message
Hendrik Borghorst
Nov. 14, 2022, 4:48 p.m. UTC
When serializing and deserializing kvm_sregs, attributes of the segment
descriptors are stored by user space. For unusable segments,
vmx_segment_access_rights skips all attributes and sets them to 0.
This means we zero out the DPL (Descriptor Privilege Level) for unusable
entries.
Unusable segments are - contrary to their name - usable in 64bit mode and
are used by guests to for example create a linear map through the
NULL selector.
VMENTER checks if SS.DPL is correct depending on the CS segment type.
For types 9 (Execute Only) and 11 (Execute Read), CS.DPL must be equal to
SS.DPL [1].
We have seen real world guests setting CS to a usable segment with DPL=3
and SS to an unusable segment with DPL=3. Once we go through an sregs
get/set cycle, SS.DPL turns to 0. This causes the virtual machine to crash
reproducibly.
This commit changes the attribute logic to always preserve attributes for
unusable segments. According to [2] SS.DPL is always saved on VM exits,
regardless of the unusable bit so user space applications should have saved
the information on serialization correctly.
[3] specifies that besides SS.DPL the rest of the attributes of the
descriptors are undefined after VM entry if unusable bit is set. So, there
should be no harm in setting them all to the previous state.
[1] Intel SDM Vol 3C 26.3.1.2 Checks on Guest Segment Registers
[2] Intel SDM Vol 3C 27.3.2 Saving Segment Registers and Descriptor-Table
Registers
[3] Intel SDM Vol 3C 26.3.2.2 Loading Guest Segment Registers and
Descriptor-Table Registers
Cc: Alexander Graf <graf@amazon.de>
Signed-off-by: Hendrik Borghorst <hborghor@amazon.de>
---
arch/x86/kvm/vmx/vmx.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
Comments
On Mon, Nov 14, 2022 at 8:50 AM Hendrik Borghorst <hborghor@amazon.de> wrote: > > When serializing and deserializing kvm_sregs, attributes of the segment > descriptors are stored by user space. For unusable segments, > vmx_segment_access_rights skips all attributes and sets them to 0. > > This means we zero out the DPL (Descriptor Privilege Level) for unusable > entries. > > Unusable segments are - contrary to their name - usable in 64bit mode and > are used by guests to for example create a linear map through the > NULL selector. > > VMENTER checks if SS.DPL is correct depending on the CS segment type. > For types 9 (Execute Only) and 11 (Execute Read), CS.DPL must be equal to > SS.DPL [1]. > > We have seen real world guests setting CS to a usable segment with DPL=3 > and SS to an unusable segment with DPL=3. Once we go through an sregs > get/set cycle, SS.DPL turns to 0. This causes the virtual machine to crash > reproducibly. > > This commit changes the attribute logic to always preserve attributes for > unusable segments. According to [2] SS.DPL is always saved on VM exits, > regardless of the unusable bit so user space applications should have saved > the information on serialization correctly. > > [3] specifies that besides SS.DPL the rest of the attributes of the > descriptors are undefined after VM entry if unusable bit is set. So, there > should be no harm in setting them all to the previous state. > > [1] Intel SDM Vol 3C 26.3.1.2 Checks on Guest Segment Registers > [2] Intel SDM Vol 3C 27.3.2 Saving Segment Registers and Descriptor-Table > Registers > [3] Intel SDM Vol 3C 26.3.2.2 Loading Guest Segment Registers and > Descriptor-Table Registers > > Cc: Alexander Graf <graf@amazon.de> > Signed-off-by: Hendrik Borghorst <hborghor@amazon.de> > --- > arch/x86/kvm/vmx/vmx.c | 21 +++++++++------------ > 1 file changed, 9 insertions(+), 12 deletions(-) > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index 63247c57c72c..4ae248e87f5e 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -3412,18 +3412,15 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var) > { > u32 ar; > > - if (var->unusable || !var->present) > - ar = 1 << 16; > - else { > - ar = var->type & 15; > - ar |= (var->s & 1) << 4; > - ar |= (var->dpl & 3) << 5; > - ar |= (var->present & 1) << 7; > - ar |= (var->avl & 1) << 12; > - ar |= (var->l & 1) << 13; > - ar |= (var->db & 1) << 14; > - ar |= (var->g & 1) << 15; > - } > + ar = var->type & 15; > + ar |= (var->s & 1) << 4; > + ar |= (var->dpl & 3) << 5; > + ar |= (var->present & 1) << 7; > + ar |= (var->avl & 1) << 12; > + ar |= (var->l & 1) << 13; > + ar |= (var->db & 1) << 14; > + ar |= (var->g & 1) << 15; > + ar |= (var->unusable || !var->present) << 16; > > return ar; > } Reviewed-by: Jim Mattson <jmattson@google.com>
On 14.11.22 17:48, Hendrik Borghorst wrote: > When serializing and deserializing kvm_sregs, attributes of the segment > descriptors are stored by user space. For unusable segments, > vmx_segment_access_rights skips all attributes and sets them to 0. > > This means we zero out the DPL (Descriptor Privilege Level) for unusable > entries. > > Unusable segments are - contrary to their name - usable in 64bit mode and > are used by guests to for example create a linear map through the > NULL selector. > > VMENTER checks if SS.DPL is correct depending on the CS segment type. > For types 9 (Execute Only) and 11 (Execute Read), CS.DPL must be equal to > SS.DPL [1]. > > We have seen real world guests setting CS to a usable segment with DPL=3 > and SS to an unusable segment with DPL=3. Once we go through an sregs > get/set cycle, SS.DPL turns to 0. This causes the virtual machine to crash > reproducibly. > > This commit changes the attribute logic to always preserve attributes for > unusable segments. According to [2] SS.DPL is always saved on VM exits, > regardless of the unusable bit so user space applications should have saved > the information on serialization correctly. > > [3] specifies that besides SS.DPL the rest of the attributes of the > descriptors are undefined after VM entry if unusable bit is set. So, there > should be no harm in setting them all to the previous state. > > [1] Intel SDM Vol 3C 26.3.1.2 Checks on Guest Segment Registers > [2] Intel SDM Vol 3C 27.3.2 Saving Segment Registers and Descriptor-Table > Registers > [3] Intel SDM Vol 3C 26.3.2.2 Loading Guest Segment Registers and > Descriptor-Table Registers > > Cc: Alexander Graf <graf@amazon.de> > Signed-off-by: Hendrik Borghorst <hborghor@amazon.de> I'm still fascinated by the fact that "unusable" means "is a valid segment under these conditions" :). Reviewed-by: Alexander Graf <graf@amazon.com> Alex Amazon Development Center Germany GmbH Krausenstr. 38 10117 Berlin Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B Sitz: Berlin Ust-ID: DE 289 237 879
On 11/14/22 17:48, Hendrik Borghorst wrote: > When serializing and deserializing kvm_sregs, attributes of the segment > descriptors are stored by user space. For unusable segments, > vmx_segment_access_rights skips all attributes and sets them to 0. > > This means we zero out the DPL (Descriptor Privilege Level) for unusable > entries. > > Unusable segments are - contrary to their name - usable in 64bit mode and > are used by guests to for example create a linear map through the > NULL selector. > > VMENTER checks if SS.DPL is correct depending on the CS segment type. > For types 9 (Execute Only) and 11 (Execute Read), CS.DPL must be equal to > SS.DPL [1]. > > We have seen real world guests setting CS to a usable segment with DPL=3 > and SS to an unusable segment with DPL=3. Once we go through an sregs > get/set cycle, SS.DPL turns to 0. This causes the virtual machine to crash > reproducibly. > > This commit changes the attribute logic to always preserve attributes for > unusable segments. According to [2] SS.DPL is always saved on VM exits, > regardless of the unusable bit so user space applications should have saved > the information on serialization correctly. > > [3] specifies that besides SS.DPL the rest of the attributes of the > descriptors are undefined after VM entry if unusable bit is set. So, there > should be no harm in setting them all to the previous state. > > [1] Intel SDM Vol 3C 26.3.1.2 Checks on Guest Segment Registers > [2] Intel SDM Vol 3C 27.3.2 Saving Segment Registers and Descriptor-Table > Registers > [3] Intel SDM Vol 3C 26.3.2.2 Loading Guest Segment Registers and > Descriptor-Table Registers > > Cc: Alexander Graf <graf@amazon.de> > Signed-off-by: Hendrik Borghorst <hborghor@amazon.de> > --- > arch/x86/kvm/vmx/vmx.c | 21 +++++++++------------ > 1 file changed, 9 insertions(+), 12 deletions(-) Hi Hendrik, thanks for the patch! I have queued it now for 6.2-rc6, and added Cc: stable. Would you mind providing a test in the form of a patch for tools/testing/selftests/kvm? I think a kvm-unit-tests testcase would be harder to do because there's no easy way to force KVM_GET_SREGS/KVM_SET_SREGS. Thanks, Paolo
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 63247c57c72c..4ae248e87f5e 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -3412,18 +3412,15 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var) { u32 ar; - if (var->unusable || !var->present) - ar = 1 << 16; - else { - ar = var->type & 15; - ar |= (var->s & 1) << 4; - ar |= (var->dpl & 3) << 5; - ar |= (var->present & 1) << 7; - ar |= (var->avl & 1) << 12; - ar |= (var->l & 1) << 13; - ar |= (var->db & 1) << 14; - ar |= (var->g & 1) << 15; - } + ar = var->type & 15; + ar |= (var->s & 1) << 4; + ar |= (var->dpl & 3) << 5; + ar |= (var->present & 1) << 7; + ar |= (var->avl & 1) << 12; + ar |= (var->l & 1) << 13; + ar |= (var->db & 1) << 14; + ar |= (var->g & 1) << 15; + ar |= (var->unusable || !var->present) << 16; return ar; }