1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

CHANGELOG and mod patches for mutex change

This commit is contained in:
dmiller
2015-09-20 19:06:12 +00:00
parent 3d9e348832
commit 54bd372ccf
3 changed files with 459 additions and 0 deletions

View File

@@ -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]

View File

@@ -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;

View File

@@ -0,0 +1,278 @@
From b91a93895633da9b8184691effc487d8b0c8e82c Mon Sep 17 00:00:00 2001
From: Daniel Miller <daniel@bonsaiviking.com>
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; i<MAX_NETWORK_ADDRESSES; i++)
{
diff --git a/libpcap/pcap-win32.c b/libpcap/pcap-win32.c
index f449f79..2e83e75 100644
--- a/libpcap/pcap-win32.c
+++ b/libpcap/pcap-win32.c
@@ -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)
--
1.9.1