Skip to content

Commit efa0dc3

Browse files
author
nnposter
committed
Fix off-by-one overflow in the IP protocol table.
Fixes nmap#2896, closes nmap#2897, closes nmap#2900
1 parent 667527c commit efa0dc3

File tree

5 files changed

+17
-12
lines changed

5 files changed

+17
-12
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ o [GH#1451] Nmap now performs forward DNS lookups in parallel, using the same
1616
o [GH#2571, GH#2572, GH#2622, GH#2784] Various bug fixes in the mssql NSE
1717
library [johnjaylward, nnposter]
1818

19+
o [GH#2900, GH#2896, GH#2897] Nmap is now able to scan IP protocol 255.
20+
[nnposter]
21+
1922
Nmap 7.95 [2024-04-23]
2023

2124
o Integrated over 4,000 of your IPv4 OS fingerprints. Added 336 signatures,

portlist.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ void PortList::setPortState(u16 portno, u8 protocol, int state, int *oldstate) {
480480
state != PORT_CLOSEDFILTERED)
481481
fatal("%s: attempt to add port number %d with illegal state %d\n", __func__, portno, state);
482482

483-
assert(protocol!=IPPROTO_IP || portno<256);
483+
assert(protocol!=IPPROTO_IP || portno<=MAX_IPPROTONUM);
484484

485485
bool created = false;
486486
current = createPort(portno, protocol, &created);
@@ -566,7 +566,7 @@ Port *PortList::nextPort(const Port *cur, Port *next,
566566
if (cur) {
567567
proto = INPROTO2PORTLISTPROTO(cur->proto);
568568
assert(port_map[proto]!=NULL); // Hmm, it's not possible to handle port that doesn't have anything in map
569-
assert(cur->proto!=IPPROTO_IP || cur->portno<256);
569+
assert(cur->proto!=IPPROTO_IP || cur->portno<=MAX_IPPROTONUM);
570570
mapped_pno = port_map[proto][cur->portno];
571571
mapped_pno++; // we're interested in next port after current
572572
} else { // running for the first time
@@ -615,7 +615,7 @@ void PortList::mapPort(u16 *portno, u8 *protocol) const {
615615
mapped_protocol = INPROTO2PORTLISTPROTO(*protocol);
616616

617617
if (*protocol == IPPROTO_IP)
618-
assert(*portno < 256);
618+
assert(*portno <= MAX_IPPROTONUM);
619619
if(port_map[mapped_protocol]==NULL || port_list[mapped_protocol]==NULL) {
620620
fatal("%s(%i,%i): you're trying to access uninitialized protocol", __func__, *portno, *protocol);
621621
}
@@ -713,7 +713,7 @@ int PortList::port_list_count[PORTLIST_PROTO_MAX];
713713
* should be sorted. */
714714
void PortList::initializePortMap(int protocol, u16 *ports, int portcount) {
715715
int i;
716-
int ports_max = (protocol == IPPROTO_IP) ? 256 : 65536;
716+
int ports_max = (protocol == IPPROTO_IP) ? MAX_IPPROTONUM + 1 : 65536;
717717
int proto = INPROTO2PORTLISTPROTO(protocol);
718718

719719
if (port_map[proto] != NULL || port_map_rev[proto] != NULL)

protocols.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct strcmp_comparator {
7979

8080
// IP Protocol number is 8 bits wide
8181
// protocol_table[IPPROTO_TCP] == {"tcp", 6}
82-
static struct nprotoent *protocol_table[UCHAR_MAX];
82+
static struct nprotoent *protocol_table[MAX_IPPROTONUM + 1];
8383
// proto_map["tcp"] = {"tcp", 6}
8484
typedef std::map<const char *, struct nprotoent, strcmp_comparator> ProtoMap;
8585
static ProtoMap proto_map;
@@ -119,7 +119,7 @@ static int nmap_protocols_init() {
119119
if (*p == '#' || *p == '\0')
120120
continue;
121121
res = sscanf(line, "%127s %hu", protocolname, &protno);
122-
if (res !=2 || protno > UCHAR_MAX) {
122+
if (res !=2 || protno > MAX_IPPROTONUM) {
123123
error("Parse error in protocols file %s line %d", filename, lineno);
124124
continue;
125125
}
@@ -191,7 +191,7 @@ const struct nprotoent *nmap_getprotbynum(int num) {
191191
if (nmap_protocols_init() == -1)
192192
return NULL;
193193

194-
assert(num >= 0 && num < UCHAR_MAX);
194+
assert(num >= 0 && num <= MAX_IPPROTONUM);
195195
return protocol_table[num];
196196
}
197197

protocols.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ int addprotocolsfromservmask(char *mask, u8 *porttbl);
7979
const struct nprotoent *nmap_getprotbynum(int num);
8080
const struct nprotoent *nmap_getprotbyname(const char *name);
8181

82+
#define MAX_IPPROTONUM 255
83+
8284
#define MAX_IPPROTOSTRLEN 4
8385
#define IPPROTO2STR(p) \
8486
((p)==IPPROTO_TCP ? "tcp" : \

scan_lists.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
165165
ports->udp_count++;
166166
if (porttbl[i] & SCAN_SCTP_PORT)
167167
ports->sctp_count++;
168-
if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
168+
if (porttbl[i] & SCAN_PROTOCOLS && i <= MAX_IPPROTONUM)
169169
ports->prot_count++;
170170
}
171171

@@ -192,7 +192,7 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
192192
ports->udp_ports[udpi++] = i;
193193
if (porttbl[i] & SCAN_SCTP_PORT)
194194
ports->sctp_ports[sctpi++] = i;
195-
if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
195+
if (porttbl[i] & SCAN_PROTOCOLS && i <= MAX_IPPROTONUM)
196196
ports->prots[proti++] = i;
197197
}
198198

@@ -388,7 +388,7 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
388388
} else if (isdigit((int) (unsigned char) *current_range)) {
389389
rangestart = strtol(current_range, &endptr, 10);
390390
if (range_type & SCAN_PROTOCOLS) {
391-
if (rangestart < 0 || rangestart > 255)
391+
if (rangestart < 0 || rangestart > MAX_IPPROTONUM)
392392
fatal("Protocols specified must be between 0 and 255 inclusive");
393393
} else {
394394
if (rangestart < 0 || rangestart > 65535)
@@ -429,13 +429,13 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
429429
if (!*current_range || *current_range == ',' || *current_range == ']') {
430430
/* Ended with a -, meaning up until the last possible port */
431431
if (range_type & SCAN_PROTOCOLS)
432-
rangeend = 255;
432+
rangeend = MAX_IPPROTONUM;
433433
else
434434
rangeend = 65535;
435435
} else if (isdigit((int) (unsigned char) *current_range)) {
436436
rangeend = strtol(current_range, &endptr, 10);
437437
if (range_type & SCAN_PROTOCOLS) {
438-
if (rangeend < 0 || rangeend > 255)
438+
if (rangeend < 0 || rangeend > MAX_IPPROTONUM)
439439
fatal("Protocols specified must be between 0 and 255 inclusive");
440440
} else {
441441
if (rangeend < 0 || rangeend > 65535)

0 commit comments

Comments
 (0)