Skip to content

Commit

Permalink
app-emulation/qemu: security fixes
Browse files Browse the repository at this point in the history
  CVE-2017-11334, bug #621292
  CVE-2017-11434, bug #625614
  CVE-2017-9503, bug #621184
  CVE-2017-9524, bug #621292

Package-Manager: Portage-2.3.6, Repoman-2.3.3
  • Loading branch information
tamiko committed Jul 26, 2017
1 parent faca608 commit e67f109
Show file tree
Hide file tree
Showing 8 changed files with 1,646 additions and 0 deletions.
40 changes: 40 additions & 0 deletions app-emulation/qemu/files/qemu-2.9.0-CVE-2017-11334.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[Qemu-devel] [PULL 21/41] exec: use qemu_ram_ptr_length to access guest
From: Prasad J Pandit <address@hidden>

When accessing guest's ram block during DMA operation, use
'qemu_ram_ptr_length' to get ram block pointer. It ensures
that DMA operation of given length is possible; And avoids
any OOB memory access situations.

Reported-by: Alex <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
exec.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/exec.c b/exec.c
index a083ff8..ad103ce 100644
--- a/exec.c
+++ b/exec.c
@@ -2929,7 +2929,7 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
- ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(mr, addr1, l);
}
@@ -3020,7 +3020,7 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
- ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
+ ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
memcpy(buf, ptr, l);
}

--
1.8.3.1
29 changes: 29 additions & 0 deletions app-emulation/qemu/files/qemu-2.9.0-CVE-2017-11434.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[Qemu-devel] [PATCH] slirp: check len against dhcp options array end
From: Prasad J Pandit <address@hidden>

While parsing dhcp options string in 'dhcp_decode', if an options'
length 'len' appeared towards the end of 'bp_vend' array, ensuing
read could lead to an OOB memory access issue. Add check to avoid it.

Reported-by: Reno Robert <address@hidden>
Signed-off-by: Prasad J Pandit <address@hidden>
---
slirp/bootp.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/slirp/bootp.c b/slirp/bootp.c
index 5a4646c..5dd1a41 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -123,6 +123,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
if (p >= p_end)
break;
len = *p++;
+ if (p + len > p_end) {
+ break;
+ }
DPRINTF("dhcp: tag=%d len=%d\n", tag, len);

