aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/random.c84
-rw-r--r--include/linux/random.h1
-rw-r--r--init/main.c1
3 files changed, 43 insertions, 43 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 9d147d456598..b800e5479b7d 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -2016,63 +2016,65 @@ struct ctl_table random_table[] = {
2016}; 2016};
2017#endif /* CONFIG_SYSCTL */ 2017#endif /* CONFIG_SYSCTL */
2018 2018
2019static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; 2019struct batched_entropy {
2020 2020 union {
2021int random_int_secret_init(void) 2021 unsigned long entropy_long[CHACHA20_BLOCK_SIZE / sizeof(unsigned long)];
2022{ 2022 unsigned int entropy_int[CHACHA20_BLOCK_SIZE / sizeof(unsigned int)];
2023 get_random_bytes(random_int_secret, sizeof(random_int_secret)); 2023 };
2024 return 0; 2024 unsigned int position;
2025} 2025};
2026
2027static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash)
2028 __aligned(sizeof(unsigned long));
2029 2026
2030/* 2027/*
2031 * Get a random word for internal kernel use only. Similar to urandom but 2028 * Get a random word for internal kernel use only. The quality of the random
2032 * with the goal of minimal entropy pool depletion. As a result, the random 2029 * number is either as good as RDRAND or as good as /dev/urandom, with the
2033 * value is not cryptographically secure but for several uses the cost of 2030 * goal of being quite fast and not depleting entropy.
2034 * depleting entropy is too high
2035 */ 2031 */
2036unsigned int get_random_int(void) 2032static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_long);
2033unsigned long get_random_long(void)
2037{ 2034{
2038 __u32 *hash; 2035 unsigned long ret;
2039 unsigned int ret; 2036 struct batched_entropy *batch;
2040 2037
2041 if (arch_get_random_int(&ret)) 2038 if (arch_get_random_long(&ret))
2042 return ret; 2039 return ret;
2043 2040
2044 hash = get_cpu_var(get_random_int_hash); 2041 batch = &get_cpu_var(batched_entropy_long);
2045 2042 if (batch->position % ARRAY_SIZE(batch->entropy_long) == 0) {
2046 hash[0] += current->pid + jiffies + random_get_entropy(); 2043 extract_crng((u8 *)batch->entropy_long);
2047 md5_transform(hash, random_int_secret); 2044 batch->position = 0;
2048 ret = hash[0]; 2045 }
2049 put_cpu_var(get_random_int_hash); 2046 ret = batch->entropy_long[batch->position++];
2050 2047 put_cpu_var(batched_entropy_long);
2051 return ret; 2048 return ret;
2052} 2049}
2053EXPORT_SYMBOL(get_random_int); 2050EXPORT_SYMBOL(get_random_long);
2054 2051
2055/* 2052#if BITS_PER_LONG == 32
2056 * Same as get_random_int(), but returns unsigned long. 2053unsigned int get_random_int(void)
2057 */
2058unsigned long get_random_long(void)
2059{ 2054{
2060 __u32 *hash; 2055 return get_random_long();
2061 unsigned long ret; 2056}
2057#else
2058static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_int);
2059unsigned int get_random_int(void)
2060{
2061 unsigned int ret;
2062 struct batched_entropy *batch;
2062 2063
2063 if (arch_get_random_long(&ret)) 2064 if (arch_get_random_int(&ret))
2064 return ret; 2065 return ret;
2065 2066
2066 hash = get_cpu_var(get_random_int_hash); 2067 batch = &get_cpu_var(batched_entropy_int);
2067 2068 if (batch->position % ARRAY_SIZE(batch->entropy_int) == 0) {
2068 hash[0] += current->pid + jiffies + random_get_entropy(); 2069 extract_crng((u8 *)batch->entropy_int);
2069 md5_transform(hash, random_int_secret); 2070 batch->position = 0;
2070 ret = *(unsigned long *)hash; 2071 }
2071 put_cpu_var(get_random_int_hash); 2072 ret = batch->entropy_int[batch->position++];
2072 2073 put_cpu_var(batched_entropy_int);
2073 return ret; 2074 return ret;
2074} 2075}
2075EXPORT_SYMBOL(get_random_long); 2076#endif
2077EXPORT_SYMBOL(get_random_int);
2076 2078
2077/** 2079/**
2078 * randomize_page - Generate a random, page aligned address 2080 * randomize_page - Generate a random, page aligned address
diff --git a/include/linux/random.h b/include/linux/random.h
index 7bd2403e4fef..16ab429735a7 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -37,7 +37,6 @@ extern void get_random_bytes(void *buf, int nbytes);
37extern int add_random_ready_callback(struct random_ready_callback *rdy); 37extern int add_random_ready_callback(struct random_ready_callback *rdy);
38extern void del_random_ready_callback(struct random_ready_callback *rdy); 38extern void del_random_ready_callback(struct random_ready_callback *rdy);
39extern void get_random_bytes_arch(void *buf, int nbytes); 39extern void get_random_bytes_arch(void *buf, int nbytes);
40extern int random_int_secret_init(void);
41 40
42#ifndef MODULE 41#ifndef MODULE
43extern const struct file_operations random_fops, urandom_fops; 42extern const struct file_operations random_fops, urandom_fops;
diff --git a/init/main.c b/init/main.c
index b0c9d6facef9..09beb7fc6e8c 100644
--- a/init/main.c
+++ b/init/main.c
@@ -879,7 +879,6 @@ static void __init do_basic_setup(void)
879 do_ctors(); 879 do_ctors();
880 usermodehelper_enable(); 880 usermodehelper_enable();
881 do_initcalls(); 881 do_initcalls();
882 random_int_secret_init();
883} 882}
884 883
885static void __init do_pre_smp_initcalls(void) 884static void __init do_pre_smp_initcalls(void)