Sophie

Sophie

distrib > Mageia > 1 > i586 > media > core-updates-src > by-pkgid > 500e6ffc762ef741c06f9c5419c6d76b > files > 2

openttd-1.1.0-1.3.mga1.src.rpm

Subject: fix for vulnerability CVE-2011-3342 for OpenTTD 1.1.0 - 1.1.1 (Buffer overflows in savegame loading)
From: OpenTTD developer team <info@openttd.org>
Origin: backport, http://vcs.openttd.org/svn/changeset/22737 http://vcs.openttd.org/svn/changeset/22843 
Bug: http://bugs.openttd.org/task/4717 http://bugs.openttd.org/task/4748 

In multiple places indices in savegames are not properly validated that allow 
(remote) attackers to cause a denial of service (crash) and possibly execute 
arbitrary code via unspecified vectors.

The bug is exploitable by passing someone a modified savegame, be it via a file
sharing site, or by running a server. In case of the server the user only has
to be able to login into the server, which is easy to accomplish: set no server
password and do not ban anyone. Then upon joining the server the savegame
will be downloaded and subsequently loaded.

Note that versions before 0.5.0 are vulnerable as well. However, these versions
are over five years old and not supported anymore. Therefore no patches for
earlier versions are provided. Before 0.3.5 it is not possible to exploit this
bug via the internet as multiplayer over internet did not exist yet.

Index: src/saveload/company_sl.cpp
===================================================================
--- src/saveload/company_sl.cpp	(revision 22703)
+++ src/saveload/company_sl.cpp	(working copy)
@@ -283,6 +283,7 @@
 	SlObject(&cprops->cur_economy, _company_economy_desc);
 
 	/* Write old economy entries. */
+	if (cprops->num_valid_stat_ent > lengthof(cprops->old_economy)) SlErrorCorrupt("Too many old economy entries");
 	for (i = 0; i < cprops->num_valid_stat_ent; i++) {
 		SlObject(&cprops->old_economy[i], _company_economy_desc);
 	}
Index: src/saveload/cheat_sl.cpp
===================================================================
--- src/saveload/cheat_sl.cpp	(revision 22703)
+++ src/saveload/cheat_sl.cpp	(working copy)
@@ -32,6 +32,8 @@
 {
 	Cheat *cht = (Cheat*)&_cheats;
 	size_t count = SlGetFieldLength() / 2;
+	/* Cannot use lengthof because _cheats is of type Cheats, not Cheat */
+	if (count > sizeof(_cheats) / sizeof(Cheat)) SlErrorCorrupt("Too many cheat values");
 
 	for (uint i = 0; i < count; i++) {
 		cht[i].been_used = (SlReadByte() != 0);
Index: src/saveload/strings_sl.cpp
===================================================================
--- src/saveload/strings_sl.cpp	(revision 22703)
+++ src/saveload/strings_sl.cpp	(working copy)
@@ -120,7 +120,12 @@
 	int index;
 
 	while ((index = SlIterateArray()) != -1) {
+		if (index >= 512) SlErrorCorrupt("Invalid old name index");
+		if (SlGetFieldLength() > 32) SlErrorCorrupt("Invalid old name length");
+
 		SlArray(&_old_name_array[32 * index], SlGetFieldLength(), SLE_UINT8);
+		/* Make sure the old name is null terminated */
+		_old_name_array[32 * index + 31] = '\0';
 	}
 }
 
Index: src/saveload/ai_sl.cpp
===================================================================
--- src/saveload/ai_sl.cpp	(revision 22703)
+++ src/saveload/ai_sl.cpp	(working copy)
@@ -66,6 +66,8 @@
 
 	CompanyID index;
 	while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) {
+		if (index >= MAX_COMPANIES) SlErrorCorrupt("Too many AI configs");
+
 		_ai_saveload_version = -1;
 		SlObject(NULL, _ai_company);