Skip to content

Commit 01430ae

Browse files
committed
nmap: Backport a patch to fix "nmap -sO" runtime error:
nmap/nmap@efa0dc3#diff-2676198037146235a5bbe1cdb0cbcf58a94ff6dfa8bca0f81a49d30c688405d7R483 root # nmap -sO 127.0.0.1 Starting Nmap 7.95 ( https://nmap.org ) at 2024-10-11 13:19 UTC Nmap scan report for localhost (127.0.0.1) Host is up (0.000030s latency). Not shown: 246 closed n/a protocols (proto-unreach) nmap: protocols.cc:194: const nprotoent* nmap_getprotbynum(int): Assertion `num >= 0 && num < UCHAR_MAX' failed. Aborted (core dumped) Signed-off-by: Lei Maohui <leimaohui@fujitsu.com>
1 parent fbabb2d commit 01430ae

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
From efa0dc36f2ecade6ba8d2ed25dd4d5fbffdea308 Mon Sep 17 00:00:00 2001
2+
From: nnposter <nnposter@e0a8ed71-7df4-0310-8962-fdc924857419>
3+
Date: Thu, 8 Aug 2024 01:31:06 +0000
4+
Subject: [PATCH] Fix off-by-one overflow in the IP protocol table. Fixes
5+
#2896, closes #2897, closes #2900
6+
7+
---
8+
portlist.cc | 8 ++++----
9+
protocols.cc | 6 +++---
10+
protocols.h | 2 ++
11+
scan_lists.cc | 10 +++++-----
12+
5 files changed, 17 insertions(+), 12 deletions(-)
13+
14+
diff --git a/portlist.cc b/portlist.cc
15+
index 9e7044795..12f8f401e 100644
16+
--- a/portlist.cc
17+
+++ b/portlist.cc
18+
@@ -480,7 +480,7 @@ void PortList::setPortState(u16 portno, u8 protocol, int state, int *oldstate) {
19+
state != PORT_CLOSEDFILTERED)
20+
fatal("%s: attempt to add port number %d with illegal state %d\n", __func__, portno, state);
21+
22+
- assert(protocol!=IPPROTO_IP || portno<256);
23+
+ assert(protocol!=IPPROTO_IP || portno<=MAX_IPPROTONUM);
24+
25+
bool created = false;
26+
current = createPort(portno, protocol, &created);
27+
@@ -566,7 +566,7 @@ Port *PortList::nextPort(const Port *cur, Port *next,
28+
if (cur) {
29+
proto = INPROTO2PORTLISTPROTO(cur->proto);
30+
assert(port_map[proto]!=NULL); // Hmm, it's not possible to handle port that doesn't have anything in map
31+
- assert(cur->proto!=IPPROTO_IP || cur->portno<256);
32+
+ assert(cur->proto!=IPPROTO_IP || cur->portno<=MAX_IPPROTONUM);
33+
mapped_pno = port_map[proto][cur->portno];
34+
mapped_pno++; // we're interested in next port after current
35+
} else { // running for the first time
36+
@@ -615,7 +615,7 @@ void PortList::mapPort(u16 *portno, u8 *protocol) const {
37+
mapped_protocol = INPROTO2PORTLISTPROTO(*protocol);
38+
39+
if (*protocol == IPPROTO_IP)
40+
- assert(*portno < 256);
41+
+ assert(*portno <= MAX_IPPROTONUM);
42+
if(port_map[mapped_protocol]==NULL || port_list[mapped_protocol]==NULL) {
43+
fatal("%s(%i,%i): you're trying to access uninitialized protocol", __func__, *portno, *protocol);
44+
}
45+
@@ -713,7 +713,7 @@ int PortList::port_list_count[PORTLIST_PROTO_MAX];
46+
* should be sorted. */
47+
void PortList::initializePortMap(int protocol, u16 *ports, int portcount) {
48+
int i;
49+
- int ports_max = (protocol == IPPROTO_IP) ? 256 : 65536;
50+
+ int ports_max = (protocol == IPPROTO_IP) ? MAX_IPPROTONUM + 1 : 65536;
51+
int proto = INPROTO2PORTLISTPROTO(protocol);
52+
53+
if (port_map[proto] != NULL || port_map_rev[proto] != NULL)
54+
diff --git a/protocols.cc b/protocols.cc
55+
index 423fc91ea..73161253e 100644
56+
--- a/protocols.cc
57+
+++ b/protocols.cc
58+
@@ -79,7 +79,7 @@ struct strcmp_comparator {
59+
60+
// IP Protocol number is 8 bits wide
61+
// protocol_table[IPPROTO_TCP] == {"tcp", 6}
62+
-static struct nprotoent *protocol_table[UCHAR_MAX];
63+
+static struct nprotoent *protocol_table[MAX_IPPROTONUM + 1];
64+
// proto_map["tcp"] = {"tcp", 6}
65+
typedef std::map<const char *, struct nprotoent, strcmp_comparator> ProtoMap;
66+
static ProtoMap proto_map;
67+
@@ -119,7 +119,7 @@ static int nmap_protocols_init() {
68+
if (*p == '#' || *p == '\0')
69+
continue;
70+
res = sscanf(line, "%127s %hu", protocolname, &protno);
71+
- if (res !=2 || protno > UCHAR_MAX) {
72+
+ if (res !=2 || protno > MAX_IPPROTONUM) {
73+
error("Parse error in protocols file %s line %d", filename, lineno);
74+
continue;
75+
}
76+
@@ -191,7 +191,7 @@ const struct nprotoent *nmap_getprotbynum(int num) {
77+
if (nmap_protocols_init() == -1)
78+
return NULL;
79+
80+
- assert(num >= 0 && num < UCHAR_MAX);
81+
+ assert(num >= 0 && num <= MAX_IPPROTONUM);
82+
return protocol_table[num];
83+
}
84+
85+
diff --git a/protocols.h b/protocols.h
86+
index 2a4b053d1..611037ac8 100644
87+
--- a/protocols.h
88+
+++ b/protocols.h
89+
@@ -79,6 +79,8 @@ int addprotocolsfromservmask(char *mask, u8 *porttbl);
90+
const struct nprotoent *nmap_getprotbynum(int num);
91+
const struct nprotoent *nmap_getprotbyname(const char *name);
92+
93+
+#define MAX_IPPROTONUM 255
94+
+
95+
#define MAX_IPPROTOSTRLEN 4
96+
#define IPPROTO2STR(p) \
97+
((p)==IPPROTO_TCP ? "tcp" : \
98+
diff --git a/scan_lists.cc b/scan_lists.cc
99+
index f02e279a1..ebe1357cf 100644
100+
--- a/scan_lists.cc
101+
+++ b/scan_lists.cc
102+
@@ -165,7 +165,7 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
103+
ports->udp_count++;
104+
if (porttbl[i] & SCAN_SCTP_PORT)
105+
ports->sctp_count++;
106+
- if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
107+
+ if (porttbl[i] & SCAN_PROTOCOLS && i <= MAX_IPPROTONUM)
108+
ports->prot_count++;
109+
}
110+
111+
@@ -192,7 +192,7 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
112+
ports->udp_ports[udpi++] = i;
113+
if (porttbl[i] & SCAN_SCTP_PORT)
114+
ports->sctp_ports[sctpi++] = i;
115+
- if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
116+
+ if (porttbl[i] & SCAN_PROTOCOLS && i <= MAX_IPPROTONUM)
117+
ports->prots[proti++] = i;
118+
}
119+
120+
@@ -388,7 +388,7 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
121+
} else if (isdigit((int) (unsigned char) *current_range)) {
122+
rangestart = strtol(current_range, &endptr, 10);
123+
if (range_type & SCAN_PROTOCOLS) {
124+
- if (rangestart < 0 || rangestart > 255)
125+
+ if (rangestart < 0 || rangestart > MAX_IPPROTONUM)
126+
fatal("Protocols specified must be between 0 and 255 inclusive");
127+
} else {
128+
if (rangestart < 0 || rangestart > 65535)
129+
@@ -429,13 +429,13 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
130+
if (!*current_range || *current_range == ',' || *current_range == ']') {
131+
/* Ended with a -, meaning up until the last possible port */
132+
if (range_type & SCAN_PROTOCOLS)
133+
- rangeend = 255;
134+
+ rangeend = MAX_IPPROTONUM;
135+
else
136+
rangeend = 65535;
137+
} else if (isdigit((int) (unsigned char) *current_range)) {
138+
rangeend = strtol(current_range, &endptr, 10);
139+
if (range_type & SCAN_PROTOCOLS) {
140+
- if (rangeend < 0 || rangeend > 255)
141+
+ if (rangeend < 0 || rangeend > MAX_IPPROTONUM)
142+
fatal("Protocols specified must be between 0 and 255 inclusive");
143+
} else {
144+
if (rangeend < 0 || rangeend > 65535)
145+
--
146+
2.34.1
147+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
2+
SRC_URI += " \
3+
file://0001-Fix-off-by-one-overflow-in-the-IP-protocol-table.patch \
4+
"

0 commit comments

Comments
 (0)