diff options
author | Ang Way Chuang <wcang79@gmail.com> | 2010-05-27 01:02:09 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-06-01 00:24:21 -0400 |
commit | 5c331fc8c19e181bffab46e9d18e1637cdc47170 (patch) | |
tree | 93ab576de4328c3861ac734f91210e2d9d9aa21e /drivers | |
parent | 84b14f181a36eea6591779156ef356f8d198bbfd (diff) |
V4L/DVB: dvb-core: Fix ULE decapsulation bug
Fix ULE decapsulation bug when less than 4 bytes of ULE SNDU is packed
into the remaining bytes of a MPEG2-TS frame
ULE (Unidirectional Lightweight Encapsulation RFC 4326) decapsulation
code has a bug that incorrectly treats ULE SNDU packed into the
remaining 2 or 3 bytes of a MPEG2-TS frame as having invalid pointer
field on the subsequent MPEG2-TS frame.
Signed-off-by: Ang Way Chuang <wcang@nav6.org>
Acked-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_net.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index f6dac2bb0ac6..6c3a8a06ccab 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c | |||
@@ -351,6 +351,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
351 | const u8 *ts, *ts_end, *from_where = NULL; | 351 | const u8 *ts, *ts_end, *from_where = NULL; |
352 | u8 ts_remain = 0, how_much = 0, new_ts = 1; | 352 | u8 ts_remain = 0, how_much = 0, new_ts = 1; |
353 | struct ethhdr *ethh = NULL; | 353 | struct ethhdr *ethh = NULL; |
354 | bool error = false; | ||
354 | 355 | ||
355 | #ifdef ULE_DEBUG | 356 | #ifdef ULE_DEBUG |
356 | /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ | 357 | /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ |
@@ -460,10 +461,16 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
460 | 461 | ||
461 | /* Drop partly decoded SNDU, reset state, resync on PUSI. */ | 462 | /* Drop partly decoded SNDU, reset state, resync on PUSI. */ |
462 | if (priv->ule_skb) { | 463 | if (priv->ule_skb) { |
463 | dev_kfree_skb( priv->ule_skb ); | 464 | error = true; |
465 | dev_kfree_skb(priv->ule_skb); | ||
466 | } | ||
467 | |||
468 | if (error || priv->ule_sndu_remain) { | ||
464 | dev->stats.rx_errors++; | 469 | dev->stats.rx_errors++; |
465 | dev->stats.rx_frame_errors++; | 470 | dev->stats.rx_frame_errors++; |
471 | error = false; | ||
466 | } | 472 | } |
473 | |||
467 | reset_ule(priv); | 474 | reset_ule(priv); |
468 | priv->need_pusi = 1; | 475 | priv->need_pusi = 1; |
469 | continue; | 476 | continue; |
@@ -535,6 +542,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
535 | from_where += 2; | 542 | from_where += 2; |
536 | } | 543 | } |
537 | 544 | ||
545 | priv->ule_sndu_remain = priv->ule_sndu_len + 2; | ||
538 | /* | 546 | /* |
539 | * State of current TS: | 547 | * State of current TS: |
540 | * ts_remain (remaining bytes in the current TS cell) | 548 | * ts_remain (remaining bytes in the current TS cell) |
@@ -544,6 +552,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
544 | */ | 552 | */ |
545 | switch (ts_remain) { | 553 | switch (ts_remain) { |
546 | case 1: | 554 | case 1: |
555 | priv->ule_sndu_remain--; | ||
547 | priv->ule_sndu_type = from_where[0] << 8; | 556 | priv->ule_sndu_type = from_where[0] << 8; |
548 | priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ | 557 | priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ |
549 | ts_remain -= 1; from_where += 1; | 558 | ts_remain -= 1; from_where += 1; |
@@ -557,6 +566,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
557 | default: /* complete ULE header is present in current TS. */ | 566 | default: /* complete ULE header is present in current TS. */ |
558 | /* Extract ULE type field. */ | 567 | /* Extract ULE type field. */ |
559 | if (priv->ule_sndu_type_1) { | 568 | if (priv->ule_sndu_type_1) { |
569 | priv->ule_sndu_type_1 = 0; | ||
560 | priv->ule_sndu_type |= from_where[0]; | 570 | priv->ule_sndu_type |= from_where[0]; |
561 | from_where += 1; /* points to payload start. */ | 571 | from_where += 1; /* points to payload start. */ |
562 | ts_remain -= 1; | 572 | ts_remain -= 1; |