uip6: sanitize parsing of ext header options

This commit is contained in:
Simon Duquennoy 2018-10-19 15:45:16 +02:00
parent ff825daaea
commit 9194e82168

View File

@ -823,10 +823,21 @@ ext_hdr_options_process(uint8_t *ext_buf)
* 8 bytes, excluding the first 8 bytes * 8 bytes, excluding the first 8 bytes
* length field in an option : the length of data in the option * length field in an option : the length of data in the option
*/ */
uint8_t opt_offset = 2; uint8_t opt_offset = 2; /* 2 first bytes in ext header */
struct uip_hbho_hdr *ext_hdr = (struct uip_hbho_hdr *)ext_buf; struct uip_hbho_hdr *ext_hdr = (struct uip_hbho_hdr *)ext_buf;
while(opt_offset < ((ext_hdr->len << 3) + 8)) { uint8_t ext_hdr_len = (ext_hdr->len << 3) + 8;
while(opt_offset + 2 <= ext_hdr_len) { /* + 2 for opt header */
struct uip_ext_hdr_opt *opt_hdr = (struct uip_ext_hdr_opt *)(ext_buf + opt_offset); struct uip_ext_hdr_opt *opt_hdr = (struct uip_ext_hdr_opt *)(ext_buf + opt_offset);
uint8_t opt_len = opt_hdr->len + 2;
if(opt_offset + opt_len > ext_hdr_len) {
LOG_ERR("RPL Option too long: Dropping Packet\n");
uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION,
(ext_buf + opt_offset) - uip_buf);
return 2;
}
switch(opt_hdr->type) { switch(opt_hdr->type) {
/* /*
* for now we do not support any options except padding ones * for now we do not support any options except padding ones
@ -839,7 +850,7 @@ ext_hdr_options_process(uint8_t *ext_buf)
break; break;
case UIP_EXT_HDR_OPT_PADN: case UIP_EXT_HDR_OPT_PADN:
LOG_DBG("Processing PADN option\n"); LOG_DBG("Processing PADN option\n");
opt_offset += ((struct uip_ext_hdr_opt_padn *)opt_hdr)->opt_len + 2; opt_offset += opt_len;
break; break;
case UIP_EXT_HDR_OPT_RPL: case UIP_EXT_HDR_OPT_RPL:
/* Fixes situation when a node that is not using RPL /* Fixes situation when a node that is not using RPL
@ -855,8 +866,8 @@ ext_hdr_options_process(uint8_t *ext_buf)
LOG_ERR("RPL Option Error: Dropping Packet\n"); LOG_ERR("RPL Option Error: Dropping Packet\n");
return 1; return 1;
} }
opt_offset += opt_hdr->len + 2; opt_offset += opt_len;
return 0; break;
default: default:
/* /*
* check the two highest order bits of the option * check the two highest order bits of the option
@ -887,7 +898,7 @@ ext_hdr_options_process(uint8_t *ext_buf)
return 2; return 2;
} }
/* in the cases were we did not discard, update ext_opt* */ /* in the cases were we did not discard, update ext_opt* */
opt_offset += opt_hdr->len + 2; opt_offset += opt_len;
break; break;
} }
} }