diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2013-03-04 18:37:08 -0500 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2013-03-04 18:41:41 -0500 |
| commit | f7f154f1246ccc5a0a7e9ce50932627d60a0c878 (patch) | |
| tree | 136b9c7b410816bc15795f47fb808bdaca504204 | |
| parent | 6dbe51c251a327e012439c4772097a13df43c5b8 (diff) | |
hw_random: make buffer usable in scatterlist.
virtio_rng feeds the randomness buffer handed by the core directly
into the scatterlist, since commit bb347d98079a547e80bd4722dee1de61e4dca0e8.
However, if CONFIG_HW_RANDOM=m, the static buffer isn't a linear address
(at least on most archs). We could fix this in virtio_rng, but it's actually
far easier to just do it in the core as virtio_rng would have to allocate
a buffer every time (it doesn't know how much the core will want to read).
Reported-by: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: stable@kernel.org
| -rw-r--r-- | drivers/char/hw_random/core.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1bafb40ec8a2..69ae5972713c 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
| 41 | #include <linux/miscdevice.h> | 41 | #include <linux/miscdevice.h> |
| 42 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
| 43 | #include <linux/slab.h> | ||
| 43 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
| 44 | 45 | ||
| 45 | 46 | ||
| @@ -52,8 +53,12 @@ static struct hwrng *current_rng; | |||
| 52 | static LIST_HEAD(rng_list); | 53 | static LIST_HEAD(rng_list); |
| 53 | static DEFINE_MUTEX(rng_mutex); | 54 | static DEFINE_MUTEX(rng_mutex); |
| 54 | static int data_avail; | 55 | static int data_avail; |
| 55 | static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] | 56 | static u8 *rng_buffer; |
| 56 | __cacheline_aligned; | 57 | |
| 58 | static size_t rng_buffer_size(void) | ||
| 59 | { | ||
| 60 | return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; | ||
| 61 | } | ||
| 57 | 62 | ||
| 58 | static inline int hwrng_init(struct hwrng *rng) | 63 | static inline int hwrng_init(struct hwrng *rng) |
| 59 | { | 64 | { |
| @@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, | |||
| 116 | 121 | ||
| 117 | if (!data_avail) { | 122 | if (!data_avail) { |
| 118 | bytes_read = rng_get_data(current_rng, rng_buffer, | 123 | bytes_read = rng_get_data(current_rng, rng_buffer, |
| 119 | sizeof(rng_buffer), | 124 | rng_buffer_size(), |
| 120 | !(filp->f_flags & O_NONBLOCK)); | 125 | !(filp->f_flags & O_NONBLOCK)); |
| 121 | if (bytes_read < 0) { | 126 | if (bytes_read < 0) { |
| 122 | err = bytes_read; | 127 | err = bytes_read; |
| @@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng) | |||
| 307 | 312 | ||
| 308 | mutex_lock(&rng_mutex); | 313 | mutex_lock(&rng_mutex); |
| 309 | 314 | ||
| 315 | /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ | ||
| 316 | err = -ENOMEM; | ||
| 317 | if (!rng_buffer) { | ||
| 318 | rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); | ||
| 319 | if (!rng_buffer) | ||
| 320 | goto out_unlock; | ||
| 321 | } | ||
| 322 | |||
| 310 | /* Must not register two RNGs with the same name. */ | 323 | /* Must not register two RNGs with the same name. */ |
| 311 | err = -EEXIST; | 324 | err = -EEXIST; |
| 312 | list_for_each_entry(tmp, &rng_list, list) { | 325 | list_for_each_entry(tmp, &rng_list, list) { |
