Skip to content

Commit 82a2499

Browse files
committed
netctld/dhcpcd: tighten up DHCP option validation
Fix various possible OOBs, and add handling for DHO_PAD. Signed-off-by: Pedro Falcato <pedro.falcato@gmail.com>
1 parent 7689ea3 commit 82a2499

1 file changed

Lines changed: 34 additions & 12 deletions

File tree

‎usystem/network/netctld/src/dhcpcd.cpp‎

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,9 @@ off_t dhcp_close_options(dhcp_packet_t *pkt, off_t off)
9898
bool packet::decode()
9999
{
100100
unsigned char *limit = (unsigned char *) packet_ + length;
101-
102101
unsigned char *opt = (unsigned char *) &packet_->options;
103102

104-
if (length <= DHCP_FIXED_NON_UDP)
103+
if (length < DHCP_FIXED_NON_UDP + 4)
105104
{
106105
fprintf(stderr, "dhcpcd: Bad packet length %zu, ignoring!\n", length);
107106
return false;
@@ -116,27 +115,50 @@ bool packet::decode()
116115
bool has_message_type = false;
117116

118117
opt += 4;
119-
while (*opt != DHO_END)
118+
while (opt < limit)
120119
{
121-
/* Check for OOB */
122-
if (opt >= limit)
120+
unsigned char type = *opt, optlen;
121+
122+
if (type == DHO_PAD)
123123
{
124-
fprintf(stderr, "dhcpcd: Went out of bounds processing options, ignoring!\n");
125-
return false;
124+
opt++;
125+
continue;
126126
}
127127

128-
unsigned char type = *opt;
128+
if (type == DHO_END)
129+
break;
130+
/* Check if the length member fits */
131+
if (opt + 1 >= limit)
132+
goto oob;
129133
opt++;
130-
unsigned char length = *opt;
134+
optlen = *opt;
135+
136+
/* Check if the option actually fits */
137+
if (opt + 1 + optlen > limit)
138+
goto oob;
139+
140+
/* No option with a "length" can be 0-sized. This also implicitly makes it so
141+
* has_message_type = true means get_option(DHO_DHCP_MESSAGE_TYPE) succeeds. */
142+
if (!optlen)
143+
{
144+
fprintf(stderr, "dhcpcd: Bad 0-length option, ignoring!\n");
145+
return false;
146+
}
131147

132148
if (type == DHO_DHCP_MESSAGE_TYPE)
133149
has_message_type = true;
134150

135-
dhcp_option option{opt + 1, type, length};
136-
151+
dhcp_option option{opt + 1, type, optlen};
137152
options.push_back(std::move(option));
153+
opt = opt + optlen + 1;
154+
}
138155

139-
opt = opt + length + 1;
156+
/* Check for OOB */
157+
if (opt >= limit)
158+
{
159+
oob:
160+
fprintf(stderr, "dhcpcd: Went out of bounds processing options, ignoring!\n");
161+
return false;
140162
}
141163

142164
if (!has_message_type)

0 commit comments

Comments
 (0)