Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp2037273imm; Mon, 16 Jul 2018 00:37:10 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfY9j3Gk/Kv0u+08Q6+NddDRskLRKl5sZCuztCiqwfTmMvMBTpin7fz+uzSDUoJORHQ8Yq/ X-Received: by 2002:a17:902:904c:: with SMTP id w12-v6mr6331141plz.95.1531726630069; Mon, 16 Jul 2018 00:37:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531726630; cv=none; d=google.com; s=arc-20160816; b=rq6A83AYCguqKSPjWs9iX22ntJsNGSTfEcf2h5N0pEbQg3X7jfqEry5aM6RSI+pdqU 2hH0rLeIFEdCplYkf4B9SyVWaFu1aYNHjEHr3D0GTYponwUSSCnV+Y4L5BNBqKwHqF9J MnearJ2JaXGmNG3xRjXF4EPkm+6OmVVRQbkxmguV9/0+uVD6MZG9JbEfVP8AIHsoR8uv fVSGqRBtsHfv1DkpuTn78KIyroTbitMygccyjapUDdKJJjmBsjJ3g8n/sMZUeZbykKHW nuidv6BEHjLxcuLktX7UomDb0dbCDLh+37eXJB8r/XSeHxQ4immaLTXesOeF+8faA95a AWMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=k6hMSp8/BkrQvPFUNqw3IhBcyHKfT1lFO61FZzmLfJw=; b=J6BmDxN92QTV4ETZeWJmU8gTO/hx5s4xKgQnBOjV2K+3Kb1e14/6d+LDAfeUcELM+L PhgzSG67/srV4R1Gw/n0+nyjtRUKTRSc7y+4uR86vl8CxmSzDKRix9+H4z6vXnEwOuww Yg43G+ixyNTJG4QJ+ZcG2onmSzKNUg8pa1oF0/2ScAl+6VIXgvI3hVhU3jprkbun+n+z ep6x8dK6xusm2A1mP17WqTA0n0krAqNYkAQjqSOiwZwROENWRJrFl9WQmuwCAVg/V6fS MB3EPuG4A1bjUfZeEfxkMsoaVtz1VjXsa2qCxz2gvMj3f/BLef4+cQWIOsrvPODFWvOV oUAQ== 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 v6-v6si29234625plp.60.2018.07.16.00.36.42; Mon, 16 Jul 2018 00:37:10 -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; 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 S1730621AbeGPIB5 (ORCPT + 99 others); Mon, 16 Jul 2018 04:01:57 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:46572 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730092AbeGPIB4 (ORCPT ); Mon, 16 Jul 2018 04:01:56 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id B63AFCB0; Mon, 16 Jul 2018 07:35:55 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Paul Burton , Serge Semin , James Hogan , Ralf Baechle , linux-mips@linux-mips.org Subject: [PATCH 4.17 04/67] MIPS: Fix ioremap() RAM check Date: Mon, 16 Jul 2018 09:34:33 +0200 Message-Id: <20180716073443.806592965@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180716073443.294323458@linuxfoundation.org> References: <20180716073443.294323458@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.17-stable review patch. If anyone has any objections, please let me know. ------------------ From: Paul Burton commit 523402fa9101090c91d2033b7ebdfdcf65880488 upstream. We currently attempt to check whether a physical address range provided to __ioremap() may be in use by the page allocator by examining the value of PageReserved for each page in the region - lowmem pages not marked reserved are presumed to be in use by the page allocator, and requests to ioremap them fail. The way we check this has been broken since commit 92923ca3aace ("mm: meminit: only set page reserved in the memblock region"), because memblock will typically not have any knowledge of non-RAM pages and therefore those pages will not have the PageReserved flag set. Thus when we attempt to ioremap a region outside of RAM we incorrectly fail believing that the region is RAM that may be in use. In most cases ioremap() on MIPS will take a fast-path to use the unmapped kseg1 or xkphys virtual address spaces and never hit this path, so the only way to hit it is for a MIPS32 system to attempt to ioremap() an address range in lowmem with flags other than _CACHE_UNCACHED. Perhaps the most straightforward way to do this is using ioremap_uncached_accelerated(), which is how the problem was discovered. Fix this by making use of walk_system_ram_range() to test the address range provided to __ioremap() against only RAM pages, rather than all lowmem pages. This means that if we have a lowmem I/O region, which is very common for MIPS systems, we're free to ioremap() address ranges within it. A nice bonus is that the test is no longer limited to lowmem. The approach here matches the way x86 performed the same test after commit c81c8a1eeede ("x86, ioremap: Speed up check for RAM pages") until x86 moved towards a slightly more complicated check using walk_mem_res() for unrelated reasons with commit 0e4c12b45aa8 ("x86/mm, resource: Use PAGE_KERNEL protection for ioremap of memory pages"). Signed-off-by: Paul Burton Reported-by: Serge Semin Tested-by: Serge Semin Fixes: 92923ca3aace ("mm: meminit: only set page reserved in the memblock region") Cc: James Hogan Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Cc: stable@vger.kernel.org # v4.2+ Patchwork: https://patchwork.linux-mips.org/patch/19786/ Signed-off-by: Greg Kroah-Hartman --- arch/mips/mm/ioremap.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) --- a/arch/mips/mm/ioremap.c +++ b/arch/mips/mm/ioremap.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -98,6 +99,20 @@ static int remap_area_pages(unsigned lon return error; } +static int __ioremap_check_ram(unsigned long start_pfn, unsigned long nr_pages, + void *arg) +{ + unsigned long i; + + for (i = 0; i < nr_pages; i++) { + if (pfn_valid(start_pfn + i) && + !PageReserved(pfn_to_page(start_pfn + i))) + return 1; + } + + return 0; +} + /* * Generic mapping function (not visible outside): */ @@ -116,8 +131,8 @@ static int remap_area_pages(unsigned lon void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long flags) { + unsigned long offset, pfn, last_pfn; struct vm_struct * area; - unsigned long offset; phys_addr_t last_addr; void * addr; @@ -137,18 +152,16 @@ void __iomem * __ioremap(phys_addr_t phy return (void __iomem *) CKSEG1ADDR(phys_addr); /* - * Don't allow anybody to remap normal RAM that we're using.. + * Don't allow anybody to remap RAM that may be allocated by the page + * allocator, since that could lead to races & data clobbering. */ - if (phys_addr < virt_to_phys(high_memory)) { - char *t_addr, *t_end; - struct page *page; - - t_addr = __va(phys_addr); - t_end = t_addr + (size - 1); - - for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) - if(!PageReserved(page)) - return NULL; + pfn = PFN_DOWN(phys_addr); + last_pfn = PFN_DOWN(last_addr); + if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL, + __ioremap_check_ram) == 1) { + WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n", + &phys_addr, &last_addr); + return NULL; } /*