| .. | .. | 
|---|
| 17 | 17 | #include <linux/random.h> | 
|---|
| 18 | 18 | #include <linux/compat.h> | 
|---|
| 19 | 19 | #include <linux/security.h> | 
|---|
| 20 |  | -#include <asm/pgalloc.h> | 
|---|
| 21 | 20 | #include <asm/elf.h> | 
|---|
| 22 | 21 |  | 
|---|
| 23 | 22 | static unsigned long stack_maxrandom_size(void) | 
|---|
| 24 | 23 | { | 
|---|
| 25 | 24 | if (!(current->flags & PF_RANDOMIZE)) | 
|---|
| 26 | 25 | return 0; | 
|---|
| 27 |  | -	if (current->personality & ADDR_NO_RANDOMIZE) | 
|---|
| 28 |  | -		return 0; | 
|---|
| 29 | 26 | return STACK_RND_MASK << PAGE_SHIFT; | 
|---|
| 30 | 27 | } | 
|---|
| 31 |  | - | 
|---|
| 32 |  | -/* | 
|---|
| 33 |  | - * Top of mmap area (just below the process stack). | 
|---|
| 34 |  | - * | 
|---|
| 35 |  | - * Leave at least a ~32 MB hole. | 
|---|
| 36 |  | - */ | 
|---|
| 37 |  | -#define MIN_GAP (32*1024*1024) | 
|---|
| 38 |  | -#define MAX_GAP (STACK_TOP/6*5) | 
|---|
| 39 | 28 |  | 
|---|
| 40 | 29 | static inline int mmap_is_legacy(struct rlimit *rlim_stack) | 
|---|
| 41 | 30 | { | 
|---|
| .. | .. | 
|---|
| 60 | 49 | struct rlimit *rlim_stack) | 
|---|
| 61 | 50 | { | 
|---|
| 62 | 51 | unsigned long gap = rlim_stack->rlim_cur; | 
|---|
|  | 52 | +	unsigned long pad = stack_maxrandom_size() + stack_guard_gap; | 
|---|
|  | 53 | +	unsigned long gap_min, gap_max; | 
|---|
| 63 | 54 |  | 
|---|
| 64 |  | -	if (gap < MIN_GAP) | 
|---|
| 65 |  | -		gap = MIN_GAP; | 
|---|
| 66 |  | -	else if (gap > MAX_GAP) | 
|---|
| 67 |  | -		gap = MAX_GAP; | 
|---|
| 68 |  | -	gap &= PAGE_MASK; | 
|---|
| 69 |  | -	return STACK_TOP - stack_maxrandom_size() - rnd - gap; | 
|---|
|  | 55 | +	/* Values close to RLIM_INFINITY can overflow. */ | 
|---|
|  | 56 | +	if (gap + pad > gap) | 
|---|
|  | 57 | +		gap += pad; | 
|---|
|  | 58 | + | 
|---|
|  | 59 | +	/* | 
|---|
|  | 60 | +	 * Top of mmap area (just below the process stack). | 
|---|
|  | 61 | +	 * Leave at least a ~32 MB hole. | 
|---|
|  | 62 | +	 */ | 
|---|
|  | 63 | +	gap_min = 32 * 1024 * 1024UL; | 
|---|
|  | 64 | +	gap_max = (STACK_TOP / 6) * 5; | 
|---|
|  | 65 | + | 
|---|
|  | 66 | +	if (gap < gap_min) | 
|---|
|  | 67 | +		gap = gap_min; | 
|---|
|  | 68 | +	else if (gap > gap_max) | 
|---|
|  | 69 | +		gap = gap_max; | 
|---|
|  | 70 | + | 
|---|
|  | 71 | +	return PAGE_ALIGN(STACK_TOP - gap - rnd); | 
|---|
| 70 | 72 | } | 
|---|
| 71 | 73 |  | 
|---|
| 72 |  | -unsigned long | 
|---|
| 73 |  | -arch_get_unmapped_area(struct file *filp, unsigned long addr, | 
|---|
| 74 |  | -		unsigned long len, unsigned long pgoff, unsigned long flags) | 
|---|
|  | 74 | +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, | 
|---|
|  | 75 | +				     unsigned long len, unsigned long pgoff, | 
|---|
|  | 76 | +				     unsigned long flags) | 
|---|
| 75 | 77 | { | 
|---|
| 76 | 78 | struct mm_struct *mm = current->mm; | 
|---|
| 77 | 79 | struct vm_area_struct *vma; | 
|---|
| 78 | 80 | struct vm_unmapped_area_info info; | 
|---|
| 79 |  | -	int rc; | 
|---|
| 80 | 81 |  | 
|---|
| 81 | 82 | if (len > TASK_SIZE - mmap_min_addr) | 
|---|
| 82 | 83 | return -ENOMEM; | 
|---|
| .. | .. | 
|---|
| 102 | 103 | info.align_mask = 0; | 
|---|
| 103 | 104 | info.align_offset = pgoff << PAGE_SHIFT; | 
|---|
| 104 | 105 | addr = vm_unmapped_area(&info); | 
|---|
| 105 |  | -	if (addr & ~PAGE_MASK) | 
|---|
|  | 106 | +	if (offset_in_page(addr)) | 
|---|
| 106 | 107 | return addr; | 
|---|
| 107 | 108 |  | 
|---|
| 108 | 109 | check_asce_limit: | 
|---|
| 109 |  | -	if (addr + len > current->mm->context.asce_limit && | 
|---|
| 110 |  | -	    addr + len <= TASK_SIZE) { | 
|---|
| 111 |  | -		rc = crst_table_upgrade(mm, addr + len); | 
|---|
| 112 |  | -		if (rc) | 
|---|
| 113 |  | -			return (unsigned long) rc; | 
|---|
| 114 |  | -	} | 
|---|
| 115 |  | - | 
|---|
| 116 |  | -	return addr; | 
|---|
|  | 110 | +	return check_asce_limit(mm, addr, len); | 
|---|
| 117 | 111 | } | 
|---|
| 118 | 112 |  | 
|---|
| 119 |  | -unsigned long | 
|---|
| 120 |  | -arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | 
|---|
| 121 |  | -			  const unsigned long len, const unsigned long pgoff, | 
|---|
| 122 |  | -			  const unsigned long flags) | 
|---|
|  | 113 | +unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, | 
|---|
|  | 114 | +					     unsigned long len, unsigned long pgoff, | 
|---|
|  | 115 | +					     unsigned long flags) | 
|---|
| 123 | 116 | { | 
|---|
| 124 | 117 | struct vm_area_struct *vma; | 
|---|
| 125 | 118 | struct mm_struct *mm = current->mm; | 
|---|
| 126 |  | -	unsigned long addr = addr0; | 
|---|
| 127 | 119 | struct vm_unmapped_area_info info; | 
|---|
| 128 |  | -	int rc; | 
|---|
| 129 | 120 |  | 
|---|
| 130 | 121 | /* requested length too big for entire address space */ | 
|---|
| 131 | 122 | if (len > TASK_SIZE - mmap_min_addr) | 
|---|
| .. | .. | 
|---|
| 160 | 151 | * can happen with large stack limits and large mmap() | 
|---|
| 161 | 152 | * allocations. | 
|---|
| 162 | 153 | */ | 
|---|
| 163 |  | -	if (addr & ~PAGE_MASK) { | 
|---|
|  | 154 | +	if (offset_in_page(addr)) { | 
|---|
| 164 | 155 | VM_BUG_ON(addr != -ENOMEM); | 
|---|
| 165 | 156 | info.flags = 0; | 
|---|
| 166 | 157 | info.low_limit = TASK_UNMAPPED_BASE; | 
|---|
| 167 | 158 | info.high_limit = TASK_SIZE; | 
|---|
| 168 | 159 | addr = vm_unmapped_area(&info); | 
|---|
| 169 |  | -		if (addr & ~PAGE_MASK) | 
|---|
|  | 160 | +		if (offset_in_page(addr)) | 
|---|
| 170 | 161 | return addr; | 
|---|
| 171 | 162 | } | 
|---|
| 172 | 163 |  | 
|---|
| 173 | 164 | check_asce_limit: | 
|---|
| 174 |  | -	if (addr + len > current->mm->context.asce_limit && | 
|---|
| 175 |  | -	    addr + len <= TASK_SIZE) { | 
|---|
| 176 |  | -		rc = crst_table_upgrade(mm, addr + len); | 
|---|
| 177 |  | -		if (rc) | 
|---|
| 178 |  | -			return (unsigned long) rc; | 
|---|
| 179 |  | -	} | 
|---|
| 180 |  | - | 
|---|
| 181 |  | -	return addr; | 
|---|
|  | 165 | +	return check_asce_limit(mm, addr, len); | 
|---|
| 182 | 166 | } | 
|---|
| 183 | 167 |  | 
|---|
| 184 | 168 | /* | 
|---|