[openjk] 01/01: Add patch adapted from ioquake3 to avoid a read buffer overflow in MSG_ReadBits (CVE-2017-11721), and check a buffer boundary more accurately in MSG_WriteBits (believed to be merely a bug, not a vulnerability).

Simon McVittie smcv at debian.org
Thu Aug 10 16:51:28 UTC 2017


This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to branch debian/master
in repository openjk.

commit 41abc9577a72af8dbb6779cdedffa696e5d2da18
Author: Simon McVittie <smcv at debian.org>
Date:   Sat Aug 5 12:26:02 2017 +0100

    Add patch adapted from ioquake3 to avoid a read buffer overflow in MSG_ReadBits (CVE-2017-11721), and check a buffer boundary more accurately in MSG_WriteBits (believed to be merely a bug, not a vulnerability).
---
 debian/changelog                                   |   9 +
 ...er-overflow-in-MSG_ReadBits-MSG_WriteBits.patch | 214 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 3 files changed, 224 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index a4c1049..9674fa7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+openjk (0~20170718+dfsg1-2) experimental; urgency=medium
+
+  * Add patch adapted from ioquake3 to avoid a read buffer overflow
+    in MSG_ReadBits (CVE-2017-11721), and check a buffer boundary
+    more accurately in MSG_WriteBits (believed to be merely a bug, not
+    a vulnerability).
+
+ -- Simon McVittie <smcv at debian.org>  Sat, 05 Aug 2017 12:25:55 +0100
+
 openjk (0~20170718+dfsg1-1) experimental; urgency=medium
 
   * New upstream snapshot
