Commit 2e5567c9 authored by Gerd Hoffmann's avatar Gerd Hoffmann
Browse files

vnc: deal with surface NULL pointers



Secondary displays in multihead setups are allowed to have a NULL
DisplaySurface.  Typically user interfaces handle this by hiding the
window which shows the display in question.

This isn't an option for vnc though because it simply hasn't a concept
of windows or outputs.  So handle the situation by showing a placeholder
DisplaySurface instead.  Also check in console_select whenever a surface
is preset in the first place before requesting an update.

This fixes a segfault which can be triggered by switching to an unused
display (via vtrl-alt-<nr>) in a multihead setup, for example using
-device virtio-vga,max_outputs=2.

Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Reviewed-by: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
Message-id: 20180308161803.6152-1-kraxel@redhat.com
parent f1bd3132
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -260,6 +260,8 @@ DisplaySurface *qemu_create_displaysurface_guestmem(int width, int height,
                                                    pixman_format_code_t format,
                                                    int linesize,
                                                    uint64_t addr);
DisplaySurface *qemu_create_message_surface(int w, int h,
                                            const char *msg);
PixelFormat qemu_default_pixelformat(int bpp);

DisplaySurface *qemu_create_displaysurface(int width, int height);
+6 −4
Original line number Diff line number Diff line
@@ -1039,9 +1039,11 @@ void console_select(unsigned int index)
                    dcl->ops->dpy_gfx_switch(dcl, s->surface);
                }
            }
            if (s->surface) {
                dpy_gfx_update(s, 0, 0, surface_width(s->surface),
                               surface_height(s->surface));
            }
        }
        if (ds->have_text) {
            dpy_text_resize(s, s->width, s->height);
        }
@@ -1370,7 +1372,7 @@ DisplaySurface *qemu_create_displaysurface_guestmem(int width, int height,
    return surface;
}

static DisplaySurface *qemu_create_message_surface(int w, int h,
DisplaySurface *qemu_create_message_surface(int w, int h,
                                            const char *msg)
{
    DisplaySurface *surface = qemu_create_displaysurface(w, h);
+10 −0
Original line number Diff line number Diff line
@@ -746,9 +746,19 @@ static void vnc_update_server_surface(VncDisplay *vd)
static void vnc_dpy_switch(DisplayChangeListener *dcl,
                           DisplaySurface *surface)
{
    static const char placeholder_msg[] =
        "Display output is not active.";
    static DisplaySurface *placeholder;
    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
    VncState *vs;

    if (surface == NULL) {
        if (placeholder == NULL) {
            placeholder = qemu_create_message_surface(640, 480, placeholder_msg);
        }
        surface = placeholder;
    }

    vnc_abort_display_jobs(vd);
    vd->ds = surface;