Fix CVE-2016-4952
[pve-qemu-kvm.git] / debian / patches / extra / CVE-2016-2858-0004-rng-add-request-queue-support-to-rng-random.patch
blob305b8c8d880165e500a2333e9d54d3d02f7339a7
1 From c33f9c1b4eb6142f6d49a72465395f111b6c968b Mon Sep 17 00:00:00 2001
2 From: Ladi Prosek <lprosek@redhat.com>
3 Date: Thu, 3 Mar 2016 09:37:18 +0100
4 Subject: [PATCH 4/5] rng: add request queue support to rng-random
6 Requests are now created in the RngBackend parent class and the
7 code path is shared by both rng-egd and rng-random.
9 This commit fixes the rng-random implementation which processed
10 only one request at a time and simply discarded all but the most
11 recent one. In the guest this manifested as delayed completion
12 of reads from virtio-rng, i.e. a read was completed only after
13 another read was issued.
15 By switching rng-random to use the same request queue as rng-egd,
16 the unsafe stack-based allocation of the entropy buffer is
17 eliminated and replaced with g_malloc.
19 Signed-off-by: Ladi Prosek <lprosek@redhat.com>
20 Reviewed-by: Amit Shah <amit.shah@redhat.com>
21 Message-Id: <1456994238-9585-5-git-send-email-lprosek@redhat.com>
22 Signed-off-by: Amit Shah <amit.shah@redhat.com>
23 ---
24 backends/rng-egd.c | 16 ++--------------
25 backends/rng-random.c | 43 +++++++++++++++++++------------------------
26 backends/rng.c | 13 ++++++++++++-
27 include/sysemu/rng.h | 3 +--
28 4 files changed, 34 insertions(+), 41 deletions(-)
30 diff --git a/backends/rng-egd.c b/backends/rng-egd.c
31 index 08301a7..de6c8d4 100644
32 --- a/backends/rng-egd.c
33 +++ b/backends/rng-egd.c
34 @@ -26,20 +26,10 @@ typedef struct RngEgd
35 char *chr_name;
36 } RngEgd;
38 -static void rng_egd_request_entropy(RngBackend *b, size_t size,
39 - EntropyReceiveFunc *receive_entropy,
40 - void *opaque)
41 +static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
43 RngEgd *s = RNG_EGD(b);
44 - RngRequest *req;
46 - req = g_malloc(sizeof(*req));
48 - req->offset = 0;
49 - req->size = size;
50 - req->receive_entropy = receive_entropy;
51 - req->opaque = opaque;
52 - req->data = g_malloc(req->size);
53 + size_t size = req->size;
55 while (size > 0) {
56 uint8_t header[2];
57 @@ -53,8 +43,6 @@ static void rng_egd_request_entropy(RngBackend *b, size_t size,
59 size -= len;
62 - s->parent.requests = g_slist_append(s->parent.requests, req);
65 static int rng_egd_chr_can_read(void *opaque)
66 diff --git a/backends/rng-random.c b/backends/rng-random.c
67 index 4e51f46..c2d8c03 100644
68 --- a/backends/rng-random.c
69 +++ b/backends/rng-random.c
70 @@ -21,10 +21,6 @@ struct RndRandom
72 int fd;
73 char *filename;
75 - EntropyReceiveFunc *receive_func;
76 - void *opaque;
77 - size_t size;
80 /**
81 @@ -37,36 +33,35 @@ struct RndRandom
82 static void entropy_available(void *opaque)
84 RndRandom *s = RNG_RANDOM(opaque);
85 - uint8_t buffer[s->size];
86 - ssize_t len;
88 - len = read(s->fd, buffer, s->size);
89 - if (len < 0 && errno == EAGAIN) {
90 - return;
91 - }
92 - g_assert(len != -1);
93 + while (s->parent.requests != NULL) {
94 + RngRequest *req = s->parent.requests->data;
95 + ssize_t len;
97 + len = read(s->fd, req->data, req->size);
98 + if (len < 0 && errno == EAGAIN) {
99 + return;
101 + g_assert(len != -1);
103 - s->receive_func(s->opaque, buffer, len);
104 - s->receive_func = NULL;
105 + req->receive_entropy(req->opaque, req->data, len);
107 + rng_backend_finalize_request(&s->parent, req);
110 + /* We've drained all requests, the fd handler can be reset. */
111 qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
114 -static void rng_random_request_entropy(RngBackend *b, size_t size,
115 - EntropyReceiveFunc *receive_entropy,
116 - void *opaque)
117 +static void rng_random_request_entropy(RngBackend *b, RngRequest *req)
119 RndRandom *s = RNG_RANDOM(b);
121 - if (s->receive_func) {
122 - s->receive_func(s->opaque, NULL, 0);
123 + if (s->parent.requests == NULL) {
124 + /* If there are no pending requests yet, we need to
125 + * install our fd handler. */
126 + qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
129 - s->receive_func = receive_entropy;
130 - s->opaque = opaque;
131 - s->size = size;
133 - qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
136 static void rng_random_opened(RngBackend *b, Error **errp)
137 diff --git a/backends/rng.c b/backends/rng.c
138 index 0d9978b..4066268 100644
139 --- a/backends/rng.c
140 +++ b/backends/rng.c
141 @@ -19,9 +19,20 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
142 void *opaque)
144 RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
145 + RngRequest *req;
147 if (k->request_entropy) {
148 - k->request_entropy(s, size, receive_entropy, opaque);
149 + req = g_malloc(sizeof(*req));
151 + req->offset = 0;
152 + req->size = size;
153 + req->receive_entropy = receive_entropy;
154 + req->opaque = opaque;
155 + req->data = g_malloc(req->size);
157 + k->request_entropy(s, req);
159 + s->requests = g_slist_append(s->requests, req);
163 diff --git a/include/sysemu/rng.h b/include/sysemu/rng.h
164 index c2c9035..a7ed580 100644
165 --- a/include/sysemu/rng.h
166 +++ b/include/sysemu/rng.h
167 @@ -46,8 +46,7 @@ struct RngBackendClass
169 ObjectClass parent_class;
171 - void (*request_entropy)(RngBackend *s, size_t size,
172 - EntropyReceiveFunc *receive_entropy, void *opaque);
173 + void (*request_entropy)(RngBackend *s, RngRequest *req);
175 void (*opened)(RngBackend *s, Error **errp);
178 2.1.4