lkml.org 
[lkml]   [2018]   [Aug]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:x86/pti] mm: Allow non-direct-map arguments to free_reserved_area()
    Commit-ID:  0d83432811f26871295a9bc24d3c387924da6071
    Gitweb: https://git.kernel.org/tip/0d83432811f26871295a9bc24d3c387924da6071
    Author: Dave Hansen <dave.hansen@linux.intel.com>
    AuthorDate: Thu, 2 Aug 2018 15:58:26 -0700
    Committer: Thomas Gleixner <tglx@linutronix.de>
    CommitDate: Sun, 5 Aug 2018 22:21:02 +0200

    mm: Allow non-direct-map arguments to free_reserved_area()

    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 not highmem pages for which virt_to_page() would fail.

    Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: keescook@google.com
    Cc: aarcange@redhat.com
    Cc: jgross@suse.com
    Cc: jpoimboe@redhat.com
    Cc: gregkh@linuxfoundation.org
    Cc: peterz@infradead.org
    Cc: hughd@google.com
    Cc: torvalds@linux-foundation.org
    Cc: bp@alien8.de
    Cc: luto@kernel.org
    Cc: ak@linux.intel.com
    Cc: Kees Cook <keescook@google.com>
    Cc: Andrea Arcangeli <aarcange@redhat.com>
    Cc: Juergen Gross <jgross@suse.com>
    Cc: Josh Poimboeuf <jpoimboe@redhat.com>
    Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Hugh Dickins <hughd@google.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Borislav Petkov <bp@alien8.de>
    Cc: Andy Lutomirski <luto@kernel.org>
    Cc: Andi Kleen <ak@linux.intel.com>
    Link: https://lkml.kernel.org/r/20180802225826.1287AE3E@viggo.jf.intel.com

    ---
    mm/page_alloc.c | 16 ++++++++++++++--
    1 file changed, 14 insertions(+), 2 deletions(-)

    diff --git a/mm/page_alloc.c b/mm/page_alloc.c
    index a790ef4be74e..3222193c46c6 100644
    --- a/mm/page_alloc.c
    +++ b/mm/page_alloc.c
    @@ -6939,9 +6939,21 @@ unsigned long free_reserved_area(void *start, void *end, int poison, char *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)
    \
     
     \ /
      Last update: 2018-08-05 22:32    [W:4.042 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site