diff --git a/backport-Fix-off-by-one-overflow-in-the-IP-protocol-table.patch b/backport-Fix-off-by-one-overflow-in-the-IP-protocol-table.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e00d787dabb08f1ceb84e2a210f1a0fb6e59aff --- /dev/null +++ b/backport-Fix-off-by-one-overflow-in-the-IP-protocol-table.patch @@ -0,0 +1,143 @@ +From 98cdf36732634822aa433a907aee8a6935176b41 Mon Sep 17 00:00:00 2001 +From: nnposter +Date: Sat, 3 Aug 2024 19:48:08 -0600 +Subject: [PATCH] Fix off-by-one overflow in the IP protocol table + +--- + portlist.cc | 8 ++++---- + protocols.cc | 6 +++--- + protocols.h | 2 ++ + scan_lists.cc | 10 +++++----- + 4 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/portlist.cc b/portlist.cc +index fb237f0..89a757e 100644 +--- a/portlist.cc ++++ b/portlist.cc +@@ -479,7 +479,7 @@ void PortList::setPortState(u16 portno, u8 protocol, int state) { + state != PORT_CLOSEDFILTERED) + fatal("%s: attempt to add port number %d with illegal state %d\n", __func__, portno, state); + +- assert(protocol!=IPPROTO_IP || portno<256); ++ assert(protocol!=IPPROTO_IP || portno<=MAX_IPPROTONUM); + + oldport = lookupPort(portno, protocol); + if (oldport != NULL) { +@@ -564,7 +564,7 @@ Port *PortList::nextPort(const Port *cur, Port *next, + if (cur) { + proto = INPROTO2PORTLISTPROTO(cur->proto); + assert(port_map[proto]!=NULL); // Hmm, it's not possible to handle port that doesn't have anything in map +- assert(cur->proto!=IPPROTO_IP || cur->portno<256); ++ assert(cur->proto!=IPPROTO_IP || cur->portno<=MAX_IPPROTONUM); + mapped_pno = port_map[proto][cur->portno]; + mapped_pno++; // we're interested in next port after current + } else { // running for the first time +@@ -613,7 +613,7 @@ void PortList::mapPort(u16 *portno, u8 *protocol) const { + mapped_protocol = INPROTO2PORTLISTPROTO(*protocol); + + if (*protocol == IPPROTO_IP) +- assert(*portno < 256); ++ assert(*portno <= MAX_IPPROTONUM); + if(port_map[mapped_protocol]==NULL || port_list[mapped_protocol]==NULL) { + fatal("%s(%i,%i): you're trying to access uninitialized protocol", __func__, *portno, *protocol); + } +@@ -709,7 +709,7 @@ int PortList::port_list_count[PORTLIST_PROTO_MAX]; + * should be sorted. */ + void PortList::initializePortMap(int protocol, u16 *ports, int portcount) { + int i; +- int ports_max = (protocol == IPPROTO_IP) ? 256 : 65536; ++ int ports_max = (protocol == IPPROTO_IP) ? MAX_IPPROTONUM + 1 : 65536; + int proto = INPROTO2PORTLISTPROTO(protocol); + + if (port_map[proto] != NULL || port_map_rev[proto] != NULL) +diff --git a/protocols.cc b/protocols.cc +index 6793c90..a3d4bd4 100644 +--- a/protocols.cc ++++ b/protocols.cc +@@ -78,7 +78,7 @@ struct strcmp_comparator { + + // IP Protocol number is 8 bits wide + // protocol_table[IPPROTO_TCP] == {"tcp", 6} +-static struct nprotoent *protocol_table[UCHAR_MAX]; ++static struct nprotoent *protocol_table[MAX_IPPROTONUM + 1]; + // proto_map["tcp"] = {"tcp", 6} + typedef std::map ProtoMap; + static ProtoMap proto_map; +@@ -118,7 +118,7 @@ static int nmap_protocols_init() { + if (*p == '#' || *p == '\0') + continue; + res = sscanf(line, "%127s %hu", protocolname, &protno); +- if (res !=2 || protno > UCHAR_MAX) { ++ if (res !=2 || protno > MAX_IPPROTONUM) { + error("Parse error in protocols file %s line %d", filename, lineno); + continue; + } +@@ -190,7 +190,7 @@ const struct nprotoent *nmap_getprotbynum(int num) { + if (nmap_protocols_init() == -1) + return NULL; + +- assert(num >= 0 && num < UCHAR_MAX); ++ assert(num >= 0 && num <= MAX_IPPROTONUM); + return protocol_table[num]; + } + +diff --git a/protocols.h b/protocols.h +index 9b9dd15..fe7ba6e 100644 +--- a/protocols.h ++++ b/protocols.h +@@ -78,6 +78,8 @@ int addprotocolsfromservmask(char *mask, u8 *porttbl); + const struct nprotoent *nmap_getprotbynum(int num); + const struct nprotoent *nmap_getprotbyname(const char *name); + ++#define MAX_IPPROTONUM 255 ++ + #define MAX_IPPROTOSTRLEN 4 + #define IPPROTO2STR(p) \ + ((p)==IPPROTO_TCP ? "tcp" : \ +diff --git a/scan_lists.cc b/scan_lists.cc +index 8d5e345..052325a 100644 +--- a/scan_lists.cc ++++ b/scan_lists.cc +@@ -164,7 +164,7 @@ void getpts(const char *origexpr, struct scan_lists *ports) { + ports->udp_count++; + if (porttbl[i] & SCAN_SCTP_PORT) + ports->sctp_count++; +- if (porttbl[i] & SCAN_PROTOCOLS && i < 256) ++ if (porttbl[i] & SCAN_PROTOCOLS && i <= MAX_IPPROTONUM) + ports->prot_count++; + } + +@@ -191,7 +191,7 @@ void getpts(const char *origexpr, struct scan_lists *ports) { + ports->udp_ports[udpi++] = i; + if (porttbl[i] & SCAN_SCTP_PORT) + ports->sctp_ports[sctpi++] = i; +- if (porttbl[i] & SCAN_PROTOCOLS && i < 256) ++ if (porttbl[i] & SCAN_PROTOCOLS && i <= MAX_IPPROTONUM) + ports->prots[proti++] = i; + } + +@@ -387,7 +387,7 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_ + } else if (isdigit((int) (unsigned char) *current_range)) { + rangestart = strtol(current_range, &endptr, 10); + if (range_type & SCAN_PROTOCOLS) { +- if (rangestart < 0 || rangestart > 255) ++ if (rangestart < 0 || rangestart > MAX_IPPROTONUM) + fatal("Protocols specified must be between 0 and 255 inclusive"); + } else { + if (rangestart < 0 || rangestart > 65535) +@@ -428,13 +428,13 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_ + if (!*current_range || *current_range == ',' || *current_range == ']') { + /* Ended with a -, meaning up until the last possible port */ + if (range_type & SCAN_PROTOCOLS) +- rangeend = 255; ++ rangeend = MAX_IPPROTONUM; + else + rangeend = 65535; + } else if (isdigit((int) (unsigned char) *current_range)) { + rangeend = strtol(current_range, &endptr, 10); + if (range_type & SCAN_PROTOCOLS) { +- if (rangeend < 0 || rangeend > 255) ++ if (rangeend < 0 || rangeend > MAX_IPPROTONUM) + fatal("Protocols specified must be between 0 and 255 inclusive"); + } else { + if (rangeend < 0 || rangeend > 65535) diff --git a/nmap.spec b/nmap.spec index 3a48987e936e8a3a83a520cb7b7a9dd1227e61c0..e146aa23cfbacf99e6ad6bc1308edfc237070e90 100644 --- a/nmap.spec +++ b/nmap.spec @@ -3,7 +3,7 @@ Name: nmap Epoch: 2 Version: 7.94 -Release: 7 +Release: 8 License: GPL-2.0-or-later Summary: A tool for network discovery and security auditing. Requires: %{name}-ncat = %{epoch}:%{version}-%{release} @@ -25,6 +25,7 @@ Patch0006: backport-nping-fix-out-of-bounds-access.patch Patch0007: backport-Ncat-server-UDP-do-not-quit-after-EOF-on-STDIN.-Fixe.patch Patch0008: remove-password-printing.patch Patch0009: backport-Bug-Lua-can-generate-wrong-code-when-_ENV-is-const.patch +Patch0010: backport-Fix-off-by-one-overflow-in-the-IP-protocol-table.patch %define pixmap_srcdir zenmap/share/pixmaps @@ -75,6 +76,11 @@ ln -s ncat %{buildroot}%{_bindir}/nc %{_mandir}/man1/*.1.gz %changelog +* Fri Jul 18 2025 andy - 2:7.94-8 +- Type:bugfix +- SUG:NA +- DESC:backport Fix off-by-one overflow in the IP protocol table + * Wed Jan 15 2025 xingwei - 2:7.94-7 - Type:CVE - CVE:CVE-2022-28805