
On Mon, Sep 30, 2013 at 09:12:35PM +0900, Yuto KAWAMURA wrote:
2013/9/20 Daniel P. Berrange <berrange@redhat.com>:
On Thu, Sep 19, 2013 at 11:26:08PM +0900, Yuto KAWAMURA(kawamuray) wrote:
diff --git a/tools/wireshark/src/moduleinfo.h b/tools/wireshark/src/moduleinfo.h new file mode 100644 index 0000000..9ab642c --- /dev/null +++ b/tools/wireshark/src/moduleinfo.h @@ -0,0 +1,37 @@ +/* moduleinfo.h --- Define constants about wireshark plugin module ... + +/* Included *after* config.h, in order to re-define these macros */ + +#ifdef PACKAGE +# undef PACKAGE +#endif + +/* Name of package */ +#define PACKAGE "libvirt"
Huh ? "PACKAGE" will already be defined to 'libvirt' so why are you redefining it.
+ + +#ifdef VERSION +# undef VERSION +#endif + +/* Version number of package */ +#define VERSION "0.0.1"
This means the wireshark plugin will have a fixed version, even when libvirt protocol changes in new releases. This seems bogus. Again I think we should just use the existing defined "VERSION".
I think this whole file can just go away completely
Right. I'll remove whole moduleinfo.h.
diff --git a/tools/wireshark/src/packet-libvirt.c b/tools/wireshark/src/packet-libvirt.c new file mode 100644 index 0000000..cd3e6ce --- /dev/null +++ b/tools/wireshark/src/packet-libvirt.c +static gboolean +dissect_xdr_bytes(tvbuff_t *tvb, proto_tree *tree, XDR *xdrs, int hf, + guint32 maxlen) +{ + goffset start; + guint8 *val = NULL; + guint32 length; + + start = xdr_getpos(xdrs); + if (xdr_bytes(xdrs, (char **)&val, &length, maxlen)) { + proto_tree_add_bytes_format_value(tree, hf, tvb, start, xdr_getpos(xdrs) - start, + NULL, "%s", format_xdr_bytes(val, length)); + /* Seems I can't call xdr_free() for this case. + It will raises SEGV by referencing out of bounds argument stack */ + xdrs->x_op = XDR_FREE; + xdr_bytes(xdrs, (char **)&val, &length, maxlen); + xdrs->x_op = XDR_DECODE;
Is accessing the internals of the 'XDR' struct really portable ? I think it would be desirable to solve the xdr_free problem rather than accessing struct internals
I'll change this to use free(), but let me explain this problem detail.
xdr_bytes may raises SEGV when it called from xdr_free. This is caused by xdr_free is accessing it's third argument 'sizep' even if it was called from xdr_free(in other word, when xdrs->x_op is XDR_FREE). This problem can't be reproduced in 64bit architecture due to 64bit system's register usage (I'll explain about this later).
Following is a small enough code to reproduce this issue:
#include <stdio.h> #include <stdlib.h> #include <rpc/xdr.h>
/* Contents of this buffer is not important to reproduce the issue */ static char xdr_buffer[] = { 0x00, 0x00, 0x00, 0x02, /* length is 2byte */ 'A', '\0', 0, 0 /* 2 byte data and 2 byte padding bytes */ };
/* Same as the prototype of xdr_bytes() */ bool_t my_xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep) { return TRUE; }
/* Same as the prototype of xdr_free() */ void my_xdr_free(xdrproc_t proc, char *objp) { XDR x; (*proc)(&x, objp, NULL/* This NULL stored at same pos of 'sizep' in xdr_bytes() */); }
int main(void) { XDR xdrs; char *opaque = NULL; unsigned int size;
xdrmem_create(&xdrs, xdr_buffer, sizeof(xdr_buffer), XDR_DECODE); if (!xdr_bytes(&xdrs, &opaque, &size, ~0)) { fprintf(stderr, "xdr_bytes() returns FALSE\n"); exit(1); }
/* Reproduce same stack-upping as call of xdr_free(xdr_bytes, &opaque). This is needed to stack-up 0x0(invalid address) on position of 'sizsp' which is third argument of xdr_bytes(). */ my_xdr_free((xdrproc_t)my_xdr_bytes, (char *)&opaque);
/* *** SEGV!! *** */ xdr_free((xdrproc_t)xdr_bytes, (char *)&opaque); /* ************** */
Ok, the scenario here is - 'xdr_bytes' takes 4 arguments - 'xdrproc_t' takes 2 mandatory args + var-args - 'xdr_free' calls the 'xdrproc_t' function with only 2 arguments - 'xdr_bytes' unconditionally accesses its 3rd argument So either - the cast from xdr_bytes -> xdrproc_t is invalid and thus xdr_bytes should not be used with xdr_free. or - xdr_bytes impl in glibc is buggy and shouldn't access the 3rd arg except when doing encode/decode operations. Regardless of which is right, we want our code to work on all xdr impls, so we must avoid problem 2. So I think we should just not use xdr_free here. Just do a plain 'free(opaque)' instead. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|