Package: release.debian.org Severity: normal Tags: wheezy User: release.debian....@packages.debian.org Usertags: pu
Dear release team, I recently became one of the uploaders of Freeciv. I would like to ask for permission to update the version in stable and to address http://bugs.debian.org/696306. The proposed update fixes two security vulnerabilities which were not deemed important enough by the security team to warrant a DSA but I think it should be fixed in a point release at least. Please find attached the debdiff against version 2.3.2-1 in stable. Regards, Markus
diff -Nru freeciv-2.3.2/debian/changelog freeciv-2.3.2/debian/changelog --- freeciv-2.3.2/debian/changelog 2012-04-21 00:44:31.000000000 +0200 +++ freeciv-2.3.2/debian/changelog 2014-02-11 14:35:46.000000000 +0100 @@ -1,3 +1,16 @@ +freeciv (2.3.2-1+deb7u1) stable; urgency=medium + + * Fix CVE-2012-5645 and CVE-2012-6083. + - CVE-2012-5645: Added return value indicating success or failure for all + dio_get_xxx() functions, and check that value to avoid infinite loop in + reading arrays from network when there's no more data even though it's + expected. + - CVE-2012-6083: Sanity check packet length received over network against + values less than header length alone to avoid situation where body length + is considered negative. + + -- Markus Koschany <a...@gambaru.de> Tue, 11 Feb 2014 14:27:45 +0100 + freeciv (2.3.2-1) unstable; urgency=low * Update to latest upstream version diff -Nru freeciv-2.3.2/debian/patches/CVE-2012-5645.patch freeciv-2.3.2/debian/patches/CVE-2012-5645.patch --- freeciv-2.3.2/debian/patches/CVE-2012-5645.patch 1970-01-01 01:00:00.000000000 +0100 +++ freeciv-2.3.2/debian/patches/CVE-2012-5645.patch 2014-02-11 14:35:46.000000000 +0100 @@ -0,0 +1,439 @@ +From: Markus Koschany <a...@gambaru.de> +Date: Tue, 11 Feb 2014 14:17:09 +0100 +Subject: CVE-2012-5645 + +http://bugs.debian.org/696306 +--- + common/dataio.c | 111 ++++++++++++++++++++++++++++++++------------- + common/dataio.h | 30 ++++++------ + common/generate_packets.py | 8 ++-- + 3 files changed, 100 insertions(+), 49 deletions(-) + +diff --git a/common/dataio.c b/common/dataio.c +index 35e2475..8038099 100644 +--- a/common/dataio.c ++++ b/common/dataio.c +@@ -408,7 +408,7 @@ void dio_put_worklist(struct data_out *dout, const struct worklist *pwl) + Receive uint8 value to dest. In case of failure, value stored to dest + will be zero. Note that zero is legal value even when there is no failure. + **************************************************************************/ +-void dio_get_uint8(struct data_in *din, int *dest) ++bool dio_get_uint8(struct data_in *din, int *dest) + { + if (enough_data(din, 1)) { + if (dest) { +@@ -421,14 +421,18 @@ void dio_get_uint8(struct data_in *din, int *dest) + din->current++; + } else if (dest) { + *dest = 0; ++ ++ return FALSE; + } ++ ++ return TRUE; + } + + /************************************************************************** + Receive uint16 value to dest. In case of failure, value stored to dest + will be zero. Note that zero is legal value even when there is no failure. + **************************************************************************/ +-void dio_get_uint16(struct data_in *din, int *dest) ++bool dio_get_uint16(struct data_in *din, int *dest) + { + if (enough_data(din, 2)) { + if (dest) { +@@ -441,14 +445,18 @@ void dio_get_uint16(struct data_in *din, int *dest) + din->current += 2; + } else if (dest) { + *dest = 0; ++ ++ return FALSE; + } ++ ++ return TRUE; + } + + /************************************************************************** + Receive uint32 value to dest. In case of failure, value stored to dest + will be zero. Note that zero is legal value even when there is no failure. + **************************************************************************/ +-void dio_get_uint32(struct data_in *din, int *dest) ++bool dio_get_uint32(struct data_in *din, int *dest) + { + if (enough_data(din, 4)) { + if (dest) { +@@ -461,17 +469,22 @@ void dio_get_uint32(struct data_in *din, int *dest) + din->current += 4; + } else if (dest) { + *dest = 0; ++ ++ return FALSE; + } ++ ++ return TRUE; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_bool8(struct data_in *din, bool * dest) ++bool dio_get_bool8(struct data_in *din, bool * dest) + { + int ival; ++ bool retval; + +- dio_get_uint8(din, &ival); ++ retval = dio_get_uint8(din, &ival); + + if (ival != 0 && ival != 1) { + log_error("Received value isn't boolean: %d", ival); +@@ -479,16 +492,19 @@ void dio_get_bool8(struct data_in *din, bool * dest) + } + + *dest = (ival != 0); ++ ++ return retval; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_bool32(struct data_in *din, bool * dest) ++bool dio_get_bool32(struct data_in *din, bool * dest) + { + int ival = 0; ++ bool retval; + +- dio_get_uint32(din, &ival); ++ retval = dio_get_uint32(din, &ival); + + if (ival != 0 && ival != 1) { + log_error("Received value isn't boolean: %d", ival); +@@ -496,57 +512,69 @@ void dio_get_bool32(struct data_in *din, bool * dest) + } + + *dest = (ival != 0); ++ ++ return retval; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_sint8(struct data_in *din, int *dest) ++bool dio_get_sint8(struct data_in *din, int *dest) + { + int tmp; ++ bool retval; + +- dio_get_uint8(din, &tmp); ++ retval = dio_get_uint8(din, &tmp); + if (dest) { + if (tmp > 0x7f) { + tmp -= 0x100; + } + *dest = tmp; + } ++ ++ return retval; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_sint16(struct data_in *din, int *dest) ++bool dio_get_sint16(struct data_in *din, int *dest) + { + int tmp = 0; ++ bool retval; + +- dio_get_uint16(din, &tmp); ++ retval = dio_get_uint16(din, &tmp); + if (dest) { + if (tmp > 0x7fff) { + tmp -= 0x10000; + } + *dest = tmp; + } ++ ++ return retval; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_memory(struct data_in *din, void *dest, size_t dest_size) ++bool dio_get_memory(struct data_in *din, void *dest, size_t dest_size) + { + if (enough_data(din, dest_size)) { + if (dest) { + memcpy(dest, ADD_TO_POINTER(din->src, din->current), dest_size); + } + din->current += dest_size; ++ } else { ++ return FALSE; + } ++ ++ return TRUE; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_string(struct data_in *din, char *dest, size_t max_dest_size) ++bool dio_get_string(struct data_in *din, char *dest, size_t max_dest_size) + { + char *c; + size_t ps_len; /* length in packet, not including null */ +@@ -556,7 +584,7 @@ void dio_get_string(struct data_in *din, char *dest, size_t max_dest_size) + + if (!enough_data(din, 1)) { + dest[0] = '\0'; +- return; ++ return FALSE; + } + + remaining = dio_input_remaining(din); +@@ -582,37 +610,40 @@ void dio_get_string(struct data_in *din, char *dest, size_t max_dest_size) + if (!din->too_short) { + din->current += (ps_len + 1); /* past terminator */ + } ++ ++ return TRUE; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_bit_string(struct data_in *din, char *dest, ++bool dio_get_bit_string(struct data_in *din, char *dest, + size_t max_dest_size) + { + int npack = 0; /* number claimed in packet */ + int i; /* iterate the bytes */ ++ bool retval; + + fc_assert(dest != NULL && max_dest_size > 0); + + if (!enough_data(din, 1)) { + dest[0] = '\0'; +- return; ++ return FALSE; + } + +- dio_get_uint16(din, &npack); ++ retval = dio_get_uint16(din, &npack); + if (npack >= max_dest_size) { + log_error("Have size for %lu, got %d", + (unsigned long) max_dest_size, npack); + din->bad_bit_string = TRUE; + dest[0] = '\0'; +- return; ++ return FALSE; + } + + for (i = 0; i < npack;) { + int bit, byte_value; + +- dio_get_uint8(din, &byte_value); ++ retval = dio_get_uint8(din, &byte_value); + for (bit = 0; bit < 8 && i < npack; bit++, i++) { + if (TEST_BIT(byte_value, bit)) { + dest[i] = '1'; +@@ -627,17 +658,20 @@ void dio_get_bit_string(struct data_in *din, char *dest, + if (din->too_short) { + din->bad_bit_string = TRUE; + } ++ ++ return retval; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_tech_list(struct data_in *din, int *dest) ++bool dio_get_tech_list(struct data_in *din, int *dest) + { + int i; ++ bool retval; + + for (i = 0; i < MAX_NUM_TECH_LIST; i++) { +- dio_get_uint8(din, &dest[i]); ++ retval = dio_get_uint8(din, &dest[i]); + if (dest[i] == A_LAST) { + break; + } +@@ -646,56 +680,66 @@ void dio_get_tech_list(struct data_in *din, int *dest) + for (; i < MAX_NUM_TECH_LIST; i++) { + dest[i] = A_LAST; + } ++ ++ return retval; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_worklist(struct data_in *din, struct worklist *pwl) ++bool dio_get_worklist(struct data_in *din, struct worklist *pwl) + { + int i, length; ++ bool retval; + + worklist_init(pwl); + +- dio_get_uint8(din, &length); ++ retval = dio_get_uint8(din, &length); + for (i = 0; i < length; i++) { + int identifier; + int kind; + + dio_get_uint8(din, &kind); +- dio_get_uint8(din, &identifier); ++ retval = dio_get_uint8(din, &identifier); + + worklist_append(pwl, universal_by_number(kind, identifier)); + } ++ ++ return retval; + } + + /************************************************************************** + ... + **************************************************************************/ +-void dio_get_uint8_vec8(struct data_in *din, int **values, int stop_value) ++bool dio_get_uint8_vec8(struct data_in *din, int **values, int stop_value) + { + int count, inx; ++ bool retval; + +- dio_get_uint8(din, &count); ++ retval = dio_get_uint8(din, &count); + if (values) { + *values = fc_calloc((count + 1), sizeof(**values)); + } + for (inx = 0; inx < count; inx++) { +- dio_get_uint8(din, values ? &((*values)[inx]) : NULL); ++ retval = dio_get_uint8(din, values ? &((*values)[inx]) : NULL); + } + if (values) { + (*values)[inx] = stop_value; + } ++ ++ return retval; + } + + /************************************************************************** + Receive vector of uint6 values. + **************************************************************************/ +-void dio_get_uint16_vec8(struct data_in *din, int **values, int stop_value) ++bool dio_get_uint16_vec8(struct data_in *din, int **values, int stop_value) + { + int count, inx; ++ bool retval; ++ ++ retval = dio_get_uint8(din, &count); + +- dio_get_uint8(din, &count); + if (values) { + *values = fc_calloc((count + 1), sizeof(**values)); + } +@@ -705,23 +749,28 @@ void dio_get_uint16_vec8(struct data_in *din, int **values, int stop_value) + if (values) { + (*values)[inx] = stop_value; + } ++ ++ return retval; + } + + /************************************************************************** + De-serialize a requirement. + **************************************************************************/ +-void dio_get_requirement(struct data_in *din, struct requirement *preq) ++bool dio_get_requirement(struct data_in *din, struct requirement *preq) + { + int type, range, value; + bool survives, negated; ++ bool retval; + + dio_get_uint8(din, &type); + dio_get_sint32(din, &value); + dio_get_uint8(din, &range); + dio_get_bool8(din, &survives); +- dio_get_bool8(din, &negated); ++ retval = dio_get_bool8(din, &negated); + + *preq = req_from_values(type, range, survives, negated, value); ++ ++ return retval; + } + + /************************************************************************** +diff --git a/common/dataio.h b/common/dataio.h +index 37dac2d..778f7c1 100644 +--- a/common/dataio.h ++++ b/common/dataio.h +@@ -53,27 +53,27 @@ size_t dio_input_remaining(struct data_in *din); + + /* gets */ + +-void dio_get_uint8(struct data_in *din, int *dest); +-void dio_get_uint16(struct data_in *din, int *dest); +-void dio_get_uint32(struct data_in *din, int *dest); ++bool dio_get_uint8(struct data_in *din, int *dest); ++bool dio_get_uint16(struct data_in *din, int *dest); ++bool dio_get_uint32(struct data_in *din, int *dest); + +-void dio_get_sint8(struct data_in *din, int *dest); +-void dio_get_sint16(struct data_in *din, int *dest); ++bool dio_get_sint8(struct data_in *din, int *dest); ++bool dio_get_sint16(struct data_in *din, int *dest); + #define dio_get_sint32(d,v) dio_get_uint32(d,v) + + +-void dio_get_bool8(struct data_in *din, bool *dest); +-void dio_get_bool32(struct data_in *din, bool *dest); +-void dio_get_memory(struct data_in *din, void *dest, size_t dest_size); +-void dio_get_string(struct data_in *din, char *dest, size_t max_dest_size); +-void dio_get_bit_string(struct data_in *din, char *dest, ++bool dio_get_bool8(struct data_in *din, bool *dest); ++bool dio_get_bool32(struct data_in *din, bool *dest); ++bool dio_get_memory(struct data_in *din, void *dest, size_t dest_size); ++bool dio_get_string(struct data_in *din, char *dest, size_t max_dest_size); ++bool dio_get_bit_string(struct data_in *din, char *dest, + size_t max_dest_size); +-void dio_get_tech_list(struct data_in *din, int *dest); +-void dio_get_worklist(struct data_in *din, struct worklist *pwl); +-void dio_get_requirement(struct data_in *din, struct requirement *preq); ++bool dio_get_tech_list(struct data_in *din, int *dest); ++bool dio_get_worklist(struct data_in *din, struct worklist *pwl); ++bool dio_get_requirement(struct data_in *din, struct requirement *preq); + +-void dio_get_uint8_vec8(struct data_in *din, int **values, int stop_value); +-void dio_get_uint16_vec8(struct data_in *din, int **values, int stop_value); ++bool dio_get_uint8_vec8(struct data_in *din, int **values, int stop_value); ++bool dio_get_uint16_vec8(struct data_in *din, int **values, int stop_value); + + /* Should be a function but we need some macro magic. */ + #define DIO_BV_GET(pdin, bv) \ +diff --git a/common/generate_packets.py b/common/generate_packets.py +index c8092ec..d962203 100755 +--- a/common/generate_packets.py ++++ b/common/generate_packets.py +@@ -546,11 +546,13 @@ class Field: + for (;;) { + int i; + +- dio_get_uint8(&din, &i); +- if(i == 255) { ++ if (!dio_get_uint8(&din, &i)) { + break; + } +- if(i > %(array_size_u)s) { ++ if (i == 255) { ++ break; ++ } ++ if (i > %(array_size_u)s) { + log_error("packets_gen.c: WARNING: ignoring intra array diff"); + } else { + %(c)s diff -Nru freeciv-2.3.2/debian/patches/CVE-2012-6083.patch freeciv-2.3.2/debian/patches/CVE-2012-6083.patch --- freeciv-2.3.2/debian/patches/CVE-2012-6083.patch 1970-01-01 01:00:00.000000000 +0100 +++ freeciv-2.3.2/debian/patches/CVE-2012-6083.patch 2014-02-11 14:35:46.000000000 +0100 @@ -0,0 +1,37 @@ +From: Markus Koschany <a...@gambaru.de> +Date: Tue, 11 Feb 2014 14:16:08 +0100 +Subject: CVE-2012-6083 + +Bug: http://bugs.debian.org/696306 +--- + common/packets.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/common/packets.c b/common/packets.c +index 2b81242..61be17a 100644 +--- a/common/packets.c ++++ b/common/packets.c +@@ -331,7 +331,7 @@ instead of just testing if the returning package is NULL as we sometimes + return a NULL packet even if everything is OK (receive_packet_goto_route). + **************************************************************************/ + void *get_packet_from_connection(struct connection *pc, +- enum packet_type *ptype, bool * presult) ++ enum packet_type *ptype, bool *presult) + { + int len_read; + int whole_packet_len; +@@ -386,6 +386,14 @@ void *get_packet_from_connection(struct connection *pc, + return NULL; /* not all data has been read */ + } + ++ if (whole_packet_len < header_size) { ++ log_verbose("The packet size is reported to be less than header alone. " ++ "The connection will be closed now."); ++ connection_close(pc, _("illegal packet size")); ++ ++ return NULL; ++ } ++ + #ifdef USE_COMPRESSION + if (compressed_packet) { + uLong compressed_size = whole_packet_len - header_size;