mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 04:52:02 +08:00
net/sixlowpan: Fix sixlowpan_uncompresshdr_hc06()
This commit fixes sixlowpan_uncompresshdr_hc06() to avoid that the frame data be bigger than the iob->io_len. Signed-off-by: Alan C. Assis <acassis@gmail.com>
This commit is contained in:
committed by
Alan C. Assis
parent
805169cebd
commit
97a50eaf45
@@ -86,6 +86,16 @@
|
||||
#define UNCOMPRESS_MACBASED (1 << 8)
|
||||
#define UNCOMPRESS_ZEROPAD (1 << 9)
|
||||
|
||||
#define HC06_CHECK(ptr, nbytes, endofframe) \
|
||||
do { \
|
||||
if ((ptr) + (nbytes) > endofframe) \
|
||||
{ \
|
||||
nerr("ERROR: HC06 frame truncated at %s:%d\n", \
|
||||
__func__, __LINE__); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@@ -1166,17 +1176,18 @@ int sixlowpan_compresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
* FRAGN frames.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* On success returns 0 otherwise a negative error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
FAR const void *metadata,
|
||||
uint16_t iplen, FAR struct iob_s *iob,
|
||||
FAR uint8_t *fptr, FAR uint8_t *bptr)
|
||||
int sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
FAR const void *metadata,
|
||||
uint16_t iplen, FAR struct iob_s *iob,
|
||||
FAR uint8_t *fptr, FAR uint8_t *bptr)
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr;
|
||||
struct netdev_varaddr_s addr;
|
||||
FAR uint8_t *endofframe;
|
||||
FAR uint8_t *iphc;
|
||||
uint8_t iphc0;
|
||||
uint8_t iphc1;
|
||||
@@ -1193,6 +1204,13 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
|
||||
g_hc06ptr = iphc + 2;
|
||||
|
||||
/* Compute the end of the IOB frame data. All g_hc06ptr accesses
|
||||
* must stay strictly before this pointer. Used by HC06_CHECK()
|
||||
* throughout this function to prevent OOB reads on crafted frames.
|
||||
*/
|
||||
|
||||
endofframe = fptr + iob->io_len;
|
||||
|
||||
ninfo("fptr=%p g_frame_hdrlen=%u iphc=%02x:%02x:%02x g_hc06ptr=%p\n",
|
||||
fptr, g_frame_hdrlen, iphc[0], iphc[1], iphc[2], g_hc06ptr);
|
||||
|
||||
@@ -1201,6 +1219,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
if ((iphc1 & SIXLOWPAN_IPHC_CID) != 0)
|
||||
{
|
||||
ninfo("CID flag set. Increase header by one\n");
|
||||
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||
g_hc06ptr++;
|
||||
}
|
||||
|
||||
@@ -1216,6 +1235,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
|
||||
memcpy(&ipv6->tcf, g_hc06ptr + 1, 3);
|
||||
tmp = *g_hc06ptr;
|
||||
HC06_CHECK(g_hc06ptr, 4, endofframe);
|
||||
g_hc06ptr += 4;
|
||||
|
||||
/* hc06 format of tc is ECN | DSCP , original is DSCP | ECN
|
||||
@@ -1238,6 +1258,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
|
||||
ipv6->tcf = (*g_hc06ptr & 0x0f) | ((*g_hc06ptr >> 2) & 0x30);
|
||||
memcpy(&ipv6->flow, g_hc06ptr + 1, 2);
|
||||
HC06_CHECK(g_hc06ptr, 3, endofframe);
|
||||
g_hc06ptr += 3;
|
||||
}
|
||||
}
|
||||
@@ -1256,6 +1277,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
ipv6->tcf = ((*g_hc06ptr << 6) & 0xc0) |
|
||||
((*g_hc06ptr >> 2) & 0x30);
|
||||
ipv6->flow = 0;
|
||||
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||
g_hc06ptr += 1;
|
||||
}
|
||||
else
|
||||
@@ -1276,6 +1298,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
|
||||
ipv6->proto = *g_hc06ptr;
|
||||
ninfo("Next header inline: %d\n", ipv6->proto);
|
||||
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||
g_hc06ptr += 1;
|
||||
}
|
||||
|
||||
@@ -1288,6 +1311,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
else
|
||||
{
|
||||
ipv6->ttl = *g_hc06ptr;
|
||||
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||
g_hc06ptr += 1;
|
||||
}
|
||||
|
||||
@@ -1301,7 +1325,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((iphc1 & SIXLOWPAN_IPHC_SAC) != 0)
|
||||
@@ -1319,7 +1343,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
if (addrcontext == NULL)
|
||||
{
|
||||
nerr("ERROR: Address context not found\n");
|
||||
return;
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1330,6 +1354,10 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
* address.
|
||||
*/
|
||||
|
||||
/* Source address: worst case 16 bytes inline */
|
||||
|
||||
HC06_CHECK(g_hc06ptr, 16, endofframe);
|
||||
|
||||
uncompress_addr(&addr,
|
||||
tmp != 0 ? addrcontext->prefix : NULL,
|
||||
g_unc_ctxconf[tmp], ipv6->srcipaddr);
|
||||
@@ -1342,6 +1370,10 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
* address.
|
||||
*/
|
||||
|
||||
/* Destination address: worst case 16 bytes inline */
|
||||
|
||||
HC06_CHECK(g_hc06ptr, 16, endofframe);
|
||||
|
||||
uncompress_addr(&addr, g_llprefix, g_unc_llconf[tmp],
|
||||
ipv6->srcipaddr);
|
||||
}
|
||||
@@ -1359,7 +1391,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((iphc1 & SIXLOWPAN_IPHC_M) != 0)
|
||||
@@ -1388,6 +1420,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
if (tmp > 0 && tmp < 3)
|
||||
{
|
||||
prefix[1] = *g_hc06ptr;
|
||||
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||
g_hc06ptr++;
|
||||
}
|
||||
|
||||
@@ -1415,7 +1448,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
if (addrcontext == NULL)
|
||||
{
|
||||
nerr("ERROR: Address context not found\n");
|
||||
return;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
uncompress_addr(&addr, addrcontext->prefix, g_unc_ctxconf[tmp],
|
||||
@@ -1456,6 +1489,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
{
|
||||
case SIXLOWPAN_NHC_UDP_CS_P_00:
|
||||
|
||||
HC06_CHECK(g_hc06ptr, 5, endofframe);
|
||||
|
||||
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
|
||||
|
||||
memcpy(&udp->srcport, g_hc06ptr + 1, 2);
|
||||
@@ -1469,6 +1504,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
|
||||
case SIXLOWPAN_NHC_UDP_CS_P_01:
|
||||
|
||||
HC06_CHECK(g_hc06ptr, 4, endofframe);
|
||||
|
||||
/* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit
|
||||
* inline
|
||||
*/
|
||||
@@ -1487,6 +1524,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
|
||||
case SIXLOWPAN_NHC_UDP_CS_P_10:
|
||||
|
||||
HC06_CHECK(g_hc06ptr, 4, endofframe);
|
||||
|
||||
/* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit
|
||||
* inline
|
||||
*/
|
||||
@@ -1505,6 +1544,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
|
||||
case SIXLOWPAN_NHC_UDP_CS_P_11:
|
||||
|
||||
HC06_CHECK(g_hc06ptr, 2, endofframe);
|
||||
|
||||
/* 1 byte for NHC, 1 byte for ports */
|
||||
|
||||
udp->srcport =
|
||||
@@ -1522,7 +1563,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
|
||||
default:
|
||||
nerr("ERROR: Error unsupported UDP compression\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!checksum_compressed)
|
||||
@@ -1571,6 +1612,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
(FAR struct udp_hdr_s *)(bptr + IPv6_HDRLEN);
|
||||
memcpy(&udp->udplen, &ipv6->len[0], 2);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */
|
||||
|
||||
@@ -457,8 +457,14 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
|
||||
SIXLOWPAN_DISPATCH_IPHC)
|
||||
{
|
||||
ninfo("IPHC Dispatch\n");
|
||||
sixlowpan_uncompresshdr_hc06(radio, metadata,
|
||||
fragsize, iob, fptr, bptr);
|
||||
ret = sixlowpan_uncompresshdr_hc06(radio, metadata,
|
||||
fragsize, iob, fptr, bptr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: HC06 header decompress failed, dropping frame: %d\n",
|
||||
ret);
|
||||
goto errout_with_reass;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */
|
||||
|
||||
@@ -495,10 +495,10 @@ int sixlowpan_compresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06
|
||||
void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
FAR const void *metadata,
|
||||
uint16_t iplen, FAR struct iob_s *iob,
|
||||
FAR uint8_t *fptr, FAR uint8_t *bptr);
|
||||
int sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||
FAR const void *metadata,
|
||||
uint16_t iplen, FAR struct iob_s *iob,
|
||||
FAR uint8_t *fptr, FAR uint8_t *bptr);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user