mirror of
https://github.com/nmap/nmap.git
synced 2026-01-18 20:29:02 +00:00
Use a mutex on Windows to avoid a hang when accessing WinPCAP driver
Reported by multiple users on Windows 8.1 and Windows Server 2012 R2. Seems to hang when the WinPCAP driver is accessed via OpenServiceA by multiple processes at once. Users report that this change, which uses a mutex to avoid concurrent access, fixes the hang.
This commit is contained in:
@@ -35,13 +35,21 @@ eth_open(const char *device)
|
||||
{
|
||||
eth_t *eth;
|
||||
char pcapdev[128];
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
|
||||
if (eth_get_pcap_devname(device, pcapdev, sizeof(pcapdev)) != 0)
|
||||
return (NULL);
|
||||
|
||||
if ((eth = calloc(1, sizeof(*eth))) == NULL)
|
||||
return (NULL);
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
eth->lpa = PacketOpenAdapter(pcapdev);
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
if (eth->lpa == NULL) {
|
||||
eth_close(eth);
|
||||
return (NULL);
|
||||
@@ -67,11 +75,21 @@ eth_send(eth_t *eth, const void *buf, size_t len)
|
||||
eth_t *
|
||||
eth_close(eth_t *eth)
|
||||
{
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
if (eth != NULL) {
|
||||
if (eth->pkt != NULL)
|
||||
PacketFreePacket(eth->pkt);
|
||||
if (eth->lpa != NULL)
|
||||
{
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
PacketCloseAdapter(eth->lpa);
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
}
|
||||
free(eth);
|
||||
}
|
||||
return (NULL);
|
||||
|
||||
@@ -427,6 +427,8 @@ intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen)
|
||||
pcap_if_t *pdev, *selected;
|
||||
intf_t *intf;
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
|
||||
if ((intf = intf_open()) == NULL)
|
||||
return (-1);
|
||||
@@ -441,10 +443,20 @@ intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
if (pcap_findalldevs(&pcapdevs, errbuf) == -1) {
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
intf_close(intf);
|
||||
return (-1);
|
||||
}
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
|
||||
/* Loop through all the pcap devices until we find a match. */
|
||||
selected = NULL;
|
||||
|
||||
@@ -4061,6 +4061,8 @@ pcap_t *my_pcap_open_live(const char *device, int snaplen, int promisc, int to_m
|
||||
with what we have then ... */
|
||||
Strncpy(pcapdev, device, sizeof(pcapdev));
|
||||
}
|
||||
HANDLE pcapMutex = CreateMutex(NULL, 0, TEXT("Global\\DnetPcapHangAvoidanceMutex"));
|
||||
DWORD wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
#else
|
||||
Strncpy(pcapdev, device, sizeof(pcapdev));
|
||||
#endif
|
||||
@@ -4078,6 +4080,10 @@ pcap_t *my_pcap_open_live(const char *device, int snaplen, int promisc, int to_m
|
||||
} while (!pt);
|
||||
|
||||
#ifdef WIN32
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
/* We want any responses back ASAP */
|
||||
pcap_setmintocopy(pt, 1);
|
||||
#endif
|
||||
|
||||
@@ -49,6 +49,8 @@ pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
|
||||
npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
|
||||
LONG if_addr_size;
|
||||
int res = 0;
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
|
||||
if_addr_size = MAX_NETWORK_ADDRESSES;
|
||||
|
||||
@@ -65,6 +67,8 @@ pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
|
||||
/*
|
||||
* Get the list of addresses for the interface.
|
||||
*/
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
|
||||
/*
|
||||
* Failure.
|
||||
@@ -75,8 +79,16 @@ pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
|
||||
*
|
||||
* We return an entry with an empty address list.
|
||||
*/
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
return (0);
|
||||
}
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
|
||||
/*
|
||||
* Now add the addresses.
|
||||
@@ -127,6 +139,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
char *AdaptersName;
|
||||
ULONG NameLength;
|
||||
char *name;
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
|
||||
/*
|
||||
* Find out how big a buffer we need.
|
||||
@@ -149,6 +166,10 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
if (!PacketGetAdapterNames(NULL, &NameLength))
|
||||
{
|
||||
DWORD last_error = GetLastError();
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
|
||||
if (last_error != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
@@ -158,6 +179,10 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
|
||||
if (NameLength > 0)
|
||||
AdaptersName = (char*) malloc(NameLength);
|
||||
@@ -172,13 +197,23 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"PacketGetAdapterNames: %s",
|
||||
pcap_win32strerror());
|
||||
free(AdaptersName);
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
return (-1);
|
||||
}
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
|
||||
/*
|
||||
* "PacketGetAdapterNames()" returned a list of
|
||||
|
||||
@@ -983,8 +983,12 @@ pcap_lookupdev(errbuf)
|
||||
{
|
||||
DWORD dwVersion;
|
||||
DWORD dwWindowsMajorVersion;
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
dwVersion = GetVersion(); /* get the OS version */
|
||||
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
|
||||
if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
|
||||
/*
|
||||
@@ -994,9 +998,21 @@ pcap_lookupdev(errbuf)
|
||||
static char AdaptersName[8192];
|
||||
|
||||
if (PacketGetAdapterNames(AdaptersName,&NameLength) )
|
||||
{
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
return (AdaptersName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
|
||||
@@ -1016,12 +1032,20 @@ pcap_lookupdev(errbuf)
|
||||
|
||||
if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
|
||||
{
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"PacketGetAdapterNames: %s",
|
||||
pcap_win32strerror());
|
||||
free(TAdaptersName);
|
||||
return NULL;
|
||||
}
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
|
||||
|
||||
tAstr = (char*)TAdaptersName;
|
||||
@@ -1056,6 +1080,10 @@ pcap_lookupdev(errbuf)
|
||||
free(TAdaptersName);
|
||||
return (char *)(AdaptersName);
|
||||
}
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -1073,11 +1101,23 @@ pcap_lookupnet(device, netp, maskp, errbuf)
|
||||
LONG if_addr_size = 1;
|
||||
struct sockaddr_in *t_addr;
|
||||
unsigned int i;
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
*netp = *maskp = 0;
|
||||
return (0);
|
||||
}
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
|
||||
for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
|
||||
{
|
||||
|
||||
@@ -492,8 +492,16 @@ pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
|
||||
static void
|
||||
pcap_cleanup_win32(pcap_t *p)
|
||||
{
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
if (p->adapter != NULL) {
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
PacketCloseAdapter(p->adapter);
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
p->adapter = NULL;
|
||||
}
|
||||
if (p->Packet) {
|
||||
@@ -508,6 +516,8 @@ pcap_activate_win32(pcap_t *p)
|
||||
{
|
||||
struct pcap_win *pw = p->priv;
|
||||
NetType type;
|
||||
HANDLE pcapMutex;
|
||||
DWORD wait;
|
||||
|
||||
if (p->opt.rfmon) {
|
||||
/*
|
||||
@@ -521,11 +531,18 @@ pcap_activate_win32(pcap_t *p)
|
||||
/* Init WinSock */
|
||||
wsockinit();
|
||||
|
||||
pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
||||
wait = WaitForSingleObject(pcapMutex, INFINITE);
|
||||
|
||||
p->adapter = PacketOpenAdapter(p->opt.source);
|
||||
|
||||
if (p->adapter == NULL)
|
||||
{
|
||||
/* Adapter detected but we are not able to open it. Return failure. */
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
@@ -533,9 +550,17 @@ pcap_activate_win32(pcap_t *p)
|
||||
/*get network type*/
|
||||
if(PacketGetNetType (p->adapter,&type) == FALSE)
|
||||
{
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
|
||||
goto bad;
|
||||
}
|
||||
if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(pcapMutex);
|
||||
}
|
||||
CloseHandle(pcapMutex);
|
||||
|
||||
/*Set the linktype*/
|
||||
switch (type.LinkType)
|
||||
|
||||
Reference in New Issue
Block a user