Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp157239imm; Thu, 2 Aug 2018 16:02:07 -0700 (PDT) X-Google-Smtp-Source: AAOMgpcxacDHkKSVfBjjkZdTpvW8o82V/M/lGAM7YnFaWWgmqEagZAPDaZ+AsHcc0RB7857q/vBT X-Received: by 2002:a62:201b:: with SMTP id g27-v6mr1464820pfg.253.1533250927396; Thu, 02 Aug 2018 16:02:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533250927; cv=none; d=google.com; s=arc-20160816; b=kdkzZ6uaGH2ice8ZaEMz9d+vH8EO8qE8kCYyWTZ7rs38JjRIbqJwZx7MTRU0MQK48Z RtPAUP3+/nkR+mxCURfO/9THN3IYrD+ryaN/bnrIs/pd7eAU4/WwGnT4xgozZ5AUpriz BjPPp3D8bHnDm7AwQMRoE18t2XYkGOeQgdeHmsb/j1exQRzDtdy6y5Dluz/qiV14f3NO xBebRtAYPxBtRGOhKbMjFntd2WRT77TRwC8N9tcXzbN7h3Og0lFVmmYoSEAZKlP/ARSY Mn7Yrn77qA3W0LBTH/Je6veAqUowlW6YPCJwbjzuubHw5tpaoA145nqm8VhsUKtVcoA2 21eA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:in-reply-to:references:date :from:cc:to:subject:arc-authentication-results; bh=91jIohsRtXZApTszt+NNa9tASiDlLJvB4A2dohhzz+Q=; b=tLfTKjeSQd35/4c26WcKgr2nx/k32Y4fTJ3A0fw7FECBJ2KPYEpvyFnD1wrEQ24q18 nYBxYoQQDsXtmRHL6+8vCOjoAA8k7pqM+bEoxsmJlVU9D8jvxTF7i+y9RsZ+Ui0YROuj sKAKJVvoT4TdQ5iFPGiKk8U+RkghD/0rfQOSklNwCwBMoCyd6h7gC4FOOSQDM7tATgGG 7JkZK4t6FvA4XqLhCkYx8TvuUrTZhHAeEqwyfHRhG5DD43+Z3QfFYwBtCv0PwXBDOUfR 0W5Q7EMokPNw+OdVDhFAxkf7xgmAjMSEa87DIEbRGW6igPxitGI9bXOwqglOWypvBAIq UQBw== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f7-v6si2425003plt.4.2018.08.02.16.01.51; Thu, 02 Aug 2018 16:02:07 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732088AbeHCAvy (ORCPT + 99 others); Thu, 2 Aug 2018 20:51:54 -0400 Received: from mga12.intel.com ([192.55.52.136]:37019 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731697AbeHCAvx (ORCPT ); Thu, 2 Aug 2018 20:51:53 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Aug 2018 15:58:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,437,1526367600"; d="scan'208";a="61641442" Received: from viggo.jf.intel.com (HELO localhost.localdomain) ([10.54.77.144]) by orsmga007.jf.intel.com with ESMTP; 02 Aug 2018 15:58:35 -0700 Subject: [PATCH 2/7] mm: allow non-direct-map arguments to free_reserved_area() To: linux-kernel@vger.kernel.org Cc: Dave Hansen , keescook@google.com, tglx@linutronix.de, mingo@kernel.org, aarcange@redhat.com, jgross@suse.com, jpoimboe@redhat.com, gregkh@linuxfoundation.org, peterz@infradead.org, hughd@google.com, torvalds@linux-foundation.org, bp@alien8.de, luto@kernel.org, ak@linux.intel.com From: Dave Hansen Date: Thu, 02 Aug 2018 15:58:26 -0700 References: <20180802225823.4711C55B@viggo.jf.intel.com> In-Reply-To: <20180802225823.4711C55B@viggo.jf.intel.com> Message-Id: <20180802225826.1287AE3E@viggo.jf.intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Dave Hansen free_reserved_area() takes pointers as arguments to show which addresses should be freed. However, it does this in a somewhat ambiguous way. If it gets a kernel direct map address, it always works. However, if it gets an address that is part of the kernel image alias mapping, it can fail. It fails if all of the following happen: * The specified address is part of the kernel image alias * Poisoning is requested (forcing a memset()) * The address is in a read-only portion of the kernel image The memset() fails on the read-only mapping, of course. free_reserved_area() *is* called both on the direct map and on kernel image alias addresses. We've just lucked out thus far that the kernel image alias areas it gets used on are read-write. I'm fairly sure this has been just a happy accident. It is quite easy to make free_reserved_area() work for all cases: just convert the address to a direct map address before doing the memset(), and do this unconditionally. There is little chance of a regression here because we previously did a virt_to_page() on the address for the memset, so we know these are no highmem pages for which virt_to_page() would fail. Signed-off-by: Dave Hansen Cc: Kees Cook Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Andrea Arcangeli Cc: Juergen Gross Cc: Josh Poimboeuf Cc: Greg Kroah-Hartman Cc: Peter Zijlstra Cc: Hugh Dickins Cc: Linus Torvalds Cc: Borislav Petkov Cc: Andy Lutomirski Cc: Andi Kleen --- b/mm/page_alloc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff -puN mm/page_alloc.c~x86-mm-init-handle-non-linear-map-ranges-free_init_pages mm/page_alloc.c --- a/mm/page_alloc.c~x86-mm-init-handle-non-linear-map-ranges-free_init_pages 2018-08-02 14:14:47.860483278 -0700 +++ b/mm/page_alloc.c 2018-08-02 14:14:47.865483278 -0700 @@ -6939,9 +6939,21 @@ unsigned long free_reserved_area(void *s start = (void *)PAGE_ALIGN((unsigned long)start); end = (void *)((unsigned long)end & PAGE_MASK); for (pos = start; pos < end; pos += PAGE_SIZE, pages++) { + struct page *page = virt_to_page(pos); + void *direct_map_addr; + + /* + * 'direct_map_addr' might be different from 'pos' + * because some architectures' virt_to_page() + * work with aliases. Getting the direct map + * address ensures that we get a _writeable_ + * alias for the memset(). + */ + direct_map_addr = page_address(page); if ((unsigned int)poison <= 0xFF) - memset(pos, poison, PAGE_SIZE); - free_reserved_page(virt_to_page(pos)); + memset(direct_map_addr, poison, PAGE_SIZE); + + free_reserved_page(page); } if (pages && s) _