• Jason A. Donenfeld's avatar
    random: use rejection sampling for uniform bounded random integers · e9a688bc
    Jason A. Donenfeld authored
    Until the very recent commits, many bounded random integers were
    calculated using `get_random_u32() % max_plus_one`, which not only
    incurs the price of a division -- indicating performance mostly was not
    a real issue -- but also does not result in a uniformly distributed
    output if max_plus_one is not a power of two. Recent commits moved to
    using `prandom_u32_max(max_plus_one)`, which replaces the division with
    a faster multiplication, but still does not solve the issue with
    non-uniform output.
    
    For some users, maybe this isn't a problem, and for others, maybe it is,
    but for the majority of users, probably the question has never been
    posed and analyzed, and nobody thought much about it, probably assuming
    random is random is random. In other words, the unthinking expectation
    of most users is likely that the resultant numbers are uniform.
    
    So we implement here an efficient way of generating uniform bounded
    random integers. Through use of compile-time evaluation, and avoiding
    divisions as much as possible, this commit introduces no measurable
    overhead. At least for hot-path uses tested, any potential difference
    was lost in the noise. On both clang and gcc, code generation is pretty
    small.
    
    The new function, get_random_u32_below(), lives in random.h, rather than
    prandom.h, and has a "get_random_xxx" function name, because it is
    suitable for all uses, including cryptography.
    
    In order to be efficient, we implement a kernel-specific variant of
    Daniel Lemire's algorithm from "Fast Random Integer Generation in an
    Interval", linked below. The kernel's variant takes advantage of
    constant folding to avoid divisions entirely in the vast majority of
    cases, works on both 32-bit and 64-bit architectures, and requests a
    minimal amount of bytes from the RNG.
    
    Link: https://arxiv.org/pdf/1805.10941.pdf
    Cc: stable@vger.kernel.org # to ease future backports that use this api
    Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
    e9a688bc
random.c 48.9 KB