diff --git a/backends/baum.c b/backends/baum.c
index 1132899..9910a74 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -561,10 +561,9 @@ static void baum_close(struct CharDriverState *chr)
     g_free(baum);
 }
 
-CharDriverState *chr_baum_init(void)
+CharDriverState *chr_baum_init(CharDriverState *chr)
 {
     BaumDriverState *baum;
-    CharDriverState *chr;
     brlapi_handle_t *handle;
 #ifdef CONFIG_SDL
     SDL_SysWMinfo info;
@@ -572,7 +571,7 @@ CharDriverState *chr_baum_init(void)
     int tty;
 
     baum = g_malloc0(sizeof(BaumDriverState));
-    baum->chr = chr = g_malloc0(sizeof(CharDriverState));
+    baum->chr = chr;
 
     chr->opaque = baum;
     chr->chr_write = baum_write;
@@ -618,7 +617,6 @@ fail:
     brlapi__closeConnection(handle);
 fail_handle:
     g_free(handle);
-    g_free(chr);
     g_free(baum);
     return NULL;
 }
diff --git a/backends/msmouse.c b/backends/msmouse.c
index c0dbfcd..b4e7a23 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -63,11 +63,8 @@ static void msmouse_chr_close (struct CharDriverState *chr)
     g_free (chr);
 }
 
-CharDriverState *qemu_chr_open_msmouse(void)
+CharDriverState *qemu_chr_open_msmouse(CharDriverState *chr)
 {
-    CharDriverState *chr;
-
-    chr = g_malloc0(sizeof(CharDriverState));
     chr->chr_write = msmouse_chr_write;
     chr->chr_close = msmouse_chr_close;
     chr->explicit_be_open = true;
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 8d144ba..75e83c3 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -291,12 +291,17 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *
 {
     /* create a event character device based on the passed eventfd */
     IVShmemState *s = opaque;
-    CharDriverState * chr;
+    CharDriverState *chr, *newchr;
     int eventfd = event_notifier_get_fd(n);
 
-    chr = qemu_chr_open_eventfd(eventfd);
-
+    newchr = g_malloc0(sizeof(*chr));
+    if (newchr == NULL) {
+        fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd);
+        exit(-1);
+    }
+    chr = qemu_chr_open_eventfd(newchr, eventfd);
     if (chr == NULL) {
+        g_free(newchr);
         fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd);
         exit(-1);
     }
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index b81a6ff..f6844dd 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -292,21 +292,22 @@ CharDriverState *qemu_chr_find(const char *name);
 
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
 
-void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *));
+void register_char_driver(const char *name,
+        CharDriverState *(*open)(CharDriverState *, QemuOpts *));
 void register_char_driver_qapi(const char *name, ChardevBackendKind kind,
         void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp));
 
 /* add an eventfd to the qemu devices that are polled */
-CharDriverState *qemu_chr_open_eventfd(int eventfd);
+CharDriverState *qemu_chr_open_eventfd(CharDriverState *chr, int eventfd);
 
 extern int term_escape_char;
 
 CharDriverState *qemu_char_get_next_serial(void);
 
 /* msmouse */
-CharDriverState *qemu_chr_open_msmouse(void);
+CharDriverState *qemu_chr_open_msmouse(CharDriverState *chr);
 
 /* baum.c */
-CharDriverState *chr_baum_init(void);
+CharDriverState *chr_baum_init(CharDriverState *chr);
 
 #endif
diff --git a/include/ui/console.h b/include/ui/console.h
index 4156a87..572a1ff 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -299,9 +299,9 @@ void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
 DisplaySurface *qemu_console_surface(QemuConsole *con);
 DisplayState *qemu_console_displaystate(QemuConsole *console);
 
-typedef CharDriverState *(VcHandler)(ChardevVC *vc);
+typedef CharDriverState *(VcHandler)(CharDriverState *chr, ChardevVC *vc);
 
-CharDriverState *vc_init(ChardevVC *vc);
+CharDriverState *vc_init(CharDriverState *chr, ChardevVC *vc);
 void register_vc_handler(VcHandler *handler);
 
 /* sdl.c */
diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h
index a93b4b2..15220a1 100644
--- a/include/ui/qemu-spice.h
+++ b/include/ui/qemu-spice.h
@@ -48,12 +48,15 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
 void do_info_spice_print(Monitor *mon, const QObject *data);
 void do_info_spice(Monitor *mon, QObject **ret_data);
 
-CharDriverState *qemu_chr_open_spice_vmc(const char *type);
+CharDriverState *qemu_chr_open_spice_vmc(CharDriverState *chr,
+                                         const char *type);
 #if SPICE_SERVER_VERSION >= 0x000c02
-CharDriverState *qemu_chr_open_spice_port(const char *name);
+CharDriverState *qemu_chr_open_spice_port(CharDriverState *chr,
+                                          const char *name);
 void qemu_spice_register_ports(void);
 #else
-static inline CharDriverState *qemu_chr_open_spice_port(const char *name)
+static inline CharDriverState *qemu_chr_open_spice_port(CharDriverState *chr,
+                                                        const char *name)
 { return NULL; }
 #endif
 
diff --git a/qemu-char.c b/qemu-char.c
index 4d50838..fc688cf 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -232,11 +232,8 @@ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     return len;
 }
 
-static CharDriverState *qemu_chr_open_null(void)
+static CharDriverState *qemu_chr_open_null(CharDriverState *chr)
 {
-    CharDriverState *chr;
-
-    chr = g_malloc0(sizeof(CharDriverState));
     chr->chr_write = null_chr_write;
     chr->explicit_be_open = true;
     return chr;
@@ -519,12 +516,11 @@ static Notifier muxes_realize_notify = {
     .notify = muxes_realize_done,
 };
 
-static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
+static CharDriverState *qemu_chr_open_mux(CharDriverState *chr,
+                                          CharDriverState *drv)
 {
-    CharDriverState *chr;
     MuxDriver *d;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     d = g_malloc0(sizeof(MuxDriver));
 
     chr->opaque = d;
@@ -894,12 +890,11 @@ static void fd_chr_close(struct CharDriverState *chr)
 }
 
 /* open a character device to a unix fd */
-static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
+static CharDriverState *qemu_chr_open_fd(CharDriverState *chr,
+                                         int fd_in, int fd_out)
 {
-    CharDriverState *chr;
     FDCharDriver *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(FDCharDriver));
     s->fd_in = io_channel_from_fd(fd_in);
     s->fd_out = io_channel_from_fd(fd_out);
@@ -914,7 +909,8 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
+static CharDriverState *qemu_chr_open_pipe(CharDriverState *chr,
+                                           ChardevHostdev *opts)
 {
     int fd_in, fd_out;
     char filename_in[256], filename_out[256];
@@ -939,7 +935,7 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
             return NULL;
         }
     }
-    return qemu_chr_open_fd(fd_in, fd_out);
+    return qemu_chr_open_fd(chr, fd_in, fd_out);
 }
 
 /* init terminal so that we can grab keys */
@@ -980,10 +976,9 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
     fd_chr_close(chr);
 }
 
