mirror of
https://git.proxmox.com/git/qemu
synced 2025-07-20 02:31:42 +00:00
CVE-2007-1320 - Cirrus LGD-54XX "bitblt" heap overflow
I have just noticed that patch for CVE-2007-1320 has never been applied to the QEMU CVS. Please find it below. | Multiple heap-based buffer overflows in the cirrus_invalidate_region | function in the Cirrus VGA extension in QEMU 0.8.2, as used in Xen and | possibly other products, might allow local users to execute arbitrary | code via unspecified vectors related to "attempting to mark | non-existent regions as dirty," aka the "bitblt" heap overflow. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4340 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
cbf5c748e2
commit
b2eb849d4b
@ -220,6 +220,20 @@
|
|||||||
#define CIRRUS_HOOK_NOT_HANDLED 0
|
#define CIRRUS_HOOK_NOT_HANDLED 0
|
||||||
#define CIRRUS_HOOK_HANDLED 1
|
#define CIRRUS_HOOK_HANDLED 1
|
||||||
|
|
||||||
|
#define BLTUNSAFE(s) \
|
||||||
|
( \
|
||||||
|
( /* check dst is within bounds */ \
|
||||||
|
(s)->cirrus_blt_height * (s)->cirrus_blt_dstpitch \
|
||||||
|
+ ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
|
||||||
|
(s)->vram_size \
|
||||||
|
) || \
|
||||||
|
( /* check src is within bounds */ \
|
||||||
|
(s)->cirrus_blt_height * (s)->cirrus_blt_srcpitch \
|
||||||
|
+ ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
|
||||||
|
(s)->vram_size \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
struct CirrusVGAState;
|
struct CirrusVGAState;
|
||||||
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
|
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
|
||||||
uint8_t * dst, const uint8_t * src,
|
uint8_t * dst, const uint8_t * src,
|
||||||
@ -639,7 +653,7 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
|
|||||||
|
|
||||||
for (y = 0; y < lines; y++) {
|
for (y = 0; y < lines; y++) {
|
||||||
off_cur = off_begin;
|
off_cur = off_begin;
|
||||||
off_cur_end = off_cur + bytesperline;
|
off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
|
||||||
off_cur &= TARGET_PAGE_MASK;
|
off_cur &= TARGET_PAGE_MASK;
|
||||||
while (off_cur < off_cur_end) {
|
while (off_cur < off_cur_end) {
|
||||||
cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
|
cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
|
||||||
@ -654,7 +668,11 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
|
|||||||
{
|
{
|
||||||
uint8_t *dst;
|
uint8_t *dst;
|
||||||
|
|
||||||
dst = s->vram_ptr + s->cirrus_blt_dstaddr;
|
dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
|
||||||
|
|
||||||
|
if (BLTUNSAFE(s))
|
||||||
|
return 0;
|
||||||
|
|
||||||
(*s->cirrus_rop) (s, dst, src,
|
(*s->cirrus_rop) (s, dst, src,
|
||||||
s->cirrus_blt_dstpitch, 0,
|
s->cirrus_blt_dstpitch, 0,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
@ -670,8 +688,10 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
|
|||||||
{
|
{
|
||||||
cirrus_fill_t rop_func;
|
cirrus_fill_t rop_func;
|
||||||
|
|
||||||
|
if (BLTUNSAFE(s))
|
||||||
|
return 0;
|
||||||
rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
|
rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
|
||||||
rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr,
|
rop_func(s, s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||||
s->cirrus_blt_dstpitch,
|
s->cirrus_blt_dstpitch,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
|
||||||
@ -690,8 +710,8 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
|
|||||||
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
|
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
|
||||||
{
|
{
|
||||||
return cirrus_bitblt_common_patterncopy(s,
|
return cirrus_bitblt_common_patterncopy(s,
|
||||||
s->vram_ptr +
|
s->vram_ptr + ((s->cirrus_blt_srcaddr & ~7) &
|
||||||
(s->cirrus_blt_srcaddr & ~7));
|
s->cirrus_addr_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
||||||
@ -741,8 +761,10 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
|
|||||||
if (notify)
|
if (notify)
|
||||||
vga_hw_update();
|
vga_hw_update();
|
||||||
|
|
||||||
(*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
|
(*s->cirrus_rop) (s, s->vram_ptr +
|
||||||
s->vram_ptr + s->cirrus_blt_srcaddr,
|
(s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||||
|
s->vram_ptr +
|
||||||
|
(s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
|
||||||
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
|
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
|
|
||||||
@ -768,8 +790,14 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
|
|||||||
s->cirrus_blt_srcaddr - s->start_addr,
|
s->cirrus_blt_srcaddr - s->start_addr,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
} else {
|
} else {
|
||||||
(*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
|
|
||||||
s->vram_ptr + s->cirrus_blt_srcaddr,
|
if (BLTUNSAFE(s))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
(*s->cirrus_rop) (s, s->vram_ptr +
|
||||||
|
(s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||||
|
s->vram_ptr +
|
||||||
|
(s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
|
||||||
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
|
s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
|
||||||
s->cirrus_blt_width, s->cirrus_blt_height);
|
s->cirrus_blt_width, s->cirrus_blt_height);
|
||||||
|
|
||||||
@ -801,8 +829,9 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
|
|||||||
} else {
|
} else {
|
||||||
/* at least one scan line */
|
/* at least one scan line */
|
||||||
do {
|
do {
|
||||||
(*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
|
(*s->cirrus_rop)(s, s->vram_ptr +
|
||||||
s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
|
(s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
|
||||||
|
s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
|
||||||
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
|
cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
|
||||||
s->cirrus_blt_width, 1);
|
s->cirrus_blt_width, 1);
|
||||||
s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
|
s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
|
||||||
@ -1920,7 +1949,7 @@ static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
|
|||||||
unsigned val = mem_value;
|
unsigned val = mem_value;
|
||||||
uint8_t *dst;
|
uint8_t *dst;
|
||||||
|
|
||||||
dst = s->vram_ptr + offset;
|
dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
|
||||||
for (x = 0; x < 8; x++) {
|
for (x = 0; x < 8; x++) {
|
||||||
if (val & 0x80) {
|
if (val & 0x80) {
|
||||||
*dst = s->cirrus_shadow_gr1;
|
*dst = s->cirrus_shadow_gr1;
|
||||||
@ -1943,7 +1972,7 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
|
|||||||
unsigned val = mem_value;
|
unsigned val = mem_value;
|
||||||
uint8_t *dst;
|
uint8_t *dst;
|
||||||
|
|
||||||
dst = s->vram_ptr + offset;
|
dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
|
||||||
for (x = 0; x < 8; x++) {
|
for (x = 0; x < 8; x++) {
|
||||||
if (val & 0x80) {
|
if (val & 0x80) {
|
||||||
*dst = s->cirrus_shadow_gr1;
|
*dst = s->cirrus_shadow_gr1;
|
||||||
|
@ -31,6 +31,12 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
|
|||||||
int x,y;
|
int x,y;
|
||||||
dstpitch -= bltwidth;
|
dstpitch -= bltwidth;
|
||||||
srcpitch -= bltwidth;
|
srcpitch -= bltwidth;
|
||||||
|
|
||||||
|
if (dstpitch < 0 || srcpitch < 0) {
|
||||||
|
/* is 0 valid? srcpitch == 0 could be useful */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (y = 0; y < bltheight; y++) {
|
for (y = 0; y < bltheight; y++) {
|
||||||
for (x = 0; x < bltwidth; x++) {
|
for (x = 0; x < bltwidth; x++) {
|
||||||
ROP_OP(*dst, *src);
|
ROP_OP(*dst, *src);
|
||||||
|
Loading…
Reference in New Issue
Block a user