diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2022-10-20 08:19:35 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-01-07 13:11:40 +0300 |
commit | 6088d8783f7b656dff34392532f94ae45fb2605d (patch) | |
tree | 21579c84304ff0cf8e5ae579ac73cc7b46be9d29 /include | |
parent | ef3ad7f447a2a8c156e40ea284a8985372be4254 (diff) | |
download | linux-6088d8783f7b656dff34392532f94ae45fb2605d.tar.xz |
random: add helpers for random numbers with given floor or range
commit 7f576b2593a978451416424e75f69ad1e3ae4efe upstream.
Now that we have get_random_u32_below(), it's nearly trivial to make
inline helpers to compute get_random_u32_above() and
get_random_u32_inclusive(), which will help clean up open coded loops
and manual computations throughout the tree.
One snag is that in order to make get_random_u32_inclusive() operate on
closed intervals, we have to do some (unlikely) special case handling if
get_random_u32_inclusive(0, U32_MAX) is called. The least expensive way
of doing this is actually to adjust the slowpath of
get_random_u32_below() to have its undefined 0 result just return the
output of get_random_u32(). We can make this basically free by calling
get_random_u32() before the branch, so that the branch latency gets
interleaved.
Cc: stable@vger.kernel.org # to ease future backports that use this api
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/random.h | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/include/linux/random.h b/include/linux/random.h index 3a82c0a8bc46..bd954ecbef90 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -92,6 +92,31 @@ static inline u32 get_random_u32_below(u32 ceil) } /* + * Returns a random integer in the interval (floor, U32_MAX], with uniform + * distribution, suitable for all uses. Fastest when floor is a constant, but + * still fast for variable floor as well. + */ +static inline u32 get_random_u32_above(u32 floor) +{ + BUILD_BUG_ON_MSG(__builtin_constant_p(floor) && floor == U32_MAX, + "get_random_u32_above() must take floor < U32_MAX"); + return floor + 1 + get_random_u32_below(U32_MAX - floor); +} + +/* + * Returns a random integer in the interval [floor, ceil], with uniform + * distribution, suitable for all uses. Fastest when floor and ceil are + * constant, but still fast for variable floor and ceil as well. + */ +static inline u32 get_random_u32_inclusive(u32 floor, u32 ceil) +{ + BUILD_BUG_ON_MSG(__builtin_constant_p(floor) && __builtin_constant_p(ceil) && + (floor > ceil || ceil - floor == U32_MAX), + "get_random_u32_inclusive() must take floor <= ceil"); + return floor + get_random_u32_below(ceil - floor + 1); +} + +/* * On 64-bit architectures, protect against non-terminated C string overflows * by zeroing out the first byte of the canary; this leaves 56 bits of entropy. */ |