The following commit has been merged in the debian branch:
commit c3398ced4dd60c63538b28fa8981f094482047f1
Author: Simon McVittie <[email protected]>
Date:   Sun Feb 19 14:19:18 2012 +0000

    Backport patches from ioquake3 to fix long-standing security bugs
    
      - CVE-2006-2082: arbitrary file download from server by a malicious client
      - CVE-2006-2236 ("the remapShader exploit"): missing bounds-checking on
        COM_StripExtension, exploitable in clients of a malicious server
      - CVE-2006-2875 ("q3cbof"): buffer overflow in CL_ParseDownload by a
        malicious server
      - CVE-2006-3324: arbitrary file overwriting in clients of a malicious
        server
      - CVE-2006-3325: arbitrary cvar overwriting (could lead to arbitrary
        code execution) in clients of a malicious server
      - CVE-2011-3012, CVE-2011-2764: DLL overwriting (leading to arbitrary
        code execution) in clients of a malicious server if auto-downloading
        is enabled

diff --git a/debian/changelog b/debian/changelog
index e2f2c24..8413f29 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,21 @@
+tremulous (1.1.0-6) UNRELEASED; urgency=medium
+
+  * Backport patches from ioquake3 to fix long-standing security bugs:
+    - CVE-2006-2082: arbitrary file download from server by a malicious client
+    - CVE-2006-2236 ("the remapShader exploit"): missing bounds-checking on
+      COM_StripExtension, exploitable in clients of a malicious server
+    - CVE-2006-2875 ("q3cbof"): buffer overflow in CL_ParseDownload by a
+      malicious server
+    - CVE-2006-3324: arbitrary file overwriting in clients of a malicious
+      server
+    - CVE-2006-3325: arbitrary cvar overwriting (could lead to arbitrary
+      code execution) in clients of a malicious server
+    - CVE-2011-3012, CVE-2011-2764: DLL overwriting (leading to arbitrary
+      code execution) in clients of a malicious server if auto-downloading
+      is enabled
+
+ -- Simon McVittie <[email protected]>  Sun, 11 Dec 2011 17:35:38 +0000
+
 tremulous (1.1.0-5) unstable; urgency=low
 
   * New maintainer - Debian Games Team
diff --git 
a/debian/patches/0010-CVE-2006-2082-do-not-allow-download-of-arbitrary-fil.patch
 
