Received: by 2002:a25:e7d8:0:0:0:0:0 with SMTP id e207csp663233ybh; Tue, 10 Mar 2020 06:06:26 -0700 (PDT) X-Google-Smtp-Source: ADFU+vvGkmT3/jlqjJsysfv9V9k33PJJj7jpAB5kUyZ+qtVWM0hYaanHWJAEV27pGTjnrvsBiCi7 X-Received: by 2002:a9d:1a4:: with SMTP id e33mr11297786ote.343.1583845586529; Tue, 10 Mar 2020 06:06:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1583845586; cv=none; d=google.com; s=arc-20160816; b=s3L5WcWjnRywcPjQsKD3ZI5wBmC2qPM9Xzjb9p0RisfEzF+AaztTOqzf9Kmj2nxrGN T6OR1DT0w69ANb+ABQAe+GgWt+ppTLjXeZg6a761s7unZc1GbRzXtnBs/JtN2wazsTfc 91DjkeryzaEs9oDqF/qvC6o2K2EVLHd00KsgKA60F0zyvJ7QfCOMXo8zsH3a0vVU66wv 2+1nToOGX4DHGEYRPz1gECcuHWG3x90qAB3EUsLVQg8pD0m6/E/GzUNH7PF9UyYwRlaL MU9mZv6Dem51pUh+URnMpEd1ioyLdZPuez/YuthDikCIVH2oKr3IIRwG36uv7QHiiXLc cLLQ== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=aHV6YF69U+cy5Gp4brGJEru2WiomahKiBmMQCBcHTaQ=; b=A3G8ueDspCHp6mjtES8SwjroAotoTzjB21GAXV6JbVkLLUHkgwHKvQN8hWA3mrP5tV 4GlroskF9ADb6fKiyfEqF+RBcX29j4pf6g6cUNm2dlCT6B/IFzKb/693i5rtpmpp5/Dw x74GiXmsWsYp7Vft+wnKjYsKfNF59oNWj5HD6baZHL0agSZPzIKvTWTCciH83Ey0Qq0/ Hz8hdgSBVMS8p787rrhjK1GXWSIV+MUy8rR2san/DIAh91CiDj3vFEtWdOLyYsRfW054 ZRqSBqqMXCX7hLMBuR93tMex3nogjELQJvGiE4q1rwn8fDiZFhCCHSWkV5gl2yI4BdTS yADw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=JCySiBjg; 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 m9si5949573otq.87.2020.03.10.06.06.04; Tue, 10 Mar 2020 06:06:26 -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=pass header.i=@kernel.org header.s=default header.b=JCySiBjg; 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 S1730708AbgCJNET (ORCPT + 99 others); Tue, 10 Mar 2020 09:04:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:49242 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729456AbgCJNEQ (ORCPT ); Tue, 10 Mar 2020 09:04:16 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 9D63E24693; Tue, 10 Mar 2020 13:04:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1583845455; bh=C8JapEoOUIN4r0cBd+3vAgQBPCVeIqxcY2yj8qwgDYk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JCySiBjglU0Md/dYRQwPTJ1aeoxzFx9UUJbcVdIij9FmZOvdg/QgDYIW3YcuQRHYI a1RRMlUUQQQ/Xsyou6uYrzqjpDyuHD199rG8G+KOf76wkElZeoq5rj8KgzYp8IV0zZ 6nPqin5JLbP+t24fbMYXjMHzY/RTynbrdda8QPic= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Ard Biesheuvel , Ingo Molnar , linux-efi@vger.kernel.org, Thomas Gleixner Subject: [PATCH 5.5 187/189] efi/x86: Handle by-ref arguments covering multiple pages in mixed mode Date: Tue, 10 Mar 2020 13:40:24 +0100 Message-Id: <20200310123658.336363020@linuxfoundation.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200310123639.608886314@linuxfoundation.org> References: <20200310123639.608886314@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ard Biesheuvel commit 8319e9d5ad98ffccd19f35664382c73cea216193 upstream. The mixed mode runtime wrappers are fragile when it comes to how the memory referred to by its pointer arguments are laid out in memory, due to the fact that it translates these addresses to physical addresses that the runtime services can dereference when running in 1:1 mode. Since vmalloc'ed pages (including the vmap'ed stack) are not contiguous in the physical address space, this scheme only works if the referenced memory objects do not cross page boundaries. Currently, the mixed mode runtime service wrappers require that all by-ref arguments that live in the vmalloc space have a size that is a power of 2, and are aligned to that same value. While this is a sensible way to construct an object that is guaranteed not to cross a page boundary, it is overly strict when it comes to checking whether a given object violates this requirement, as we can simply take the physical address of the first and the last byte, and verify that they point into the same physical page. When this check fails, we emit a WARN(), but then simply proceed with the call, which could cause data corruption if the next physical page belongs to a mapping that is entirely unrelated. Given that with vmap'ed stacks, this condition is much more likely to trigger, let's relax the condition a bit, but fail the runtime service call if it does trigger. Fixes: f6697df36bdf0bf7 ("x86/efi: Prevent mixed mode boot corruption with CONFIG_VMAP_STACK=y") Signed-off-by: Ard Biesheuvel Signed-off-by: Ingo Molnar Cc: linux-efi@vger.kernel.org Cc: Ingo Molnar Cc: Thomas Gleixner Link: https://lore.kernel.org/r/20200221084849.26878-4-ardb@kernel.org Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/efi/efi_64.c | 45 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 19 deletions(-) --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -316,7 +316,7 @@ void efi_sync_low_kernel_mappings(void) static inline phys_addr_t virt_to_phys_or_null_size(void *va, unsigned long size) { - bool bad_size; + phys_addr_t pa; if (!va) return 0; @@ -324,16 +324,13 @@ virt_to_phys_or_null_size(void *va, unsi if (virt_addr_valid(va)) return virt_to_phys(va); - /* - * A fully aligned variable on the stack is guaranteed not to - * cross a page bounary. Try to catch strings on the stack by - * checking that 'size' is a power of two. - */ - bad_size = size > PAGE_SIZE || !is_power_of_2(size); + pa = slow_virt_to_phys(va); - WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size); + /* check if the object crosses a page boundary */ + if (WARN_ON((pa ^ (pa + size - 1)) & PAGE_MASK)) + return 0; - return slow_virt_to_phys(va); + return pa; } #define virt_to_phys_or_null(addr) \ @@ -808,8 +805,11 @@ efi_thunk_get_variable(efi_char16_t *nam phys_attr = virt_to_phys_or_null(attr); phys_data = virt_to_phys_or_null_size(data, *data_size); - status = efi_thunk(get_variable, phys_name, phys_vendor, - phys_attr, phys_data_size, phys_data); + if (!phys_name || (data && !phys_data)) + status = EFI_INVALID_PARAMETER; + else + status = efi_thunk(get_variable, phys_name, phys_vendor, + phys_attr, phys_data_size, phys_data); spin_unlock_irqrestore(&efi_runtime_lock, flags); @@ -834,9 +834,11 @@ efi_thunk_set_variable(efi_char16_t *nam phys_vendor = virt_to_phys_or_null(vnd); phys_data = virt_to_phys_or_null_size(data, data_size); - /* If data_size is > sizeof(u32) we've got problems */ - status = efi_thunk(set_variable, phys_name, phys_vendor, - attr, data_size, phys_data); + if (!phys_name || !phys_data) + status = EFI_INVALID_PARAMETER; + else + status = efi_thunk(set_variable, phys_name, phys_vendor, + attr, data_size, phys_data); spin_unlock_irqrestore(&efi_runtime_lock, flags); @@ -863,9 +865,11 @@ efi_thunk_set_variable_nonblocking(efi_c phys_vendor = virt_to_phys_or_null(vnd); phys_data = virt_to_phys_or_null_size(data, data_size); - /* If data_size is > sizeof(u32) we've got problems */ - status = efi_thunk(set_variable, phys_name, phys_vendor, - attr, data_size, phys_data); + if (!phys_name || !phys_data) + status = EFI_INVALID_PARAMETER; + else + status = efi_thunk(set_variable, phys_name, phys_vendor, + attr, data_size, phys_data); spin_unlock_irqrestore(&efi_runtime_lock, flags); @@ -891,8 +895,11 @@ efi_thunk_get_next_variable(unsigned lon phys_vendor = virt_to_phys_or_null(vnd); phys_name = virt_to_phys_or_null_size(name, *name_size); - status = efi_thunk(get_next_variable, phys_name_size, - phys_name, phys_vendor); + if (!phys_name) + status = EFI_INVALID_PARAMETER; + else + status = efi_thunk(get_next_variable, phys_name_size, + phys_name, phys_vendor); spin_unlock_irqrestore(&efi_runtime_lock, flags);