Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2975654imu; Sun, 9 Dec 2018 14:05:40 -0800 (PST) X-Google-Smtp-Source: AFSGD/V5ulSY/8cAVGv6F8BgbVeZLHy7VRxrMQUS3gMQMj/q2NOX5VbUS0C99Zj77/bO6TB8PJYB X-Received: by 2002:a62:6f88:: with SMTP id k130mr9997722pfc.234.1544393140677; Sun, 09 Dec 2018 14:05:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544393140; cv=none; d=google.com; s=arc-20160816; b=x5s7sRq5loKITBPt4/cptqInUpP7p8MpwcgWKqsv4yHj6pVtO0qtqoEP6Xze24myKN ikW9AZ5VUlSxWMajq3YaYC7rM+NIsXtI2Xbj2nS+/IH735aJd3wGint5lUEgVy4h0gdK sSKyAfbY09AqVii7ATlW/fGOs/6r5Z7KUCYGUcuRNYkL/2x2bvhiTfqG9kf66Yu0eAYe wQiun/0GPBTboJn0078X/rl6imHeABrmD/QuGpRRglnj/uncHcsbiqKb5gNdDI49zY4O E1C3aul00eM7xUj57EOgUc6dZ8DTmPhBeqIolIjiHX5egp6jLv365DOXH+96cgwTXDyT kgQw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition; bh=7KXFiJZsVWuBsSLFghRAE6BYeJMhvKQv32lH80Q3fdU=; b=d1+diimi3niZCAQBeogEIO4X+fWxVs8EkL14BpOsrGqx0qSJOrr4LC7thT2kAoWw56 7o9GM/u8JUddbk1GK4qYA9LtLqvgoFyshtJy35hqmprZX5DsNqeizChGRRGCGJCaRn52 viJiaOESQmgU83kQd3/gwGPWLndLYW5TVxMAH6mQTFk5sF0muSY9GeJfffBYf1zkTyEm uHREWPc0Ciy07TFIx8SSf0vrCgP9lKzs2dSc/Ovdi+uccXE1iTqnsYj3z5J6f2B4Wxct PhRievwFMJygovCa1CT3hF754dnIpVvfpavXBbGnwNYs6jmIiU+Fi4gtzPzQfrWmH2Il FQgw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l36si8480576plb.433.2018.12.09.14.05.25; Sun, 09 Dec 2018 14:05:40 -0800 (PST) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726975AbeLIWEH (ORCPT + 99 others); Sun, 9 Dec 2018 17:04:07 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:35846 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726652AbeLIVzb (ORCPT ); Sun, 9 Dec 2018 16:55:31 -0500 Received: from pub.yeoldevic.com ([81.174.156.145] helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1gW72u-0002im-0s; Sun, 09 Dec 2018 21:55:28 +0000 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1gW72k-0003dP-4M; Sun, 09 Dec 2018 21:55:18 +0000 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Christoffer Dall" , "Marc Zyngier" , "Dave Martin" , "Mark Rutland" , "Will Deacon" Date: Sun, 09 Dec 2018 21:50:33 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) X-Patchwork-Hint: ignore Subject: [PATCH 3.16 283/328] arm64: KVM: Tighten guest core register access from userspace In-Reply-To: X-SA-Exim-Connect-IP: 81.174.156.145 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.62-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Dave Martin commit d26c25a9d19b5976b319af528886f89cf455692d upstream. We currently allow userspace to access the core register file in about any possible way, including straddling multiple registers and doing unaligned accesses. This is not the expected use of the ABI, and nobody is actually using it that way. Let's tighten it by explicitly checking the size and alignment for each field of the register file. Fixes: 2f4a07c5f9fe ("arm64: KVM: guest one-reg interface") Reviewed-by: Christoffer Dall Reviewed-by: Mark Rutland Signed-off-by: Dave Martin [maz: rewrote Dave's initial patch to be more easily backported] Signed-off-by: Marc Zyngier Signed-off-by: Will Deacon Signed-off-by: Ben Hutchings --- arch/arm64/kvm/guest.c | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -46,6 +46,45 @@ static u64 core_reg_offset_from_id(u64 i return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE); } +static int validate_core_offset(const struct kvm_one_reg *reg) +{ + u64 off = core_reg_offset_from_id(reg->id); + int size; + + switch (off) { + case KVM_REG_ARM_CORE_REG(regs.regs[0]) ... + KVM_REG_ARM_CORE_REG(regs.regs[30]): + case KVM_REG_ARM_CORE_REG(regs.sp): + case KVM_REG_ARM_CORE_REG(regs.pc): + case KVM_REG_ARM_CORE_REG(regs.pstate): + case KVM_REG_ARM_CORE_REG(sp_el1): + case KVM_REG_ARM_CORE_REG(elr_el1): + case KVM_REG_ARM_CORE_REG(spsr[0]) ... + KVM_REG_ARM_CORE_REG(spsr[KVM_NR_SPSR - 1]): + size = sizeof(__u64); + break; + + case KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]) ... + KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]): + size = sizeof(__uint128_t); + break; + + case KVM_REG_ARM_CORE_REG(fp_regs.fpsr): + case KVM_REG_ARM_CORE_REG(fp_regs.fpcr): + size = sizeof(__u32); + break; + + default: + return -EINVAL; + } + + if (KVM_REG_SIZE(reg->id) == size && + IS_ALIGNED(off, size / sizeof(__u32))) + return 0; + + return -EINVAL; +} + static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { /* @@ -65,6 +104,9 @@ static int get_core_reg(struct kvm_vcpu (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs) return -ENOENT; + if (validate_core_offset(reg)) + return -EINVAL; + if (copy_to_user(uaddr, ((u32 *)regs) + off, KVM_REG_SIZE(reg->id))) return -EFAULT; @@ -87,6 +129,9 @@ static int set_core_reg(struct kvm_vcpu (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs) return -ENOENT; + if (validate_core_offset(reg)) + return -EINVAL; + if (KVM_REG_SIZE(reg->id) > sizeof(tmp)) return -EINVAL;