diff options
author | Thomas Haller <thaller@redhat.com> | 2014-10-06 15:15:34 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2014-10-08 10:50:39 +0200 |
commit | b439d6d13ec8a8e4ff247b7d042424f10574aa84 (patch) | |
tree | 656fc7e95ef91a13e620610e6b201a40921a0dba | |
parent | c744b04814098ea3647de8d618bd88e5554e1a26 (diff) | |
download | external_libqmi-b439d6d13ec8a8e4ff247b7d042424f10574aa84.zip external_libqmi-b439d6d13ec8a8e4ff247b7d042424f10574aa84.tar.gz external_libqmi-b439d6d13ec8a8e4ff247b7d042424f10574aa84.tar.bz2 |
qmi-codegen: avoid buffer overlow in emit_input_tlv_add()
https://bugzilla.redhat.com/show_bug.cgi?id=1031738
Reported-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r-- | build-aux/qmi-codegen/Field.py | 12 | ||||
-rw-r--r-- | build-aux/qmi-codegen/Variable.py | 2 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableArray.py | 8 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableInteger.py | 46 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableSequence.py | 4 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableString.py | 29 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableStruct.py | 4 |
7 files changed, 77 insertions, 28 deletions
diff --git a/build-aux/qmi-codegen/Field.py b/build-aux/qmi-codegen/Field.py index ddbcfe1..8542690 100644 --- a/build-aux/qmi-codegen/Field.py +++ b/build-aux/qmi-codegen/Field.py @@ -216,9 +216,11 @@ class Field: Emit the code responsible for adding the TLV to the QMI message """ def emit_input_tlv_add(self, f, line_prefix): + error_label = 'ERR_EMIT_BUFFER_OVERFLOW_' + self.id_enum_name translations = { 'name' : self.name, 'tlv_id' : self.id_enum_name, 'variable_name' : self.variable_name, + 'error_label' : error_label, 'lp' : line_prefix } template = ( @@ -229,15 +231,23 @@ class Field: f.write(string.Template(template).substitute(translations)) # Now, write the contents of the variable into the buffer - self.variable.emit_buffer_write(f, line_prefix, 'input->' + self.variable_name, 'buffer_aux', 'buffer_len') + self.variable.emit_buffer_write(f, line_prefix, 'input->' + self.variable_name, 'buffer_aux', 'buffer_len', error_label) template = ( '\n' + '${lp}if (FALSE) {\n' + '${lp} ${error_label}:\n' + '${lp} g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_TLV_TOO_LONG, "result larger then 1024 bytes");\n' + '${lp} goto OUT_${error_label};\n' + '${lp}}\n' + '\n' + '${lp}g_assert (buffer_len <= 1024);\n' '${lp}if (!qmi_message_add_raw_tlv (self,\n' '${lp} (guint8)${tlv_id},\n' '${lp} buffer,\n' '${lp} (1024 - buffer_len),\n' '${lp} error)) {\n' + '${lp} OUT_${error_label}:\n' '${lp} g_prefix_error (error, \"Couldn\'t set the ${name} TLV: \");\n' '${lp} qmi_message_unref (self);\n' '${lp} return NULL;\n' diff --git a/build-aux/qmi-codegen/Variable.py b/build-aux/qmi-codegen/Variable.py index c238471..fbc93f5 100644 --- a/build-aux/qmi-codegen/Variable.py +++ b/build-aux/qmi-codegen/Variable.py @@ -81,7 +81,7 @@ class Variable: Emits the code involved in writing the variable to the raw byte stream from the specific private format. """ - def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label): pass diff --git a/build-aux/qmi-codegen/VariableArray.py b/build-aux/qmi-codegen/VariableArray.py index 7f38202..6af3c2d 100644 --- a/build-aux/qmi-codegen/VariableArray.py +++ b/build-aux/qmi-codegen/VariableArray.py @@ -296,7 +296,7 @@ class VariableArray(Variable): Writing an array to the raw byte buffer is just about providing a loop to write every array element one by one. """ - def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'variable_name' : variable_name, @@ -319,10 +319,10 @@ class VariableArray(Variable): '${lp} ${common_var_prefix}_n_items = (${array_size_element_format}) ${variable_name}->len;\n') f.write(string.Template(template).substitute(translations)) - self.array_size_element.emit_buffer_write(f, line_prefix + ' ', common_var_prefix + '_n_items', buffer_name, buffer_len) + self.array_size_element.emit_buffer_write(f, line_prefix + ' ', common_var_prefix + '_n_items', buffer_name, buffer_len, error_label) if self.array_sequence_element != '': - self.array_sequence_element.emit_buffer_write(f, line_prefix + ' ', variable_name + '_sequence', buffer_name, buffer_len) + self.array_sequence_element.emit_buffer_write(f, line_prefix + ' ', variable_name + '_sequence', buffer_name, buffer_len, error_label) template = ( @@ -330,7 +330,7 @@ class VariableArray(Variable): '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${variable_name}->len; ${common_var_prefix}_i++) {\n') f.write(string.Template(template).substitute(translations)) - self.array_element.emit_buffer_write(f, line_prefix + ' ', 'g_array_index (' + variable_name + ', ' + self.array_element.public_format + ',' + common_var_prefix + '_i)', buffer_name, buffer_len) + self.array_element.emit_buffer_write(f, line_prefix + ' ', 'g_array_index (' + variable_name + ', ' + self.array_element.public_format + ',' + common_var_prefix + '_i)', buffer_name, buffer_len, error_label) template = ( '${lp} }\n' diff --git a/build-aux/qmi-codegen/VariableInteger.py b/build-aux/qmi-codegen/VariableInteger.py index 235b552..37e587d 100644 --- a/build-aux/qmi-codegen/VariableInteger.py +++ b/build-aux/qmi-codegen/VariableInteger.py @@ -130,22 +130,47 @@ class VariableInteger(Variable): '${lp}${variable_name} += 8;\n') f.write(string.Template(template).substitute(translations)) + """ + Return the data type size of fixed c-types + """ + @staticmethod + def fixed_type_byte_size(fmt): + if fmt == 'guint8': + return 1 + if fmt == 'guint16': + return 2 + if fmt == 'guint32': + return 4 + if fmt == 'guint64': + return 8 + if fmt == 'gint8': + return 1 + if fmt == 'gint16': + return 2 + if fmt == 'gint32': + return 4 + if fmt == 'gint64': + return 8 + raise Exception("Unsupported format %s" % (fmt)) """ Write a single integer to the raw byte buffer """ - def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label): translations = { 'lp' : line_prefix, 'private_format' : self.private_format, 'len' : self.guint_sized_size, 'variable_name' : variable_name, 'buffer_name' : buffer_name, 'buffer_len' : buffer_len, + 'error_label' : error_label, 'endian' : self.endian } if self.format == 'guint-sized': template = ( '${lp}/* Write the ${len}-byte long variable to the buffer */\n' + '${lp}if (${buffer_len} < ${len})\n' + '${lp} goto ${error_label};\n' '${lp}qmi_utils_write_sized_guint_to_buffer (\n' '${lp} &${buffer_name},\n' '${lp} &${buffer_len},\n' @@ -153,19 +178,26 @@ class VariableInteger(Variable): '${lp} ${endian},\n' '${lp} &(${variable_name}));\n') elif self.private_format == self.public_format: + translations['byte_size'] = VariableInteger.fixed_type_byte_size(self.private_format) template = ( '${lp}/* Write the ${private_format} variable to the buffer */\n' - '${lp}qmi_utils_write_${private_format}_to_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n') + '${lp}if (${buffer_len} < ${byte_size})\n' + '${lp} goto ${error_label};\n' + '${lp}else\n' + '${lp} qmi_utils_write_${private_format}_to_buffer (\n' + '${lp} &${buffer_name},\n' + '${lp} &${buffer_len},\n') if self.private_format != 'guint8' and self.private_format != 'gint8': template += ( - '${lp} ${endian},\n') + '${lp} ${endian},\n') template += ( - '${lp} &(${variable_name}));\n') + '${lp} &(${variable_name}));\n') else: + translations['byte_size'] = VariableInteger.fixed_type_byte_size(self.private_format) template = ( - '${lp}{\n' + '${lp}if (${buffer_len} < ${byte_size})\n' + '${lp} goto ${error_label};\n' + '${lp}else {\n' '${lp} ${private_format} tmp;\n' '\n' '${lp} tmp = (${private_format})${variable_name};\n' diff --git a/build-aux/qmi-codegen/VariableSequence.py b/build-aux/qmi-codegen/VariableSequence.py index 0ea5a9d..bacc541 100644 --- a/build-aux/qmi-codegen/VariableSequence.py +++ b/build-aux/qmi-codegen/VariableSequence.py @@ -92,9 +92,9 @@ class VariableSequence(Variable): Writing the contents of a sequence is just about writing each of the sequence fields one by one. """ - def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label): for member in self.members: - member['object'].emit_buffer_write(f, line_prefix, variable_name + '_' + member['name'], buffer_name, buffer_len) + member['object'].emit_buffer_write(f, line_prefix, variable_name + '_' + member['name'], buffer_name, buffer_len, error_label) """ diff --git a/build-aux/qmi-codegen/VariableString.py b/build-aux/qmi-codegen/VariableString.py index 0ea3bd3..9678fbd 100644 --- a/build-aux/qmi-codegen/VariableString.py +++ b/build-aux/qmi-codegen/VariableString.py @@ -157,30 +157,37 @@ class VariableString(Variable): """ Write a string to the raw byte buffer. """ - def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label): translations = { 'lp' : line_prefix, 'variable_name' : variable_name, 'buffer_name' : buffer_name, + 'error_label' : error_label, 'buffer_len' : buffer_len } if self.is_fixed_size: translations['fixed_size'] = self.fixed_size template = ( '${lp}/* Write the fixed-size string variable to the buffer */\n' - '${lp}qmi_utils_write_fixed_size_string_to_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n' - '${lp} ${fixed_size},\n' - '${lp} ${variable_name});\n') + '${lp}if (${buffer_len} < ${fixed_size})\n' + '${lp} goto ${error_label};\n' + '${lp}else\n' + '${lp} qmi_utils_write_fixed_size_string_to_buffer (\n' + '${lp} &${buffer_name},\n' + '${lp} &${buffer_len},\n' + '${lp} ${fixed_size},\n' + '${lp} ${variable_name});\n') else: translations['length_prefix_size'] = self.length_prefix_size template = ( '${lp}/* Write the string variable to the buffer */\n' - '${lp}qmi_utils_write_string_to_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n' - '${lp} ${length_prefix_size},\n' - '${lp} ${variable_name});\n') + '${lp}if (!${variable_name} || ${buffer_len} < ${length_prefix_size} + strlen (${variable_name}))\n' + '${lp} goto ${error_label};\n' + '${lp}else\n' + '${lp} qmi_utils_write_string_to_buffer (\n' + '${lp} &${buffer_name},\n' + '${lp} &${buffer_len},\n' + '${lp} ${length_prefix_size},\n' + '${lp} ${variable_name});\n') f.write(string.Template(template).substitute(translations)) diff --git a/build-aux/qmi-codegen/VariableStruct.py b/build-aux/qmi-codegen/VariableStruct.py index 522551e..041e6ab 100644 --- a/build-aux/qmi-codegen/VariableStruct.py +++ b/build-aux/qmi-codegen/VariableStruct.py @@ -121,9 +121,9 @@ class VariableStruct(Variable): Writing the contents of a struct is just about writing each of the struct fields one by one. """ - def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label): for member in self.members: - member['object'].emit_buffer_write(f, line_prefix, variable_name + '.' + member['name'], buffer_name, buffer_len) + member['object'].emit_buffer_write(f, line_prefix, variable_name + '.' + member['name'], buffer_name, buffer_len, error_label) """ |