Bug 1326708 - qemu-kvm: Infinite loop in gem_receive()
Summary: qemu-kvm: Infinite loop in gem_receive()
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks: 1326713
TreeView+ depends on / blocked
 
Reported: 2016-04-13 10:54 UTC by Adam Mariš
Modified: 2021-03-26 18:48 UTC (History)
40 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2016-09-21 06:17:45 UTC


Attachments (Terms of Use)
Crash report (3.46 KB, text/plain)
2016-04-13 10:56 UTC, Adam Mariš
no flags Details

Description Adam Mariš 2016-04-13 10:54:40 UTC
An infinite loop vulnerability was found in gem_receive().

Vulnerable code:

static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
{
...

rxbufsize = ((s->regs[GEM_DMACFG] & GEM_DMACFG_RBUFSZ_M) >> // here set the rxbufsize=0
GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;
bytes_to_copy = size;

...

DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);

while (bytes_to_copy) { // the bytes_to_copy never be changed
/* Do nothing if receive is not enabled. */
if (!gem_can_receive(nc)) {
assert(!first_desc);
return -1;
}

DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),
rx_desc_get_buffer(s->rx_desc));

/* Copy packet data to emulated DMA buffer */
cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + rxbuf_offset,
rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
bytes_to_copy -= MIN(bytes_to_copy, rxbufsize); // the bytes_to_copy never change


...

/* Descriptor write-back. */
cpu_physical_memory_write(s->rx_desc_addr,
(uint8_t *)s->rx_desc, sizeof(s->rx_desc));

/* Next descriptor */
if (rx_desc_get_wrap(s->rx_desc)) {
DB_PRINT("wrapping RX descriptor list\n");
s->rx_desc_addr = s->regs[GEM_RXQBASE];
} else {
DB_PRINT("incrementing RX descriptor list\n");
s->rx_desc_addr += 8; // provide a lot of rx_desc_addr so let this run correctly
}
gem_get_rx_desc(s);
}

...

return size;
}

By setting rxbufsize to 0 (via setting s->regs[GEM_DMACFG]=0), the while condition bytes_to_copy will never change. Although gem_can_receive() has got check for s->rx_desc, by raising s->rx_desc_addr the statement will be executed everytime, causing an infinite loop.

Comment 1 Adam Mariš 2016-04-13 10:55:01 UTC
Acknowledgments:

Name: Li Qiang (Qihoo 360 Inc.)

Comment 3 Adam Mariš 2016-04-13 10:56:43 UTC
Created attachment 1146825 [details]
Crash report

Comment 4 Prasad Pandit 2016-09-21 06:08:29 UTC
Upstream fix:
-------------
  -> git.qemu.org/?p=qemu.git;a=commit;h=f265ae8c79ce8c194de481e9def1daa3a80dbb96


Note You need to log in before you can comment on or make changes to this bug.