-static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
+static CharDriverState *qemu_chr_open_stdio(CharDriverState *chr,
+                                            ChardevStdio *opts)
 {
-    CharDriverState *chr;
-
     if (is_daemonized()) {
         error_report("cannot use stdio with -daemonize");
         return NULL;
@@ -993,7 +988,7 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
     fcntl(0, F_SETFL, O_NONBLOCK);
     atexit(term_exit);
 
-    chr = qemu_chr_open_fd(0, 1);
+    qemu_chr_open_fd(chr, 0, 1);
     chr->chr_close = qemu_chr_close_stdio;
     chr->chr_set_echo = qemu_chr_set_echo_stdio;
     if (opts->has_signal) {
@@ -1160,10 +1155,10 @@ static void pty_chr_close(struct CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_pty(const char *id,
+static CharDriverState *qemu_chr_open_pty(CharDriverState *chr,
+                                          const char *id,
                                           ChardevReturn *ret)
 {
-    CharDriverState *chr;
     PtyCharDriver *s;
     int master_fd, slave_fd;
     char pty_name[PATH_MAX];
@@ -1175,8 +1170,6 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
 
     close(slave_fd);
 
-    chr = g_malloc0(sizeof(CharDriverState));
-
     chr->filename = g_strdup_printf("pty:%s", pty_name);
     ret->pty = g_strdup(pty_name);
     ret->has_pty = true;
@@ -1398,12 +1391,10 @@ static void qemu_chr_close_tty(CharDriverState *chr)
     }
 }
 
-static CharDriverState *qemu_chr_open_tty_fd(int fd)
+static CharDriverState *qemu_chr_open_tty_fd(CharDriverState *chr, int fd)
 {
-    CharDriverState *chr;
-
     tty_serial_init(fd, 115200, 'N', 8, 1);
-    chr = qemu_chr_open_fd(fd, fd);
+    qemu_chr_open_fd(chr, fd, fd);
     chr->chr_ioctl = tty_serial_ioctl;
     chr->chr_close = qemu_chr_close_tty;
     return chr;
@@ -1523,9 +1514,8 @@ static void pp_close(CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_pp_fd(int fd)
+static CharDriverState *qemu_chr_open_pp_fd(CharDriverState *chr, int fd)
 {
-    CharDriverState *chr;
     ParallelCharDriver *drv;
 
     if (ioctl(fd, PPCLAIM) < 0) {
@@ -1537,7 +1527,6 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
     drv->fd = fd;
     drv->mode = IEEE1284_MODE_COMPAT;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
     chr->chr_close = pp_close;
@@ -1588,11 +1577,8 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
     return 0;
 }
 
-static CharDriverState *qemu_chr_open_pp_fd(int fd)
+static CharDriverState *qemu_chr_open_pp_fd(CharDriverState *chr, int fd)
 {
-    CharDriverState *chr;
-
-    chr = g_malloc0(sizeof(CharDriverState));
     chr->opaque = (void *)(intptr_t)fd;
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
@@ -1811,12 +1797,11 @@ static int win_chr_poll(void *opaque)
     return 0;
 }
 
-static CharDriverState *qemu_chr_open_win_path(const char *filename)
+static CharDriverState *qemu_chr_open_win_path(CharDriverState *chr,
+                                               const char *filename)
 {
-    CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(WinCharState));
     chr->opaque = s;
     chr->chr_write = win_chr_write;
@@ -1824,7 +1809,6 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename)
 
     if (win_chr_init(chr, filename) < 0) {
         g_free(s);
-        g_free(chr);
         return NULL;
     }
     return chr;
@@ -1909,13 +1893,12 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
 }
 
 
-static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
+static CharDriverState *qemu_chr_open_pipe(CharDriverState *chr,
+                                           ChardevHostdev *opts)
 {
     const char *filename = opts->device;
-    CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(WinCharState));
     chr->opaque = s;
     chr->chr_write = win_chr_write;
@@ -1923,18 +1906,16 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
 
     if (win_chr_pipe_init(chr, filename) < 0) {
         g_free(s);
-        g_free(chr);
         return NULL;
     }
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
+static CharDriverState *qemu_chr_open_win_file(CharDriverState *chr,
+                                               HANDLE fd_out)
 {
-    CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(WinCharState));
     s->hcom = fd_out;
     chr->opaque = s;
@@ -1942,9 +1923,9 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_win_con(void)
+static CharDriverState *qemu_chr_open_win_con(CharDriverState *chr)
 {
-    return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
+    return qemu_chr_open_win_file(chr, GetStdHandle(STD_OUTPUT_HANDLE));
 }
 
 static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -2083,14 +2064,13 @@ static void win_stdio_close(CharDriverState *chr)
     g_free(chr);
 }
 
-static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
+static CharDriverState *qemu_chr_open_stdio(CharDriverState *chr,
+                                            ChardevStdio *opts)
 {
-    CharDriverState   *chr;
     WinStdioCharState *stdio;
     DWORD              dwMode;
     int                is_console = 0;
 
-    chr   = g_malloc0(sizeof(CharDriverState));
     stdio = g_malloc0(sizeof(WinStdioCharState));
 
     stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
@@ -2247,12 +2227,10 @@ static void udp_chr_close(CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_udp_fd(int fd)
+static CharDriverState *qemu_chr_open_udp_fd(CharDriverState *chr, int fd)
 {
-    CharDriverState *chr = NULL;
     NetCharDriver *s = NULL;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(NetCharDriver));
 
     s->fd = fd;
@@ -2268,7 +2246,7 @@ static CharDriverState *qemu_chr_open_udp_fd(int fd)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_udp(CharDriverState *chr, QemuOpts *opts)
 {
     Error *local_err = NULL;
     int fd = -1;
@@ -2279,7 +2257,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
         error_free(local_err);
         return NULL;
     }
-    return qemu_chr_open_udp_fd(fd);
+    return qemu_chr_open_udp_fd(chr, fd);
 }
 
 /***********************************************************/
@@ -2490,9 +2468,9 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
 }
 
 #ifndef _WIN32
-CharDriverState *qemu_chr_open_eventfd(int eventfd)
+CharDriverState *qemu_chr_open_eventfd(CharDriverState *chr, int eventfd)
 {
-    return qemu_chr_open_fd(eventfd, eventfd);
+    return qemu_chr_open_fd(chr, eventfd, eventfd);
 }
 #endif
 
@@ -2607,12 +2585,12 @@ static void tcp_chr_close(CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
+static CharDriverState *qemu_chr_open_socket_fd(CharDriverState *chr,
+                                                int fd, bool do_nodelay,
                                                 bool is_listen, bool is_telnet,
                                                 bool is_waitconnect,
                                                 Error **errp)
 {
-    CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
     char host[NI_MAXHOST], serv[NI_MAXSERV];
     const char *left = "", *right = "";
@@ -2625,7 +2603,6 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
         return NULL;
     }
 
-    chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(TCPCharDriver));
 
     s->connected = 0;
@@ -2691,9 +2668,9 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_socket(CharDriverState *chr,
+                                             QemuOpts *opts)
 {
-    CharDriverState *chr = NULL;
     Error *local_err = NULL;
     int fd = -1;
 
@@ -2723,8 +2700,8 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     if (!is_waitconnect)
         qemu_set_nonblock(fd);
 
-    chr = qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, is_telnet,
-                                  is_waitconnect, &local_err);
+    qemu_chr_open_socket_fd(chr, fd, do_nodelay, is_listen, is_telnet,
+                            is_waitconnect, &local_err);
     if (local_err) {
         goto fail;
     }
@@ -2741,7 +2718,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     }
     if (chr) {
         g_free(chr->opaque);
-        g_free(chr);
     }
     return NULL;
 }
@@ -2803,13 +2779,12 @@ static void ringbuf_chr_close(struct CharDriverState *chr)
     chr->opaque = NULL;
 }
 
-static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts,
+static CharDriverState *qemu_chr_open_ringbuf(struct CharDriverState *chr,
+                                              ChardevRingbuf *opts,
                                               Error **errp)
 {
-    CharDriverState *chr;
     RingBufCharDriver *d;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     d = g_malloc(sizeof(*d));
 
     d->size = opts->has_size ? opts->size : 65536;
@@ -2832,7 +2807,6 @@ static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts,
 
 fail:
     g_free(d);
-    g_free(chr);
     return NULL;
 }
 
@@ -3155,7 +3129,7 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
 typedef struct CharDriver {
     const char *name;
     /* old, pre qapi */
-    CharDriverState *(*open)(QemuOpts *opts);
+    CharDriverState *(*open)(CharDriverState *chr, QemuOpts *opts);
     /* new, qapi-based */
     ChardevBackendKind kind;
     void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
@@ -3163,7 +3137,8 @@ typedef struct CharDriver {
 
 static GSList *backends;
 
-void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *))
+void register_char_driver(const char *name,
+                          CharDriverState *(*open)(CharDriverState*,QemuOpts *))
 {
     CharDriver *s;
 
@@ -3268,7 +3243,8 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
         return chr;
     }
 
-    chr = cd->open(opts);
+    chr = g_malloc0(sizeof(CharDriverState));
+    chr = cd->open(chr, opts);
     if (!chr) {
         error_setg(errp, "chardev: opening backend \"%s\" failed",
                    qemu_opt_get(opts, "backend"));
@@ -3291,7 +3267,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
         int len = strlen(qemu_opts_id(opts)) + 6;
         base->label = g_malloc(len);
         snprintf(base->label, len, "%s-base", qemu_opts_id(opts));
-        chr = qemu_chr_open_mux(base);
+        chr = qemu_chr_open_mux(chr, base);
         chr->filename = base->filename;
         chr->avail_connections = MAX_MUX;
         QTAILQ_INSERT_TAIL(&chardevs, chr, next);
@@ -3560,7 +3536,8 @@ QemuOptsList qemu_chardev_opts = {
 
 #ifdef _WIN32
 
-static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
+static CharDriverState *qmp_chardev_open_file(CharDriverState *chr,
+                                              ChardevFile *file, Error **errp)
 {
     HANDLE out;
 
@@ -3578,13 +3555,15 @@ static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
     return qemu_chr_open_win_file(out);
 }
 
-static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
+static CharDriverState *qmp_chardev_open_serial(CharDriverState *chr,
+                                                ChardevHostdev *serial,
                                                 Error **errp)
 {
     return qemu_chr_open_win_path(serial->device);
 }
 
-static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel,
+static CharDriverState *qmp_chardev_open_parallel(CharDriverState *chr,
+                                                  ChardevHostdev *parallel,
                                                   Error **errp)
 {
     error_setg(errp, "character device backend type 'parallel' not supported");
@@ -3605,7 +3584,8 @@ static int qmp_chardev_open_file_source(char *src, int flags,
     return fd;
 }
 
-static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
+static CharDriverState *qmp_chardev_open_file(CharDriverState *chr,
+                                              ChardevFile *file, Error **errp)
 {
     int flags, in = -1, out = -1;
 
@@ -3624,10 +3604,11 @@ static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
         }
     }
 
-    return qemu_chr_open_fd(in, out);
+    return qemu_chr_open_fd(chr, in, out);
 }
 
-static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
+static CharDriverState *qmp_chardev_open_serial(CharDriverState *chr,
+                                                ChardevHostdev *serial,
                                                 Error **errp)
 {
 #ifdef HAVE_CHARDEV_TTY
@@ -3638,14 +3619,15 @@ static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
         return NULL;
     }
     qemu_set_nonblock(fd);
-    return qemu_chr_open_tty_fd(fd);
+    return qemu_chr_open_tty_fd(chr, fd);
 #else
     error_setg(errp, "character device backend type 'serial' not supported");
     return NULL;
 #endif
 }
 
-static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel,
+static CharDriverState *qmp_chardev_open_parallel(CharDriverState *chr,
+                                                  ChardevHostdev *parallel,
                                                   Error **errp)
 {
 #ifdef HAVE_CHARDEV_PARPORT
@@ -3655,7 +3637,7 @@ static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel,
     if (error_is_set(errp)) {
         return NULL;
     }
-    return qemu_chr_open_pp_fd(fd);
+    return qemu_chr_open_pp_fd(chr, fd);
 #else
     error_setg(errp, "character device backend type 'parallel' not supported");
     return NULL;
@@ -3664,7 +3646,8 @@ static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel,
 
 #endif /* WIN32 */
 
-static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock,
+static CharDriverState *qmp_chardev_open_socket(CharDriverState *chr,
+                                                ChardevSocket *sock,
                                                 Error **errp)
 {
     SocketAddress *addr = sock->addr;
@@ -3682,11 +3665,12 @@ static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock,
     if (error_is_set(errp)) {
         return NULL;
     }
-    return qemu_chr_open_socket_fd(fd, do_nodelay, is_listen,
+    return qemu_chr_open_socket_fd(chr, fd, do_nodelay, is_listen,
                                    is_telnet, is_waitconnect, errp);
 }
 
-static CharDriverState *qmp_chardev_open_udp(ChardevUdp *udp,
+static CharDriverState *qmp_chardev_open_udp(CharDriverState *chr,
+                                             ChardevUdp *udp,
                                              Error **errp)
 {
     int fd;
@@ -3695,14 +3679,14 @@ static CharDriverState *qmp_chardev_open_udp(ChardevUdp *udp,
     if (error_is_set(errp)) {
         return NULL;
     }
-    return qemu_chr_open_udp_fd(fd);
+    return qemu_chr_open_udp_fd(chr, fd);
 }
 
 ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
                                Error **errp)
 {
     ChardevReturn *ret = g_new0(ChardevReturn, 1);
-    CharDriverState *base, *chr = NULL;
+    CharDriverState *base, *chr, *newchr;
 
     chr = qemu_chr_find(id);
     if (chr) {
@@ -3711,32 +3695,34 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
         return NULL;
     }
 
+    newchr = g_malloc0(sizeof(CharDriverState));
+
     switch (backend->kind) {
     case CHARDEV_BACKEND_KIND_FILE:
-        chr = qmp_chardev_open_file(backend->file, errp);
+        chr = qmp_chardev_open_file(newchr, backend->file, errp);
         break;
     case CHARDEV_BACKEND_KIND_SERIAL:
-        chr = qmp_chardev_open_serial(backend->serial, errp);
+        chr = qmp_chardev_open_serial(newchr, backend->serial, errp);
         break;
     case CHARDEV_BACKEND_KIND_PARALLEL:
-        chr = qmp_chardev_open_parallel(backend->parallel, errp);
+        chr = qmp_chardev_open_parallel(newchr, backend->parallel, errp);
         break;
     case CHARDEV_BACKEND_KIND_PIPE:
-        chr = qemu_chr_open_pipe(backend->pipe);
+        chr = qemu_chr_open_pipe(newchr, backend->pipe);
         break;
     case CHARDEV_BACKEND_KIND_SOCKET:
-        chr = qmp_chardev_open_socket(backend->socket, errp);
+        chr = qmp_chardev_open_socket(newchr, backend->socket, errp);
         break;
     case CHARDEV_BACKEND_KIND_UDP:
-        chr = qmp_chardev_open_udp(backend->udp, errp);
+        chr = qmp_chardev_open_udp(newchr, backend->udp, errp);
         break;
 #ifdef HAVE_CHARDEV_TTY
     case CHARDEV_BACKEND_KIND_PTY:
-        chr = qemu_chr_open_pty(id, ret);
+        chr = qemu_chr_open_pty(newchr, id, ret);
         break;
 #endif
     case CHARDEV_BACKEND_KIND_NULL:
-        chr = qemu_chr_open_null();
+        chr = qemu_chr_open_null(newchr);
         break;
     case CHARDEV_BACKEND_KIND_MUX:
         base = qemu_chr_find(backend->mux->chardev);
@@ -3745,38 +3731,38 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
                        backend->mux->chardev);
             break;
         }
-        chr = qemu_chr_open_mux(base);
+        chr = qemu_chr_open_mux(newchr, base);
         break;
     case CHARDEV_BACKEND_KIND_MSMOUSE:
-        chr = qemu_chr_open_msmouse();
+        chr = qemu_chr_open_msmouse(newchr);
         break;
 #ifdef CONFIG_BRLAPI
     case CHARDEV_BACKEND_KIND_BRAILLE:
-        chr = chr_baum_init();
+        chr = chr_baum_init(newchr);
         break;
 #endif
     case CHARDEV_BACKEND_KIND_STDIO:
-        chr = qemu_chr_open_stdio(backend->stdio);
+        chr = qemu_chr_open_stdio(newchr, backend->stdio);
         break;
 #ifdef _WIN32
     case CHARDEV_BACKEND_KIND_CONSOLE:
-        chr = qemu_chr_open_win_con();
+        chr = qemu_chr_open_win_con(newchr);
         break;
 #endif
 #ifdef CONFIG_SPICE
     case CHARDEV_BACKEND_KIND_SPICEVMC:
-        chr = qemu_chr_open_spice_vmc(backend->spicevmc->type);
+        chr = qemu_chr_open_spice_vmc(newchr, backend->spicevmc->type);
         break;
     case CHARDEV_BACKEND_KIND_SPICEPORT:
-        chr = qemu_chr_open_spice_port(backend->spiceport->fqdn);
+        chr = qemu_chr_open_spice_port(newchr, backend->spiceport->fqdn);
         break;
 #endif
     case CHARDEV_BACKEND_KIND_VC:
-        chr = vc_init(backend->vc);
+        chr = vc_init(newchr, backend->vc);
         break;
     case CHARDEV_BACKEND_KIND_RINGBUF:
     case CHARDEV_BACKEND_KIND_MEMORY:
-        chr = qemu_chr_open_ringbuf(backend->ringbuf, errp);
+        chr = qemu_chr_open_ringbuf(newchr, backend->ringbuf, errp);
         break;
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
@@ -3799,6 +3785,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
         QTAILQ_INSERT_TAIL(&chardevs, chr, next);
         return ret;
     } else {
+        g_free(newchr);
         g_free(ret);
         return NULL;
     }
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 6624559..c2f5375 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -261,14 +261,11 @@ static void print_allowed_subtypes(void)
     fprintf(stderr, "\n");
 }
 
-static CharDriverState *chr_open(const char *subtype,
+static CharDriverState *chr_open(CharDriverState *chr, const char *subtype,
     void (*set_fe_open)(struct CharDriverState *, int))
-
 {
-    CharDriverState *chr;
     SpiceCharDriver *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(SpiceCharDriver));
     s->chr = chr;
     s->active = false;
@@ -286,7 +283,7 @@ static CharDriverState *chr_open(const char *subtype,
     return chr;
 }
 
-CharDriverState *qemu_chr_open_spice_vmc(const char *type)
+CharDriverState *qemu_chr_open_spice_vmc(CharDriverState *chr, const char *type)
 {
     const char **psubtype = spice_server_char_device_recognized_subtypes();
 
@@ -306,13 +303,13 @@ CharDriverState *qemu_chr_open_spice_vmc(const char *type)
         return NULL;
     }
 
-    return chr_open(type, spice_vmc_set_fe_open);
+    return chr_open(chr, type, spice_vmc_set_fe_open);
 }
 
 #if SPICE_SERVER_VERSION >= 0x000c02
-CharDriverState *qemu_chr_open_spice_port(const char *name)
+CharDriverState *qemu_chr_open_spice_port(CharDriverState *chr,
+                                          const char *name)
 {
-    CharDriverState *chr;
     SpiceCharDriver *s;
 
     if (name == NULL) {
@@ -320,7 +317,7 @@ CharDriverState *qemu_chr_open_spice_port(const char *name)
         return NULL;
     }
 
-    chr = chr_open("port", spice_port_set_fe_open);
+    chr = chr_open(chr, "port", spice_port_set_fe_open);
     s = chr->opaque;
     s->sin.portname = g_strdup(name);
 
diff --git a/ui/console.c b/ui/console.c
index 502e160..0ac45c5 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1724,15 +1724,12 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
         chr->init(chr);
 }
 
-static CharDriverState *text_console_init(ChardevVC *vc)
+static CharDriverState *text_console_init(CharDriverState *chr, ChardevVC *vc)
 {
-    CharDriverState *chr;
     QemuConsole *s;
     unsigned width = 0;
     unsigned height = 0;
 
-    chr = g_malloc0(sizeof(CharDriverState));
-
     if (vc->has_width) {
         width = vc->width;
     } else if (vc->has_cols) {
@@ -1754,7 +1751,6 @@ static CharDriverState *text_console_init(ChardevVC *vc)
     }
 
     if (!s) {
-        g_free(chr);
         return NULL;
     }
 
@@ -1774,9 +1770,9 @@ static CharDriverState *text_console_init(ChardevVC *vc)
 
 static VcHandler *vc_handler = text_console_init;
 
-CharDriverState *vc_init(ChardevVC *vc)
+CharDriverState *vc_init(CharDriverState *chr, ChardevVC *vc)
 {
-    return vc_handler(vc);
+    return vc_handler(chr, vc);
 }
 
 void register_vc_handler(VcHandler *handler)
diff --git a/ui/gtk.c b/ui/gtk.c
index a633d89..0ecc26a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1125,11 +1125,8 @@ static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 static int nb_vcs;
 static CharDriverState *vcs[MAX_VCS];
 
-static CharDriverState *gd_vc_handler(ChardevVC *unused)
+static CharDriverState *gd_vc_handler(CharDriverState *chr, ChardevVC *unused)
 {
-    CharDriverState *chr;
-
-    chr = g_malloc0(sizeof(*chr));
     chr->chr_write = gd_vc_chr_write;
     /* defer OPENED events until our vc is fully initialized */
     chr->explicit_be_open = true;
