Skip to content

Commit

Permalink
ivshmem: Fix potential OOB r/w access
Browse files Browse the repository at this point in the history
Fix OOB access via malformed incoming_posn parameters
and check that requested memory is actually alloc'ed.

Signed-off-by: Sebastian Krahmer <krahmer@suse.de>
[AF: Rebased, cleanups, avoid fd leak]
Cc: qemu-stable@nongnu.org
Signed-off-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

(cherry picked from commit 34bc07c)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
  • Loading branch information
Sebastian Krahmer authored and mdroth committed Jan 6, 2015
1 parent 15905fd commit a95569d
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions hw/misc/ivshmem.c
Expand Up @@ -29,6 +29,7 @@

#include <sys/mman.h>
#include <sys/types.h>
#include <limits.h>

#define PCI_VENDOR_ID_IVSHMEM PCI_VENDOR_ID_REDHAT_QUMRANET
#define PCI_DEVICE_ID_IVSHMEM 0x1110
Expand Down Expand Up @@ -406,14 +407,24 @@ static void close_guest_eventfds(IVShmemState *s, int posn)

/* this function increase the dynamic storage need to store data about other
* guests */
static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
static int increase_dynamic_storage(IVShmemState *s, int new_min_size)
{

int j, old_nb_alloc;

/* check for integer overflow */
if (new_min_size >= INT_MAX / sizeof(Peer) - 1 || new_min_size <= 0) {
return -1;
}

old_nb_alloc = s->nb_peers;

while (new_min_size >= s->nb_peers)
s->nb_peers = s->nb_peers * 2;
if (new_min_size >= s->nb_peers) {
/* +1 because #new_min_size is used as last array index */
s->nb_peers = new_min_size + 1;
} else {
return 0;
}

IVSHMEM_DPRINTF("bumping storage to %d guests\n", s->nb_peers);
s->peers = g_realloc(s->peers, s->nb_peers * sizeof(Peer));
Expand All @@ -423,6 +434,8 @@ static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
s->peers[j].eventfds = NULL;
s->peers[j].nb_eventfds = 0;
}

return 0;
}

static void ivshmem_read(void *opaque, const uint8_t *buf, int size)
Expand Down Expand Up @@ -465,7 +478,13 @@ static void ivshmem_read(void *opaque, const uint8_t *buf, int size)

/* make sure we have enough space for this guest */
if (incoming_posn >= s->nb_peers) {
increase_dynamic_storage(s, incoming_posn);
if (increase_dynamic_storage(s, incoming_posn) < 0) {
error_report("increase_dynamic_storage() failed");
if (tmp_fd != -1) {
close(tmp_fd);
}
return;
}
}

if (tmp_fd == -1) {
Expand Down

0 comments on commit a95569d

Please sign in to comment.