]> git.ipfire.org Git - people/ms/linux.git/blobdiff - mm/page_alloc.c
Importing "grsecurity-3.1-3.19.2-201503201903.patch"
[people/ms/linux.git] / mm / page_alloc.c
index 8bbef06de720b0d7916830269f9030c77d35930e..a8d1989937980a9ec45d136eded0a2b7236d84be 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/hugetlb.h>
 #include <linux/sched/rt.h>
 #include <linux/page_owner.h>
+#include <linux/random.h>
 
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
@@ -358,7 +359,7 @@ out:
  * This usage means that zero-order pages may not be compound.
  */
 
-static void free_compound_page(struct page *page)
+void free_compound_page(struct page *page)
 {
        __free_pages_ok(page, compound_order(page));
 }
@@ -511,7 +512,7 @@ static inline void clear_page_guard(struct zone *zone, struct page *page,
                __mod_zone_freepage_state(zone, (1 << order), migratetype);
 }
 #else
-struct page_ext_operations debug_guardpage_ops = { NULL, };
+struct page_ext_operations debug_guardpage_ops = { .need = NULL, .init = NULL };
 static inline void set_page_guard(struct zone *zone, struct page *page,
                                unsigned int order, int migratetype) {}
 static inline void clear_page_guard(struct zone *zone, struct page *page,
@@ -802,6 +803,10 @@ static bool free_pages_prepare(struct page *page, unsigned int order)
        int i;
        int bad = 0;
 
+#ifdef CONFIG_PAX_MEMORY_SANITIZE
+       unsigned long index = 1UL << order;
+#endif
+
        VM_BUG_ON_PAGE(PageTail(page), page);
        VM_BUG_ON_PAGE(PageHead(page) && compound_order(page) != order, page);
 
@@ -823,6 +828,12 @@ static bool free_pages_prepare(struct page *page, unsigned int order)
                debug_check_no_obj_freed(page_address(page),
                                           PAGE_SIZE << order);
        }
+
+#ifdef CONFIG_PAX_MEMORY_SANITIZE
+       for (; index; --index)
+               sanitize_highpage(page + index - 1);
+#endif
+
        arch_free_page(page, order);
        kernel_map_pages(page, 1 << order, 0);
 
@@ -846,6 +857,20 @@ static void __free_pages_ok(struct page *page, unsigned int order)
        local_irq_restore(flags);
 }
 
+#ifdef CONFIG_PAX_LATENT_ENTROPY
+bool __meminitdata extra_latent_entropy;
+
+static int __init setup_pax_extra_latent_entropy(char *str)
+{
+       extra_latent_entropy = true;
+       return 0;
+}
+early_param("pax_extra_latent_entropy", setup_pax_extra_latent_entropy);
+
+volatile u64 latent_entropy __latent_entropy;
+EXPORT_SYMBOL(latent_entropy);
+#endif
+
 void __init __free_pages_bootmem(struct page *page, unsigned int order)
 {
        unsigned int nr_pages = 1 << order;
@@ -861,6 +886,19 @@ void __init __free_pages_bootmem(struct page *page, unsigned int order)
        __ClearPageReserved(p);
        set_page_count(p, 0);
 
+#ifdef CONFIG_PAX_LATENT_ENTROPY
+       if (extra_latent_entropy && !PageHighMem(page) && page_to_pfn(page) < 0x100000) {
+               u64 hash = 0;
+               size_t index, end = PAGE_SIZE * nr_pages / sizeof hash;
+               const u64 *data = lowmem_page_address(page);
+
+               for (index = 0; index < end; index++)
+                       hash ^= hash + data[index];
+               latent_entropy ^= hash;
+               add_device_randomness((const void *)&latent_entropy, sizeof(latent_entropy));
+       }
+#endif
+
        page_zone(page)->managed_pages += nr_pages;
        set_page_refcounted(page);
        __free_pages(page, order);
@@ -986,8 +1024,10 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags)
        arch_alloc_page(page, order);
        kernel_map_pages(page, 1 << order, 1);
 
+#ifndef CONFIG_PAX_MEMORY_SANITIZE
        if (gfp_flags & __GFP_ZERO)
                prep_zero_page(page, order, gfp_flags);
+#endif
 
        if (order && (gfp_flags & __GFP_COMP))
                prep_compound_page(page, order);
@@ -1700,7 +1740,7 @@ again:
        }
 
        __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order));
-       if (atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH]) <= 0 &&
+       if (atomic_long_read_unchecked(&zone->vm_stat[NR_ALLOC_BATCH]) <= 0 &&
            !test_bit(ZONE_FAIR_DEPLETED, &zone->flags))
                set_bit(ZONE_FAIR_DEPLETED, &zone->flags);
 
@@ -2021,7 +2061,7 @@ static void reset_alloc_batches(struct zone *preferred_zone)
        do {
                mod_zone_page_state(zone, NR_ALLOC_BATCH,
                        high_wmark_pages(zone) - low_wmark_pages(zone) -
-                       atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH]));
+                       atomic_long_read_unchecked(&zone->vm_stat[NR_ALLOC_BATCH]));
                clear_bit(ZONE_FAIR_DEPLETED, &zone->flags);
        } while (zone++ != preferred_zone);
 }
@@ -5781,7 +5821,7 @@ static void __setup_per_zone_wmarks(void)
 
                __mod_zone_page_state(zone, NR_ALLOC_BATCH,
                        high_wmark_pages(zone) - low_wmark_pages(zone) -
-                       atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH]));
+                       atomic_long_read_unchecked(&zone->vm_stat[NR_ALLOC_BATCH]));
 
                setup_zone_migrate_reserve(zone);
                spin_unlock_irqrestore(&zone->lock, flags);