[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#854827: marked as done (unblock: gtk-vnc/0.6.0-3)



Your message dated Sat, 11 Feb 2017 05:09:00 +0000
with message-id <fb083af8-6e77-7e89-a01c-820b8723b3df@thykier.net>
and subject line Re: Bug#854827: unblock: gtk-vnc/0.6.0-3
has caused the Debian Bug report #854827,
regarding unblock: gtk-vnc/0.6.0-3
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
854827: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=854827
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package gtk-vnc

It fixes CVE-2017-5885 and CVE-2017-5884. There's more noise in the diff
than there should be since wanted to bring patches into a more
git-format-patch compatible layout. The diff is probably easier to read
here:

  https://anonscm.debian.org/cgit/pkg-libvirt/gtk-vnc.git/log/    

unblock gtk-vnc/0.6.0-3

-- System Information:
Debian Release: 9.0
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable-debug'), (500, 'testing-debug'), (500, 'stable-updates'), (500, 'unstable'), (500, 'stable'), (500, 'oldstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.9.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
diff --git a/debian/changelog b/debian/changelog
index 8698ecc..28203ee 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,14 @@
+gtk-vnc (0.6.0-3) unstable; urgency=medium
+
+  * [b8d9918] CVE-2017-5884: Fix bounds checking for RRE, hextile & copyrect
+    encodings
+  * [ca87ace] CVE-2017-5885: Correctly validate color map range indexes
+    (Closes: #854450)
+  * [0e71020] Link against GIO_LIBS explicitly to fix build failure
+  * [7d3fdde] Rediff patches to make them more git-format-patch compatible
+
+ -- Guido Günther <agx@sigxcpu.org>  Fri, 10 Feb 2017 14:20:29 +0100
+
 gtk-vnc (0.6.0-2) unstable; urgency=medium
 
   * Team upload.
diff --git a/debian/patches/Add-I-m4-to-Makefile.am.patch b/debian/patches/Add-I-m4-to-Makefile.am.patch
new file mode 100644
index 0000000..8d44369
--- /dev/null
+++ b/debian/patches/Add-I-m4-to-Makefile.am.patch
@@ -0,0 +1,19 @@
+From: Joao Eriberto Mota Filho <eriberto@debian.org>
+Date: Fri, 10 Feb 2017 10:22:10 +0100
+Subject: Add -I m4 to Makefile.am
+
+---
+ Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 69d1f50..dabb899 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,5 +1,5 @@
+ SUBDIRS = src tools examples po vapi
+-ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
++ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
+ 
+ pkgconfig_DATA = $(PACKAGE)-$(GTK_VNC_API_VERSION).pc gvnc-1.0.pc
+ pkgconfigdir = $(libdir)/pkgconfig
diff --git a/debian/patches/Add-m4.patch b/debian/patches/Add-m4.patch
deleted file mode 100644
index c5bdca4..0000000
--- a/debian/patches/Add-m4.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-Description: add -I m4 to Makefile.am
-Author: Joao Eriberto Mota Filho <eriberto@debian.org>
-Last-Update: 2017-01-08
---- gtk-vnc-0.6.0.orig/Makefile.am
-+++ gtk-vnc-0.6.0/Makefile.am
-@@ -1,5 +1,5 @@
- SUBDIRS = src tools examples po vapi
--ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
-+ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
- 
- pkgconfig_DATA = $(PACKAGE)-$(GTK_VNC_API_VERSION).pc gvnc-1.0.pc
- pkgconfigdir = $(libdir)/pkgconfig
diff --git a/debian/patches/Link-against-GIO_LIBS-explicitly.patch b/debian/patches/Link-against-GIO_LIBS-explicitly.patch
new file mode 100644
index 0000000..d962eb4
--- /dev/null
+++ b/debian/patches/Link-against-GIO_LIBS-explicitly.patch
@@ -0,0 +1,31 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Fri, 10 Feb 2017 13:16:26 +0100
+Subject: Link against GIO_LIBS explicitly
+
+to avoid
+
+libtool: link: gcc -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -g -O2 -fdebug-prefix-map=/build/gtk-vnc-0.6.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wl,-z -Wl,relro
+ -Wl,-z -Wl,now -o .libs/vncconnectiontest vncconnectiontest-vncconnectiontest.o  ./.libs/libgvnc-1.0.so -lz -pthread
+/usr/bin/ld: vncconnectiontest-vncconnectiontest.o: undefined reference to symbol 'g_io_stream_get_output_stream'
+//usr/lib/x86_64-linux-gnu/libgio-2.0.so.0: error adding symbols: DSO missing from command line
+
+Also make the use of *_CFLAGS and *_LIBS match.
+---
+ src/Makefile.am | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index f7c1d9d..8bc9085 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -317,8 +317,8 @@ BUILT_SOURCES += $(MARSHAL_FILES) $(ENUM_FILES)
+ CLEANFILES = $(MARSHAL_FILES) $(ENUM_FILES)
+ 
+ vncconnectiontest_SOURCES = vncconnectiontest.c
+-vncconnectiontest_CFLAGS = $(GOBJECT_CFLAGS)
+-vncconnectiontest_LDADD = libgvnc-1.0.la
++vncconnectiontest_CFLAGS = $(GOBJECT_CFLAGS) $(GIO_CLFAGS)
++vncconnectiontest_LDADD = libgvnc-1.0.la $(GOBJECT_LIBS) $(GIO_LIBS)
+ 
+ if WITH_PYTHON
+ pyexec_LTLIBRARIES = gtkvnc.la
diff --git a/debian/patches/Remove-GNUmakefile-links.patch b/debian/patches/Remove-GNUmakefile-links.patch
index e35e3b9..a25c47f 100644
--- a/debian/patches/Remove-GNUmakefile-links.patch
+++ b/debian/patches/Remove-GNUmakefile-links.patch
@@ -9,10 +9,10 @@ since it breaks the out of tree build
  2 files changed, 22 deletions(-)
 
 diff --git a/configure b/configure
-index 9e779d3..7e8162d 100755
+index 6974f35..d103091 100755
 --- a/configure
 +++ b/configure
-@@ -12015,17 +12015,6 @@ cat >>confdefs.h <<_ACEOF
+@@ -12615,17 +12615,6 @@ cat >>confdefs.h <<_ACEOF
  #define VERSION_MICRO $VERSION_MICRO
  _ACEOF
  
@@ -31,10 +31,10 @@ index 9e779d3..7e8162d 100755
    no) :
      ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #(
 diff --git a/configure.ac b/configure.ac
-index ff38b17..3568a2b 100644
+index a208501..f4f3dbd 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -56,17 +56,6 @@ AC_DEFINE_UNQUOTED([VERSION_MAJOR], [$VERSION_MAJOR], [Major version number of p
+@@ -55,17 +55,6 @@ AC_DEFINE_UNQUOTED([VERSION_MAJOR], [$VERSION_MAJOR], [Major version number of p
  AC_DEFINE_UNQUOTED([VERSION_MINOR], [$VERSION_MINOR], [Minor version number of package])
  AC_DEFINE_UNQUOTED([VERSION_MICRO], [$VERSION_MICRO], [Micro version number of package])
  
diff --git a/debian/patches/security/Correctly-validate-color-map-range-indexes.patch b/debian/patches/security/Correctly-validate-color-map-range-indexes.patch
new file mode 100644
index 0000000..7bf63e0
--- /dev/null
+++ b/debian/patches/security/Correctly-validate-color-map-range-indexes.patch
@@ -0,0 +1,178 @@
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Thu, 2 Feb 2017 18:18:48 +0000
+Subject: Correctly validate color map range indexes
+
+The color map index could wrap around to zero causing negative
+array index accesses.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=778050
+
+CVE-2017-5885
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+---
+ src/vnccolormap.c       |  4 +--
+ src/vncconnection.c     | 18 +++++++++---
+ src/vncconnectiontest.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 92 insertions(+), 6 deletions(-)
+
+diff --git a/src/vnccolormap.c b/src/vnccolormap.c
+index 25cd2fc..f3e153a 100644
+--- a/src/vnccolormap.c
++++ b/src/vnccolormap.c
+@@ -119,7 +119,7 @@ gboolean vnc_color_map_set(VncColorMap *map,
+                            guint16 green,
+                            guint16 blue)
+ {
+-    if (idx >= (map->size + map->offset))
++    if (idx < map->offset || idx >= (map->size + map->offset))
+         return FALSE;
+ 
+     map->colors[idx - map->offset].red = red;
+@@ -149,7 +149,7 @@ gboolean vnc_color_map_lookup(VncColorMap *map,
+                               guint16 *green,
+                               guint16 *blue)
+ {
+-    if (idx >= (map->size + map->offset))
++    if (idx < map->offset || idx >= (map->size + map->offset))
+         return FALSE;
+ 
+     *red = map->colors[idx - map->offset].red;
+diff --git a/src/vncconnection.c b/src/vncconnection.c
+index 8290b65..e95811f 100644
+--- a/src/vncconnection.c
++++ b/src/vncconnection.c
+@@ -3344,8 +3344,13 @@ static gboolean vnc_connection_server_message(VncConnection *conn)
+ 
+         VNC_DEBUG("Colour map from %d with %d entries",
+                   first_color, n_colors);
+-        map = vnc_color_map_new(first_color, n_colors);
+ 
++        if (first_color > (65536 - n_colors)) {
++            vnc_connection_set_error(conn, "Colormap start %d out of range %d", first_color, 65536 - n_colors);
++            break;
++        }
++
++        map = vnc_color_map_new(first_color, n_colors);
+         for (i = 0; i < n_colors; i++) {
+             guint16 red, green, blue;
+ 
+@@ -3353,9 +3358,14 @@ static gboolean vnc_connection_server_message(VncConnection *conn)
+             green = vnc_connection_read_u16(conn);
+             blue = vnc_connection_read_u16(conn);
+ 
+-            vnc_color_map_set(map,
+-                              i + first_color,
+-                              red, green, blue);
++            if (!vnc_color_map_set(map,
++                                   i + first_color,
++                                   red, green, blue)) {
++                /* Should not be reachable given earlier range check */
++                vnc_connection_set_error(conn, "Colormap index %d out of range %d,%d",
++                                         i + first_color, first_color, 65536 - n_colors);
++                break;
++            }
+         }
+ 
+         vnc_framebuffer_set_color_map(priv->fb, map);
+diff --git a/src/vncconnectiontest.c b/src/vncconnectiontest.c
+index 521529e..4917b2f 100644
+--- a/src/vncconnectiontest.c
++++ b/src/vncconnectiontest.c
+@@ -445,6 +445,76 @@ static void test_unexpected_cmap_server(GInputStream *is, GOutputStream *os)
+ }
+ 
+ 
++static void test_overflow_cmap_server(GInputStream *is, GOutputStream *os)
++{
++    /* Frame buffer width / height */
++    test_send_u16(os, 100);
++    test_send_u16(os, 100);
++
++    /* BPP, depth, endian, true color */
++    test_send_u8(os, 32);
++    test_send_u8(os, 8);
++    test_send_u8(os, 1);
++    test_send_u8(os, 0);
++
++    /* RGB max + shift*/
++    test_send_u16(os, 255);
++    test_send_u16(os, 255);
++    test_send_u16(os, 255);
++    test_send_u8(os, 0);
++    test_send_u8(os, 8);
++    test_send_u8(os, 16);
++
++    guint8 pad[3] = {0};
++    test_send_bytes(os, pad, G_N_ELEMENTS(pad));
++
++    /* name */
++    guint8 name[] = { 'T', 'e', 's', 't' };
++    test_send_u32(os, G_N_ELEMENTS(name));
++    test_send_bytes(os, name, G_N_ELEMENTS(name));
++
++    /* n-encodings */
++    test_recv_u8(is, 2);
++    /* pad */
++    test_recv_u8(is, 0);
++    /* num encodings */
++    test_recv_u16(is, 5);
++
++    /* encodings */
++    test_recv_s32(is, 16);
++    test_recv_s32(is, 5);
++    test_recv_s32(is, 2);
++    test_recv_s32(is, 1);
++    test_recv_s32(is, 0);
++
++    /* update request */
++    test_recv_u8(is, 3);
++    /* ! incremental */
++    test_recv_u8(is, 0);
++
++    /* x, y, w, h */
++    test_recv_u16(is, 0);
++    test_recv_u16(is, 0);
++    test_recv_u16(is, 100);
++    test_recv_u16(is, 100);
++
++    /* set color map */
++    test_send_u8(os, 1);
++    /* pad */
++    test_send_u8(os, 0);
++    /* first color, ncolors */
++    test_send_u16(os, 65535);
++    test_send_u16(os, 2);
++
++    /* r,g,b */
++    for (int i = 0 ; i < 2; i++) {
++        test_send_u16(os, i);
++        test_send_u16(os, i);
++        test_send_u16(os, i);
++    }
++}
++
++
+ static void test_validation(void (*test_func)(GInputStream *, GOutputStream *))
+ {
+     struct GVncTest *test;
+@@ -526,6 +596,11 @@ static void test_validation_unexpected_cmap(void)
+ {
+     test_validation(test_unexpected_cmap_server);
+ }
++
++static void test_validation_overflow_cmap(void)
++{
++    test_validation(test_overflow_cmap_server);
++}
+ #endif
+ 
+ int main(int argc, char **argv) {
+@@ -541,6 +616,7 @@ int main(int argc, char **argv) {
+     g_test_add_func("/conn/validation/copyrect", test_validation_copyrect);
+     g_test_add_func("/conn/validation/hextile", test_validation_hextile);
+     g_test_add_func("/conn/validation/unexpectedcmap", test_validation_unexpected_cmap);
++    g_test_add_func("/conn/validation/overflowcmap", test_validation_overflow_cmap);
+ #endif
+ 
+     return g_test_run();
diff --git a/debian/patches/security/Don-t-accept-color-map-entries-for-true-color-pixel-forma.patch b/debian/patches/security/Don-t-accept-color-map-entries-for-true-color-pixel-forma.patch
new file mode 100644
index 0000000..1d9ddc5
--- /dev/null
+++ b/debian/patches/security/Don-t-accept-color-map-entries-for-true-color-pixel-forma.patch
@@ -0,0 +1,171 @@
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Thu, 2 Feb 2017 18:01:53 +0000
+Subject: Don't accept color map entries for true-color pixel format
+
+The color map entries should only be sent by the server
+when true-color flag is false.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+---
+ src/vncconnection.c     |  5 +++
+ src/vncconnectiontest.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 99 insertions(+), 2 deletions(-)
+
+diff --git a/src/vncconnection.c b/src/vncconnection.c
+index 39f1966..8290b65 100644
+--- a/src/vncconnection.c
++++ b/src/vncconnection.c
+@@ -3333,6 +3333,11 @@ static gboolean vnc_connection_server_message(VncConnection *conn)
+         VncColorMap *map;
+         int i;
+ 
++        if (priv->fmt.true_color_flag) {
++            vnc_connection_set_error(conn, "Got color map entries in true-color pix format");
++            break;
++        }
++
+         vnc_connection_read(conn, pad, 1);
+         first_color = vnc_connection_read_u16(conn);
+         n_colors = vnc_connection_read_u16(conn);
+diff --git a/src/vncconnectiontest.c b/src/vncconnectiontest.c
+index 7ae7265..521529e 100644
+--- a/src/vncconnectiontest.c
++++ b/src/vncconnectiontest.c
+@@ -88,6 +88,22 @@ static void test_recv_u8(GInputStream *is, guint8 v)
+     g_assert(e == v);
+ }
+ 
++static void test_recv_u16(GInputStream *is, guint16 v)
++{
++    guint16 e;
++    g_assert(g_input_stream_read_all(is, &e, 2, NULL, NULL, NULL));
++    e = GINT16_FROM_BE(e);
++    g_assert(e == v);
++}
++
++static void test_recv_s32(GInputStream *is, gint32 v)
++{
++    gint32 e;
++    g_assert(g_input_stream_read_all(is, &e, 4, NULL, NULL, NULL));
++    e = GINT32_FROM_BE(e);
++    g_assert(e == v);
++}
++
+ 
+ static gpointer test_helper_server(gpointer opaque)
+ {
+@@ -128,6 +144,9 @@ static gpointer test_helper_server(gpointer opaque)
+     /* auth result */
+     test_send_u32(os, 0);
+ 
++    /* shared flag */
++    test_recv_u8(is, 0);
++
+     data->test_func(is, os);
+ 
+     g_mutex_lock(&data->clock);
+@@ -179,8 +198,7 @@ static void test_helper_initialized(VncConnection *conn,
+                                     gpointer opaque)
+ {
+     struct GVncTest *test = opaque;
+-    gint32 encodings[] = {  VNC_CONNECTION_ENCODING_DESKTOP_RESIZE,
+-                            VNC_CONNECTION_ENCODING_ZRLE,
++    gint32 encodings[] = {  VNC_CONNECTION_ENCODING_ZRLE,
+                             VNC_CONNECTION_ENCODING_HEXTILE,
+                             VNC_CONNECTION_ENCODING_RRE,
+                             VNC_CONNECTION_ENCODING_COPY_RECT,
+@@ -359,6 +377,74 @@ static void test_copyrect_bounds_server(GInputStream *is, GOutputStream *os)
+ }
+ 
+ 
++static void test_unexpected_cmap_server(GInputStream *is, GOutputStream *os)
++{
++    /* Frame buffer width / height */
++    test_send_u16(os, 100);
++    test_send_u16(os, 100);
++
++    /* BPP, depth, endian, true color */
++    test_send_u8(os, 32);
++    test_send_u8(os, 8);
++    test_send_u8(os, 1);
++    test_send_u8(os, 1);
++
++    /* RGB max + shift*/
++    test_send_u16(os, 255);
++    test_send_u16(os, 255);
++    test_send_u16(os, 255);
++    test_send_u8(os, 0);
++    test_send_u8(os, 8);
++    test_send_u8(os, 16);
++
++    guint8 pad[3] = {0};
++    test_send_bytes(os, pad, G_N_ELEMENTS(pad));
++
++    /* name */
++    guint8 name[] = { 'T', 'e', 's', 't' };
++    test_send_u32(os, G_N_ELEMENTS(name));
++    test_send_bytes(os, name, G_N_ELEMENTS(name));
++
++    /* n-encodings */
++    test_recv_u8(is, 2);
++    /* pad */
++    test_recv_u8(is, 0);
++    /* num encodings */
++    test_recv_u16(is, 5);
++
++    /* encodings */
++    test_recv_s32(is, 16);
++    test_recv_s32(is, 5);
++    test_recv_s32(is, 2);
++    test_recv_s32(is, 1);
++    test_recv_s32(is, 0);
++
++    /* update request */
++    test_recv_u8(is, 3);
++    /* ! incremental */
++    test_recv_u8(is, 0);
++
++    /* x, y, w, h */
++    test_recv_u16(is, 0);
++    test_recv_u16(is, 0);
++    test_recv_u16(is, 100);
++    test_recv_u16(is, 100);
++
++    /* set color map */
++    test_send_u8(os, 1);
++    /* pad */
++    test_send_u8(os, 0);
++    /* first color, ncolors */
++    test_send_u16(os, 0);
++    test_send_u16(os, 1);
++
++    /* r,g,b */
++    test_send_u16(os, 128);
++    test_send_u16(os, 128);
++    test_send_u16(os, 128);
++}
++
++
+ static void test_validation(void (*test_func)(GInputStream *, GOutputStream *))
+ {
+     struct GVncTest *test;
+@@ -435,6 +521,11 @@ static void test_validation_copyrect(void)
+ {
+     test_validation(test_copyrect_bounds_server);
+ }
++
++static void test_validation_unexpected_cmap(void)
++{
++    test_validation(test_unexpected_cmap_server);
++}
+ #endif
+ 
+ int main(int argc, char **argv) {
+@@ -449,6 +540,7 @@ int main(int argc, char **argv) {
+     g_test_add_func("/conn/validation/rre", test_validation_rre);
+     g_test_add_func("/conn/validation/copyrect", test_validation_copyrect);
+     g_test_add_func("/conn/validation/hextile", test_validation_hextile);
++    g_test_add_func("/conn/validation/unexpectedcmap", test_validation_unexpected_cmap);
+ #endif
+ 
+     return g_test_run();
diff --git a/debian/patches/security/Fix-bounds-checking-for-RRE-hextile-copyrect-encodings.patch b/debian/patches/security/Fix-bounds-checking-for-RRE-hextile-copyrect-encodings.patch
new file mode 100644
index 0000000..3f4ac46
--- /dev/null
+++ b/debian/patches/security/Fix-bounds-checking-for-RRE-hextile-copyrect-encodings.patch
@@ -0,0 +1,610 @@
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Thu, 2 Feb 2017 17:34:47 +0000
+Subject: Fix bounds checking for RRE, hextile & copyrect encodings
+
+While the client would bounds check the overall update
+region, it failed to bounds check the payload data
+parameters.
+
+Add a test case to validate bounds checking.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=778048
+
+CVE-2017-5884
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+---
+ cfg.mk                  |   2 +-
+ src/Makefile.am         |   8 +
+ src/vncconnection.c     |  41 +++--
+ src/vncconnectiontest.c | 462 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 496 insertions(+), 17 deletions(-)
+ create mode 100644 src/vncconnectiontest.c
+
+diff --git a/cfg.mk b/cfg.mk
+index 524a330..cd4a264 100644
+--- a/cfg.mk
++++ b/cfg.mk
+@@ -109,7 +109,7 @@ sc_copyright_format:
+ prev_version_file = /dev/null
+ 
+ 
+-exclude_file_name_regexp--sc_bindtextdomain = ^examples/
++exclude_file_name_regexp--sc_bindtextdomain = ^examples/|src/.*test.c
+ 
+ exclude_file_name_regexp--sc_preprocessor_indentation = ^*/*.[ch]
+ 
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 996f5e0..f7c1d9d 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1,6 +1,10 @@
+ 
+ EXTRA_DIST = libgvnc_sym.version libgvncpulse_sym.version libgtk-vnc_sym.version vncmarshal.txt
+ 
++TESTS = vncconnectiontest
++
++noinst_PROGRAMS = $(TESTS)
++
+ lib_LTLIBRARIES = libgvnc-1.0.la
+ 
+ BUILT_SOURCES =
+@@ -312,6 +316,10 @@ BUILT_SOURCES += $(MARSHAL_FILES) $(ENUM_FILES)
+ 
+ CLEANFILES = $(MARSHAL_FILES) $(ENUM_FILES)
+ 
++vncconnectiontest_SOURCES = vncconnectiontest.c
++vncconnectiontest_CFLAGS = $(GOBJECT_CFLAGS)
++vncconnectiontest_LDADD = libgvnc-1.0.la
++
+ if WITH_PYTHON
+ pyexec_LTLIBRARIES = gtkvnc.la
+ 
+diff --git a/src/vncconnection.c b/src/vncconnection.c
+index 89f07d0..39f1966 100644
+--- a/src/vncconnection.c
++++ b/src/vncconnection.c
+@@ -2168,6 +2168,21 @@ static vnc_connection_tight_sum_pixel_func *vnc_connection_tight_sum_pixel_table
+     (vnc_connection_tight_sum_pixel_func *)vnc_connection_tight_sum_pixel_32x32,
+ };
+ 
++static gboolean vnc_connection_validate_boundary(VncConnection *conn,
++                                                 guint16 x, guint16 y,
++                                                 guint16 width, guint16 height)
++{
++    VncConnectionPrivate *priv = conn->priv;
++
++    if ((x + width) > priv->width || (y + height) > priv->height) {
++        vnc_connection_set_error(conn, "Framebuffer update %dx%d at %d,%d "
++                                 "outside boundary %dx%d",
++                                 width, height, x, y, priv->width, priv->height);
++    }
++
++    return !vnc_connection_has_error(conn);
++}
++
+ 
+ static void vnc_connection_raw_update(VncConnection *conn,
+                                       guint16 x, guint16 y,
+@@ -2215,6 +2230,9 @@ static void vnc_connection_copyrect_update(VncConnection *conn,
+     src_x = vnc_connection_read_u16(conn);
+     src_y = vnc_connection_read_u16(conn);
+ 
++    if (!vnc_connection_validate_boundary(conn, src_x, src_y, width, height))
++        return;
++
+     vnc_framebuffer_copyrect(priv->fb,
+                              src_x, src_y,
+                              dst_x, dst_y,
+@@ -2257,6 +2275,10 @@ static void vnc_connection_hextile_rect(VncConnection *conn,
+                 xy = vnc_connection_read_u8(conn);
+                 wh = vnc_connection_read_u8(conn);
+ 
++                if (!vnc_connection_validate_boundary(conn, x + nibhi(xy), y + niblo(xy),
++                                                      nibhi(wh) + 1, niblo(wh) + 1))
++                    return;
++
+                 vnc_framebuffer_fill(priv->fb, fg,
+                                      x + nibhi(xy), y + niblo(xy),
+                                      nibhi(wh) + 1, niblo(wh) + 1);
+@@ -2313,6 +2335,9 @@ static void vnc_connection_rre_update(VncConnection *conn,
+         sub_w = vnc_connection_read_u16(conn);
+         sub_h = vnc_connection_read_u16(conn);
+ 
++        if (!vnc_connection_validate_boundary(conn, x + sub_x, y + sub_y, sub_w, sub_h))
++            break;
++
+         vnc_framebuffer_fill(priv->fb, fg,
+                              x + sub_x, y + sub_y, sub_w, sub_h);
+     }
+@@ -3079,22 +3104,6 @@ static void vnc_connection_ext_key_event(VncConnection *conn)
+ }
+ 
+ 
+-static gboolean vnc_connection_validate_boundary(VncConnection *conn,
+-                                                 guint16 x, guint16 y,
+-                                                 guint16 width, guint16 height)
+-{
+-    VncConnectionPrivate *priv = conn->priv;
+-
+-    if ((x + width) > priv->width || (y + height) > priv->height) {
+-        vnc_connection_set_error(conn, "Framebuffer update %dx%d at %d,%d "
+-                                 "outside boundary %dx%d",
+-                                 width, height, x, y, priv->width, priv->height);
+-    }
+-
+-    return !vnc_connection_has_error(conn);
+-}
+-
+-
+ static gboolean vnc_connection_framebuffer_update(VncConnection *conn, gint32 etype,
+                                                   guint16 x, guint16 y,
+                                                   guint16 width, guint16 height)
+diff --git a/src/vncconnectiontest.c b/src/vncconnectiontest.c
+new file mode 100644
+index 0000000..7ae7265
+--- /dev/null
++++ b/src/vncconnectiontest.c
+@@ -0,0 +1,462 @@
++/*
++ * GTK VNC Widget
++ *
++ * Copyright (C) 2006  Anthony Liguori <anthony@codemonkey.ws>
++ * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.0 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
++ */
++
++#include <config.h>
++
++#include <string.h>
++#include <stdlib.h>
++
++#include "vncconnection.h"
++#include "vncbaseframebuffer.h"
++
++static gboolean debug;
++
++#if GLIB_CHECK_VERSION(2, 22, 0)
++
++struct GVncTest {
++    GMutex lock;
++    GMutex clock;
++    GCond cond;
++    int port;
++    VncConnection *conn;
++    GMainLoop *loop;
++    gboolean connected;
++    gboolean quit;
++    char *error;
++
++    char *pixels;
++
++    void (*test_func)(GInputStream *, GOutputStream *);
++};
++
++
++static void test_send_bytes(GOutputStream *os, const guint8 *str, gsize len)
++{
++    g_assert(g_output_stream_write_all(os, str, len, NULL, NULL, NULL));
++}
++
++static void test_send_u8(GOutputStream *os, guint8 v)
++{
++    g_assert(g_output_stream_write_all(os, &v, 1, NULL, NULL, NULL));
++}
++
++static void test_send_u16(GOutputStream *os, guint16 v)
++{
++    v = GUINT16_TO_BE(v);
++    g_assert(g_output_stream_write_all(os, &v, 2, NULL, NULL, NULL));
++}
++
++static void test_send_u32(GOutputStream *os, guint32 v)
++{
++    v = GUINT32_TO_BE(v);
++    g_assert(g_output_stream_write_all(os, &v, 4, NULL, NULL, NULL));
++}
++
++static void test_send_s32(GOutputStream *os, gint32 v)
++{
++    v = GINT32_TO_BE(v);
++    g_assert(g_output_stream_write_all(os, &v, 4, NULL, NULL, NULL));
++}
++
++static void test_recv_bytes(GInputStream *is, guint8 *str, gsize len)
++{
++    g_assert(g_input_stream_read_all(is, str, len, NULL, NULL, NULL));
++}
++
++static void test_recv_u8(GInputStream *is, guint8 v)
++{
++    guint8 e;
++    g_assert(g_input_stream_read_all(is, &e, 1, NULL, NULL, NULL));
++    g_assert(e == v);
++}
++
++
++static gpointer test_helper_server(gpointer opaque)
++{
++    struct GVncTest *data = opaque;
++    GSocketListener *server;
++    GSocketConnection *client;
++    GIOStream *ios;
++    GInputStream *is;
++    GOutputStream *os;
++
++    server = g_socket_listener_new();
++
++    data->port = g_socket_listener_add_any_inet_port(server, NULL, NULL);
++    g_mutex_unlock(&data->lock);
++
++    client = g_socket_listener_accept(server, NULL, NULL, NULL);
++
++    ios = G_IO_STREAM(client);
++    is = g_io_stream_get_input_stream(ios);
++    os = g_io_stream_get_output_stream(ios);
++
++    guint8 greeting[] = {
++        'R', 'F', 'B', ' ',
++        '0', '0', '3', '.',
++        '0', '0', '8', '\n',
++    };
++
++    /* Greeting */
++    test_send_bytes(os, greeting, G_N_ELEMENTS(greeting));
++    test_recv_bytes(is, greeting, G_N_ELEMENTS(greeting));
++
++    /* N auth */
++    test_send_u8(os, 1);
++    /* auth == none */
++    test_send_u8(os, 1);
++    test_recv_u8(is, 1);
++
++    /* auth result */
++    test_send_u32(os, 0);
++
++    data->test_func(is, os);
++
++    g_mutex_lock(&data->clock);
++    while (!data->quit) {
++        g_cond_wait(&data->cond, &data->clock);
++    }
++
++    g_object_unref(client);
++}
++
++static void test_helper_desktop_resize(VncConnection *conn,
++                                       int width, int height,
++                                       gpointer opaque)
++{
++    struct GVncTest *test = opaque;
++    const VncPixelFormat *remoteFormat;
++    VncPixelFormat localFormat = {
++        .bits_per_pixel = 32,
++        .depth = 32,
++        .byte_order = G_BYTE_ORDER,
++        .true_color_flag = TRUE,
++        .red_max = 255,
++        .green_max = 255,
++        .blue_max = 255,
++        .red_shift = 0,
++        .green_shift = 8,
++        .blue_shift = 16,
++    };
++    VncBaseFramebuffer *fb;
++
++
++    VNC_DEBUG("Resize %dx%d", width, height);
++    remoteFormat = vnc_connection_get_pixel_format(conn);
++
++    /* We'll fix our local copy as rgb888 */
++    test->pixels = g_new0(char, width * height * 4);
++
++    fb = vnc_base_framebuffer_new(test->pixels, width, height, width * 4,
++                                  remoteFormat,
++                                  &localFormat);
++
++    vnc_connection_set_framebuffer(conn, VNC_FRAMEBUFFER(fb));
++
++    g_object_unref(fb);
++}
++
++
++static void test_helper_initialized(VncConnection *conn,
++                                    gpointer opaque)
++{
++    struct GVncTest *test = opaque;
++    gint32 encodings[] = {  VNC_CONNECTION_ENCODING_DESKTOP_RESIZE,
++                            VNC_CONNECTION_ENCODING_ZRLE,
++                            VNC_CONNECTION_ENCODING_HEXTILE,
++                            VNC_CONNECTION_ENCODING_RRE,
++                            VNC_CONNECTION_ENCODING_COPY_RECT,
++                            VNC_CONNECTION_ENCODING_RAW };
++    gint32 *encodingsp;
++    int n_encodings;
++
++    test_helper_desktop_resize(conn,
++                               vnc_connection_get_width(conn),
++                               vnc_connection_get_height(conn),
++                               test);
++
++    encodingsp = encodings;
++    n_encodings = G_N_ELEMENTS(encodings);
++
++    VNC_DEBUG("Sending %d encodings", n_encodings);
++    if (!vnc_connection_set_encodings(conn, n_encodings, encodingsp))
++        goto error;
++
++    VNC_DEBUG("Requesting first framebuffer update");
++    if (!vnc_connection_framebuffer_update_request(test->conn,
++                                                   0, 0, 0,
++                                                   vnc_connection_get_width(test->conn),
++                                                   vnc_connection_get_height(test->conn)))
++        vnc_connection_shutdown(test->conn);
++
++    test->connected = TRUE;
++    return;
++
++ error:
++    vnc_connection_shutdown(conn);
++}
++
++static void test_helper_auth_choose_type(VncConnection *conn,
++                                         GValueArray *types G_GNUC_UNUSED,
++                                         gpointer opaque G_GNUC_UNUSED)
++{
++    vnc_connection_set_auth_type(conn, VNC_CONNECTION_AUTH_NONE);
++}
++
++
++static void test_helper_disconnected(VncConnection *conn G_GNUC_UNUSED,
++                                     gpointer opaque)
++{
++    struct GVncTest *test = opaque;
++    g_main_quit(test->loop);
++}
++
++static void test_helper_error(VncConnection *conn,
++                              const char *str,
++                              gpointer opaque)
++{
++    struct GVncTest *test = opaque;
++    test->error = g_strdup(str);
++}
++
++static void test_common_bounds_server(GInputStream *is, GOutputStream *os)
++{
++    /* Frame buffer width / height */
++    test_send_u16(os, 100);
++    test_send_u16(os, 100);
++
++    /* BPP, depth, endian, true color */
++    test_send_u8(os, 32);
++    test_send_u8(os, 8);
++    test_send_u8(os, 1);
++    test_send_u8(os, 1);
++
++    /* RGB max + shift*/
++    test_send_u16(os, 255);
++    test_send_u16(os, 255);
++    test_send_u16(os, 255);
++    test_send_u8(os, 0);
++    test_send_u8(os, 8);
++    test_send_u8(os, 16);
++
++    guint8 pad[3] = {0};
++    test_send_bytes(os, pad, G_N_ELEMENTS(pad));
++
++    /* name */
++    guint8 name[] = { 'T', 'e', 's', 't' };
++    test_send_u32(os, G_N_ELEMENTS(name));
++    test_send_bytes(os, name, G_N_ELEMENTS(name));
++}
++
++static void test_rre_bounds_server(GInputStream *is, GOutputStream *os)
++{
++    test_common_bounds_server(is, os);
++
++    /* Message type & pad */
++    test_send_u8(os, 0);
++    test_send_u8(os, 0);
++
++    /* num rect */
++    test_send_u16(os, 1);
++    /* x, y, w, h */
++    test_send_u16(os, 90);
++    test_send_u16(os, 90);
++    test_send_u16(os, 10);
++    test_send_u16(os, 10);
++
++    /* encoding=rre */
++    test_send_s32(os, 2);
++
++    /* num rect */
++    test_send_u32(os, 1);
++
++    /* bg pix, fg pix */
++    test_send_u32(os, 0x41414141);
++    test_send_u32(os, 0x42424242);
++
++    /* x, y, w, h */
++    test_send_u16(os, 10);
++    test_send_u16(os, 10000);
++    test_send_u16(os, 1);
++    test_send_u16(os, 1);
++}
++
++
++static void test_hextile_bounds_server(GInputStream *is, GOutputStream *os)
++{
++    test_common_bounds_server(is, os);
++
++    /* Message type & pad */
++    test_send_u8(os, 0);
++    test_send_u8(os, 0);
++
++    /* num rect */
++    test_send_u16(os, 1);
++    /* x, y, w, h */
++    test_send_u16(os, 90);
++    test_send_u16(os, 90);
++    test_send_u16(os, 10);
++    test_send_u16(os, 10);
++
++    /* encoding=hextile */
++    test_send_s32(os, 5);
++
++    /* tile type */
++    test_send_u8(os, 0x18);
++
++    /* num rect */
++    test_send_u8(os, 1);
++
++    /* fg pix */
++    test_send_u32(os, 0x12345678);
++
++    /* x, y */
++    test_send_u8(os, 0xff);
++    test_send_u8(os, 0xff);
++}
++
++
++static void test_copyrect_bounds_server(GInputStream *is, GOutputStream *os)
++{
++    test_common_bounds_server(is, os);
++
++    /* Message type & pad */
++    test_send_u8(os, 0);
++    test_send_u8(os, 0);
++
++    /* num rect */
++    test_send_u16(os, 1);
++    /* x, y, w, h */
++    test_send_u16(os, 90);
++    test_send_u16(os, 90);
++    test_send_u16(os, 10);
++    test_send_u16(os, 10);
++
++    /* encoding=copyrect */
++    test_send_s32(os, 1);
++
++    /* src x, y */
++    test_send_u16(os, 91);
++    test_send_u16(os, 91);
++}
++
++
++static void test_validation(void (*test_func)(GInputStream *, GOutputStream *))
++{
++    struct GVncTest *test;
++    char *port;
++    GMainLoop *loop;
++    GThread *th;
++
++    test = g_new0(struct GVncTest, 1);
++    test->test_func = test_func;
++
++    g_mutex_init(&test->lock);
++    g_mutex_init(&test->clock);
++    g_cond_init(&test->cond);
++    g_mutex_lock(&test->lock);
++
++    loop = g_main_loop_new(g_main_context_default(), FALSE);
++
++    th = g_thread_new("rre-server", test_helper_server, test);
++
++    g_mutex_lock(&test->lock);
++    port = g_strdup_printf("%d", test->port);
++
++    test->conn = vnc_connection_new();
++
++    g_signal_connect(test->conn, "vnc-initialized",
++                     G_CALLBACK(test_helper_initialized), test);
++    g_signal_connect(test->conn, "vnc-disconnected",
++                     G_CALLBACK(test_helper_disconnected), test);
++    g_signal_connect(test->conn, "vnc-auth-choose-type",
++                     G_CALLBACK(test_helper_auth_choose_type), test);
++    g_signal_connect(test->conn, "vnc-desktop-resize",
++                     G_CALLBACK(test_helper_desktop_resize), test);
++    g_signal_connect(test->conn, "vnc-error",
++                     G_CALLBACK(test_helper_error), test);
++
++    vnc_connection_open_host(test->conn, "127.0.0.1", port);
++
++    test->loop = g_main_loop_new(g_main_context_default(), FALSE);
++
++    g_main_loop_run(test->loop);
++
++    g_mutex_lock(&test->clock);
++    test->quit = TRUE;
++    g_mutex_unlock(&test->clock);
++    g_cond_signal(&test->cond);
++
++    g_thread_join(th);
++
++    vnc_connection_shutdown(test->conn);
++    g_object_unref(test->conn);
++    g_free(test->pixels);
++    g_main_loop_unref(test->loop);
++
++    g_assert(test->error);
++    if (debug)
++        g_printerr("Got err %s\n", test->error);
++    g_free(test->error);
++
++    g_free(port);
++    g_free(test);
++}
++
++static void test_validation_rre(void)
++{
++    test_validation(test_rre_bounds_server);
++}
++
++static void test_validation_hextile(void)
++{
++    test_validation(test_hextile_bounds_server);
++}
++
++static void test_validation_copyrect(void)
++{
++    test_validation(test_copyrect_bounds_server);
++}
++#endif
++
++int main(int argc, char **argv) {
++    g_test_init(&argc, &argv, NULL);
++
++    if (getenv("GTK_VNC_DEBUG")) {
++        debug = TRUE;
++        vnc_util_set_debug(TRUE);
++    }
++
++#if GLIB_CHECK_VERSION(2, 22, 0)
++    g_test_add_func("/conn/validation/rre", test_validation_rre);
++    g_test_add_func("/conn/validation/copyrect", test_validation_copyrect);
++    g_test_add_func("/conn/validation/hextile", test_validation_hextile);
++#endif
++
++    return g_test_run();
++}
++/*
++ * Local variables:
++ *  c-indent-level: 4
++ *  c-basic-offset: 4
++ *  indent-tabs-mode: nil
++ * End:
++ */
diff --git a/debian/patches/series b/debian/patches/series
index 5620351..6af8186 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,6 @@
 Remove-GNUmakefile-links.patch
-Add-m4.patch
+Add-I-m4-to-Makefile.am.patch
+security/Fix-bounds-checking-for-RRE-hextile-copyrect-encodings.patch
+security/Don-t-accept-color-map-entries-for-true-color-pixel-forma.patch
+security/Correctly-validate-color-map-range-indexes.patch
+Link-against-GIO_LIBS-explicitly.patch

--- End Message ---
--- Begin Message ---
Guido Günther:
> Package: release.debian.org
> Severity: normal
> User: release.debian.org@packages.debian.org
> Usertags: unblock
> 
> Please unblock package gtk-vnc
> 
> It fixes CVE-2017-5885 and CVE-2017-5884. There's more noise in the diff
> than there should be since wanted to bring patches into a more
> git-format-patch compatible layout. The diff is probably easier to read
> here:
> 
>   https://anonscm.debian.org/cgit/pkg-libvirt/gtk-vnc.git/log/    
> 
> unblock gtk-vnc/0.6.0-3
> 
> [...]

Unblocked, thanks.

~Niels

--- End Message ---

Reply to: