[gcr] Fix crash on parsing some certificates (#894157)

Tomas Bzatek tbzatek at fedoraproject.org
Mon Jan 14 17:21:04 UTC 2013


commit cb7d14a486b983ccba17e9485a6e05abf17e4172
Author: Tomas Bzatek <tbzatek at redhat.com>
Date:   Mon Jan 14 18:20:46 2013 +0100

    Fix crash on parsing some certificates (#894157)

 gcr-3.7.2-egg-armor-memrchr-negative.patch  |  269 +++++++++++++++++++++++++++
 gcr-3.7.2-egg-armor-memrchr-truncated.patch |   40 ++++
 gcr.spec                                    |   13 ++-
 3 files changed, 321 insertions(+), 1 deletions(-)
---
diff --git a/gcr-3.7.2-egg-armor-memrchr-negative.patch b/gcr-3.7.2-egg-armor-memrchr-negative.patch
new file mode 100644
index 0000000..ca9d343
--- /dev/null
+++ b/gcr-3.7.2-egg-armor-memrchr-negative.patch
@@ -0,0 +1,269 @@
+From 155912092ab90b5597817b4a3c67ccc8dec00cb9 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw at gnome.org>
+Date: Fri, 11 Jan 2013 20:23:12 +0000
+Subject: egg-armor: Fix memrchr() call with negative string length
+
+ * Initial patch by Gustavo Luiz Duarte <gustavold at linux.vnet.ibm.com>
+ * The cause of this bug was reusing argument variables for other
+   purposes in parsing functions when that didn't really make sense,
+   so fix this as well.
+ * Add tests that catch this issue.
+
+See https://bugzilla.redhat.com/show_bug.cgi?id=893162
+
+https://bugzilla.gnome.org/show_bug.cgi?id=691505
+---
+diff --git a/egg/egg-armor.c b/egg/egg-armor.c
+index 812f1aa..dd213d0 100644
+--- a/egg/egg-armor.c
++++ b/egg/egg-armor.c
+@@ -104,18 +104,20 @@ armor_find_begin (const gchar *data,
+                   const gchar **outer)
+ {
+ 	const gchar *pref, *suff;
++	const gchar *at;
+ 	gchar *stype;
++	gsize len;
+ 
+ 	/* Look for a prefix */
+ 	pref = g_strstr_len ((gchar*)data, n_data, ARMOR_PREF_BEGIN);
+ 	if (!pref)
+ 		return NULL;
+ 
+-	n_data -= (pref - data) + ARMOR_PREF_BEGIN_L;
+-	data = pref + ARMOR_PREF_BEGIN_L;
++	len = n_data - ((pref - data) + ARMOR_PREF_BEGIN_L);
++	at = pref + ARMOR_PREF_BEGIN_L;
+ 
+ 	/* Look for the end of that begin */
+-	suff = g_strstr_len ((gchar*)data, n_data, ARMOR_SUFF);
++	suff = g_strstr_len ((gchar *)at, len, ARMOR_SUFF);
+ 	if (!suff)
+ 		return NULL;
+ 
+@@ -149,6 +151,8 @@ armor_find_end (const gchar *data,
+ 	const gchar *stype;
+ 	const gchar *pref;
+ 	const gchar *line;
++	const gchar *at;
++	gsize len;
+ 	gsize n_type;
+ 
+ 	/* Look for a prefix */
+@@ -156,20 +160,20 @@ armor_find_end (const gchar *data,
+ 	if (!pref)
+ 		return NULL;
+ 
+-	n_data -= (pref - data) + ARMOR_PREF_END_L;
+-	data = pref + ARMOR_PREF_END_L;
++	len = n_data - ((pref - data) + ARMOR_PREF_END_L);
++	at = pref + ARMOR_PREF_END_L;
+ 
+ 	/* Next comes the type string */
+ 	stype = g_quark_to_string (type);
+ 	n_type = strlen (stype);
+-	if (n_type > n_data || strncmp ((gchar*)data, stype, n_type) != 0)
++	if (n_type > len || strncmp ((gchar*)at, stype, n_type) != 0)
+ 		return NULL;
+ 
+-	n_data -= n_type;
+-	data += n_type;
++	len -= n_type;
++	at += n_type;
+ 
+ 	/* Next comes the suffix */
+-	if (ARMOR_SUFF_L > n_data && strncmp ((gchar*)data, ARMOR_SUFF, ARMOR_SUFF_L) != 0)
++	if (ARMOR_SUFF_L > len && strncmp ((gchar*)at, ARMOR_SUFF, ARMOR_SUFF_L) != 0)
+ 		return NULL;
+ 
+ 	/*
+@@ -182,10 +186,10 @@ armor_find_end (const gchar *data,
+ 		pref = line;
+ 
+ 	if (outer != NULL) {
+-		data += ARMOR_SUFF_L;
+-		if (isspace (data[0]))
+-			data++;
+-		*outer = data;
++		at += ARMOR_SUFF_L;
++		if (isspace (at[0]))
++			at++;
++		*outer = at;
+ 	}
+ 
+ 	/* The end of the data */
+diff --git a/egg/tests/Makefile.am b/egg/tests/Makefile.am
+index 2e8335b..7cb1830 100644
+--- a/egg/tests/Makefile.am
++++ b/egg/tests/Makefile.am
+@@ -32,6 +32,7 @@ TEST_PROGS = \
+ 	test-secmem \
+ 	test-padding \
+ 	test-symkey \
++	test-armor \
+ 	test-openssl \
+ 	test-dh
+ 
+diff --git a/egg/tests/test-armor.c b/egg/tests/test-armor.c
+new file mode 100644
+index 0000000..d5a366b
+--- a/dev/null
++++ b/egg/tests/test-armor.c
+@@ -0,0 +1,155 @@
++/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
++/* test-armor.c: Test PEM and Armor parsing
++
++   Copyright (C) 2012 Red Hat Inc.
++
++   The Gnome Keyring Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Library General Public License as
++   published by the Free Software Foundation; either version 2 of the
++   License, or (at your option) any later version.
++
++   The Gnome Keyring 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
++   Library General Public License for more details.
++
++   You should have received a copy of the GNU Library General Public
++   License along with the Gnome Library; see the file COPYING.LIB.  If not,
++   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.
++
++   Author: Stef Walter <stefw at gnome.org>
++*/
++
++#include "config.h"
++
++#include "egg/egg-armor.h"
++#include "egg/egg-symkey.h"
++#include "egg/egg-openssl.h"
++#include "egg/egg-secure-memory.h"
++#include "egg/egg-testing.h"
++
++#include <glib.h>
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <unistd.h>
++
++EGG_SECURE_DEFINE_GLIB_GLOBALS ();
++
++static void
++on_pem_get_contents (GQuark type,
++                     GBytes *data,
++                     GBytes *outer,
++                     GHashTable *headers,
++                     gpointer user_data)
++{
++	GBytes **contents = user_data;
++
++	g_assert_cmpstr (g_quark_to_string (type), ==, "TEST");
++	g_assert (*contents == NULL);
++	*contents = g_bytes_ref (data);
++}
++
++
++static void
++test_armor_parse (void)
++{
++	const char *pem_data = "-----BEGIN TEST-----\n"
++	                       "Z29vZCBtb3JuaW5nIGV2ZXJ5b25lCg==\n"
++	                       "-----END TEST-----\n";
++
++	GBytes *contents = NULL;
++	GBytes *check;
++	GBytes *bytes;
++	guint num;
++
++	bytes = g_bytes_new_static (pem_data, strlen (pem_data));
++
++	num = egg_armor_parse (bytes, on_pem_get_contents, &contents);
++	g_assert_cmpint (num, ==, 1);
++	g_assert (contents != NULL);
++
++	check = g_bytes_new ("good morning everyone\n", 22);
++	g_assert (g_bytes_equal (check, contents));
++
++	g_bytes_unref (check);
++	g_bytes_unref (contents);
++	g_bytes_unref (bytes);
++}
++
++static void
++test_armor_skip_checksum (void)
++{
++	const char *pem_data = "-----BEGIN TEST-----\n"
++	                       "Z29vZCBtb3JuaW5nIGV2ZXJ5b25lCg==\n"
++	                       "=checksum"
++	                       "-----END TEST-----\n";
++
++	GBytes *contents = NULL;
++	GBytes *check;
++	GBytes *bytes;
++	guint num;
++
++	/* Check that the (above invalid) OpenPGP checksum is skipped */
++
++	bytes = g_bytes_new_static (pem_data, strlen (pem_data));
++
++	num = egg_armor_parse (bytes, on_pem_get_contents, &contents);
++	g_assert_cmpint (num, ==, 1);
++	g_assert (contents != NULL);
++
++	check = g_bytes_new ("good morning everyone\n", 22);
++	g_assert (g_bytes_equal (check, contents));
++
++	g_bytes_unref (check);
++	g_bytes_unref (contents);
++	g_bytes_unref (bytes);
++}
++
++static void
++test_invalid (gconstpointer data)
++{
++	GBytes *bytes;
++	guint num;
++
++	/* Invalid opening line above */
++
++	bytes = g_bytes_new_static (data, strlen (data));
++
++	num = egg_armor_parse (bytes, NULL, NULL);
++	g_assert_cmpint (num, ==, 0);
++
++	g_bytes_unref (bytes);
++}
++
++int
++main (int argc, char **argv)
++{
++	g_test_init (&argc, &argv, NULL);
++
++	g_test_add_func ("/armor/parse", test_armor_parse);
++	g_test_add_func ("/armor/skip-checksum", test_armor_skip_checksum);
++
++	g_test_add_data_func ("/armor/invalid-start",
++	                      "-----BEGIN TEST--",
++	                      test_invalid);
++	g_test_add_data_func ("/armor/invalid-end",
++	                      "-----BEGIN TEST-----\n"
++	                      "Z29vZCBtb3JuaW5nIGV2ZXJ5b25lCg==\n"
++	                      "--END TEST-----\n",
++	                      test_invalid);
++	g_test_add_data_func ("/armor/invalid-mismatch",
++	                      "-----BEGIN TEST-----\n"
++	                      "Z29vZCBtb3JuaW5nIGV2ZXJ5b25lCg==\n"
++	                      "-----END CERTIFICATE-----\n",
++	                      test_invalid);
++	g_test_add_data_func ("/armor/invalid-suffix",
++	                      "-----BEGIN TEST-----\n"
++	                      "Z29vZCBtb3JuaW5nIGV2ZXJ5b25lCg==\n"
++	                      "-----END TEST--\n",
++	                      test_invalid);
++
++	return g_test_run ();
++}
+--
+cgit v0.9.0.2
diff --git a/gcr-3.7.2-egg-armor-memrchr-truncated.patch b/gcr-3.7.2-egg-armor-memrchr-truncated.patch
new file mode 100644
index 0000000..5188d45
--- /dev/null
+++ b/gcr-3.7.2-egg-armor-memrchr-truncated.patch
@@ -0,0 +1,40 @@
+From 61de15c7c7fe50d075ee77b2c9c4ce7c6284ce12 Mon Sep 17 00:00:00 2001
+From: Stef Walter <stefw at gnome.org>
+Date: Fri, 11 Jan 2013 20:48:23 +0000
+Subject: egg-armor: Handle mismatched but not truncated suffix line
+
+ * Discovered by Gustavo Luiz Duarte <gustavold at linux.vnet.ibm.com>
+
+https://bugzilla.gnome.org/show_bug.cgi?id=691505
+---
+diff --git a/egg/egg-armor.c b/egg/egg-armor.c
+index dd213d0..02e7646 100644
+--- a/egg/egg-armor.c
++++ b/egg/egg-armor.c
+@@ -173,7 +173,7 @@ armor_find_end (const gchar *data,
+ 	at += n_type;
+ 
+ 	/* Next comes the suffix */
+-	if (ARMOR_SUFF_L > len && strncmp ((gchar*)at, ARMOR_SUFF, ARMOR_SUFF_L) != 0)
++	if (ARMOR_SUFF_L > len || strncmp ((gchar *)at, ARMOR_SUFF, ARMOR_SUFF_L) != 0)
+ 		return NULL;
+ 
+ 	/*
+diff --git a/egg/tests/test-armor.c b/egg/tests/test-armor.c
+index d5a366b..7435a10 100644
+--- a/egg/tests/test-armor.c
++++ b/egg/tests/test-armor.c
+@@ -148,6 +148,11 @@ main (int argc, char **argv)
+ 	g_test_add_data_func ("/armor/invalid-suffix",
+ 	                      "-----BEGIN TEST-----\n"
+ 	                      "Z29vZCBtb3JuaW5nIGV2ZXJ5b25lCg==\n"
++	                      "-----END TEST--xxxxxxxx\n",
++	                      test_invalid);
++	g_test_add_data_func ("/armor/invalid-truncated",
++	                      "-----BEGIN TEST-----\n"
++	                      "Z29vZCBtb3JuaW5nIGV2ZXJ5b25lCg==\n"
+ 	                      "-----END TEST--\n",
+ 	                      test_invalid);
+ 
+--
+cgit v0.9.0.2
diff --git a/gcr.spec b/gcr.spec
index 61819c6..fbff9b2 100644
--- a/gcr.spec
+++ b/gcr.spec
@@ -1,6 +1,6 @@
 Name:           gcr
 Version:        3.7.2
-Release:        1%{?dist}
+Release:        2%{?dist}
 Summary:        A library for bits of crypto UI and parsing
 
 Group:          Development/Libraries
@@ -8,6 +8,11 @@ License:        LGPLv2+
 URL:            http://live.gnome.org/CryptoGlue/
 Source0:        http://download.gnome.org/sources/gcr/3.7/gcr-%{version}.tar.xz
 
+# https://bugzilla.redhat.com/show_bug.cgi?id=894157
+# gnome-keyring coredumps while parsing certificate
+Patch1: gcr-3.7.2-egg-armor-memrchr-negative.patch
+Patch2: gcr-3.7.2-egg-armor-memrchr-truncated.patch
+
 BuildRequires:  desktop-file-utils
 BuildRequires:  intltool
 BuildRequires:  glib2-devel
@@ -41,6 +46,9 @@ The gcr-devel package includes the header files for the gcr library.
 %prep
 %setup -q
 
+%patch1 -p1 -b .egg-armor-memrchr-negative
+%patch2 -p1 -b .egg-armor-memrchr-truncated
+
 %build
 %configure --enable-introspection
 make %{?_smp_mflags}
@@ -117,6 +125,9 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas >&/dev/null || :
 
 
 %changelog
+* Mon Jan 14 2013 Tomas Bzatek <tbzatek at redhat.com> - 3.7.2-2
+- Fix crash on parsing some certificates (#894157)
+
 * Wed Jan 09 2013 Richard Hughes <hughsient at gmail.com> - 3.7.2-1
 - Update to 3.7.2
 


More information about the scm-commits mailing list