diff options
-rw-r--r-- | net/rose/rose_subr.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 1734abba26a2..174d51c9ce37 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
@@ -290,10 +290,15 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
290 | facilities->source_ndigis = 0; | 290 | facilities->source_ndigis = 0; |
291 | facilities->dest_ndigis = 0; | 291 | facilities->dest_ndigis = 0; |
292 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { | 292 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { |
293 | if (pt[6] & AX25_HBIT) | 293 | if (pt[6] & AX25_HBIT) { |
294 | if (facilities->dest_ndigis >= ROSE_MAX_DIGIS) | ||
295 | return -1; | ||
294 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); | 296 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); |
295 | else | 297 | } else { |
298 | if (facilities->source_ndigis >= ROSE_MAX_DIGIS) | ||
299 | return -1; | ||
296 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); | 300 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); |
301 | } | ||
297 | } | 302 | } |
298 | } | 303 | } |
299 | p += l + 2; | 304 | p += l + 2; |
@@ -333,6 +338,11 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
333 | 338 | ||
334 | case 0xC0: | 339 | case 0xC0: |
335 | l = p[1]; | 340 | l = p[1]; |
341 | |||
342 | /* Prevent overflows*/ | ||
343 | if (l < 10 || l > 20) | ||
344 | return -1; | ||
345 | |||
336 | if (*p == FAC_CCITT_DEST_NSAP) { | 346 | if (*p == FAC_CCITT_DEST_NSAP) { |
337 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); | 347 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); |
338 | memcpy(callsign, p + 12, l - 10); | 348 | memcpy(callsign, p + 12, l - 10); |
@@ -373,12 +383,16 @@ int rose_parse_facilities(unsigned char *p, | |||
373 | switch (*p) { | 383 | switch (*p) { |
374 | case FAC_NATIONAL: /* National */ | 384 | case FAC_NATIONAL: /* National */ |
375 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); | 385 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); |
386 | if (len < 0) | ||
387 | return 0; | ||
376 | facilities_len -= len + 1; | 388 | facilities_len -= len + 1; |
377 | p += len + 1; | 389 | p += len + 1; |
378 | break; | 390 | break; |
379 | 391 | ||
380 | case FAC_CCITT: /* CCITT */ | 392 | case FAC_CCITT: /* CCITT */ |
381 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); | 393 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); |
394 | if (len < 0) | ||
395 | return 0; | ||
382 | facilities_len -= len + 1; | 396 | facilities_len -= len + 1; |
383 | p += len + 1; | 397 | p += len + 1; |
384 | break; | 398 | break; |