On 20.01.2014 15:04, Yuto KAWAMURA wrote:
2014/1/16 Michal Privoznik <mprivozn(a)redhat.com>:
> On 15.01.2014 18:06, Yuto KAWAMURA(kawamuray) wrote:
>> From: "Yuto KAWAMURA(kawamuray)" <kawamuray.dadada(a)gmail.com>
>>
>> Introduce Wireshark dissector plugin which adds support to Wireshark
>> for dissecting libvirt RPC protocol.
>> Added following files to build Wireshark dissector from libvirt source
>> tree.
>> * tools/wireshark/*: Source tree of Wireshark dissector plugin.
>>
>> Added followings to configure.ac or Makefile.am.
>> configure.ac
>> * --with-wireshark-dissector: Enable support for building Wireshark
>> dissector.
>> * --with-ws-plugindir: Specify wireshark plugin directory that dissector
>> will installed.
>> * Added tools/wireshark/{Makefile,src/Makefile} to AC_CONFIG_FILES.
>> Makefile.am
>> * Added tools/wireshark/ to SUBDIR.
>> ---
>> .gitignore | 2 +
>> Makefile.am | 3 +-
>> cfg.mk | 8 +-
>> configure.ac | 72 ++-
>> tools/wireshark/Makefile.am | 22 +
>> tools/wireshark/README.md | 31 +
>> tools/wireshark/src/Makefile.am | 42 ++
>> tools/wireshark/src/packet-libvirt.c | 512 ++++++++++++++++
>> tools/wireshark/src/packet-libvirt.h | 128 ++++
>> tools/wireshark/util/genxdrstub.pl | 1011 +++++++++++++++++++++++++++++++
>> tools/wireshark/util/make-dissector-reg | 198 ++++++
>> 11 files changed, 2023 insertions(+), 6 deletions(-)
>> create mode 100644 tools/wireshark/Makefile.am
>> create mode 100644 tools/wireshark/README.md
>> create mode 100644 tools/wireshark/src/Makefile.am
>> create mode 100644 tools/wireshark/src/packet-libvirt.c
>> create mode 100644 tools/wireshark/src/packet-libvirt.h
>> create mode 100755 tools/wireshark/util/genxdrstub.pl
>> create mode 100755 tools/wireshark/util/make-dissector-reg
>>
>
>> diff --git a/tools/wireshark/src/packet-libvirt.c
b/tools/wireshark/src/packet-libvirt.c
>> new file mode 100644
>> index 0000000..2d0350c
>> --- /dev/null
>> +++ b/tools/wireshark/src/packet-libvirt.c
>
>> +static void
>> +dissect_libvirt_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
>> +{
>> + goffset offset;
>> + guint32 prog, proc, type, serial, status;
>> + const value_string *vs;
>> +
>> + col_set_str(pinfo->cinfo, COL_PROTOCOL, "Libvirt");
>> + col_clear(pinfo->cinfo, COL_INFO);
>> +
>> + offset = 4; /* End of length field */
>> + prog = tvb_get_ntohl(tvb, offset); offset += 4;
>> + offset += 4; /* Ignore version header field */
>> + proc = tvb_get_ntohl(tvb, offset); offset += 4;
>> + type = tvb_get_ntohl(tvb, offset); offset += 4;
>> + serial = tvb_get_ntohl(tvb, offset); offset += 4;
>> + status = tvb_get_ntohl(tvb, offset); offset += 4;
>> +
>> + col_add_fstr(pinfo->cinfo, COL_INFO, "Prog=%s",
>> + val_to_str(prog, program_strings, "%x"));
>> +
>> + vs = get_program_data(prog, VIR_PROGRAM_PROCSTRINGS);
>> + if (vs == NULL) {
>> + col_append_fstr(pinfo->cinfo, COL_INFO, " Proc=%u", proc);
>> + } else {
>> + col_append_fstr(pinfo->cinfo, COL_INFO, " Proc=%s",
val_to_str(proc, vs, "%d"));
>> + }
>> +
>> + col_append_fstr(pinfo->cinfo, COL_INFO, " Type=%s Serial=%u
Status=%s",
>> + val_to_str(type, type_strings, "%d"), serial,
>> + val_to_str(status, status_strings, "%d"));
>> +
>> + if (tree) {
>> + gint hf_proc;
>> + proto_item *ti;
>> + proto_tree *libvirt_tree;
>> +
>> + ti = proto_tree_add_item(tree, proto_libvirt, tvb, 0, tvb_length(tvb),
ENC_NA);
>> + libvirt_tree = proto_item_add_subtree(ti, ett_libvirt);
>> +
>> + offset = 0;
>> + proto_tree_add_item(libvirt_tree, hf_libvirt_length, tvb, offset, 4,
ENC_NA); offset += 4;
>> + proto_tree_add_item(libvirt_tree, hf_libvirt_program, tvb, offset, 4,
ENC_NA); offset += 4;
>> + proto_tree_add_item(libvirt_tree, hf_libvirt_version, tvb, offset, 4,
ENC_NA); offset += 4;
>> +
>> + hf_proc = *(int *)get_program_data(prog, VIR_PROGRAM_PROCHFVAR);
>
> There's a possible NULL dereference here. get_program might return NULL in case
@prog is not one of REMOTE, QEMU, LXC, KEEPALIVE. This can possibly happen and it did for
me indeed:
>
> Program terminated with signal 11, Segmentation fault.
> #0 0x00007fac1cc60a86 in dissect_libvirt_message (tvb=0x387acc0,
pinfo=0x7fffb9a03100, tree=0x3883090) at packet-libvirt.c:396
> 396 hf_proc = *(int *)get_program_data(prog, VIR_PROGRAM_PROCHFVAR);
> (gdb) bt
> #0 0x00007fac1cc60a86 in dissect_libvirt_message (tvb=0x387acc0,
pinfo=0x7fffb9a03100, tree=0x3883090) at packet-libvirt.c:396
> #1 0x00000034469198fe in tcp_dissect_pdus () from /usr/lib64/libwireshark.so.3
> #2 0x00007fac1cc60c0c in dissect_libvirt (tvb=0x3879aa0, pinfo=0x7fffb9a03100,
tree=0x3883090) at packet-libvirt.c:424
> #3 0x00000034462dff54 in ?? () from /usr/lib64/libwireshark.so.3
> #4 0x00000034462e0608 in ?? () from /usr/lib64/libwireshark.so.3
> #5 0x00000034462e0e0c in ?? () from /usr/lib64/libwireshark.so.3
> #6 0x00000034462e0e67 in dissector_try_uint () from /usr/lib64/libwireshark.so.3
> ...
>
> (gdb) p /x VIR_PROGRAM_PROCHFVAR
> $1 = 0x0
> (gdb) p /x prog
> $2 = 0xd21c44f9
>
> This happened if I used sasl for authentication (auth_tcp="sasl"
listen_tcp=1 listen_tls=0)
>
>> + if (hf_proc == -1) {
>> + proto_tree_add_none_format(libvirt_tree, -1, tvb, offset, 4,
"Unknown proc: %u", proc);
>> + } else {
>> + proto_tree_add_item(libvirt_tree, hf_proc, tvb, offset, 4, ENC_NA);
>> + }
>> + offset += 4;
>
> I've tried to fixed this by applying:
> @@ -381,7 +381,7 @@ dissect_libvirt_message(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree)
> val_to_str(status, status_strings, "%d"));
>
> if (tree) {
> - gint hf_proc;
> + gint *hf_proc;
> proto_item *ti;
> proto_tree *libvirt_tree;
>
> @@ -393,11 +393,11 @@ dissect_libvirt_message(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree)
> proto_tree_add_item(libvirt_tree, hf_libvirt_program, tvb, offset, 4,
ENC_NA); offset += 4;
> proto_tree_add_item(libvirt_tree, hf_libvirt_version, tvb, offset, 4,
ENC_NA); offset += 4;
>
> - hf_proc = *(int *)get_program_data(prog, VIR_PROGRAM_PROCHFVAR);
> - if (hf_proc == -1) {
> + hf_proc = (int *)get_program_data(prog, VIR_PROGRAM_PROCHFVAR);
> + if (!hf_proc || *hf_proc == -1) {
> proto_tree_add_none_format(libvirt_tree, -1, tvb, offset, 4,
"Unknown proc: %u", proc);
> } else {
> - proto_tree_add_item(libvirt_tree, hf_proc, tvb, offset, 4, ENC_NA);
> + proto_tree_add_item(libvirt_tree, *hf_proc, tvb, offset, 4, ENC_NA);
> }
> offset += 4;
>
>
> but it worked only partially as then I was seeing this error messages (but no
segfault :) ):
>
> 12:29:09 Warn Dissector bug, protocol libvirt, in packet 32: proto.c:1854:
failed assertion "(guint)hfindex < gpa_hfinfo.len" (Unregistered hf!)
>
> The error message kept repeating over and over again. The rest of the patch looks
okay. Once you fix this (sending a follow-up patch is just fine) I'll push this.
Thanks for taking care of the dissector!
>
> Michal
>
Thanks for review Michal.
Fix patch for this bug is following.
Regoards.
diff --git a/tools/wireshark/src/packet-libvirt.c
b/tools/wireshark/src/packet-libvirt.c
index 2d0350c..d64ecce 100644
--- a/tools/wireshark/src/packet-libvirt.c
+++ b/tools/wireshark/src/packet-libvirt.c
@@ -39,6 +39,7 @@ static int proto_libvirt = -1;
static int hf_libvirt_length = -1;
static int hf_libvirt_program = -1;
static int hf_libvirt_version = -1;
+static int hf_libvirt_procedure = -1;
static int hf_libvirt_type = -1;
static int hf_libvirt_serial = -1;
static int hf_libvirt_status = -1;
@@ -381,7 +382,7 @@ dissect_libvirt_message(tvbuff_t *tvb, packet_info
*pinfo, proto_tree *tree)
val_to_str(status, status_strings, "%d"));
if (tree) {
- gint hf_proc;
+ gint *hf_proc;
proto_item *ti;
proto_tree *libvirt_tree;
@@ -393,11 +394,12 @@ dissect_libvirt_message(tvbuff_t *tvb,
packet_info *pinfo, proto_tree *tree)
proto_tree_add_item(libvirt_tree, hf_libvirt_program, tvb,
offset, 4, ENC_NA); offset += 4;
proto_tree_add_item(libvirt_tree, hf_libvirt_version, tvb,
offset, 4, ENC_NA); offset += 4;
- hf_proc = *(int *)get_program_data(prog, VIR_PROGRAM_PROCHFVAR);
- if (hf_proc == -1) {
- proto_tree_add_none_format(libvirt_tree, -1, tvb, offset,
4, "Unknown proc: %u", proc);
+ hf_proc = (int *)get_program_data(prog, VIR_PROGRAM_PROCHFVAR);
+ if (hf_proc != NULL && *hf_proc != -1) {
+ proto_tree_add_item(libvirt_tree, *hf_proc, tvb, offset,
4, ENC_NA);
} else {
- proto_tree_add_item(libvirt_tree, hf_proc, tvb, offset, 4, ENC_NA);
+ /* No string representation, but still useful displaying
proc number */
+ proto_tree_add_item(libvirt_tree, hf_libvirt_procedure,
tvb, offset, 4, ENC_NA);
}
offset += 4;
@@ -446,6 +448,12 @@ proto_register_libvirt(void)
NULL, 0x0,
NULL, HFILL}
},
+ { &hf_libvirt_procedure,
+ { "procedure", "libvirt.procedure",
+ FT_INT32, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL}
+ },
{ &hf_libvirt_type,
{ "type", "libvirt.type",
FT_INT32, BASE_DEC,
Yes, this fixes the problem. ACK. I'm squashing this in and pushing the
series. Thanks!
Michal