diff --git a/debian/patches/Fix-improve-buffer-overflow-in-MSG_ReadBits-MSG_WriteBits.patch b/debian/patches/Fix-improve-buffer-overflow-in-MSG_ReadBits-MSG_WriteBits.patch
new file mode 100644
index 0000000..b9740a7
--- /dev/null
+++ b/debian/patches/Fix-improve-buffer-overflow-in-MSG_ReadBits-MSG_WriteBits.patch
@@ -0,0 +1,214 @@
+From: Zack Middleton <zack at cloemail.com>
+Date: Wed, 2 Aug 2017 14:55:10 -0500
+Subject: Fix/improve buffer overflow in MSG_ReadBits/MSG_WriteBits
+
+Prevent reading past end of message in MSG_ReadBits. If read past
+end of msg->data buffer (16348 bytes) the engine could SEGFAULT.
+Make MSG_WriteBits use an exact buffer overflow check instead of
+possibly failing with a few bytes left.
+
+[smcv: Adapt for OpenJK]
+---
+ codemp/qcommon/huffman.cpp | 27 ++++++++++++++++++---------
+ codemp/qcommon/msg.cpp     | 41 ++++++++++++++++++++++++++++++++++++-----
+ codemp/qcommon/qcommon.h   |  6 +++---
+ 3 files changed, 57 insertions(+), 17 deletions(-)
+
+diff --git a/codemp/qcommon/huffman.cpp b/codemp/qcommon/huffman.cpp
+index a08e5fa..9745a99 100644
+--- a/codemp/qcommon/huffman.cpp
++++ b/codemp/qcommon/huffman.cpp
+@@ -269,9 +269,14 @@ int Huff_Receive (node_t *node, int *ch, byte *fin) {
+ }
+ 
+ /* Get a symbol */
+-void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
++void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset, int maxoffset) {
+ 	bloc = *offset;
+ 	while (node && node->symbol == INTERNAL_NODE) {
++		if (bloc >= maxoffset) {
++			*ch = 0;
++			*offset = maxoffset + 1;
++			return;
++		}
+ 		if (get_bit(fin)) {
+ 			node = node->right;
+ 		} else {
+@@ -288,11 +293,15 @@ void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
+ }
+ 
+ /* Send the prefix code for this node */
+-static void send(node_t *node, node_t *child, byte *fout) {
++static void send(node_t *node, node_t *child, byte *fout, int maxoffset) {
+ 	if (node->parent) {
+-		send(node->parent, node, fout);
++		send(node->parent, node, fout, maxoffset);
+ 	}
+ 	if (child) {
++		if (bloc >= maxoffset) {
++			bloc = maxoffset + 1;
++			return;
++		}
+ 		if (node->right == child) {
+ 			add_bit(1, fout);
+ 		} else {
+@@ -302,22 +311,22 @@ static void send(node_t *node, node_t *child, byte *fout) {
+ }
+ 
+ /* Send a symbol */
+-void Huff_transmit (huff_t *huff, int ch, byte *fout) {
++void Huff_transmit (huff_t *huff, int ch, byte *fout, int maxoffset) {
+ 	int i;
+ 	if (huff->loc[ch] == NULL) {
+ 		/* node_t hasn't been transmitted, send a NYT, then the symbol */
+-		Huff_transmit(huff, NYT, fout);
++		Huff_transmit(huff, NYT, fout, maxoffset);
+ 		for (i = 7; i >= 0; i--) {
+ 			add_bit((char)((ch >> i) & 0x1), fout);
+ 		}
+ 	} else {
+-		send(huff->loc[ch], NULL, fout);
++		send(huff->loc[ch], NULL, fout, maxoffset);
+ 	}
+ }
+ 
+-void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset) {
++void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset, int maxoffset) {
+ 	bloc = *offset;
+-	send(huff->loc[ch], NULL, fout);
++	send(huff->loc[ch], NULL, fout, maxoffset);
+ 	*offset = bloc;
+ }
+ 
+@@ -404,7 +413,7 @@ void Huff_Compress(msg_t *mbuf, int offset) {
+ 
+ 	for (i=0; i<size; i++ ) {
+ 		ch = buffer[i];
+-		Huff_transmit(&huff, ch, seq);						/* Transmit symbol */
++		Huff_transmit(&huff, ch, seq, size<<3);						/* Transmit symbol */
+ 		Huff_addRef(&huff, (byte)ch);								/* Do update */
+ 	}
+ 
+diff --git a/codemp/qcommon/msg.cpp b/codemp/qcommon/msg.cpp
+index ac178d3..79d511e 100644
+--- a/codemp/qcommon/msg.cpp
++++ b/codemp/qcommon/msg.cpp
+@@ -139,9 +139,7 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
+ 
+ 	oldsize += bits;
+ 
+-	// this isn't an exact overflow check, but close enough
+-	if ( msg->maxsize - msg->cursize < 4 ) {
+-		msg->overflowed = qtrue;
++	if ( msg->overflowed ) {
+ 		return;
+ 	}
+ 
+@@ -175,6 +173,11 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
+ 		bits = -bits;
+ 	}
+ 	if (msg->oob) {
++		if ( msg->cursize + ( bits >> 3 ) > msg->maxsize ) {
++			msg->overflowed = qtrue;
++			return;
++		}
++
+ 		if (bits==8) {
+ 			msg->data[msg->cursize] = value;
+ 			msg->cursize += 1;
+@@ -197,6 +200,10 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
+ 		if (bits&7) {
+ 			int nbits;
+ 			nbits = bits&7;
++			if ( msg->bit + nbits > msg->maxsize << 3 ) {
++				msg->overflowed = qtrue;
++				return;
++			}
+ 			for(i=0;i<nbits;i++) {
+ 				Huff_putBit((value&1), msg->data, &msg->bit);
+ 				value = (value>>1);
+@@ -208,8 +215,13 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
+ #ifdef _NEWHUFFTABLE_
+ 				fwrite(&value, 1, 1, fp);
+ #endif // _NEWHUFFTABLE_
+-				Huff_offsetTransmit (&msgHuff.compressor, (value&0xff), msg->data, &msg->bit);
++				Huff_offsetTransmit (&msgHuff.compressor, (value&0xff), msg->data, &msg->bit, msg->maxsize << 3);
+ 				value = (value>>8);
++
++				if ( msg->bit > msg->maxsize << 3 ) {
++					msg->overflowed = qtrue;
++					return;
++				}
+ 			}
+ 		}
+ 		msg->cursize = (msg->bit>>3)+1;
+@@ -221,6 +233,11 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
+ 	int			get;
+ 	qboolean	sgn;
+ 	int			i, nbits;
++
++	if ( msg->readcount > msg->cursize ) {
++		return 0;
++	}
++
+ 	value = 0;
+ 
+ 	if ( bits < 0 ) {
+@@ -231,6 +248,11 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
+ 	}
+ 
+ 	if (msg->oob) {
++		if (msg->readcount + (bits>>3) > msg->cursize) {
++			msg->readcount = msg->cursize + 1;
++			return 0;
++		}
++
+ 		if (bits==8) {
+ 			value = msg->data[msg->readcount];
+ 			msg->readcount += 1;
+@@ -253,6 +275,10 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
+ 		nbits = 0;
+ 		if (bits&7) {
+ 			nbits = bits&7;
++			if (msg->bit + nbits > msg->cursize << 3) {
++				msg->readcount = msg->cursize + 1;
++				return 0;
++			}
+ 			for(i=0;i<nbits;i++) {
+ 				value |= (Huff_getBit(msg->data, &msg->bit)<<i);
+ 			}
+@@ -260,11 +286,16 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
+ 		}
+ 		if (bits) {
+ 			for(i=0;i<bits;i+=8) {
+-				Huff_offsetReceive (msgHuff.decompressor.tree, &get, msg->data, &msg->bit);
++				Huff_offsetReceive (msgHuff.decompressor.tree, &get, msg->data, &msg->bit, msg->cursize<<3);
+ #ifdef _NEWHUFFTABLE_
+ 				fwrite(&get, 1, 1, fp);
+ #endif // _NEWHUFFTABLE_
+ 				value |= (get<<(i+nbits));
++
++				if (msg->bit > msg->cursize<<3) {
++					msg->readcount = msg->cursize + 1;
++					return 0;
++				}
+ 			}
+ 		}
+ 		msg->readcount = (msg->bit>>3)+1;
+diff --git a/codemp/qcommon/qcommon.h b/codemp/qcommon/qcommon.h
+index d7c09ab..9c64c95 100644
+--- a/codemp/qcommon/qcommon.h
++++ b/codemp/qcommon/qcommon.h
+@@ -1033,9 +1033,9 @@ void	Huff_Decompress(msg_t *buf, int offset);
+ void	Huff_Init(huffman_t *huff);
+ void	Huff_addRef(huff_t* huff, byte ch);
+ int		Huff_Receive (node_t *node, int *ch, byte *fin);
+-void	Huff_transmit (huff_t *huff, int ch, byte *fout);
+-void	Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset);
+-void	Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset);
++void	Huff_transmit (huff_t *huff, int ch, byte *fout, int maxoffset);
++void	Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset, int maxoffset);
++void	Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset, int maxoffset);
+ void	Huff_putBit( int bit, byte *fout, int *offset);
+ int		Huff_getBit( byte *fout, int *offset);
+ 
diff --git a/debian/patches/series b/debian/patches/series
index e0f7a6b..0fdb9b6 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
+Fix-improve-buffer-overflow-in-MSG_ReadBits-MSG_WriteBits.patch
 g_utils-disarm-debug-code-that-writes-to-c-nofreeent.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/openjk.git



More information about the Pkg-games-commits mailing list