NULL pointer dereference in red-parse-qxl.cpp
There seems to be a NULL pointer dereference in the red-parse-qxl.cpp
, which may lead to DoS if QEMU is started with SPICE enabled and an attacker in the guest can do IOs with the qxl device.
SPICE Version
release 0.15, commit 3c1d87cc
Affected Code
https://gitlab.freedesktop.org/spice/spice/-/blob/master/server/red-parse-qxl.cpp#L535
if (qxl_flags & QXL_BITMAP_DIRECT) {
red->u.bitmap.data = red_get_image_data_flat(slots, group_id,
qxl->bitmap.data,
bitmap_size);
Since qxl->bitmap.data
may from the guest, an attacker can make the memslot_get_virt()
check in red_get_image_data_flat()
fail and return a null.
https://gitlab.freedesktop.org/spice/spice/-/blob/master/server/red-parse-qxl.cpp#L550
if (qxl_flags & QXL_BITMAP_UNSTABLE) {
red->u.bitmap.data->flags |= SPICE_CHUNKS_FLAGS_UNSTABLE;
}
qxl_flags
is assigned as qxl->bitmap.flags
before, which can also be controlled by the attacker, resulting in a NULL pointer dereference.
This dereference seems to be introduced by commit 5ac88aa7.
Call Backtrace
libspice-server thread:
- red_get_image()
- red_get_copy_ptr()
- red_get_native_drawable()
- red_get_drawable()
- red_drawable_new()
- red_process_display()
- worker_source_dispatch()
- g_main_context_dispatch()
- jmp 0x7ffff79bb824
- g_main_loop_run()
QEMU Command
qemu-system-x86_64 -machine type=q35,accel=kvm,vmport=off -cpu host -m 4G \
-hda kali_2021.1.img -vga qxl -spice port=5900,disable-ticketing=on \
-device intel-hda -device hda-duplex -device virtio-serial \
-chardev spicevmc,id=vdagent,debug=0,name=vdagent \
-device virtserialport,chardev=vdagent,name=com.redhat.spice.0
Patch
Signed-off-by: Qiuhao Li <Qiuhao.Li@outlook.com>
---
server/red-parse-qxl.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/server/red-parse-qxl.cpp b/server/red-parse-qxl.cpp
index 9724401d..35754362 100644
--- a/server/red-parse-qxl.cpp
+++ b/server/red-parse-qxl.cpp
@@ -535,6 +535,9 @@ static SpiceImage *red_get_image(RedMemSlotInfo *slots, int group_id,
red->u.bitmap.data = red_get_image_data_flat(slots, group_id,
qxl->bitmap.data,
bitmap_size);
+ if (red->u.bitmap.data == nullptr) {
+ goto error;
+ }
} else {
size = red_get_data_chunks(slots, group_id,
&chunks, qxl->bitmap.data);
--
2.27.0
Thank you.
Qiuhao Li