[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#738662: wheezy-pu: package freeciv/2.3.2-1+deb7u1



Package: release.debian.org
Severity: normal
Tags: wheezy
User: release.debian.org@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 <apo@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 <apo@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 <apo@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;

Reply to: