mirror of
https://github.com/apache/nuttx.git
synced 2026-05-29 20:56:47 +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_MACBASED (1 << 8)
|
||||||
#define UNCOMPRESS_ZEROPAD (1 << 9)
|
#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
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -1166,17 +1176,18 @@ int sixlowpan_compresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
* FRAGN frames.
|
* FRAGN frames.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None
|
* On success returns 0 otherwise a negative error
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
int sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||||
FAR const void *metadata,
|
FAR const void *metadata,
|
||||||
uint16_t iplen, FAR struct iob_s *iob,
|
uint16_t iplen, FAR struct iob_s *iob,
|
||||||
FAR uint8_t *fptr, FAR uint8_t *bptr)
|
FAR uint8_t *fptr, FAR uint8_t *bptr)
|
||||||
{
|
{
|
||||||
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr;
|
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr;
|
||||||
struct netdev_varaddr_s addr;
|
struct netdev_varaddr_s addr;
|
||||||
|
FAR uint8_t *endofframe;
|
||||||
FAR uint8_t *iphc;
|
FAR uint8_t *iphc;
|
||||||
uint8_t iphc0;
|
uint8_t iphc0;
|
||||||
uint8_t iphc1;
|
uint8_t iphc1;
|
||||||
@@ -1193,6 +1204,13 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
|
|
||||||
g_hc06ptr = iphc + 2;
|
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",
|
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);
|
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)
|
if ((iphc1 & SIXLOWPAN_IPHC_CID) != 0)
|
||||||
{
|
{
|
||||||
ninfo("CID flag set. Increase header by one\n");
|
ninfo("CID flag set. Increase header by one\n");
|
||||||
|
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||||
g_hc06ptr++;
|
g_hc06ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1216,6 +1235,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
|
|
||||||
memcpy(&ipv6->tcf, g_hc06ptr + 1, 3);
|
memcpy(&ipv6->tcf, g_hc06ptr + 1, 3);
|
||||||
tmp = *g_hc06ptr;
|
tmp = *g_hc06ptr;
|
||||||
|
HC06_CHECK(g_hc06ptr, 4, endofframe);
|
||||||
g_hc06ptr += 4;
|
g_hc06ptr += 4;
|
||||||
|
|
||||||
/* hc06 format of tc is ECN | DSCP , original is DSCP | ECN
|
/* 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);
|
ipv6->tcf = (*g_hc06ptr & 0x0f) | ((*g_hc06ptr >> 2) & 0x30);
|
||||||
memcpy(&ipv6->flow, g_hc06ptr + 1, 2);
|
memcpy(&ipv6->flow, g_hc06ptr + 1, 2);
|
||||||
|
HC06_CHECK(g_hc06ptr, 3, endofframe);
|
||||||
g_hc06ptr += 3;
|
g_hc06ptr += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1256,6 +1277,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
ipv6->tcf = ((*g_hc06ptr << 6) & 0xc0) |
|
ipv6->tcf = ((*g_hc06ptr << 6) & 0xc0) |
|
||||||
((*g_hc06ptr >> 2) & 0x30);
|
((*g_hc06ptr >> 2) & 0x30);
|
||||||
ipv6->flow = 0;
|
ipv6->flow = 0;
|
||||||
|
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||||
g_hc06ptr += 1;
|
g_hc06ptr += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1276,6 +1298,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
|
|
||||||
ipv6->proto = *g_hc06ptr;
|
ipv6->proto = *g_hc06ptr;
|
||||||
ninfo("Next header inline: %d\n", ipv6->proto);
|
ninfo("Next header inline: %d\n", ipv6->proto);
|
||||||
|
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||||
g_hc06ptr += 1;
|
g_hc06ptr += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1288,6 +1311,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ipv6->ttl = *g_hc06ptr;
|
ipv6->ttl = *g_hc06ptr;
|
||||||
|
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||||
g_hc06ptr += 1;
|
g_hc06ptr += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1301,7 +1325,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
|
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
|
||||||
return;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((iphc1 & SIXLOWPAN_IPHC_SAC) != 0)
|
if ((iphc1 & SIXLOWPAN_IPHC_SAC) != 0)
|
||||||
@@ -1319,7 +1343,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
if (addrcontext == NULL)
|
if (addrcontext == NULL)
|
||||||
{
|
{
|
||||||
nerr("ERROR: Address context not found\n");
|
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.
|
* address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Source address: worst case 16 bytes inline */
|
||||||
|
|
||||||
|
HC06_CHECK(g_hc06ptr, 16, endofframe);
|
||||||
|
|
||||||
uncompress_addr(&addr,
|
uncompress_addr(&addr,
|
||||||
tmp != 0 ? addrcontext->prefix : NULL,
|
tmp != 0 ? addrcontext->prefix : NULL,
|
||||||
g_unc_ctxconf[tmp], ipv6->srcipaddr);
|
g_unc_ctxconf[tmp], ipv6->srcipaddr);
|
||||||
@@ -1342,6 +1370,10 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
* address.
|
* address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Destination address: worst case 16 bytes inline */
|
||||||
|
|
||||||
|
HC06_CHECK(g_hc06ptr, 16, endofframe);
|
||||||
|
|
||||||
uncompress_addr(&addr, g_llprefix, g_unc_llconf[tmp],
|
uncompress_addr(&addr, g_llprefix, g_unc_llconf[tmp],
|
||||||
ipv6->srcipaddr);
|
ipv6->srcipaddr);
|
||||||
}
|
}
|
||||||
@@ -1359,7 +1391,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
|
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
|
||||||
return;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((iphc1 & SIXLOWPAN_IPHC_M) != 0)
|
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)
|
if (tmp > 0 && tmp < 3)
|
||||||
{
|
{
|
||||||
prefix[1] = *g_hc06ptr;
|
prefix[1] = *g_hc06ptr;
|
||||||
|
HC06_CHECK(g_hc06ptr, 1, endofframe);
|
||||||
g_hc06ptr++;
|
g_hc06ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1415,7 +1448,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
if (addrcontext == NULL)
|
if (addrcontext == NULL)
|
||||||
{
|
{
|
||||||
nerr("ERROR: Address context not found\n");
|
nerr("ERROR: Address context not found\n");
|
||||||
return;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uncompress_addr(&addr, addrcontext->prefix, g_unc_ctxconf[tmp],
|
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:
|
case SIXLOWPAN_NHC_UDP_CS_P_00:
|
||||||
|
|
||||||
|
HC06_CHECK(g_hc06ptr, 5, endofframe);
|
||||||
|
|
||||||
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
|
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
|
||||||
|
|
||||||
memcpy(&udp->srcport, g_hc06ptr + 1, 2);
|
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:
|
case SIXLOWPAN_NHC_UDP_CS_P_01:
|
||||||
|
|
||||||
|
HC06_CHECK(g_hc06ptr, 4, endofframe);
|
||||||
|
|
||||||
/* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit
|
/* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit
|
||||||
* inline
|
* inline
|
||||||
*/
|
*/
|
||||||
@@ -1487,6 +1524,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
|
|
||||||
case SIXLOWPAN_NHC_UDP_CS_P_10:
|
case SIXLOWPAN_NHC_UDP_CS_P_10:
|
||||||
|
|
||||||
|
HC06_CHECK(g_hc06ptr, 4, endofframe);
|
||||||
|
|
||||||
/* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit
|
/* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit
|
||||||
* inline
|
* inline
|
||||||
*/
|
*/
|
||||||
@@ -1505,6 +1544,8 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
|
|
||||||
case SIXLOWPAN_NHC_UDP_CS_P_11:
|
case SIXLOWPAN_NHC_UDP_CS_P_11:
|
||||||
|
|
||||||
|
HC06_CHECK(g_hc06ptr, 2, endofframe);
|
||||||
|
|
||||||
/* 1 byte for NHC, 1 byte for ports */
|
/* 1 byte for NHC, 1 byte for ports */
|
||||||
|
|
||||||
udp->srcport =
|
udp->srcport =
|
||||||
@@ -1522,7 +1563,7 @@ void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
nerr("ERROR: Error unsupported UDP compression\n");
|
nerr("ERROR: Error unsupported UDP compression\n");
|
||||||
return;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checksum_compressed)
|
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);
|
(FAR struct udp_hdr_s *)(bptr + IPv6_HDRLEN);
|
||||||
memcpy(&udp->udplen, &ipv6->len[0], 2);
|
memcpy(&udp->udplen, &ipv6->len[0], 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */
|
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */
|
||||||
|
|||||||
@@ -457,8 +457,14 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
|
|||||||
SIXLOWPAN_DISPATCH_IPHC)
|
SIXLOWPAN_DISPATCH_IPHC)
|
||||||
{
|
{
|
||||||
ninfo("IPHC Dispatch\n");
|
ninfo("IPHC Dispatch\n");
|
||||||
sixlowpan_uncompresshdr_hc06(radio, metadata,
|
ret = sixlowpan_uncompresshdr_hc06(radio, metadata,
|
||||||
fragsize, iob, fptr, bptr);
|
fragsize, iob, fptr, bptr);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nerr("ERROR: HC06 header decompress failed, dropping frame: %d\n",
|
||||||
|
ret);
|
||||||
|
goto errout_with_reass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */
|
#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
|
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06
|
||||||
void sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
int sixlowpan_uncompresshdr_hc06(FAR struct radio_driver_s *radio,
|
||||||
FAR const void *metadata,
|
FAR const void *metadata,
|
||||||
uint16_t iplen, FAR struct iob_s *iob,
|
uint16_t iplen, FAR struct iob_s *iob,
|
||||||
FAR uint8_t *fptr, FAR uint8_t *bptr);
|
FAR uint8_t *fptr, FAR uint8_t *bptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user