diff options
Diffstat (limited to 'mm/util.c')
| -rw-r--r-- | mm/util.c | 32 | 
1 files changed, 32 insertions, 0 deletions
diff --git a/mm/util.c b/mm/util.c index 3492a9e81aa3..ac63e5ca8b21 100644 --- a/mm/util.c +++ b/mm/util.c @@ -343,6 +343,38 @@ unsigned long randomize_stack_top(unsigned long stack_top)  #endif  } +/** + * randomize_page - Generate a random, page aligned address + * @start:	The smallest acceptable address the caller will take. + * @range:	The size of the area, starting at @start, within which the + *		random address must fall. + * + * If @start + @range would overflow, @range is capped. + * + * NOTE: Historical use of randomize_range, which this replaces, presumed that + * @start was already page aligned.  We now align it regardless. + * + * Return: A page aligned address within [start, start + range).  On error, + * @start is returned. + */ +unsigned long randomize_page(unsigned long start, unsigned long range) +{ +	if (!PAGE_ALIGNED(start)) { +		range -= PAGE_ALIGN(start) - start; +		start = PAGE_ALIGN(start); +	} + +	if (start > ULONG_MAX - range) +		range = ULONG_MAX - start; + +	range >>= PAGE_SHIFT; + +	if (range == 0) +		return start; + +	return start + (get_random_long() % range << PAGE_SHIFT); +} +  #ifdef CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT  unsigned long arch_randomize_brk(struct mm_struct *mm)  {  | 
