dhcpc: fix potential invalid memory reads
- check for minimum packet length (44 bytes, which includes the fields we read next) - pass the correct remaining buffer length to dhcpc_parseoptions() - dhcpc_parseoptions(): ensure we never read past the end of the buffer
This commit is contained in:
parent
21f48846dd
commit
7fdd751b7a
@ -326,52 +326,98 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult,
|
||||
|
||||
/* Get subnet mask in network order */
|
||||
|
||||
if (optptr + 6 <= end)
|
||||
{
|
||||
memcpy(&presult->netmask.s_addr, optptr + 2, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
nerr("Packet too short (netmask missing)\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_ROUTER:
|
||||
|
||||
/* Get the default router address in network order */
|
||||
|
||||
if (optptr + 6 <= end)
|
||||
{
|
||||
memcpy(&presult->default_router.s_addr, optptr + 2, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
nerr("Packet too short (router address missing)\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_DNS_SERVER:
|
||||
|
||||
/* Get the DNS server address in network order */
|
||||
|
||||
if (optptr + 6 <= end)
|
||||
{
|
||||
memcpy(&presult->dnsaddr.s_addr, optptr + 2, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
nerr("Packet too short (DNS address missing)\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_MSG_TYPE:
|
||||
|
||||
/* Get message type */
|
||||
|
||||
if (optptr + 3 <= end)
|
||||
{
|
||||
type = *(optptr + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
nerr("Packet too short (type missing)\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_SERVER_ID:
|
||||
|
||||
/* Get server address in network order */
|
||||
|
||||
if (optptr + 6 <= end)
|
||||
{
|
||||
memcpy(&presult->serverid.s_addr, optptr + 2, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
nerr("Packet too short (server address missing)\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_LEASE_TIME:
|
||||
{
|
||||
|
||||
/* Get lease time (in seconds) in host order */
|
||||
|
||||
if (optptr + 6 <= end)
|
||||
{
|
||||
uint16_t tmp[2];
|
||||
memcpy(tmp, optptr + 2, 4);
|
||||
presult->lease_time = ((uint32_t)ntohs(tmp[0])) << 16 |
|
||||
(uint32_t)ntohs(tmp[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
nerr("Packet too short (lease time missing)\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_END:
|
||||
return type;
|
||||
}
|
||||
|
||||
if (optptr + 1 >= end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
optptr += optptr[1] + 2;
|
||||
}
|
||||
|
||||
@ -385,13 +431,15 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult,
|
||||
static uint8_t dhcpc_parsemsg(FAR struct dhcpc_state_s *pdhcpc, int buflen,
|
||||
FAR struct dhcpc_state *presult)
|
||||
{
|
||||
if (pdhcpc->packet.op == DHCP_REPLY &&
|
||||
if (buflen >= 44 && pdhcpc->packet.op == DHCP_REPLY &&
|
||||
memcmp(pdhcpc->packet.xid, xid, sizeof(xid)) == 0 &&
|
||||
memcmp(pdhcpc->packet.chaddr,
|
||||
pdhcpc->ds_macaddr, pdhcpc->ds_maclen) == 0)
|
||||
{
|
||||
memcpy(&presult->ipaddr.s_addr, pdhcpc->packet.yiaddr, 4);
|
||||
return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4], buflen);
|
||||
return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4],
|
||||
buflen -
|
||||
(offsetof(struct dhcp_msg, options) + 4));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user