From patchwork Thu Dec 12 20:36:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 3334061 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 69B479F243 for ; Thu, 12 Dec 2013 20:38:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8EAE3207C6 for ; Thu, 12 Dec 2013 20:38:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7DC92206CB for ; Thu, 12 Dec 2013 20:38:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751798Ab3LLUiJ (ORCPT ); Thu, 12 Dec 2013 15:38:09 -0500 Received: from mail-ee0-f54.google.com ([74.125.83.54]:48290 "EHLO mail-ee0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751884Ab3LLUhS (ORCPT ); Thu, 12 Dec 2013 15:37:18 -0500 Received: by mail-ee0-f54.google.com with SMTP id e51so406857eek.13 for ; Thu, 12 Dec 2013 12:37:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id; bh=VG00enyRpNYeJLwAwqWOGuy3mCBmvpmEBgLPB1IiKNo=; b=p0BlraPBMTIxTXGUuJyYTYRxuMKATenNpVX01fyzNpSYZsMruyMU/sJ8gdc2991eao ZU+66Xlnbd+AyQiuq4P9sMv6Gvax6MvJg04SMZWnLWoZGonmIIwSPch1UKLSJzRN7K+N +Ot3jLtNBYBoREljPkbscbMVOJ2y+S7N61oOZ7IHZNyXVFWDlW8aunduSgc3cytBEhkx UMUUbHVLo+XrXtuggFrmn8oUfJ1hiHQSpOyx8bi0ztxlEjL4DEFpJsKbjRe4sGRgeUy6 dRk+7dEcILKBTRVvXaJSriXG5bhZTbcZ5gZab27Ilm1H8Va5Z6R+9C1AwX2x5CQA7Mb1 Edug== X-Received: by 10.14.107.3 with SMTP id n3mr9951281eeg.67.1386880636981; Thu, 12 Dec 2013 12:37:16 -0800 (PST) Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54]) by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.15 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Dec 2013 12:37:16 -0800 (PST) From: Paolo Bonzini To: linux-kernel@vger.kernel.org Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, stable@vger.kernel.org Subject: [PATCH] KVM: x86: fix guest-initiated crash with x2apic (CVE-2013-6376) Date: Thu, 12 Dec 2013 21:36:54 +0100 Message-Id: <1386880614-23300-4-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Gleb Natapov A guest can cause a BUG_ON() leading to a host kernel crash. When the guest writes to the ICR to request an IPI, while in x2apic mode the following things happen, the destination is read from ICR2, which is a register that the guest can control. kvm_irq_delivery_to_apic_fast uses the high 16 bits of ICR2 as the cluster id. A BUG_ON is triggered, which is a protection against accessing map->logical_map with an out-of-bounds access and manages to avoid that anything really unsafe occurs. The logic in the code is correct from real HW point of view. The problem is that KVM supports only one cluster with ID 0 in clustered mode, but the code that has the bug does not take this into account. Reported-by: Lars Bull Cc: stable@vger.kernel.org Signed-off-by: Gleb Natapov Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index b8bec45c1610..801dc3fd66e1 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -143,6 +143,8 @@ static inline int kvm_apic_id(struct kvm_lapic *apic) return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff; } +#define KMV_X2APIC_CID_BITS 0 + static void recalculate_apic_map(struct kvm *kvm) { struct kvm_apic_map *new, *old = NULL; @@ -180,7 +182,8 @@ static void recalculate_apic_map(struct kvm *kvm) if (apic_x2apic_mode(apic)) { new->ldr_bits = 32; new->cid_shift = 16; - new->cid_mask = new->lid_mask = 0xffff; + new->cid_mask = (1 << KMV_X2APIC_CID_BITS) - 1; + new->lid_mask = 0xffff; } else if (kvm_apic_sw_enabled(apic) && !new->cid_mask /* flat mode */ && kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_CLUSTER) {