Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp1150984imm; Wed, 1 Aug 2018 11:02:09 -0700 (PDT) X-Google-Smtp-Source: AAOMgpflCGpatOnVq5roHXnceEWcY243gi1XkqP0GecE1qcmCyvpyXUntvQ9h5IT1l4MYU4d6FOL X-Received: by 2002:a65:40cd:: with SMTP id u13-v6mr26116025pgp.334.1533146529797; Wed, 01 Aug 2018 11:02:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533146529; cv=none; d=google.com; s=arc-20160816; b=fu/X4/LUY+tfFpkW8v7yya9edYMVp6u0vxRgJmKVIl6cJJEZqwVCOU7ydVGJV776T8 2R2RObp9JV9EKQ7Q6Iwa2eg/lfKkxTISEPoAAZOOb7Xdzqj4LxoLL+ni6ui45Y49a2Rc WLcbF238DSJv2J+4pBJLG6EMVzDqAX85rspmy2bpTCxlklX8DcMiYx2MiYswy4pTfV2e F8W7fPv2/r9IwV5RPDwke0Tu8VQOrSdXKQdplB/Tu2H0e0VvtgT5GpSAWgSluzkWKls/ mTyHufMQ2uaUfZeMRlWcegmuH6dnA2KqTJPDMWr25vJXQUfOfWIQ8L4B+iyfjuT7XoGo PayQ== 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=8kM0Zzrfr5wg+A6Db1cMV6wDEQg3IcxOJ6X6hvgund8=; b=l4aWmnGDla18i0i8taZTE71/h0lIP+bDbRJYWsa2zbizio2odUEm0aMeH25FAKDJf7 ZZJan7UyJBB5FShnSfw/DYLE7XjJk6B9XKC3TKikKcID678vXCxMpzbxSy0rVAVHvurW BD2t3brc/iCHy6nl9ozg/6Iwm9/ldNI+DJPRnDQOGUSq5F6tNPwA7YELgkrz+DHkLV9Q wSrkVa/P0ISgqhsk21yQ26t1/WaEmdeC9hhEn7EQop6WPlBuwaq/TuHoR5MsuVG+8DCV 3PCgaQRrTji/klMRQyAFR1kloNBS9wi8fsnSwni7gRscZUxEpGxg5CLswGsHw8lfmQ3U QCAA== 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 140-v6si16256371pgd.19.2018.08.01.11.01.55; Wed, 01 Aug 2018 11:02:09 -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 S1732455AbeHATr6 (ORCPT + 99 others); Wed, 1 Aug 2018 15:47:58 -0400 Received: from mga06.intel.com ([134.134.136.31]:6229 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726136AbeHATr5 (ORCPT ); Wed, 1 Aug 2018 15:47:57 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 01 Aug 2018 11:01:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,432,1526367600"; d="scan'208";a="61592987" Received: from viggo.jf.intel.com (HELO localhost.localdomain) ([10.54.77.144]) by orsmga008.jf.intel.com with ESMTP; 01 Aug 2018 11:01:04 -0700 Subject: [PATCH 2/5] 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: Wed, 01 Aug 2018 11:01:01 -0700 References: <20180801180058.EC46D963@viggo.jf.intel.com> In-Reply-To: <20180801180058.EC46D963@viggo.jf.intel.com> Message-Id: <20180801180101.2A388EF8@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-07-30 09:53:13.259915693 -0700 +++ b/mm/page_alloc.c 2018-07-30 09:53:13.264915693 -0700 @@ -6934,9 +6934,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) _