From ecd60cc7feb95b54ea5e3c0114150f9b9063eccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sun, 5 Jan 2020 16:06:54 +0100 Subject: USB Audio: Fix Feature Unit Descriptor dissection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly calculate the number of logical channels in the cluster. Report expert info if number of channels does not turn into integer. Bug: 16305 Change-Id: I028f3f00912629351641ef9297864ea832629cf0 Reviewed-on: https://code.wireshark.org/review/35656 Petri-Dish: Tomasz Moń Tested-by: Petri Dish Buildbot Reviewed-by: Alexis La Goutte --- epan/dissectors/packet-usb-audio.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/epan/dissectors/packet-usb-audio.c b/epan/dissectors/packet-usb-audio.c index 97e98f0d98..58f21ec9ca 100644 --- a/epan/dissectors/packet-usb-audio.c +++ b/epan/dissectors/packet-usb-audio.c @@ -638,6 +638,7 @@ static gint ett_sysex_msg_fragment = -1; static gint ett_sysex_msg_fragments = -1; static expert_field ei_usb_audio_undecoded = EI_INIT; +static expert_field ei_usb_audio_invalid_feature_unit_length = EI_INIT; static const fragment_items sysex_msg_frag_items = { /* Fragment subtrees */ @@ -1078,6 +1079,8 @@ dissect_ac_if_feature_unit(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, proto_tree *tree, usb_conv_info_t *usb_conv_info _U_, guint8 desc_len) { gint offset_start; + gint i; + gint ch; guint8 controlsize; proto_tree *bitmap_tree; proto_item *ti; @@ -1108,25 +1111,35 @@ dissect_ac_if_feature_unit(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, offset += 1; proto_tree_add_item(tree, hf_ac_if_fu_controlsize, tvb, offset, 1, ENC_LITTLE_ENDIAN); - controlsize = tvb_get_guint8(tvb, offset) + 1; + controlsize = tvb_get_guint8(tvb, offset); offset += 1; - ti = proto_tree_add_item(tree, hf_ac_if_fu_controls, tvb, offset, controlsize, ENC_NA); - bitmap_tree = proto_item_add_subtree(ti, ett_ac_if_fu_controls); - - proto_tree_add_bitmask(bitmap_tree, tvb, offset, hf_ac_if_fu_control, ett_ac_if_fu_controls0, fu_controls0, ENC_LITTLE_ENDIAN); - - if(controlsize >= 1){ - proto_tree_add_bitmask(bitmap_tree, tvb, offset + 1, hf_ac_if_fu_control, ett_ac_if_fu_controls1, fu_controls1, ENC_LITTLE_ENDIAN); + /* Descriptor size is 7+(ch+1)*n where n is controlsize, calculate and validate ch */ + ch = (controlsize > 0) ? (((desc_len - 7) / (controlsize)) - 1) : 0; + if (((7 + ((ch + 1) * controlsize)) != desc_len) || (ch < 0) || (controlsize == 0)){ + /* Report malformed packet, do not attempt further dissection */ + proto_tree_add_expert(tree, pinfo, &ei_usb_audio_invalid_feature_unit_length, tvb, offset, desc_len-offset); + offset += desc_len-offset; + return offset-offset_start; } - offset += controlsize; + ti = proto_tree_add_item(tree, hf_ac_if_fu_controls, tvb, offset, controlsize * (ch + 1), ENC_NA); + bitmap_tree = proto_item_add_subtree(ti, ett_ac_if_fu_controls); - if(offset < desc_len){ - proto_tree_add_item(tree, hf_ac_if_fu_ifeature, tvb, offset, 1, ENC_LITTLE_ENDIAN); - offset += 1; + /* bmaControls has 1 master channel 0 controls, and variable number of logical channel controls */ + for (i = 0; i < (ch + 1); i++) { + ti = proto_tree_add_bitmask(bitmap_tree, tvb, offset, hf_ac_if_fu_control, ett_ac_if_fu_controls0, fu_controls0, ENC_LITTLE_ENDIAN); + proto_item_prepend_text(ti, "%s channel %d ", (i == 0) ? "Master" : "Logical", i); + if (controlsize > 1) { + ti = proto_tree_add_bitmask(bitmap_tree, tvb, offset + 1, hf_ac_if_fu_control, ett_ac_if_fu_controls1, fu_controls1, ENC_LITTLE_ENDIAN); + proto_item_prepend_text(ti, "%s channel %d", (i == 0) ? "Master" : "Logical", i); + } + offset += controlsize; } + proto_tree_add_item(tree, hf_ac_if_fu_ifeature, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset += 1; + return offset-offset_start; } @@ -2837,6 +2850,7 @@ proto_register_usb_audio(void) static ei_register_info ei[] = { { &ei_usb_audio_undecoded, { "usbaudio.undecoded", PI_UNDECODED, PI_WARN, "Not dissected yet (report to wireshark.org)", EXPFILL }}, + { &ei_usb_audio_invalid_feature_unit_length, { "usbaudio.ac_if_fu.invalid_length", PI_MALFORMED, PI_ERROR, "Descriptor size is not 7+(ch+1)*n where n=bControlSize", EXPFILL }}, }; expert_module_t *expert_usb_audio; -- cgit v1.2.3