Nmap Development mailing list archives
Assertion error related to Lua garbage collection of nsock pcap objects
From: Daniel Miller <bonsaiviking () gmail com>
Date: Mon, 30 Jul 2012 17:35:49 -0500
List,Henri and I have been tracking down a bug that so far only I have been able to reproduce. The bug presents as an assertion error:
nmap: nsock_event.c:406: msevent_new: Assertion `msiod->state != NSIOD_STATE_DELETED' failed.
I have been able to narrow the circumstances down to a run with these arguments:
sudo ./nmap -d --datadir . --script sniffer-detect.nse -T5 192.168.1.0/24 -sn -n
The issue is a call to nsock_pcap_read_packet (from nmap.pcap_receive() in NSE) on a socket/IOD that has been closed with nsi_delete. By setting a breakpoint on nsi_delete, I found it was being called from pcap_gc() in nse_nsock.cc. The nsock_iod object is kept as a weak value in the table KEY_PCAP, meaning that it can be garbage-collected when it is not reachable in any other way from Lua-land.
I think (wild speculation follows!) that the problem is that the nsock_iod objects are not reachable from Lua because they are part of a full userdata object, the nse_nsock_udata, and Lua can't look inside userdata objects (they are considered blobs of memory). Because they are not reachable from Lua except through the KEY_PCAP weak table, they are subject to garbage collection. If this is the case, I don't know why it hasn't affected more people.
If this is true, then one solution may be to store the entire nse_nsock_udata object as the value in KEY_PCAP, instead of just the nsock_iod. This would allow the garbage collector to see it from the Lua threads that have "socket" objects open. However, this would prevent nse_nsock_udata objects from sharing pcap IODs, which would remove a large efficiency and probably break things.
A different solution would be to make sure that the Lua garbage collector can reach the nsock_iod from the nse_nsock_udata. The garbage collector follows metatable entries, and userdata can have metatables, so setting an entry in the nse_nsock_udata's metatable would make this work. All nse_nsock_udata objects currently share a single metatable, so this would have to be done as a sub-table to the metatable, with keys that uniquely identify the nse_nsock_udata object. When socket:pcap_open() is called (l_pcap_open), a new entry in this table would be made to make the nsock_iod object reachable. The nsock_gc function handles finalization of collected nse_nsock_udata objects, and would be responsible for removing the object's entry (if any) in the shared metatable, making the nsock_iod object reachable by one less path.
This is all a bit beyond my knowledge, so I really need an expert eye (*cough*Patrick*cough*) to make sure my theories make sense before I start mucking with the code.
Dan _______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://seclists.org/nmap-dev/
Current thread:
- Assertion error related to Lua garbage collection of nsock pcap objects Daniel Miller (Jul 30)
- Re: Assertion error related to Lua garbage collection of nsock pcap objects Daniel Miller (Jul 30)
- Re: Assertion error related to Lua garbage collection of nsock pcap objects Patrick Donnelly (Jul 30)
- Re: Assertion error related to Lua garbage collection of nsock pcap objects Daniel Miller (Jul 31)
- Re: Assertion error related to Lua garbage collection of nsock pcap objects Patrick Donnelly (Jul 31)
- Re: Assertion error related to Lua garbage collection of nsock pcap objects Daniel Miller (Jul 31)
- Re: Assertion error related to Lua garbage collection of nsock pcap objects jah (Jul 31)
- Re: Assertion error related to Lua garbage collection of nsock pcap objects Daniel Miller (Jul 31)