switch(tag) {
--
2.9.4
272 changes: 272 additions & 0 deletions app-emulation/qemu/files/qemu-2.9.0-CVE-2017-7539.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
From 2b0bbc4f8809c972bad134bc1a2570dbb01dea0b Mon Sep 17 00:00:00 2001
From: Vladimir Sementsov-Ogievskiy <[email protected]>
Date: Fri, 2 Jun 2017 18:01:41 +0300
Subject: [PATCH] nbd/server: get rid of nbd_negotiate_read and friends

Functions nbd_negotiate_{read,write,drop_sync} were introduced in
1a6245a5b, when nbd_rwv (was nbd_wr_sync) was working through
qemu_co_sendv_recvv (the path is nbd_wr_sync -> qemu_co_{recv/send} ->
qemu_co_send_recv -> qemu_co_sendv_recvv), which just yields, without
setting any handlers. But starting from ff82911cd nbd_rwv (was
nbd_wr_syncv) works through qio_channel_yield() which sets handlers, so
watchers are redundant in nbd_negotiate_{read,write,drop_sync}, then,
let's just use nbd_{read,write,drop} functions.

Functions nbd_{read,write,drop} has errp parameter, which is unused in
this patch. This will be fixed later.

Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]>
Reviewed-by: Eric Blake <[email protected]>
Message-Id: <[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
---
nbd/server.c | 107 ++++++++++++-----------------------------------------------
1 file changed, 22 insertions(+), 85 deletions(-)

diff --git a/nbd/server.c b/nbd/server.c
index d8bd927013..7f44ef0b15 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -104,69 +104,6 @@ struct NBDClient {

static void nbd_client_receive_next_request(NBDClient *client);

-static gboolean nbd_negotiate_continue(QIOChannel *ioc,
- GIOCondition condition,
- void *opaque)
-{
- qemu_coroutine_enter(opaque);
- return TRUE;
-}
-
-static int nbd_negotiate_read(QIOChannel *ioc, void *buffer, size_t size)
-{
- ssize_t ret;
- guint watch;
-
- assert(qemu_in_coroutine());
- /* Negotiation are always in main loop. */
- watch = qio_channel_add_watch(ioc,
- G_IO_IN,
- nbd_negotiate_continue,
- qemu_coroutine_self(),
- NULL);
- ret = nbd_read(ioc, buffer, size, NULL);
- g_source_remove(watch);
- return ret;
-
-}
-
-static int nbd_negotiate_write(QIOChannel *ioc, const void *buffer, size_t size)
-{
- ssize_t ret;
- guint watch;
-
- assert(qemu_in_coroutine());
- /* Negotiation are always in main loop. */
- watch = qio_channel_add_watch(ioc,
- G_IO_OUT,
- nbd_negotiate_continue,
- qemu_coroutine_self(),
- NULL);
- ret = nbd_write(ioc, buffer, size, NULL);
- g_source_remove(watch);
- return ret;
-}
-
-static int nbd_negotiate_drop_sync(QIOChannel *ioc, size_t size)
-{
- ssize_t ret;
- uint8_t *buffer = g_malloc(MIN(65536, size));
-
- while (size > 0) {
- size_t count = MIN(65536, size);
- ret = nbd_negotiate_read(ioc, buffer, count);
- if (ret < 0) {
- g_free(buffer);
- return ret;
- }
-
- size -= count;
- }
-
- g_free(buffer);
- return 0;
-}
-
/* Basic flow for negotiation

Server Client
@@ -205,22 +142,22 @@ static int nbd_negotiate_send_rep_len(QIOChannel *ioc, uint32_t type,
type, opt, len);

magic = cpu_to_be64(NBD_REP_MAGIC);
- if (nbd_negotiate_write(ioc, &magic, sizeof(magic)) < 0) {
+ if (nbd_write(ioc, &magic, sizeof(magic), NULL) < 0) {
LOG("write failed (rep magic)");
return -EINVAL;
}
opt = cpu_to_be32(opt);
- if (nbd_negotiate_write(ioc, &opt, sizeof(opt)) < 0) {
+ if (nbd_write(ioc, &opt, sizeof(opt), NULL) < 0) {
LOG("write failed (rep opt)");
return -EINVAL;
}
type = cpu_to_be32(type);
- if (nbd_negotiate_write(ioc, &type, sizeof(type)) < 0) {
+ if (nbd_write(ioc, &type, sizeof(type), NULL) < 0) {
LOG("write failed (rep type)");
return -EINVAL;
}
len = cpu_to_be32(len);
- if (nbd_negotiate_write(ioc, &len, sizeof(len)) < 0) {
+ if (nbd_write(ioc, &len, sizeof(len), NULL) < 0) {
LOG("write failed (rep data length)");
return -EINVAL;
}
@@ -255,7 +192,7 @@ nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type,
if (ret < 0) {
goto out;
}
- if (nbd_negotiate_write(ioc, msg, len) < 0) {
+ if (nbd_write(ioc, msg, len, NULL) < 0) {
LOG("write failed (error message)");
ret = -EIO;
} else {
@@ -286,15 +223,15 @@ static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp)
}

len = cpu_to_be32(name_len);
- if (nbd_negotiate_write(ioc, &len, sizeof(len)) < 0) {
+ if (nbd_write(ioc, &len, sizeof(len), NULL) < 0) {
LOG("write failed (name length)");
return -EINVAL;
}
- if (nbd_negotiate_write(ioc, name, name_len) < 0) {
+ if (nbd_write(ioc, name, name_len, NULL) < 0) {
LOG("write failed (name buffer)");
return -EINVAL;
}
- if (nbd_negotiate_write(ioc, desc, desc_len) < 0) {
+ if (nbd_write(ioc, desc, desc_len, NULL) < 0) {
LOG("write failed (description buffer)");
return -EINVAL;
}
@@ -308,7 +245,7 @@ static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length)
NBDExport *exp;

if (length) {
- if (nbd_negotiate_drop_sync(client->ioc, length) < 0) {
+ if (nbd_drop(client->ioc, length, NULL) < 0) {
return -EIO;
}
return nbd_negotiate_send_rep_err(client->ioc,
@@ -339,7 +276,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length)
LOG("Bad length received");
goto fail;
}
- if (nbd_negotiate_read(client->ioc, name, length) < 0) {
+ if (nbd_read(client->ioc, name, length, NULL) < 0) {
LOG("read failed");
goto fail;
}
@@ -372,7 +309,7 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
TRACE("Setting up TLS");
ioc = client->ioc;
if (length) {
- if (nbd_negotiate_drop_sync(ioc, length) < 0) {
+ if (nbd_drop(ioc, length, NULL) < 0) {
return NULL;
}
nbd_negotiate_send_rep_err(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS,
@@ -436,7 +373,7 @@ static int nbd_negotiate_options(NBDClient *client)
... Rest of request
*/

- if (nbd_negotiate_read(client->ioc, &flags, sizeof(flags)) < 0) {
+ if (nbd_read(client->ioc, &flags, sizeof(flags), NULL) < 0) {
LOG("read failed");
return -EIO;
}
@@ -462,7 +399,7 @@ static int nbd_negotiate_options(NBDClient *client)
uint32_t clientflags, length;
uint64_t magic;

- if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) < 0) {
+ if (nbd_read(client->ioc, &magic, sizeof(magic), NULL) < 0) {
LOG("read failed");
return -EINVAL;
}
@@ -472,15 +409,15 @@ static int nbd_negotiate_options(NBDClient *client)
return -EINVAL;
}

- if (nbd_negotiate_read(client->ioc, &clientflags,
- sizeof(clientflags)) < 0)
+ if (nbd_read(client->ioc, &clientflags,
+ sizeof(clientflags), NULL) < 0)
{
LOG("read failed");
return -EINVAL;
}
clientflags = be32_to_cpu(clientflags);

- if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) < 0) {
+ if (nbd_read(client->ioc, &length, sizeof(length), NULL) < 0) {
LOG("read failed");
return -EINVAL;
}
@@ -510,7 +447,7 @@ static int nbd_negotiate_options(NBDClient *client)
return -EINVAL;

default:
- if (nbd_negotiate_drop_sync(client->ioc, length) < 0) {
+ if (nbd_drop(client->ioc, length, NULL) < 0) {
return -EIO;
}
ret = nbd_negotiate_send_rep_err(client->ioc,
@@ -548,7 +485,7 @@ static int nbd_negotiate_options(NBDClient *client)
return nbd_negotiate_handle_export_name(client, length);

case NBD_OPT_STARTTLS:
- if (nbd_negotiate_drop_sync(client->ioc, length) < 0) {
+ if (nbd_drop(client->ioc, length, NULL) < 0) {
return -EIO;
}
if (client->tlscreds) {
@@ -567,7 +504,7 @@ static int nbd_negotiate_options(NBDClient *client)
}
break;
default:
- if (nbd_negotiate_drop_sync(client->ioc, length) < 0) {
+ if (nbd_drop(client->ioc, length, NULL) < 0) {
return -EIO;
}
ret = nbd_negotiate_send_rep_err(client->ioc,
@@ -656,12 +593,12 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
TRACE("TLS cannot be enabled with oldstyle protocol");
goto fail;
}
- if (nbd_negotiate_write(client->ioc, buf, sizeof(buf)) < 0) {
+ if (nbd_write(client->ioc, buf, sizeof(buf), NULL) < 0) {
LOG("write failed");
goto fail;
}
} else {
- if (nbd_negotiate_write(client->ioc, buf, 18) < 0) {
+ if (nbd_write(client->ioc, buf, 18, NULL) < 0) {
LOG("write failed");
goto fail;
}
@@ -676,7 +613,7 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
stq_be_p(buf + 18, client->exp->size);
stw_be_p(buf + 26, client->exp->nbdflags | myflags);
len = client->no_zeroes ? 10 : sizeof(buf) - 18;
- if (nbd_negotiate_write(client->ioc, buf + 18, len) < 0) {
+ if (nbd_write(client->ioc, buf + 18, len, NULL) < 0) {
LOG("write failed");
goto fail;
}
--
2.13.0

Loading

0 comments on commit e67f109

Please sign in to comment.