diff options
author | Jason Cooper <[email protected]> | 2016-10-11 13:53:52 -0700 |
---|---|---|
committer | Linus Torvalds <[email protected]> | 2016-10-11 15:06:32 -0700 |
commit | 99fdafdeacfa99ca9047641b684fa2aaf094a661 (patch) | |
tree | 9c37c6fd906ed2027bf2e5b15747960edb6ab8a5 | |
parent | 7836a2d9803c6203d2922e7116307c9f0dfe87f9 (diff) |
random: simplify API for random address requests
To date, all callers of randomize_range() have set the length to 0, and
check for a zero return value. For the current callers, the only way to
get zero returned is if end <= start. Since they are all adding a
constant to the start address, this is unnecessary.
We can remove a bunch of needless checks by simplifying the API to do just
what everyone wants, return an address between [start, start + range).
While we're here, s/get_random_int/get_random_long/. No current call site
is adversely affected by get_random_int(), since all current range
requests are < UINT_MAX. However, we should match caller expectations to
avoid coming up short (ha!) in the future.
All current callers to randomize_range() chose to use the start address if
randomize_range() failed. Therefore, we simplify things by just returning
the start address on error.
randomize_range() will be removed once all callers have been converted
over to randomize_addr().
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Jason Cooper <[email protected]>
Acked-by: Kees Cook <[email protected]>
Cc: Michael Ellerman <[email protected]>
Cc: "Roberts, William C" <[email protected]>
Cc: Yann Droneaud <[email protected]>
Cc: Russell King <[email protected]>
Cc: "Theodore Ts'o" <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: Ralf Baechle <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: "H . Peter Anvin" <[email protected]>
Cc: Nick Kralevich <[email protected]>
Cc: Jeffrey Vander Stoep <[email protected]>
Cc: Daniel Cashman <[email protected]>
Cc: Chris Metcalf <[email protected]>
Cc: Guan Xuetao <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
-rw-r--r-- | drivers/char/random.c | 33 | ||||
-rw-r--r-- | include/linux/random.h | 1 |
2 files changed, 34 insertions, 0 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 3efb3bf0ab83..40eb07e79b02 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -2119,6 +2119,39 @@ randomize_range(unsigned long start, unsigned long end, unsigned long len) return PAGE_ALIGN(get_random_int() % range + start); } +/** + * 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); +} + /* Interface for in-kernel drivers of true hardware RNGs. * Those devices may produce endless random bits and will be throttled * when our pool is full. diff --git a/include/linux/random.h b/include/linux/random.h index 3d6e9815cd85..26741892828a 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -35,6 +35,7 @@ extern const struct file_operations random_fops, urandom_fops; unsigned int get_random_int(void); unsigned long get_random_long(void); unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len); +unsigned long randomize_page(unsigned long start, unsigned long range); u32 prandom_u32(void); void prandom_bytes(void *buf, size_t nbytes); |