Date: Thursday, March 16, 2017 @ 22:11:00 Author: jgc Revision: 290964
upgpkg: spice 0.12.8-2 Apply (security) fixes from git Add signature Switch to https Use sha256 instead of md5 Added: spice/trunk/git-fixes.patch Modified: spice/trunk/PKGBUILD Deleted: spice/trunk/CVE-2013-4282.patch ---------------------+ CVE-2013-4282.patch | 104 -------------------------------------------------- PKGBUILD | 17 ++++++-- git-fixes.patch | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 108 deletions(-) Deleted: CVE-2013-4282.patch =================================================================== --- CVE-2013-4282.patch 2017-03-16 21:33:42 UTC (rev 290963) +++ CVE-2013-4282.patch 2017-03-16 22:11:00 UTC (rev 290964) @@ -1,104 +0,0 @@ -From 8af619009660b24e0b41ad26b30289eea288fcc2 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau <cferg...@redhat.com> -Date: Fri, 23 Aug 2013 09:29:44 +0000 -Subject: Fix buffer overflow when decrypting client SPICE ticket - -reds_handle_ticket uses a fixed size 'password' buffer for the decrypted -password whose size is SPICE_MAX_PASSWORD_LENGTH. However, -RSA_private_decrypt which we call for the decryption expects the -destination buffer to be at least RSA_size(link->tiTicketing.rsa) -bytes long. On my spice-server build, SPICE_MAX_PASSWORD_LENGTH -is 60 while RSA_size() is 128, so we end up overflowing 'password' -when using long passwords (this was reproduced using the string: -'fullscreen=1proxy=#enter proxy here; e.g spice_proxy = http://[proxy]:[port]' -as a password). - -When the overflow occurs, QEMU dies with: -*** stack smashing detected ***: qemu-system-x86_64 terminated - -This commit ensures we use a corectly sized 'password' buffer, -and that it's correctly nul-terminated so that we can use strcmp -instead of strncmp. To keep using strncmp, we'd need to figure out -which one of 'password' and 'taTicket.password' is the smaller buffer, -and use that size. - -This fixes rhbz#999839 ---- -diff --git a/server/reds.c b/server/reds.c -index 892d247..2a0002b 100644 ---- a/server/reds.c -+++ b/server/reds.c -@@ -1926,39 +1926,59 @@ static void reds_handle_link(RedLinkInfo *link) - static void reds_handle_ticket(void *opaque) - { - RedLinkInfo *link = (RedLinkInfo *)opaque; -- char password[SPICE_MAX_PASSWORD_LENGTH]; -+ char *password; - time_t ltime; -+ int password_size; - - //todo: use monotonic time - time(<ime); -- RSA_private_decrypt(link->tiTicketing.rsa_size, -- link->tiTicketing.encrypted_ticket.encrypted_data, -- (unsigned char *)password, link->tiTicketing.rsa, RSA_PKCS1_OAEP_PADDING); -+ if (RSA_size(link->tiTicketing.rsa) < SPICE_MAX_PASSWORD_LENGTH) { -+ spice_warning("RSA modulus size is smaller than SPICE_MAX_PASSWORD_LENGTH (%d < %d), " -+ "SPICE ticket sent from client may be truncated", -+ RSA_size(link->tiTicketing.rsa), SPICE_MAX_PASSWORD_LENGTH); -+ } -+ -+ password = g_malloc0(RSA_size(link->tiTicketing.rsa) + 1); -+ password_size = RSA_private_decrypt(link->tiTicketing.rsa_size, -+ link->tiTicketing.encrypted_ticket.encrypted_data, -+ (unsigned char *)password, -+ link->tiTicketing.rsa, -+ RSA_PKCS1_OAEP_PADDING); -+ if (password_size == -1) { -+ spice_warning("failed to decrypt RSA encrypted password: %s", -+ ERR_error_string(ERR_get_error(), NULL)); -+ goto error; -+ } -+ password[password_size] = '\0'; - - if (ticketing_enabled && !link->skip_auth) { - int expired = taTicket.expiration_time < ltime; - - if (strlen(taTicket.password) == 0) { -- reds_send_link_result(link, SPICE_LINK_ERR_PERMISSION_DENIED); - spice_warning("Ticketing is enabled, but no password is set. " -- "please set a ticket first"); -- reds_link_free(link); -- return; -+ "please set a ticket first"); -+ goto error; - } - -- if (expired || strncmp(password, taTicket.password, SPICE_MAX_PASSWORD_LENGTH) != 0) { -+ if (expired || strcmp(password, taTicket.password) != 0) { - if (expired) { - spice_warning("Ticket has expired"); - } else { - spice_warning("Invalid password"); - } -- reds_send_link_result(link, SPICE_LINK_ERR_PERMISSION_DENIED); -- reds_link_free(link); -- return; -+ goto error; - } - } - - reds_handle_link(link); -+ goto end; -+ -+error: -+ reds_send_link_result(link, SPICE_LINK_ERR_PERMISSION_DENIED); -+ reds_link_free(link); -+ -+end: -+ g_free(password); - } - - static inline void async_read_clear_handlers(AsyncRead *obj) --- -cgit v0.9.0.2-2-gbebe Modified: PKGBUILD =================================================================== --- PKGBUILD 2017-03-16 21:33:42 UTC (rev 290963) +++ PKGBUILD 2017-03-16 22:11:00 UTC (rev 290964) @@ -4,15 +4,25 @@ pkgname=spice pkgver=0.12.8 -pkgrel=1 +pkgrel=2 pkgdesc="SPICE client and server" arch=('i686' 'x86_64') -url="http://spice-space.org" +url="https://www.spice-space.org" license=('LGPL2.1') depends=(alsa-lib celt0.5.1 libcacard libjpeg-turbo libsasl libxinerama libxfixes libxrandr pixman) makedepends=(python2-pyparsing python2-six qemu spice-protocol) -source=(http://spice-space.org/download/releases/$pkgname-$pkgver.tar.bz2) +source=(https://www.spice-space.org/download/releases/$pkgname-$pkgver.tar.bz2{,.sign} + git-fixes.patch) +validpgpkeys=('94A9F75661F77A6168649B23A9D8C21429AC6C82') +sha256sums=('f901a5c5873d61acac84642f9eea5c4d6386fc3e525c2b68792322794e1c407d' + 'SKIP' + '70a6d71e24095bc0864f659b0f3b196ffea5c618e8799281607112726dc2484d') +prepare() { + cd "$srcdir/$pkgname-$pkgver" + patch -Np1 -i ../git-fixes.patch +} + build() { cd "$srcdir/$pkgname-$pkgver" PYTHON=python2 ./configure --prefix=/usr --disable-static --enable-smartcard --enable-client @@ -23,4 +33,3 @@ cd "$srcdir/$pkgname-$pkgver" make DESTDIR="$pkgdir/" install } -md5sums=('376853d11b9921aa34a06c4dbef81874') Added: git-fixes.patch =================================================================== --- git-fixes.patch (rev 0) +++ git-fixes.patch 2017-03-16 22:11:00 UTC (rev 290964) @@ -0,0 +1,98 @@ +diff --git a/server/main_channel.c b/server/main_channel.c +index 0ecc9df8..1fc39155 100644 +--- a/server/main_channel.c ++++ b/server/main_channel.c +@@ -1026,6 +1026,9 @@ static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc, + + if (type == SPICE_MSGC_MAIN_AGENT_DATA) { + return reds_get_agent_data_buffer(mcc, size); ++ } else if (size > sizeof(main_chan->recv_buf)) { ++ /* message too large, caller will log a message and close the connection */ ++ return NULL; + } else { + return main_chan->recv_buf; + } +diff --git a/server/reds.c b/server/reds.c +index 61bf7357..f439a366 100644 +--- a/server/reds.c ++++ b/server/reds.c +@@ -2110,6 +2110,14 @@ static void reds_handle_read_link_done(void *opaque) + link_mess->num_channel_caps = GUINT32_FROM_LE(link_mess->num_channel_caps); + link_mess->num_common_caps = GUINT32_FROM_LE(link_mess->num_common_caps); + ++ /* Prevent DoS. Currently we defined only 13 capabilities, ++ * I expect 1024 to be valid for quite a lot time */ ++ if (link_mess->num_channel_caps > 1024 || link_mess->num_common_caps > 1024) { ++ reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA); ++ reds_link_free(link); ++ return; ++ } ++ + num_caps = link_mess->num_common_caps + link_mess->num_channel_caps; + caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset); + +@@ -2184,12 +2192,6 @@ static void reds_handle_read_header_done(void *opaque) + header->minor_version = GUINT32_FROM_LE(header->minor_version); + header->size = GUINT32_FROM_LE(header->size); + +- if (header->magic != SPICE_MAGIC) { +- reds_send_link_error(link, SPICE_LINK_ERR_INVALID_MAGIC); +- reds_link_free(link); +- return; +- } +- + if (header->major_version != SPICE_VERSION_MAJOR) { + if (header->major_version > 0) { + reds_send_link_error(link, SPICE_LINK_ERR_VERSION_MISMATCH); +@@ -2202,7 +2204,8 @@ static void reds_handle_read_header_done(void *opaque) + + reds->peer_minor_version = header->minor_version; + +- if (header->size < sizeof(SpiceLinkMess)) { ++ /* the check for 4096 is to avoid clients to cause arbitrary big memory allocations */ ++ if (header->size < sizeof(SpiceLinkMess) || header->size > 4096) { + reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA); + spice_warning("bad size %u", header->size); + reds_link_free(link); +@@ -2218,13 +2221,31 @@ static void reds_handle_read_header_done(void *opaque) + link); + } + ++static void reds_handle_read_magic_done(void *opaque) ++{ ++ RedLinkInfo *link = (RedLinkInfo *)opaque; ++ const SpiceLinkHeader *header = &link->link_header; ++ ++ if (header->magic != SPICE_MAGIC) { ++ reds_send_link_error(link, SPICE_LINK_ERR_INVALID_MAGIC); ++ reds_link_free(link); ++ return; ++ } ++ ++ reds_stream_async_read(link->stream, ++ ((uint8_t *)&link->link_header) + sizeof(header->magic), ++ sizeof(SpiceLinkHeader) - sizeof(header->magic), ++ reds_handle_read_header_done, ++ link); ++} ++ + static void reds_handle_new_link(RedLinkInfo *link) + { + reds_stream_set_async_error_handler(link->stream, reds_handle_link_error); + reds_stream_async_read(link->stream, + (uint8_t *)&link->link_header, +- sizeof(SpiceLinkHeader), +- reds_handle_read_header_done, ++ sizeof(link->link_header.magic), ++ reds_handle_read_magic_done, + link); + } + +@@ -2816,6 +2837,7 @@ static void reds_mig_fill_wait_disconnect(void) + wait_client->client = client; + ring_add(&reds->mig_wait_disconnect_clients, &wait_client->link); + } ++ reds->mig_wait_connect = FALSE; + reds->mig_wait_disconnect = TRUE; + core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT); + }