[libxml-libxml-perl] 01/03: CVE-2017-10672: Use-after-free by controlling the arguments to a replaceChild call
Salvatore Bonaccorso
carnil at debian.org
Thu Aug 3 20:09:51 UTC 2017
This is an automated email from the git hooks/post-receive script.
carnil pushed a commit to branch master
in repository libxml-libxml-perl.
commit 0700a409b364370343bb6aff1a1ad91e11de973e
Author: Salvatore Bonaccorso <carnil at debian.org>
Date: Wed Aug 2 21:28:13 2017 +0200
CVE-2017-10672: Use-after-free by controlling the arguments to a replaceChild call
Closes: #866676
---
debian/patches/CVE-2017-10672.patch | 227 ++++++++++++++++++++++++++++++++++++
debian/patches/series | 1 +
2 files changed, 228 insertions(+)
diff --git a/debian/patches/CVE-2017-10672.patch b/debian/patches/CVE-2017-10672.patch
new file mode 100644
index 0000000..d747c7e
--- /dev/null
+++ b/debian/patches/CVE-2017-10672.patch
@@ -0,0 +1,227 @@
+From: Torsten Lüttgert <torsten.luettgert at thinkproject.com>
+Date: Mon, 31 Jul 2017 15:38:17 +0200
+Subject: fix CVE-2017-10672, found by tadinhsung at gmail.com
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-10672
+Bug-Debian: https://bugs.debian.org/866676
+Bug-SuSE: https://bugzilla.novell.com/show_bug.cgi?id=1046848
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1470204
+
+and add a test.
+---
+ LibXML.xs | 108 +++++++++++++++++++++++++++------------------------
+ MANIFEST | 1 +
+ t/92CVE-2017-10672.t | 61 +++++++++++++++++++++++++++++
+ 3 files changed, 120 insertions(+), 50 deletions(-)
+ create mode 100644 t/92CVE-2017-10672.t
+
+diff --git a/LibXML.xs b/LibXML.xs
+index ad415c8..eaf48af 100644
+--- a/LibXML.xs
++++ b/LibXML.xs
+@@ -4829,38 +4829,42 @@ replaceChild( self, nNode, oNode )
+ PREINIT:
+ xmlNodePtr ret = NULL;
+ CODE:
+- if ( self->type == XML_DOCUMENT_NODE ) {
++ if( nNode == oNode ) {
++ RETVAL = nNode;
++ }else{
++ if ( self->type == XML_DOCUMENT_NODE ) {
+ switch ( nNode->type ) {
+- case XML_ELEMENT_NODE:
+- warn("replaceChild with an element on a document node not supported yet!");
+- XSRETURN_UNDEF;
+- break;
+- case XML_DOCUMENT_FRAG_NODE:
+- warn("replaceChild with a document fragment node on a document node not supported yet!");
+- XSRETURN_UNDEF;
+- break;
+- case XML_TEXT_NODE:
+- case XML_CDATA_SECTION_NODE:
+- warn("replaceChild with a text node not supported on a document node!");
+- XSRETURN_UNDEF;
+- break;
+- default:
+- break;
++ case XML_ELEMENT_NODE:
++ warn("replaceChild with an element on a document node not supported yet!");
++ XSRETURN_UNDEF;
++ break;
++ case XML_DOCUMENT_FRAG_NODE:
++ warn("replaceChild with a document fragment node on a document node not supported yet!");
++ XSRETURN_UNDEF;
++ break;
++ case XML_TEXT_NODE:
++ case XML_CDATA_SECTION_NODE:
++ warn("replaceChild with a text node not supported on a document node!");
++ XSRETURN_UNDEF;
++ break;
++ default:
++ break;
+ }
+- }
+- ret = domReplaceChild( self, nNode, oNode );
+- if (ret == NULL) {
+- XSRETURN_UNDEF;
+- }
+- else {
+- LibXML_reparent_removed_node(ret);
+- RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
+- if (nNode->type == XML_DTD_NODE) {
+- LibXML_set_int_subset(nNode->doc, nNode);
+ }
+- if ( nNode->_private != NULL ) {
+- PmmFixOwner( PmmPROXYNODE(nNode),
+- PmmOWNERPO(PmmPROXYNODE(self)) );
++ ret = domReplaceChild( self, nNode, oNode );
++ if (ret == NULL) {
++ XSRETURN_UNDEF;
++ }
++ else {
++ LibXML_reparent_removed_node(ret);
++ RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
++ if (nNode->type == XML_DTD_NODE) {
++ LibXML_set_int_subset(nNode->doc, nNode);
++ }
++ if ( nNode->_private != NULL ) {
++ PmmFixOwner( PmmPROXYNODE(nNode),
++ PmmOWNERPO(PmmPROXYNODE(self)) );
++ }
+ }
+ }
+ OUTPUT:
+@@ -4874,30 +4878,34 @@ replaceNode( self,nNode )
+ xmlNodePtr ret = NULL;
+ ProxyNodePtr owner = NULL;
+ CODE:
+- if ( domIsParent( self, nNode ) == 1 ) {
+- XSRETURN_UNDEF;
+- }
+- owner = PmmOWNERPO(PmmPROXYNODE(self));
++ if( self == nNode ) {
++ RETVAL = nNode;
++ }else{
++ if ( domIsParent( self, nNode ) == 1 ) {
++ XSRETURN_UNDEF;
++ }
++ owner = PmmOWNERPO(PmmPROXYNODE(self));
+
+- if ( self->type != XML_ATTRIBUTE_NODE ) {
+- ret = domReplaceChild( self->parent, nNode, self);
+- }
+- else {
+- ret = xmlReplaceNode( self, nNode );
+- }
+- if ( ret ) {
+- LibXML_reparent_removed_node(ret);
+- RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
+- if (nNode->type == XML_DTD_NODE) {
+- LibXML_set_int_subset(nNode->doc, nNode);
++ if ( self->type != XML_ATTRIBUTE_NODE ) {
++ ret = domReplaceChild( self->parent, nNode, self);
+ }
+- if ( nNode->_private != NULL ) {
+- PmmFixOwner(PmmPROXYNODE(nNode), owner);
++ else {
++ ret = xmlReplaceNode( self, nNode );
++ }
++ if ( ret ) {
++ LibXML_reparent_removed_node(ret);
++ RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
++ if (nNode->type == XML_DTD_NODE) {
++ LibXML_set_int_subset(nNode->doc, nNode);
++ }
++ if ( nNode->_private != NULL ) {
++ PmmFixOwner(PmmPROXYNODE(nNode), owner);
++ }
++ }
++ else {
++ croak( "replacement failed" );
++ XSRETURN_UNDEF;
+ }
+- }
+- else {
+- croak( "replacement failed" );
+- XSRETURN_UNDEF;
+ }
+ OUTPUT:
+ RETVAL
+diff --git a/MANIFEST b/MANIFEST
+index 72fc36f..98efe6c 100644
+--- a/MANIFEST
++++ b/MANIFEST
+@@ -183,6 +183,7 @@ t/90shared_clone_failed_rt_91800.t
+ t/90stack.t
+ t/90threads.t
+ t/91unique_key.t
++t/92CVE-2017-10672.t
+ t/cpan-changes.t
+ t/data/callbacks_returning_undef.xml
+ t/data/chinese.xml
+diff --git a/t/92CVE-2017-10672.t b/t/92CVE-2017-10672.t
+new file mode 100644
+index 0000000..aa7bbef
+--- /dev/null
++++ b/t/92CVE-2017-10672.t
+@@ -0,0 +1,61 @@
++# -*- cperl -*-
++# $Id$
++
++##
++# This test checks if replacing a node with itself
++# leads to use-after-free condition.
++# The bug was found and demonstrated by tadinhsung at gmail.com
++# and fixed by t.luettgert at gmail.com
++
++use Test::More tests => 1;
++use utf8;
++
++use XML::LibXML;
++use strict;
++
++binmode STDOUT, ":utf8";
++use open ':encoding(utf8)';
++BEGIN { $| = 1 }
++my $data='<mipu94><pwn4fun><ufanode>-------------------------------------------------------tadinhsung-at-gmail-dot-com-----------------------------------------------------</ufanode></pwn4fun></mipu94>';
++
++my $x;
++my $alive = 1;
++my $parser = XML::LibXML->new();
++my $info = $parser->load_xml(string=>$data) or die;
++my $root = $info->findnodes("mipu94")->[0];
++my $ufanode = $root->findnodes("pwn4fun/ufanode")->[0];
++$root->replaceChild($ufanode,$ufanode); # triggle free ufanode
++my $k =$root->toString;
++print $k;
++Encode::_utf8_off($k); # need off utf8 to get wide characters
++$x=index($k,"\xff\x7f");
++my $heapoff=substr($k,18,3)."\x00";
++my $libcoff=substr($k,$x-4,6)."\x00\x00";
++
++my $heap = unpack("I",$heapoff);
++my $libc = unpack("Q",$libcoff);
++my $tmp = 0xfffffffff000;
++$libc = $libc & $tmp;
++
++print sprintf("heap: 0x%x\n",$heap);
++print sprintf("libc: 0x%x\n",$libc);
++my $payload=pack("Q", 0x0).
++pack("Q",0x4141414142424242)x11;
++#try malloc again and refill to create fake ufanode
++my $fill="$payload";
++my $fill1="$payload";
++my $fill2="$payload";
++my $fill3="$payload";
++my $fill4="$payload";
++my $fill5="$payload";
++#
++my $fakenode=$root->lastChild->lastChild;
++print "i'm still ok and go more far!\n";
++
++# TEST
++is(
++ $alive,
++ 1,
++ "crash after replacing a node with itself"
++);
++
diff --git a/debian/patches/series b/debian/patches/series
index c15e2c3..d6ec529 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,3 @@
fail-build-no-libxml2.patch
disable_runtime-version_warning.patch
+CVE-2017-10672.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libxml-libxml-perl.git
More information about the Pkg-perl-cvs-commits
mailing list