From 54bd372ccfc970f6aa93b577e8583d75e5a2df49 Mon Sep 17 00:00:00 2001 From: dmiller Date: Sun, 20 Sep 2015 19:06:12 +0000 Subject: [PATCH] CHANGELOG and mod patches for mutex change --- CHANGELOG | 6 + libdnet-stripped/NMAP_MODIFICATIONS | 175 +++++++++++ ...indows-to-avoid-a-hang-when-accessin.patch | 278 ++++++++++++++++++ 3 files changed, 459 insertions(+) create mode 100644 libpcap/NMAP_MODIFICATIONS/0004-Use-a-mutex-on-Windows-to-avoid-a-hang-when-accessin.patch diff --git a/CHANGELOG b/CHANGELOG index 48a6c28c5b..36c36f26f5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,11 @@ # Nmap Changelog ($Id$); -*-text-*- +o 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. + Nmap hangs 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. [Daniel Miller] + o [NSE] Enhanced reporting of elliptic curve names and strengths in ssl-enum-ciphers. The name of the curve is now reported instead of just "ec" [Brandon Paulsen] diff --git a/libdnet-stripped/NMAP_MODIFICATIONS b/libdnet-stripped/NMAP_MODIFICATIONS index e82ac8d609..8e763a0ba8 100644 --- a/libdnet-stripped/NMAP_MODIFICATIONS +++ b/libdnet-stripped/NMAP_MODIFICATIONS @@ -2087,3 +2087,178 @@ index 2df6a4d..b71fb82 100644 continue; } #endif + +o Avoid a strange hang with the WinPCAP driver when running multiple instances + of Nmap concurrently. + +diff --git a/libdnet-stripped/src/eth-win32.c b/libdnet-stripped/src/eth-win32.c +index 9cbb3f9..de0320e 100644 +--- a/libdnet-stripped/src/eth-win32.c ++++ b/libdnet-stripped/src/eth-win32.c +@@ -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); +diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c +index 3c09f9c..77225b6 100644 +--- a/libdnet-stripped/src/intf-win32.c ++++ b/libdnet-stripped/src/intf-win32.c +@@ -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; + +o 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. + +diff --git a/libdnet-stripped/src/eth-win32.c b/libdnet-stripped/src/eth-win32.c +index 9cbb3f9..de0320e 100644 +--- a/libdnet-stripped/src/eth-win32.c ++++ b/libdnet-stripped/src/eth-win32.c +@@ -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); +diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c +index 3c09f9c..77225b6 100644 +--- a/libdnet-stripped/src/intf-win32.c ++++ b/libdnet-stripped/src/intf-win32.c +@@ -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; diff --git a/libpcap/NMAP_MODIFICATIONS/0004-Use-a-mutex-on-Windows-to-avoid-a-hang-when-accessin.patch b/libpcap/NMAP_MODIFICATIONS/0004-Use-a-mutex-on-Windows-to-avoid-a-hang-when-accessin.patch new file mode 100644 index 0000000000..b1fa0c3638 --- /dev/null +++ b/libpcap/NMAP_MODIFICATIONS/0004-Use-a-mutex-on-Windows-to-avoid-a-hang-when-accessin.patch @@ -0,0 +1,278 @@ +From b91a93895633da9b8184691effc487d8b0c8e82c Mon Sep 17 00:00:00 2001 +From: Daniel Miller +Date: Sun, 20 Sep 2015 18:45:22 +0000 +Subject: [PATCH] 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. +--- + libpcap/fad-win32.c | 35 ++++++++++++++++++++++++++++++++++ + libpcap/inet.c | 40 +++++++++++++++++++++++++++++++++++++++ + libpcap/pcap-win32.c | 25 ++++++++++++++++++++++++ + 3 files changed, 100 insertions(+) + +diff --git a/libpcap/fad-win32.c b/libpcap/fad-win32.c +index 0c856b1..f849d40 100644 +--- a/libpcap/fad-win32.c ++++ b/libpcap/fad-win32.c +@@ -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 +diff --git a/libpcap/inet.c b/libpcap/inet.c +index e7d2104..359557f 100644 +--- a/libpcap/inet.c ++++ b/libpcap/inet.c +@@ -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; iadapter != 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) +-- +1.9.1 +