Commit 4e106275 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

Pull crypto fixes from Herbert Xu:
 "This push fixes a boot hang in virt guests when the virtio RNG is
  enabled"

* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  hwrng: virtio - ensure reads happen after successful probe
  hwrng: fetch randomness only after device init
parents f8397191 e052dbf5
...@@ -55,16 +55,41 @@ static DEFINE_MUTEX(rng_mutex); ...@@ -55,16 +55,41 @@ static DEFINE_MUTEX(rng_mutex);
static int data_avail; static int data_avail;
static u8 *rng_buffer; static u8 *rng_buffer;
static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
int wait);
static size_t rng_buffer_size(void) static size_t rng_buffer_size(void)
{ {
return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
} }
static void add_early_randomness(struct hwrng *rng)
{
unsigned char bytes[16];
int bytes_read;
/*
* Currently only virtio-rng cannot return data during device
* probe, and that's handled in virtio-rng.c itself. If there
* are more such devices, this call to rng_get_data can be
* made conditional here instead of doing it per-device.
*/
bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
if (bytes_read > 0)
add_device_randomness(bytes, bytes_read);
}
static inline int hwrng_init(struct hwrng *rng) static inline int hwrng_init(struct hwrng *rng)
{ {
if (!rng->init) if (rng->init) {
return 0; int ret;
return rng->init(rng);
ret = rng->init(rng);
if (ret)
return ret;
}
add_early_randomness(rng);
return 0;
} }
static inline void hwrng_cleanup(struct hwrng *rng) static inline void hwrng_cleanup(struct hwrng *rng)
...@@ -304,8 +329,6 @@ int hwrng_register(struct hwrng *rng) ...@@ -304,8 +329,6 @@ int hwrng_register(struct hwrng *rng)
{ {
int err = -EINVAL; int err = -EINVAL;
struct hwrng *old_rng, *tmp; struct hwrng *old_rng, *tmp;
unsigned char bytes[16];
int bytes_read;
if (rng->name == NULL || if (rng->name == NULL ||
(rng->data_read == NULL && rng->read == NULL)) (rng->data_read == NULL && rng->read == NULL))
...@@ -347,9 +370,17 @@ int hwrng_register(struct hwrng *rng) ...@@ -347,9 +370,17 @@ int hwrng_register(struct hwrng *rng)
INIT_LIST_HEAD(&rng->list); INIT_LIST_HEAD(&rng->list);
list_add_tail(&rng->list, &rng_list); list_add_tail(&rng->list, &rng_list);
bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1); if (old_rng && !rng->init) {
if (bytes_read > 0) /*
add_device_randomness(bytes, bytes_read); * Use a new device's input to add some randomness to
* the system. If this rng device isn't going to be
* used right away, its init function hasn't been
* called yet; so only use the randomness from devices
* that don't need an init callback.
*/
add_early_randomness(rng);
}
out_unlock: out_unlock:
mutex_unlock(&rng_mutex); mutex_unlock(&rng_mutex);
out: out:
......
...@@ -38,6 +38,8 @@ struct virtrng_info { ...@@ -38,6 +38,8 @@ struct virtrng_info {
int index; int index;
}; };
static bool probe_done;
static void random_recv_done(struct virtqueue *vq) static void random_recv_done(struct virtqueue *vq)
{ {
struct virtrng_info *vi = vq->vdev->priv; struct virtrng_info *vi = vq->vdev->priv;
...@@ -67,6 +69,13 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) ...@@ -67,6 +69,13 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
int ret; int ret;
struct virtrng_info *vi = (struct virtrng_info *)rng->priv; struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
/*
* Don't ask host for data till we're setup. This call can
* happen during hwrng_register(), after commit d9e7972619.
*/
if (unlikely(!probe_done))
return 0;
if (!vi->busy) { if (!vi->busy) {
vi->busy = true; vi->busy = true;
init_completion(&vi->have_data); init_completion(&vi->have_data);
...@@ -137,6 +146,7 @@ static int probe_common(struct virtio_device *vdev) ...@@ -137,6 +146,7 @@ static int probe_common(struct virtio_device *vdev)
return err; return err;
} }
probe_done = true;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment