Skip to content

Commit 70c3096

Browse files
committed
net/sixlowpan: Check if g_frame_hdrlen + IPv6_HDRLEN <= iob->io_len
This commit checks if the incoming 6LoWPAN frame header len + the IPv6_HDRLEN will fit inside the b->io_len. Signed-off-by: Alan C. Assis <acassis@gmail.com>
1 parent 99d639b commit 70c3096

1 file changed

Lines changed: 55 additions & 11 deletions

File tree

net/sixlowpan/sixlowpan_input.c

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -141,30 +141,41 @@ static uint8_t g_bitbucket[UNCOMP_MAXHDR];
141141
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142142
*
143143
* Input Parameters:
144+
* iob - Pointer to the iob struct
144145
* fptr - Pointer to the beginning of the frame under construction
145146
* bptr - Output goes here. Normally this is a known offset into d_buf,
146147
* may be redirected to g_bitbucket on the case of FRAGN frames.
147-
* proto - True: Copy the protocol header following the IPv6 header too.
148148
*
149149
* Returned Value:
150-
* None
150+
* On success returns 0 and a negative error otherwise
151151
*
152152
****************************************************************************/
153153

154-
static void sixlowpan_uncompress_ipv6hdr(FAR uint8_t *fptr,
155-
FAR uint8_t *bptr)
154+
static int sixlowpan_uncompress_ipv6hdr(FAR struct iob_s *iob,
155+
FAR uint8_t *fptr,
156+
FAR uint8_t *bptr)
156157
{
157158
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr;
159+
FAR uint8_t *endofframe = fptr + iob->io_len;
158160

159161
/* Put uncompressed IPv6 header in d_buf. */
160162

161163
g_frame_hdrlen += SIXLOWPAN_IPV6_HDR_LEN;
164+
165+
if (fptr + g_frame_hdrlen + IPv6_HDRLEN > endofframe)
166+
{
167+
nerr("ERROR: Frame too short for IPv6 header\n");
168+
return -EINVAL;
169+
}
170+
162171
memcpy(ipv6, fptr + g_frame_hdrlen, IPv6_HDRLEN);
163172

164173
/* Update g_uncomp_hdrlen and g_frame_hdrlen. */
165174

166175
g_frame_hdrlen += IPv6_HDRLEN;
167176
g_uncomp_hdrlen += IPv6_HDRLEN;
177+
178+
return OK;
168179
}
169180

170181
/****************************************************************************
@@ -174,20 +185,22 @@ static void sixlowpan_uncompress_ipv6hdr(FAR uint8_t *fptr,
174185
* Copy the protocol header following the IPv4 header
175186
*
176187
* Input Parameters:
188+
* iob - Pointer to the iob struct
177189
* fptr - Pointer to the beginning of the frame under construction
178190
* bptr - Output goes here. Normally this is a known offset into d_buf,
179191
* may be redirected to g_bitbucket on the case of FRAGN frames.
180-
* proto - True: Copy the protocol header following the IPv6 header too.
181192
*
182193
* Returned Value:
183-
* The size of the protocol header that was copied.
194+
* The size of the protocol header that was copied or a negative error.
184195
*
185196
****************************************************************************/
186197

187-
static uint16_t sixlowpan_uncompress_ipv6proto(FAR uint8_t *fptr,
188-
FAR uint8_t *bptr)
198+
static int sixlowpan_uncompress_ipv6proto(FAR struct iob_s *iob,
199+
FAR uint8_t *fptr,
200+
FAR uint8_t *bptr)
189201
{
190202
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr;
203+
FAR uint8_t *endofframe = fptr + iob->io_len;
191204
uint16_t protosize = 0;
192205

193206
/* Copy the following protocol header. */
@@ -200,6 +213,14 @@ static uint16_t sixlowpan_uncompress_ipv6proto(FAR uint8_t *fptr,
200213
FAR struct tcp_hdr_s *tcp =
201214
(FAR struct tcp_hdr_s *)(fptr + g_frame_hdrlen);
202215

216+
/* Check if the frame is too short */
217+
218+
if (fptr + g_frame_hdrlen + sizeof(struct tcp_hdr_s) > endofframe)
219+
{
220+
nerr("ERROR: Frame too short for TCP header\n");
221+
return -EINVAL;
222+
}
223+
203224
/* The TCP header length is encoded in the top 4 bits of the
204225
* tcpoffset field (in units of 32-bit words).
205226
*/
@@ -226,14 +247,23 @@ static uint16_t sixlowpan_uncompress_ipv6proto(FAR uint8_t *fptr,
226247
return 0;
227248
}
228249

250+
/* Check if the TCP header exceeds the frame size */
251+
252+
if (fptr + g_frame_hdrlen + protosize > endofframe)
253+
{
254+
nerr("ERROR: TCP header size from tcpoffset exceeds frame bounds\n");
255+
return -EINVAL;
256+
}
257+
229258
/* Copy the protocol header. */
230259

231260
memcpy((FAR uint8_t *)ipv6 + g_uncomp_hdrlen, fptr + g_frame_hdrlen,
232261
protosize);
233262

234263
g_frame_hdrlen += protosize;
235264
g_uncomp_hdrlen += protosize;
236-
return protosize;
265+
266+
return (int)protosize;
237267
}
238268

239269
/****************************************************************************
@@ -485,7 +515,13 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
485515

486516
/* Uncompress the IPv6 header */
487517

488-
sixlowpan_uncompress_ipv6hdr(fptr, bptr);
518+
ret = sixlowpan_uncompress_ipv6hdr(iob, fptr, bptr);
519+
if (ret < 0)
520+
{
521+
nerr("ERROR: Failed to uncompress IPv6 header: %d\n",
522+
ret);
523+
goto errout_with_reass;
524+
}
489525

490526
/* A protocol header will follow the IPv6 header only on a non-
491527
* fragmented packet or on the first fragment of a fragmented
@@ -494,7 +530,15 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
494530

495531
if (!isfrag || isfrag1)
496532
{
497-
protosize = sixlowpan_uncompress_ipv6proto(fptr, bptr);
533+
ret = sixlowpan_uncompress_ipv6proto(iob, fptr, bptr);
534+
if (ret < 0)
535+
{
536+
nerr("ERROR: Failed to uncompress IPv6 proto header: %d\n",
537+
ret);
538+
goto errout_with_reass;
539+
}
540+
541+
protosize = (uint8_t) ret;
498542
}
499543
}
500544
else

0 commit comments

Comments
 (0)