]> git.ipfire.org Git - people/ms/linux.git/blobdiff - arch/sparc/kernel/sys_sparc_64.c
Importing "grsecurity-3.1-3.19.2-201503201903.patch"
[people/ms/linux.git] / arch / sparc / kernel / sys_sparc_64.c
index c85403d0496c24f7639a32fa06b7dc53c1559381..6af95c93031297b582f1ec3ea3fa11eae7abe47a 100644 (file)
@@ -89,13 +89,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
        struct vm_area_struct * vma;
        unsigned long task_size = TASK_SIZE;
        int do_color_align;
+       unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags);
        struct vm_unmapped_area_info info;
 
        if (flags & MAP_FIXED) {
                /* We do not accept a shared mapping if it would violate
                 * cache aliasing constraints.
                 */
-               if ((flags & MAP_SHARED) &&
+               if ((filp || (flags & MAP_SHARED)) &&
                    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
                        return -EINVAL;
                return addr;
@@ -110,6 +111,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
        if (filp || (flags & MAP_SHARED))
                do_color_align = 1;
 
+#ifdef CONFIG_PAX_RANDMMAP
+       if (!(mm->pax_flags & MF_PAX_RANDMMAP))
+#endif
+
        if (addr) {
                if (do_color_align)
                        addr = COLOR_ALIGN(addr, pgoff);
@@ -117,22 +122,28 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
                        addr = PAGE_ALIGN(addr);
 
                vma = find_vma(mm, addr);
-               if (task_size - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+               if (task_size - len >= addr && check_heap_stack_gap(vma, addr, len, offset))
                        return addr;
        }
 
        info.flags = 0;
        info.length = len;
-       info.low_limit = TASK_UNMAPPED_BASE;
+       info.low_limit = mm->mmap_base;
        info.high_limit = min(task_size, VA_EXCLUDE_START);
        info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
        info.align_offset = pgoff << PAGE_SHIFT;
+       info.threadstack_offset = offset;
        addr = vm_unmapped_area(&info);
 
        if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
                VM_BUG_ON(addr != -ENOMEM);
                info.low_limit = VA_EXCLUDE_END;
+
+#ifdef CONFIG_PAX_RANDMMAP
+               if (mm->pax_flags & MF_PAX_RANDMMAP)
+                       info.low_limit += mm->delta_mmap;
+#endif
+
                info.high_limit = task_size;
                addr = vm_unmapped_area(&info);
        }
@@ -150,6 +161,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        unsigned long task_size = STACK_TOP32;
        unsigned long addr = addr0;
        int do_color_align;
+       unsigned long offset = gr_rand_threadstack_offset(mm, filp, flags);
        struct vm_unmapped_area_info info;
 
        /* This should only ever run for 32-bit processes.  */
@@ -159,7 +171,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                /* We do not accept a shared mapping if it would violate
                 * cache aliasing constraints.
                 */
-               if ((flags & MAP_SHARED) &&
+               if ((filp || (flags & MAP_SHARED)) &&
                    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
                        return -EINVAL;
                return addr;
@@ -172,6 +184,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        if (filp || (flags & MAP_SHARED))
                do_color_align = 1;
 
+#ifdef CONFIG_PAX_RANDMMAP
+       if (!(mm->pax_flags & MF_PAX_RANDMMAP))
+#endif
+
        /* requesting a specific address */
        if (addr) {
                if (do_color_align)
@@ -180,8 +196,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                        addr = PAGE_ALIGN(addr);
 
                vma = find_vma(mm, addr);
-               if (task_size - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+               if (task_size - len >= addr && check_heap_stack_gap(vma, addr, len, offset))
                        return addr;
        }
 
@@ -191,6 +206,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        info.high_limit = mm->mmap_base;
        info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
        info.align_offset = pgoff << PAGE_SHIFT;
+       info.threadstack_offset = offset;
        addr = vm_unmapped_area(&info);
 
        /*
@@ -203,6 +219,12 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                VM_BUG_ON(addr != -ENOMEM);
                info.flags = 0;
                info.low_limit = TASK_UNMAPPED_BASE;
+
+#ifdef CONFIG_PAX_RANDMMAP
+               if (mm->pax_flags & MF_PAX_RANDMMAP)
+                       info.low_limit += mm->delta_mmap;
+#endif
+
                info.high_limit = STACK_TOP32;
                addr = vm_unmapped_area(&info);
        }
@@ -259,10 +281,14 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
 EXPORT_SYMBOL(get_fb_unmapped_area);
 
 /* Essentially the same as PowerPC.  */
-static unsigned long mmap_rnd(void)
+static unsigned long mmap_rnd(struct mm_struct *mm)
 {
        unsigned long rnd = 0UL;
 
+#ifdef CONFIG_PAX_RANDMMAP
+       if (!(mm->pax_flags & MF_PAX_RANDMMAP))
+#endif
+
        if (current->flags & PF_RANDOMIZE) {
                unsigned long val = get_random_int();
                if (test_thread_flag(TIF_32BIT))
@@ -275,7 +301,7 @@ static unsigned long mmap_rnd(void)
 
 void arch_pick_mmap_layout(struct mm_struct *mm)
 {
-       unsigned long random_factor = mmap_rnd();
+       unsigned long random_factor = mmap_rnd(mm);
        unsigned long gap;
 
        /*
@@ -288,6 +314,12 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
            gap == RLIM_INFINITY ||
            sysctl_legacy_va_layout) {
                mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
+
+#ifdef CONFIG_PAX_RANDMMAP
+               if (mm->pax_flags & MF_PAX_RANDMMAP)
+                       mm->mmap_base += mm->delta_mmap;
+#endif
+
                mm->get_unmapped_area = arch_get_unmapped_area;
        } else {
                /* We know it's 32-bit */
@@ -299,6 +331,12 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
                        gap = (task_size / 6 * 5);
 
                mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor);
+
+#ifdef CONFIG_PAX_RANDMMAP
+               if (mm->pax_flags & MF_PAX_RANDMMAP)
+                       mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
+#endif
+
                mm->get_unmapped_area = arch_get_unmapped_area_topdown;
        }
 }