lkml.org 
[lkml]   [2010]   [Dec]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[112/289] mm, page-allocator: do not check the state of a non-existant buddy during free
    2.6.36-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Mel Gorman <mel@csn.ul.ie>

    commit b7f50cfa3630b6e079929ffccfd442d65064ee1f upstream.

    There is a bug in commit 6dda9d55 ("page allocator: reduce fragmentation
    in buddy allocator by adding buddies that are merging to the tail of the
    free lists") that means a buddy at order MAX_ORDER is checked for merging.
    A page of this order never exists so at times, an effectively random
    piece of memory is being checked.

    Alan Curry has reported that this is causing memory corruption in
    userspace data on a PPC32 platform (http://lkml.org/lkml/2010/10/9/32).
    It is not clear why this is happening. It could be a cache coherency
    problem where pages mapped in both user and kernel space are getting
    different cache lines due to the bad read from kernel space
    (http://lkml.org/lkml/2010/10/13/179). It could also be that there are
    some special registers being io-remapped at the end of the memmap array
    and that a read has special meaning on them. Compiler bugs have been
    ruled out because the assembly before and after the patch looks relatively
    harmless.

    This patch fixes the problem by ensuring we are not reading a possibly
    invalid location of memory. It's not clear why the read causes corruption
    but one way or the other it is a buggy read.

    Signed-off-by: Mel Gorman <mel@csn.ul.ie>
    Cc: Corrado Zoccolo <czoccolo@gmail.com>
    Reported-by: Alan Curry <pacman@kosh.dhis.org>
    Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
    Cc: Christoph Lameter <cl@linux-foundation.org>
    Cc: Rik van Riel <riel@redhat.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    mm/page_alloc.c | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    --- a/mm/page_alloc.c
    +++ b/mm/page_alloc.c
    @@ -530,7 +530,7 @@ static inline void __free_one_page(struc
    * so it's less likely to be used soon and more likely to be merged
    * as a higher order page
    */
    - if ((order < MAX_ORDER-1) && pfn_valid_within(page_to_pfn(buddy))) {
    + if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) {
    struct page *higher_page, *higher_buddy;
    combined_idx = __find_combined_index(page_idx, order);
    higher_page = page + combined_idx - page_idx;



    \
     
     \ /
      Last update: 2010-12-08 02:11    [W:2.261 / U:0.108 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site