From 0a0a490c805fadc7191489277e77fbf9688b39ab Mon Sep 17 00:00:00 2001 From: jiangdongxu Date: Thu, 10 Feb 2022 21:32:37 +0800 Subject: [PATCH 1/6] bugfix: fix some illegal memory access and memory leak Signed-off-by: yuxiating Signed-off-by: jiangdongxu --- contrib/elf2dmp/main.c | 1 + hw/display/cirrus_vga.c | 2 +- util/range.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 20b477d582..3f0d1eb709 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -125,6 +125,7 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb, if (va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 0)) { eprintf("Failed to extract entire KDBG\n"); + free(kdbg); return NULL; } diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index fdca6ca659..c66ed801ef 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -834,7 +834,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) word alignment, so we keep them for the next line */ /* XXX: keep alignment to speed up transfer */ end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; - copy_count = s->cirrus_srcptr_end - end_ptr; + copy_count = MIN(s->cirrus_srcptr_end - end_ptr, CIRRUS_BLTBUFSIZE); memmove(s->cirrus_bltbuf, end_ptr, copy_count); s->cirrus_srcptr = s->cirrus_bltbuf + copy_count; s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; diff --git a/util/range.c b/util/range.c index 098d9d2dc0..83d1a6c302 100644 --- a/util/range.c +++ b/util/range.c @@ -65,6 +65,7 @@ GList *range_list_insert(GList *list, Range *data) range_extend(l->data, l->next->data); g_free(l->next->data); new_l = g_list_delete_link(list, l->next); + l->next = NULL; assert(new_l == list); } -- Gitee From 03e7e232a323c45205d3c6ecb7d8e52e7209d9eb Mon Sep 17 00:00:00 2001 From: jiangdongxu Date: Thu, 10 Feb 2022 22:12:50 +0800 Subject: [PATCH 2/6] bugfix: fix possible memory leak Signed-off-by: caojinhua Signed-off-by: jiangdongxu --- migration/savevm.c | 2 ++ qga/main.c | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/migration/savevm.c b/migration/savevm.c index d59e976d50..803cd9004d 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1427,6 +1427,7 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, ret = vmstate_save(f, se, vmdesc); if (ret) { qemu_file_set_error(f, ret); + json_writer_free(vmdesc); return ret; } trace_savevm_section_end(se->idstr, se->section_id, 0); @@ -1443,6 +1444,7 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, error_report("%s: bdrv_inactivate_all() failed (%d)", __func__, ret); qemu_file_set_error(f, ret); + json_writer_free(vmdesc); return ret; } } diff --git a/qga/main.c b/qga/main.c index 15fd3a4149..6f09a689ac 100644 --- a/qga/main.c +++ b/qga/main.c @@ -1283,7 +1283,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) if (g_mkdir_with_parents(config->state_dir, S_IRWXU) == -1) { g_critical("unable to create (an ancestor of) the state directory" " '%s': %s", config->state_dir, strerror(errno)); - return NULL; + goto failed; } #endif @@ -1308,7 +1308,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) if (!log_file) { g_critical("unable to open specified log file: %s", strerror(errno)); - return NULL; + goto failed; } s->log_file = log_file; } @@ -1319,7 +1319,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) s->pstate_filepath, ga_is_frozen(s))) { g_critical("failed to load persistent state"); - return NULL; + goto failed; } config->blacklist = ga_command_blacklist_init(config->blacklist); @@ -1340,7 +1340,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) #ifndef _WIN32 if (!register_signal_handlers()) { g_critical("failed to register signal handlers"); - return NULL; + goto failed; } #endif @@ -1353,12 +1353,20 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) s->wakeup_event = CreateEvent(NULL, TRUE, FALSE, TEXT("WakeUp")); if (s->wakeup_event == NULL) { g_critical("CreateEvent failed"); - return NULL; + goto failed; } #endif ga_state = s; return s; +failed: + g_free(s->pstate_filepath); + g_free(s->state_filepath_isfrozen); + if (s->log_file) { + fclose(s->log_file); + } + g_free(s); + return NULL; } static void cleanup_agent(GAState *s) -- Gitee From 02a17066ac3dfb5e53b72b15a80643154990191b Mon Sep 17 00:00:00 2001 From: jiangdongxu Date: Thu, 10 Feb 2022 21:50:28 +0800 Subject: [PATCH 3/6] bugfix: fix eventfds may double free when vm_id reused in ivshmem As the ivshmem Server-Client Protol describes, when a client disconnects from the server, server sends disconnect notifications to the other clients. And the other clients will free the eventfds of the disconnected client according to the client ID. If the client ID is reused, the eventfds may be double freed. It will be solved by setting eventfds to NULL after freeing and allocating memory for it when it's used. Signed-off-by: Peng Liang Signed-off-by: jiangdongxu --- hw/misc/ivshmem.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 1ba4a98377..05f06ed6cf 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -400,6 +400,7 @@ static void close_peer_eventfds(IVShmemState *s, int posn) } g_free(s->peers[posn].eventfds); + s->peers[posn].eventfds = NULL; s->peers[posn].nb_eventfds = 0; } @@ -530,6 +531,10 @@ static void process_msg_connect(IVShmemState *s, uint16_t posn, int fd, close(fd); return; } + if (peer->eventfds == NULL) { + peer->eventfds = g_new0(EventNotifier, s->vectors); + peer->nb_eventfds = 0; + } vector = peer->nb_eventfds++; IVSHMEM_DPRINTF("eventfds[%d][%d] = %d\n", posn, vector, fd); -- Gitee From 7448eb87ee59856aa0f0853f2aa5b803c832fccf Mon Sep 17 00:00:00 2001 From: jiangdongxu Date: Thu, 10 Feb 2022 21:37:49 +0800 Subject: [PATCH 4/6] block/mirror: fix file-system went to read-only after block-mirror config vm disk with prdm, keep the disk writing data continuously during block-mirror, the file-system will went to read-only after block-mirror, fix it. Signed-off-by: caojinhua Signed-off-by: jiangdongxu --- block/mirror.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/mirror.c b/block/mirror.c index efec2c7674..b7f0cba9b9 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1640,7 +1640,7 @@ static BlockJob *mirror_start_job( * reads on the top, while disabling it in the intermediate nodes, and make * the backing chain writable. */ mirror_top_bs = bdrv_new_open_driver(&bdrv_mirror_top, filter_node_name, - BDRV_O_RDWR, errp); + BDRV_O_RDWR | BDRV_O_NOCACHE, errp); if (mirror_top_bs == NULL) { return NULL; } -- Gitee From f14ea0bd2596f94ad926009411b8ffda9c2c2cda Mon Sep 17 00:00:00 2001 From: jiangdongxu Date: Thu, 10 Feb 2022 22:42:23 +0800 Subject: [PATCH 5/6] bugfix: fix mmio information leak and ehci vm escape 0-day vulnerability Signed-off-by: Yutao Ai Signed-off-by: jiangdongxu --- hw/usb/core.c | 20 ++++++++++++++++++-- hw/usb/hcd-ehci.c | 2 ++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/hw/usb/core.c b/hw/usb/core.c index 51b36126ca..a62826e051 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -206,7 +206,15 @@ static void do_token_in(USBDevice *s, USBPacket *p) case SETUP_STATE_DATA: if (s->setup_buf[0] & USB_DIR_IN) { - int len = s->setup_len - s->setup_index; + int len; + if (s->setup_len > sizeof(s->data_buf)) { + fprintf(stderr, + "usb_generic_handle_packet: ctrl buffer too small do_token_in(%d > %zu)\n", + s->setup_len, sizeof(s->data_buf)); + p->status = USB_RET_STALL; + return; + } + len = s->setup_len - s->setup_index; if (len > p->iov.size) { len = p->iov.size; } @@ -244,7 +252,15 @@ static void do_token_out(USBDevice *s, USBPacket *p) case SETUP_STATE_DATA: if (!(s->setup_buf[0] & USB_DIR_IN)) { - int len = s->setup_len - s->setup_index; + int len; + if (s->setup_len > sizeof(s->data_buf)) { + fprintf(stderr, + "usb_generic_handle_packet: ctrl buffer too small do_token_out(%d > %zu)\n", + s->setup_len, sizeof(s->data_buf)); + p->status = USB_RET_STALL; + return; + } + len = s->setup_len - s->setup_index; if (len > p->iov.size) { len = p->iov.size; } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 6caa7ac6c2..1415107315 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -612,6 +612,8 @@ static void ehci_free_queue(EHCIQueue *q, const char *warn) ehci_trace_guest_bug(q->ehci, warn); } QTAILQ_REMOVE(head, q, next); + memset(q, 0, sizeof(*q)); + *(volatile char *)q = *(volatile char *)q; g_free(q); } -- Gitee From 6e070be26502e171fd5d43a128dea99f1d34429b Mon Sep 17 00:00:00 2001 From: jiangdongxu Date: Thu, 10 Feb 2022 21:41:06 +0800 Subject: [PATCH 6/6] target-i386: Fix the RES memory inc which caused by the coroutine created for better performance, change the POOL_BATCH_SIZE from 64 to 128. Signed-off-by: caojinhua Signed-off-by: jiangdongxu --- util/qemu-coroutine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c index 38fb6d3084..b9586d6929 100644 --- a/util/qemu-coroutine.c +++ b/util/qemu-coroutine.c @@ -21,7 +21,7 @@ #include "block/aio.h" enum { - POOL_BATCH_SIZE = 64, + POOL_BATCH_SIZE = 128, }; /** Free list to speed up creation */ -- Gitee