Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BACKPORT] dhcpc: fix potential invalid memory reads #11

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 61 additions & 13 deletions netutils/dhcpc/dhcpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,52 +323,98 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult,

/* Get subnet mask in network order */

memcpy(&presult->netmask.s_addr, optptr + 2, 4);
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 */

memcpy(&presult->default_router.s_addr, optptr + 2, 4);
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 */

memcpy(&presult->dnsaddr.s_addr, optptr + 2, 4);
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 */

type = *(optptr + 2);
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 */

memcpy(&presult->serverid.s_addr, optptr + 2, 4);
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 */

uint16_t tmp[2];
memcpy(tmp, optptr + 2, 4);
presult->lease_time = ((uint32_t)ntohs(tmp[0])) << 16 |
(uint32_t)ntohs(tmp[1]);
}
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;
}

Expand All @@ -382,13 +428,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;
Expand Down