Wireshark mailing list archives
Simplifying (and fixing) tvbuff [Long]
From: Bill Meier <wmeier () newsguy com>
Date: Mon, 12 Dec 2011 16:55:50 -0500
Summary ------- I've recently been digging into the tvbuff code.After doing so, I've come to the conclusion that the current tvbuff implementation of managing tvb's with usage_counts and used_in lists:
- doesn't really provide some of what I understand to be the intended functionality;- is not necessary given the ways that Wireshark actually uses tvbuffs; - can be significantly simplified by doing away with usage counts
and used_in lists.(Comment: I started digging into the tvbuff code while reviewing the patch provided with Bug #6573:
"tvbuff_t values leak if they have a child tvbuff_t (memory leak)".The patch does, in fact, improve matters significantly but the patched tvbuff still has issues).
Below I give a few examples of issues related to the current tvbuff implementation and then describe how tvbuff can be simplified.
I've attached new versions of tvbuff-int.h and tvbuff.c with revised code for managing REAL_DATA and SUBSET tvb's. The changes are fairly simple. Wireshark seems to work AOK with the new versions (although I certainly haven't yet done extensive testing).
I think the revised code: - provides the functionality required by Wireshark; - is simpler and easier to understand. Comments are welcome ! Bill Some current tvbuff issues --------------------------Based upon comments in tvbuff.h[1] and in epan.c[2] it seems a design goal for the tvbuff code was to allow a dissector to do things like the following:
a. Do tvb_subset_new() and then, when done with the subset, tvb_free() ; b. Increment the usage count of a tvb which the dissector wishes to "save for later use".Neither of the above sequences currently work properly (and thus are not currently actually used in Wireshark). (See [3] below for some details).
c. The following sequence will fail: x1 = tvb_new_real_data(); x2 = tvb_new_child_real_data(); tvb_free(x2); tvb_free_chain(x1); issue: For REAL_DATA there's no "back-pointer" in x2 pointing to x1 and thus the tvb_free() can't clean the "used_in" list for x1. d. composite tvbuff's don't currently work (with respect to usage-counts, used-in lists and tvb_free()). The patch with bug #6573 certainly improves matters, but my brain fries when I try to work thru all the scenarios.I expect there are more issues which I didn't see or have forgotten as I worked through the code.
Proposal -------- Essentially: 1. API: Any new tvbs created by a dissector which are based upon or chained to a tvb handed to the dissector should not (must not) be free'd or "saved for later use" by the dissector. (AFAIKT Wireshark dissectors currently work this way so no dissector changes are required). (See Note below). A dissector can create a new tvb using tvb_new_real_data() with data storage allocated by the dissector. - Since the tvb is owned and managed by the dissector (and not chained to any tvb handed to the dissector), the dissector can do whatever is desired with that tvb (e.g., save the tvb for later use when dissecting another frame). - The dissector must eventually free the tvb (and possibly the storage) via a call to tvb_free_chain() for that tvb. Note: - tvb_free_chain() is the only way to free tvb's. [Existing dissector calls to tvb_free() can simply be replaced by calls to tvb_free_chain()]. - tvb_free_chain must be called only for the tvb which is the first tvb in the chain. [XXX: It may be that it will turn out to be OK to allow a dissector to do a tvb_free_chain() for any tvb created by that dissector (even if based upon or chained to a tvb handed to the dissector). 2. Implementation: a. Do away with usage_counts and the used_in lists altogether; All the existing tvb_new..() functions work pretty much as is except they don't try to maintain usage_counts & used_in lists & etc. b. tvb's (real, subset & composite) are "chained" using a simple doubly-linked list (maintained via new tvbuff_t *pointers in the tvb struct ('next' and 'previous'). (A composite tvb should always be part of a chain so that it eventually gets free'd). [XXX: - This means that all members of a composite must be part of the same chain as the composite. - One way to add a composite tvb to the chain: tvb_child_finalize_composite() or some thing similar. TBD]. c. tvb_free_chain() just goes down the list freeing each tvb in turn. The only special actions are to exec the call-back function for REAL_DATA tvb's and to clear the COMPOSITE GSLISTs. No special action is required for SUBSET tvb's. [XXX: If it's possible to guarantee that any subset/composite tvb in the list only references tvbs earlier in the list then it should be OK to allow free_chain() to start at any place in the list]. Notes: [1] From tvbuff.h: * The caller can artificially increment/decrement the usage count * with tvbuff_increment_usage_count()/tvbuff_decrement_usage_count(). [2] From packet.h /* Free all tvb's created from this tvb, unless dissector * wanted to store the pointer (in which case, the dissector * would have incremented the usage count on that tvbuff_t*) */ tvb_free_chain(edt->tvb); [3]a. tvb_free() of a subset doesn't remove the tvb from the parent "used_in" list and thus a subsequent tvb_free_chain() fails.
(The patch for bug #6573 added some code to fix this).b. In general, the sequence tvb_increment_usage_count(tvb)/tvb_free(tvb) as implemented does work correctly.
However: Note that most likely a tvb handed to dissector is ultimately based upon a "top-level" real tvb which is based, AFAIKT, on a data buffer filled in by wiretap (which will be overwritten when the next frame is read).
So: trying to "keep around" a tvb in such a case won't actually work as intended. The tvb needs to be copied if it is to be saved.
Attachment:
tvbuff.c
Description:
Attachment:
tvbuff-int.h
Description:
___________________________________________________________________________ Sent via: Wireshark-dev mailing list <wireshark-dev () wireshark org> Archives: http://www.wireshark.org/lists/wireshark-dev Unsubscribe: https://wireshark.org/mailman/options/wireshark-dev mailto:wireshark-dev-request () wireshark org?subject=unsubscribe
Current thread:
- Simplifying (and fixing) tvbuff [Long] Bill Meier (Dec 12)
- Re: Simplifying (and fixing) tvbuff [Long] Bill Meier (Dec 12)
- Re: Simplifying (and fixing) tvbuff [Long] Bill Meier (Dec 13)
- Re: Simplifying (and fixing) tvbuff [Long] Chris Maynard (Dec 14)
- Re: Simplifying (and fixing) tvbuff [Long] Jaap Keuter (Dec 14)
- Re: Simplifying (and fixing) tvbuff [Long] Chris Maynard (Dec 14)
- Re: Simplifying (and fixing) tvbuff [Long] Bill Meier (Dec 21)
- Re: Simplifying (and fixing) tvbuff [Long] Bill Meier (Dec 21)
- Re: Simplifying (and fixing) tvbuff [Long] Jaap Keuter (Dec 24)
- Re: Simplifying (and fixing) tvbuff [Long] Bill Meier (Dec 21)