b/debian/patches/0010-CVE-2006-2082-do-not-allow-download-of-arbitrary-fil.patch
new file mode 100644
index 0000000..a41f689
--- /dev/null
+++ 
b/debian/patches/0010-CVE-2006-2082-do-not-allow-download-of-arbitrary-fil.patch
@@ -0,0 +1,97 @@
+From: Simon McVittie <[email protected]>
+Date: Sat, 18 Feb 2012 20:33:51 +0000
+Subject: CVE-2006-2082 - do not allow download of arbitrary files from a
+ server
+
+Any file readable by the server user could be read, via ../ sequences.
+
+Original patches by Thilo Schulz, ioquake3 r777 (which fixed the
+vulnerability) and r781 (which fixed a regression in r777 where
+uninitialized variables led to some allowed downloads being rejected too).
+
+Origin: backport
+Bug-CVE: http://security-tracker.debian.org/tracker/CVE-2006-2082
+---
+ src/server/sv_client.c |   51 ++++++++++++++++++++++++++++++++++++++++-------
+ 1 files changed, 43 insertions(+), 8 deletions(-)
+
+diff --git a/src/server/sv_client.c b/src/server/sv_client.c
+index 0272fab..53f5998 100644
+--- a/src/server/sv_client.c
++++ b/src/server/sv_client.c
+@@ -618,24 +618,57 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg 
)
+       int curindex;
+       int rate;
+       int blockspersnap;
+-      int idPack, missionPack;
++      int idPack = 0, missionPack = 0, unreferenced = 1;
+       char errorMessage[1024];
++      char pakbuf[MAX_QPATH], *pakptr;
++      int numRefPaks;
+ 
+       if (!*cl->downloadName)
+               return; // Nothing being downloaded
+ 
+       if (!cl->download) {
+-              // We open the file here
++              // Chop off filename extension.
++              Com_sprintf(pakbuf, sizeof(pakbuf), "%s", cl->downloadName);
++              pakptr = Q_strrchr(pakbuf, '.');
+ 
+-              Com_Printf( "clientDownload: %d : begining \"%s\"\n", cl - 
svs.clients, cl->downloadName );
++              if (pakptr)
++              {
++                      *pakptr = '\0';
+ 
+-              missionPack = FS_idPak(cl->downloadName, "missionpack");
+-              idPack = missionPack || FS_idPak(cl->downloadName, "baseq3");
++                      // Check for pk3 filename extension
++                      if(!Q_stricmp(pakptr + 1, "pk3"))
++                      {
++                              const char *referencedPaks = 
FS_ReferencedPakNames();
++
++                              // Check whether the file appears in the list 
of referenced
++                              // paks to prevent downloading of arbitrary 
files
++                              Cmd_TokenizeStringIgnoreQuotes(referencedPaks);
++                              numRefPaks = Cmd_Argc();
++
++                              for(curindex = 0; curindex < numRefPaks; 
curindex++)
++                              {
++                                      
if(!FS_FilenameCompare(Cmd_Argv(curindex), pakbuf))
++                                      {
++                                              unreferenced = 0;
++                                              // now that we know the file is 
referenced, check whether it's legal to download it.
++                                              missionPack = FS_idPak(pakbuf, 
"missionpack");
++                                              idPack = missionPack || 
FS_idPak(pakbuf, BASEGAME);
++                                              break;
++                                      }
++                              }
++                      }
++              }
+ 
+-              if ( !sv_allowDownload->integer || idPack ||
++              // We open the file here
++              if ( !sv_allowDownload->integer || idPack || unreferenced ||
+                       ( cl->downloadSize = FS_SV_FOpenFileRead( 
cl->downloadName, &cl->download ) ) <= 0 ) {
+                       // cannot auto-download file
+-                      if (idPack) {
++                      if(unreferenced)
++                      {
++                              Com_Printf("clientDownload: %d : \"%s\" is not 
referenced and cannot be downloaded.\n", cl - svs.clients, cl->downloadName);
++                              Com_sprintf(errorMessage, sizeof(errorMessage), 
"File \"%s\" is not referenced and cannot be downloaded.", cl->downloadName);
++                      }
++                      else if (idPack) {
+                               Com_Printf("clientDownload: %d : \"%s\" cannot 
download id pk3 files\n", cl - svs.clients, cl->downloadName);
+                               if (missionPack) {
+                                       Com_sprintf(errorMessage, 
sizeof(errorMessage), "Cannot autodownload Team Arena file \"%s\"\n"
+@@ -670,7 +703,9 @@ void SV_WriteDownloadToClient( client_t *cl , msg_t *msg )
+                       *cl->downloadName = 0;
+                       return;
+               }
+- 
++
++              Com_Printf( "clientDownload: %d : beginning \"%s\"\n", cl - 
svs.clients, cl->downloadName );
++              
+               // Init
+               cl->downloadCurrentBlock = cl->downloadClientBlock = 
cl->downloadXmitBlock = 0;
+               cl->downloadCount = 0;
diff --git 
a/debian/patches/0011-CVE-2006-2236-add-bounds-checking-to-COM_StripExtens.patch
 
b/debian/patches/0011-CVE-2006-2236-add-bounds-checking-to-COM_StripExtens.patch
new file mode 100644
index 0000000..0819d5f
--- /dev/null
+++ 
b/debian/patches/0011-CVE-2006-2236-add-bounds-checking-to-COM_StripExtens.patch
@@ -0,0 +1,197 @@
+From: Simon McVittie <[email protected]>
+Date: Fri, 18 Nov 2011 18:44:44 +0000
+Subject: CVE-2006-2236 - add bounds-checking to COM_StripExtension
+
+This fixes the "remapShader" exploit by backporting ioquake3 r765, with
+a further change to avoid strncpy'ing a string into itself.
+Original patch by Thilo Schulz.
+
+Origin: backport
+Bug-CVE: http://security-tracker.debian.org/tracker/CVE-2006-2236
+Bug-Fedora: https://bugzilla.redhat.com/show_bug.cgi?id=455458
+---
+ src/cgame/cg_weapons.c   |    6 +++---
+ src/client/cl_main.c     |    2 +-
+ src/qcommon/files.c      |    2 +-
+ src/qcommon/q_shared.c   |    6 ++++--
+ src/qcommon/q_shared.h   |    2 +-
+ src/qcommon/vm.c         |    2 +-
+ src/renderer/tr_bsp.c    |    2 +-
+ src/renderer/tr_shader.c |    6 +++---
+ src/ui/ui_main.c         |    2 +-
+ src/ui/ui_players.c      |    4 ++--
+ 10 files changed, 18 insertions(+), 16 deletions(-)
+
+diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
+index ecb2499..87a9b4c 100644
+--- a/src/cgame/cg_weapons.c
++++ b/src/cgame/cg_weapons.c
+@@ -503,17 +503,17 @@ static qboolean CG_ParseWeaponFile( const char 
*filename, weaponInfo_t *wi )
+         CG_Printf( S_COLOR_RED "ERROR: weapon model not found %s\n", token );
+ 
+       strcpy( path, token );
+-      COM_StripExtension( path, path );
++      COM_StripExtension( path, path, sizeof(path) );
+       strcat( path, "_flash.md3" );
+       wi->flashModel = trap_R_RegisterModel( path );
+ 
+       strcpy( path, token );
+-      COM_StripExtension( path, path );
++      COM_StripExtension( path, path, sizeof(path) );
+       strcat( path, "_barrel.md3" );
+       wi->barrelModel = trap_R_RegisterModel( path );
+ 
+       strcpy( path, token );
+-      COM_StripExtension( path, path );
++      COM_StripExtension( path, path, sizeof(path) );
+       strcat( path, "_hand.md3" );
+       wi->handsModel = trap_R_RegisterModel( path );
+ 
+diff --git a/src/client/cl_main.c b/src/client/cl_main.c
+index 3db1d6d..7b562bd 100644
+--- a/src/client/cl_main.c
++++ b/src/client/cl_main.c
+@@ -2014,7 +2014,7 @@ void CL_Frame ( int msec ) {
+                       }
+ 
+                       Q_strncpyz( mapName, COM_SkipPath( cl.mapname ), 
sizeof( cl.mapname ) );
+-                      COM_StripExtension( mapName, mapName );
++                      COM_StripExtension(mapName, mapName, sizeof(mapName));
+ 
+                       Cbuf_ExecuteText( EXEC_NOW,
+                                       va( "record %s-%s-%s", nowString, 
serverName, mapName ) );
+diff --git a/src/qcommon/files.c b/src/qcommon/files.c
+index 84db5b1..67f375c 100644
+--- a/src/qcommon/files.c
++++ b/src/qcommon/files.c
+@@ -3377,7 +3377,7 @@ void     FS_FilenameCompletion( const char *dir, const 
char *ext,
+               Q_strncpyz( filename, filenames[ i ], MAX_STRING_CHARS );
+ 
+               if( stripExt ) {
+-                      COM_StripExtension( filename, filename );
++                      COM_StripExtension(filename, filename, 
sizeof(filename));
+               }
+ 
+               callback( filename );
+diff --git a/src/qcommon/q_shared.c b/src/qcommon/q_shared.c
+index 9f152d6..44085cc 100644
+--- a/src/qcommon/q_shared.c
++++ b/src/qcommon/q_shared.c
+@@ -59,10 +59,12 @@ char *COM_SkipPath (char *pathname)
+ COM_StripExtension
+ ============
+ */
+-void COM_StripExtension( const char *in, char *out ) {
++void COM_StripExtension( const char *in, char *out, int destsize ) {
+       int             length;
+ 
+-      strcpy( out, in );
++      if (in != out) {
++              Q_strncpyz(out, in, destsize);
++      }
+ 
+       length = strlen(out)-1;
+       while (length > 0 && out[length] != '.')
+diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h
+index 0059cdf..03b2e03 100644
+--- a/src/qcommon/q_shared.h
++++ b/src/qcommon/q_shared.h
+@@ -627,7 +627,7 @@ vec_t DistanceBetweenLineSegments(
+ float Com_Clamp( float min, float max, float value );
+ 
+ char  *COM_SkipPath( char *pathname );
+-void  COM_StripExtension( const char *in, char *out );
++void  COM_StripExtension(const char *in, char *out, int destsize);
+ void  COM_DefaultExtension( char *path, int maxSize, const char *extension );
+ 
+ void  COM_BeginParseSession( const char *name );
+diff --git a/src/qcommon/vm.c b/src/qcommon/vm.c
+index 0235ffe..8fb588d 100644
+--- a/src/qcommon/vm.c
++++ b/src/qcommon/vm.c
+@@ -231,7 +231,7 @@ void VM_LoadSymbols( vm_t *vm ) {
+               return;
+       }
+ 
+-      COM_StripExtension( vm->name, name );
++      COM_StripExtension(vm->name, name, sizeof(name));
+       Com_sprintf( symbols, sizeof( symbols ), "vm/%s.map", name );
+       len = FS_ReadFile( symbols, (void **)&mapfile );
+       if ( !mapfile ) {
+diff --git a/src/renderer/tr_bsp.c b/src/renderer/tr_bsp.c
+index eb57da8..2eff834 100644
+--- a/src/renderer/tr_bsp.c
++++ b/src/renderer/tr_bsp.c
+@@ -1824,7 +1824,7 @@ void RE_LoadWorldMap( const char *name ) {
+       Q_strncpyz( s_worldData.name, name, sizeof( s_worldData.name ) );
+ 
+       Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), 
sizeof( s_worldData.name ) );
+-      COM_StripExtension( s_worldData.baseName, s_worldData.baseName );
++      COM_StripExtension(s_worldData.baseName, s_worldData.baseName, 
sizeof(s_worldData.baseName));
+ 
+       startMarker = ri.Hunk_Alloc(0, h_low);
+       c_gridVerts = 0;
+diff --git a/src/renderer/tr_shader.c b/src/renderer/tr_shader.c
+index 380f9bf..c349b15 100644
+--- a/src/renderer/tr_shader.c
++++ b/src/renderer/tr_shader.c
+@@ -96,7 +96,7 @@ void R_RemapShader(const char *shaderName, const char 
*newShaderName, const char
+ 
+       // remap all the shaders with the given name
+       // even tho they might have different lightmaps
+-      COM_StripExtension( shaderName, strippedName );
++      COM_StripExtension(shaderName, strippedName, sizeof(strippedName));
+       hash = generateHashValue(strippedName, FILE_HASH_SIZE);
+       for (sh = hashTable[hash]; sh; sh = sh->next) {
+               if (Q_stricmp(sh->name, strippedName) == 0) {
+@@ -2366,7 +2366,7 @@ shader_t *R_FindShaderByName( const char *name ) {
+               return tr.defaultShader;
+       }
+ 
+-      COM_StripExtension( name, strippedName );
++      COM_StripExtension(name, strippedName, sizeof(strippedName));
+ 
+       hash = generateHashValue(strippedName, FILE_HASH_SIZE);
+ 
+@@ -2434,7 +2434,7 @@ shader_t *R_FindShader( const char *name, int 
lightmapIndex, qboolean mipRawImag
+               lightmapIndex = LIGHTMAP_BY_VERTEX;
+       }
+ 
+-      COM_StripExtension( name, strippedName );
++      COM_StripExtension(name, strippedName, sizeof(strippedName));
+ 
+       hash = generateHashValue(strippedName, FILE_HASH_SIZE);
+ 
+diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c
+index 7509d9b..604e709 100644
+--- a/src/ui/ui_main.c
++++ b/src/ui/ui_main.c
+@@ -5376,7 +5376,7 @@ static void UI_BuildQ3Model_List( void )
+     {
+       filelen = strlen(fileptr);
+ 
+-      COM_StripExtension(fileptr,skinname);
++      COM_StripExtension(fileptr, skinname, sizeof(skinname));
+ 
+       // look for icon_????
+       if (Q_stricmpn(skinname, "icon_", 5) == 0 && 
!(Q_stricmp(skinname,"icon_blue") == 0 || Q_stricmp(skinname,"icon_red") == 0))
+diff --git a/src/ui/ui_players.c b/src/ui/ui_players.c
+index 5dbfdd3..f7baf31 100644
+--- a/src/ui/ui_players.c
++++ b/src/ui/ui_players.c
+@@ -84,13 +84,13 @@ tryagain:
+ 
+   if ( weaponNum == WP_MACHINEGUN ) {
+     strcpy( path, item->world_model[0] );
+-    COM_StripExtension( path, path );
++    COM_StripExtension( path, path, sizeof(path) );
+     strcat( path, "_barrel.md3" );
+     pi->barrelModel = trap_R_RegisterModel( path );
+   }
+ 
+   strcpy( path, item->world_model[0] );
+-  COM_StripExtension( path, path );
++  COM_StripExtension( path, path, sizeof(path) );
+   strcat( path, "_flash.md3" );
+   pi->flashModel = trap_R_RegisterModel( path );
+ 
diff --git 
a/debian/patches/0012-CVE-2006-2875-fix-stack-buffer-overflow-in-CL_ParseD.patch
 
b/debian/patches/0012-CVE-2006-2875-fix-stack-buffer-overflow-in-CL_ParseD.patch
new file mode 100644
index 0000000..12f9c78
--- /dev/null
+++ 
b/debian/patches/0012-CVE-2006-2875-fix-stack-buffer-overflow-in-CL_ParseD.patch
@@ -0,0 +1,73 @@
+From: Simon McVittie <[email protected]>
+Date: Fri, 18 Nov 2011 20:56:32 +0000
+Subject: CVE-2006-2875 - fix stack buffer overflow in CL_ParseDownload
+
+This is exploitable by a modified server. Original patch by Thilo
+Schulz, ioquake3 r796.
+
+Origin: backport
+Bug-CVE: http://security-tracker.debian.org/tracker/CVE-2006-2875
+---
+ src/client/cl_parse.c |   28 ++++++++++++++++++++--------
+ 1 files changed, 20 insertions(+), 8 deletions(-)
+
+diff --git a/src/client/cl_parse.c b/src/client/cl_parse.c
+index 7f219b3..dc14cd6 100644
+--- a/src/client/cl_parse.c
++++ b/src/client/cl_parse.c
+@@ -256,6 +256,13 @@ void CL_ParseSnapshot( msg_t *msg ) {
+ 
+       // read areamask
+       len = MSG_ReadByte( msg );
++      
++      if(len > sizeof(newSnap.areamask))
++      {
++              Com_Error (ERR_DROP,"CL_ParseSnapshot: Invalid size %d for 
areamask.", len);
++              return;
++      }
++      
+       MSG_ReadData( msg, &newSnap.areamask, len);
+ 
+       // read playerinfo
+@@ -476,6 +483,12 @@ void CL_ParseDownload ( msg_t *msg ) {
+       unsigned char data[MAX_MSGLEN];
+       int block;
+ 
++      if (!*clc.downloadTempName) {
++              Com_Printf("Server sending download, but no download was 
requested\n");
++              CL_AddReliableCommand( "stopdl" );
++              return;
++      }
++
+       // read the data
+       block = MSG_ReadShort ( msg );
+ 
+@@ -494,8 +507,13 @@ void CL_ParseDownload ( msg_t *msg ) {
+       }
+ 
+       size = MSG_ReadShort ( msg );
+-      if (size > 0)
+-              MSG_ReadData( msg, data, size );
++      if (size < 0 || size > sizeof(data))
++      {
++              Com_Error(ERR_DROP, "CL_ParseDownload: Invalid size %d for 
download chunk.", size);
++              return;
++      }
++      
++      MSG_ReadData(msg, data, size);
+ 
+       if (clc.downloadBlock != block) {
+               Com_DPrintf( "CL_ParseDownload: Expected block %d, got %d\n", 
clc.downloadBlock, block);
+@@ -505,12 +523,6 @@ void CL_ParseDownload ( msg_t *msg ) {
+       // open the file if not opened yet
+       if (!clc.download)
+       {
+-              if (!*clc.downloadTempName) {
+-                      Com_Printf("Server sending download, but no download 
was requested\n");
+-                      CL_AddReliableCommand( "stopdl" );
+-                      return;
+-              }
+-
+               clc.download = FS_SV_FOpenFileWrite( clc.downloadTempName );
+ 
+               if (!clc.download) {
diff --git 
a/debian/patches/0013-CVE-2006-3324-fix-arbitrary-file-overwrite-on-client.patch
 
b/debian/patches/0013-CVE-2006-3324-fix-arbitrary-file-overwrite-on-client.patch
new file mode 100644
index 0000000..1fd00bc
--- /dev/null
+++ 
b/debian/patches/0013-CVE-2006-3324-fix-arbitrary-file-overwrite-on-client.patch
@@ -0,0 +1,135 @@
+From: Simon McVittie <[email protected]>
+Date: Mon, 20 Feb 2012 21:57:46 +0000
+Subject: CVE-2006-3324 - fix arbitrary file overwrite on client by malicious
+ server
+
+Original patches by Thilo Schulz, ioquake3 r790, r794, r804.
+This commit also includes "a few sanity checks for checksum/pakname storage
+to fix a crash that can occur under certain circumstances", from r804
+and r805.
+
+Bug-CVE: http://security-tracker.debian.org/tracker/CVE-2006-3324
+Origin: backport
+---
+ src/qcommon/files.c |   51 +++++++++++++++++++++++++++++++++++++++------------
+ 1 files changed, 39 insertions(+), 12 deletions(-)
+
+diff --git a/src/qcommon/files.c b/src/qcommon/files.c
+index 67f375c..34afb4b 100644
+--- a/src/qcommon/files.c
++++ b/src/qcommon/files.c
+@@ -2591,15 +2591,16 @@ we are not interested in a download string format, we 
want something human-reada
+ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring ) {
+       searchpath_t    *sp;
+       qboolean havepak, badchecksum;
++      char *origpos = neededpaks;
+       int i;
+ 
+-      if ( !fs_numServerReferencedPaks ) {
++      if (!fs_numServerReferencedPaks)
+               return qfalse; // Server didn't send any pack information along
+-      }
+ 
+       *neededpaks = 0;
+ 
+-      for ( i = 0 ; i < fs_numServerReferencedPaks ; i++ ) {
++      for ( i = 0 ; i < fs_numServerReferencedPaks ; i++ )
++      {
+               // Ok, see if we have this pak file
+               badchecksum = qfalse;
+               havepak = qfalse;
+@@ -2609,6 +2610,13 @@ qboolean FS_ComparePaks( char *neededpaks, int len, 
qboolean dlstring ) {
+                       continue;
+               }
+ 
++              // Make sure the server cannot make us write to non-quake3 
directories.
++              if(strstr(fs_serverReferencedPakNames[i], "../") || 
strstr(fs_serverReferencedPakNames[i], "..\\"))
++                {
++                      Com_Printf("WARNING: Invalid download name %s\n", 
fs_serverReferencedPakNames[i]);
++                        continue;
++                }
++
+               for ( sp = fs_searchpaths ; sp ; sp = sp->next ) {
+                       if ( sp->pack && sp->pack->checksum == 
fs_serverReferencedPaks[i] ) {
+                               havepak = qtrue; // This is it!
+@@ -2621,6 +2629,12 @@ qboolean FS_ComparePaks( char *neededpaks, int len, 
qboolean dlstring ) {
+ 
+       if (dlstring)
+       {
++      // We need this to make sure we won't hit the end of the buffer or the 
server could
++      // overwrite non-pk3 files on clients by writing so much crap into 
neededpaks that
++      // Q_strcat cuts off the .pk3 extension.
++      
++      origpos += strlen(origpos);
++      
+         // Remote name
+         Q_strcat( neededpaks, len, "@");
+         Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
+@@ -2641,6 +2655,14 @@ qboolean FS_ComparePaks( char *neededpaks, int len, 
qboolean dlstring ) {
+           Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
+           Q_strcat( neededpaks, len, ".pk3" );
+         }
++        
++        // Find out whether it might have overflowed the buffer and don't add 
this file to the
++        // list if that is the case.
++        if(strlen(origpos) + (origpos - neededpaks) >= len - 1)
++      {
++              *origpos = '\0';
++              break;
++      }
+       }
+       else
+       {
+@@ -3146,7 +3168,7 @@ checksums to see if any pk3 files need to be 
auto-downloaded.
+ =====================
+ */
+ void FS_PureServerSetReferencedPaks( const char *pakSums, const char 
*pakNames ) {
+-      int             i, c, d;
++      int             i, c, d = 0;
+ 
+       Cmd_TokenizeString( pakSums );
+ 
+@@ -3155,30 +3177,35 @@ void FS_PureServerSetReferencedPaks( const char 
*pakSums, const char *pakNames )
+               c = MAX_SEARCH_PATHS;
+       }
+ 
+-      fs_numServerReferencedPaks = c;
+-
+       for ( i = 0 ; i < c ; i++ ) {
+               fs_serverReferencedPaks[i] = atoi( Cmd_Argv( i ) );
+       }
+ 
+-      for ( i = 0 ; i < c ; i++ ) {
+-              if (fs_serverReferencedPakNames[i]) {
++      for (i = 0 ; i < sizeof(fs_serverReferencedPakNames) / 
sizeof(*fs_serverReferencedPakNames); i++)
++      {
++              if(fs_serverReferencedPakNames[i])
+                       Z_Free(fs_serverReferencedPakNames[i]);
+-              }
++
+               fs_serverReferencedPakNames[i] = NULL;
+       }
++
+       if ( pakNames && *pakNames ) {
+               Cmd_TokenizeString( pakNames );
+ 
+               d = Cmd_Argc();
+-              if ( d > MAX_SEARCH_PATHS ) {
+-                      d = MAX_SEARCH_PATHS;
+-              }
++              if(d > c)
++                      d = c;
+ 
+               for ( i = 0 ; i < d ; i++ ) {
+                       fs_serverReferencedPakNames[i] = CopyString( Cmd_Argv( 
i ) );
+               }
+       }
++      
++      // ensure that there are as many checksums as there are pak names.
++      if(d < c)
++              c = d;
++      
++      fs_numServerReferencedPaks = c; 
+ }
+ 
+ /*
diff --git 
a/debian/patches/0014-CVE-2006-3325-fix-arbitrary-cvar-overwriting.patch 
b/debian/patches/0014-CVE-2006-3325-fix-arbitrary-cvar-overwriting.patch
new file mode 100644
index 0000000..8a5f432
--- /dev/null
+++ b/debian/patches/0014-CVE-2006-3325-fix-arbitrary-cvar-overwriting.patch
@@ -0,0 +1,156 @@
+From: Simon McVittie <[email protected]>
+Date: Fri, 18 Nov 2011 21:03:07 +0000
+Subject: CVE-2006-3325: fix arbitrary cvar overwriting
+
+Original patch by Thilo Schulz, ioquake3 r811.
+
+Bug-CVE: http://security-tracker.debian.org/tracker/CVE-2006-3325
+Origin: backport
+---
+ src/client/cl_parse.c  |   23 +++++++++++++++++++++--
+ src/qcommon/cvar.c     |   14 ++++++++++++++
+ src/qcommon/files.c    |   19 ++++++++++++++++++-
+ src/qcommon/q_shared.h |    3 +++
+ src/qcommon/qcommon.h  |    4 ++++
+ 5 files changed, 60 insertions(+), 3 deletions(-)
+
+diff --git a/src/client/cl_parse.c b/src/client/cl_parse.c
+index dc14cd6..2d36aa1 100644
+--- a/src/client/cl_parse.c
++++ b/src/client/cl_parse.c
+@@ -369,16 +369,35 @@ void CL_SystemInfoChanged( void ) {
+       // scan through all the variables in the systeminfo and locally set 
cvars to match
+       s = systemInfo;
+       while ( s ) {
++              int cvar_flags;
++              
+               Info_NextPair( &s, key, value );
+               if ( !key[0] ) {
+                       break;
+               }
++              
+               // ehw!
+-              if ( !Q_stricmp( key, "fs_game" ) ) {
++              if (!Q_stricmp(key, "fs_game"))
++              {
++                      if(FS_CheckDirTraversal(value))
++                      {
++                              Com_Printf("WARNING: Server sent invalid 
fs_game value %s\n", value);
++                              continue;
++                      }
++                              
+                       gameSet = qtrue;
+               }
+ 
+-              Cvar_Set( key, value );
++              if((cvar_flags = Cvar_Flags(key)) == CVAR_NONEXISTENT)
++                      Cvar_Get(key, value, CVAR_SERVER_CREATED | CVAR_ROM);
++              else
++              {
++                      // If this cvar may not be modified by a server discard 
the value.
++                      if(!(cvar_flags & (CVAR_SYSTEMINFO | 
CVAR_SERVER_CREATED)))
++                              continue;
++
++                      Cvar_Set(key, value);
++              }
+       }
+       // if game folder should not be set and it is set at the client side
+       if ( !gameSet && *Cvar_VariableString("fs_game") ) {
+diff --git a/src/qcommon/cvar.c b/src/qcommon/cvar.c
+index a306d88..f6caea8 100644
+--- a/src/qcommon/cvar.c
++++ b/src/qcommon/cvar.c
+@@ -162,6 +162,20 @@ void Cvar_VariableStringBuffer( const char *var_name, 
char *buffer, int bufsize
+       }
+ }
+ 
++/*
++============
++Cvar_Flags
++============
++*/
++int Cvar_Flags(const char *var_name)
++{
++      cvar_t *var;
++      
++      if(! (var = Cvar_FindVar(var_name)) )
++              return CVAR_NONEXISTENT;
++      else
++              return var->flags;
++}
+ 
+ /*
+ ============
+diff --git a/src/qcommon/files.c b/src/qcommon/files.c
+index 34afb4b..49390a0 100644
+--- a/src/qcommon/files.c
++++ b/src/qcommon/files.c
+@@ -2564,6 +2564,23 @@ qboolean FS_idPak( char *pak, char *base ) {
+ 
+ /*
+ ================
++FS_idPak
++
++Check whether the string contains stuff like "../" to prevent directory 
traversal bugs
++and return qtrue if it does.
++================
++*/
++
++qboolean FS_CheckDirTraversal(const char *checkdir)
++{
++      if(strstr(checkdir, "../") || strstr(checkdir, "..\\"))
++              return qtrue;
++      
++      return qfalse;
++}
++
++/*
++================
+ FS_ComparePaks
+ 
+ ----------------
+@@ -2611,7 +2628,7 @@ qboolean FS_ComparePaks( char *neededpaks, int len, 
qboolean dlstring ) {
+               }
+ 
+               // Make sure the server cannot make us write to non-quake3 
directories.
+-              if(strstr(fs_serverReferencedPakNames[i], "../") || 
strstr(fs_serverReferencedPakNames[i], "..\\"))
++              if(FS_CheckDirTraversal(fs_serverReferencedPakNames[i]))
+                 {
+                       Com_Printf("WARNING: Invalid download name %s\n", 
fs_serverReferencedPakNames[i]);
+                         continue;
+diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h
+index 03b2e03..d491708 100644
+--- a/src/qcommon/q_shared.h
++++ b/src/qcommon/q_shared.h
+@@ -795,6 +795,9 @@ default values.
+ #define CVAR_CHEAT                    512     // can not be changed if cheats 
are disabled
+ #define CVAR_NORESTART                1024    // do not clear when a 
cvar_restart is issued
+ 
++#define CVAR_SERVER_CREATED   2048    // cvar was created by a server the 
client connected to.
++#define CVAR_NONEXISTENT      0xFFFFFFFF      // Cvar doesn't exist.
++
+ // nothing outside the Cvar_*() functions should modify these fields!
+ typedef struct cvar_s {
+       char            *name;
+diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h
+index e6ae058..7b2fb8a 100644
+--- a/src/qcommon/qcommon.h
++++ b/src/qcommon/qcommon.h
+@@ -477,6 +477,9 @@ char       *Cvar_VariableString( const char *var_name );
+ void  Cvar_VariableStringBuffer( const char *var_name, char *buffer, int 
bufsize );
+ // returns an empty string if not defined
+ 
++int   Cvar_Flags(const char *var_name);
++// returns CVAR_NONEXISTENT if cvar doesn't exist or the flags of that 
particular CVAR.
++
+ void  Cvar_CommandCompletion( void(*callback)(const char *s) );
+ // callback with each valid string
+ 
+@@ -647,6 +650,7 @@ void FS_PureServerSetLoadedPaks( const char *pakSums, 
const char *pakNames );
+ // separated checksums will be checked for files, with the
+ // sole exception of .cfg files.
+ 
++qboolean FS_CheckDirTraversal(const char *checkdir);
+ qboolean FS_idPak( char *pak, char *base );
+ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring );
+ 
diff --git 
a/debian/patches/0015-CVE-2011-3012-CVE-2011-2764-backport-from-ioquake3-t.patch
 
b/debian/patches/0015-CVE-2011-3012-CVE-2011-2764-backport-from-ioquake3-t.patch
new file mode 100644
index 0000000..12adb99
--- /dev/null
+++ 
b/debian/patches/0015-CVE-2011-3012-CVE-2011-2764-backport-from-ioquake3-t.patch
@@ -0,0 +1,171 @@
+From: Simon McVittie <[email protected]>
+Date: Thu, 16 Feb 2012 20:28:58 +0000
+Subject: CVE-2011-3012, CVE-2011-2764 - backport from ioquake3 to prevent DLL
+ overwriting
+
+This is a backport of several patches:
+
+* part of ioquake3 r1405, from TsT (attempt to prevent DLL overwriting,
+  CVE-2011-3012)
+* part of ioquake3 r1456, from Patrick Baggett (using __func__)
+* ioquake3 r1499, from Tim Angus (fix potential buffer underrun)
+* ioquake3 r2098, from Thilo Schulz (fix incomplete DLL overwrite prevention
+  in previous commits, CVE-2011-2764)
+
+Origin: backport
+Bug-CVE: http://security-tracker.debian.org/tracker/CVE-2011-3012
+Bug-CVE: http://security-tracker.debian.org/tracker/CVE-2011-2764
+---
+ src/qcommon/files.c    |   34 ++++++++++++++++++++++++++++++++++
+ src/qcommon/q_shared.c |   24 ++++++++++++++++++++++++
+ src/qcommon/q_shared.h |    1 +
+ 3 files changed, 59 insertions(+), 0 deletions(-)
+
+diff --git a/src/qcommon/files.c b/src/qcommon/files.c
+index 49390a0..2e28cab 100644
+--- a/src/qcommon/files.c
++++ b/src/qcommon/files.c
+@@ -510,6 +510,24 @@ static qboolean FS_CreatePath (char *OSPath) {
+ 
+ /*
+ =================
++FS_CheckFilenameIsNotExecutable
++
++ERR_FATAL if trying to maniuplate a file with the platform library extension
++=================
++ */
++static void FS_CheckFilenameIsNotExecutable( const char *filename, const char 
*function )
++{
++       // Check if the filename ends with the library extension
++      if(COM_CompareExtension(filename, DLL_EXT))
++      {
++              Com_Error( ERR_FATAL, "%s: Not allowed to manipulate '%s' due "
++                      "to %s extension\n", function, filename, DLL_EXT );
++      }
++}
++
++
++/*
++=================
+ FS_CopyFile
+ 
+ Copy a fully specified file from one place to another
+@@ -522,6 +540,8 @@ static void FS_CopyFile( char *fromOSPath, char *toOSPath 
) {
+ 
+       Com_Printf( "copy %s to %s\n", fromOSPath, toOSPath );
+ 
++      FS_CheckFilenameIsNotExecutable( toOSPath, __func__ );
++
+       if (strstr(fromOSPath, "journal.dat") || strstr(fromOSPath, 
"journaldata.dat")) {
+               Com_Printf( "Ignoring journal files\n");
+               return;
+@@ -563,6 +583,8 @@ FS_Remove
+ ===========
+ */
+ void FS_Remove( const char *osPath ) {
++      FS_CheckFilenameIsNotExecutable( osPath, __func__ );
++
+       remove( osPath );
+ }
+ 
+@@ -573,6 +595,8 @@ FS_HomeRemove
+ ===========
+ */
+ void FS_HomeRemove( const char *homePath ) {
++      FS_CheckFilenameIsNotExecutable( homePath, __func__ );
++
+       remove( FS_BuildOSPath( fs_homepath->string,
+                       fs_gamedir, homePath ) );
+ }
+@@ -650,6 +674,8 @@ fileHandle_t FS_SV_FOpenFileWrite( const char *filename ) {
+               Com_Printf( "FS_SV_FOpenFileWrite: %s\n", ospath );
+       }
+ 
++      FS_CheckFilenameIsNotExecutable( ospath, __func__ );
++
+       if( FS_CreatePath( ospath ) ) {
+               return 0;
+       }
+@@ -775,6 +801,8 @@ void FS_SV_Rename( const char *from, const char *to ) {
+               Com_Printf( "FS_SV_Rename: %s --> %s\n", from_ospath, to_ospath 
);
+       }
+ 
++      FS_CheckFilenameIsNotExecutable( to_ospath, __func__ );
++
+       if (rename( from_ospath, to_ospath )) {
+               // Failed, try copying it and deleting the original
+               FS_CopyFile ( from_ospath, to_ospath );
+@@ -807,6 +835,8 @@ void FS_Rename( const char *from, const char *to ) {
+               Com_Printf( "FS_Rename: %s --> %s\n", from_ospath, to_ospath );
+       }
+ 
++      FS_CheckFilenameIsNotExecutable( to_ospath, __func__ );
++
+       if (rename( from_ospath, to_ospath )) {
+               // Failed, try copying it and deleting the original
+               FS_CopyFile ( from_ospath, to_ospath );
+@@ -871,6 +901,8 @@ fileHandle_t FS_FOpenFileWrite( const char *filename ) {
+               Com_Printf( "FS_FOpenFileWrite: %s\n", ospath );
+       }
+ 
++      FS_CheckFilenameIsNotExecutable( ospath, __func__ );
++
+       if( FS_CreatePath( ospath ) ) {
+               return 0;
+       }
+@@ -917,6 +949,8 @@ fileHandle_t FS_FOpenFileAppend( const char *filename ) {
+               Com_Printf( "FS_FOpenFileAppend: %s\n", ospath );
+       }
+ 
++      FS_CheckFilenameIsNotExecutable( ospath, __func__ );
++
+       if( FS_CreatePath( ospath ) ) {
+               return 0;
+       }
+diff --git a/src/qcommon/q_shared.c b/src/qcommon/q_shared.c
+index 44085cc..c87b44b 100644
+--- a/src/qcommon/q_shared.c
++++ b/src/qcommon/q_shared.c
+@@ -77,6 +77,30 @@ void COM_StripExtension( const char *in, char *out, int 
destsize ) {
+               out[length] = 0;
+ }
+ 
++/*
++============
++COM_CompareExtension
++
++string compare the end of the strings and return qtrue if strings match
++============
++*/
++qboolean COM_CompareExtension(const char *in, const char *ext)
++{
++      int inlen, extlen;
++      
++      inlen = strlen(in);
++      extlen = strlen(ext);
++      
++      if(extlen <= inlen)
++      {
++              in += inlen - extlen;
++              
++              if(!Q_stricmp(in, ext))
++                      return qtrue;
++      }
++      
++      return qfalse;
++}
+ 
+ /*
+ ==================
+diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h
+index d491708..83f5789 100644
+--- a/src/qcommon/q_shared.h
++++ b/src/qcommon/q_shared.h
+@@ -628,6 +628,7 @@ float Com_Clamp( float min, float max, float value );
+ 
+ char  *COM_SkipPath( char *pathname );
+ void  COM_StripExtension(const char *in, char *out, int destsize);
++qboolean COM_CompareExtension(const char *in, const char *ext);
+ void  COM_DefaultExtension( char *path, int maxSize, const char *extension );
+ 
+ void  COM_BeginParseSession( const char *name );
diff --git a/debian/patches/series b/debian/patches/series
index 14204cd..012065f 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -7,3 +7,9 @@
 0007-Fix-to-disappearing-cursor-on-map-load-Com_Error-bug.patch
 0008-Fixed-sort-by-ping.patch
 0009-Disable-JIT-QVM-interpreter-on-x86-64.patch
+0010-CVE-2006-2082-do-not-allow-download-of-arbitrary-fil.patch
+0011-CVE-2006-2236-add-bounds-checking-to-COM_StripExtens.patch
+0012-CVE-2006-2875-fix-stack-buffer-overflow-in-CL_ParseD.patch
+0013-CVE-2006-3324-fix-arbitrary-file-overwrite-on-client.patch
+0014-CVE-2006-3325-fix-arbitrary-cvar-overwriting.patch
+0015-CVE-2011-3012-CVE-2011-2764-backport-from-ioquake3-t.patch

-- 
team based FPS game - packaging

_______________________________________________
Pkg-games-commits mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to