diff options
author | Ang Way Chuang <wcang79@gmail.com> | 2010-05-27 02:02:09 -0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-02 10:21:26 -0700 |
commit | 65019a1c668d1dbcc4c6bdcdb7bb66d8ea714752 (patch) | |
tree | 9ac05a6ee3a46bf8dbf5e09a19b07dd87893b2b1 /drivers/media | |
parent | ac633f17d4a5030d5924c1a85bbcde1ad42c3998 (diff) |
V4L/DVB: dvb-core: Fix ULE decapsulation bug
commit 5c331fc8c19e181bffab46e9d18e1637cdc47170 upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/media')
-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 dddfc46c890d..55e591daf717 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -350,6 +350,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) const u8 *ts, *ts_end, *from_where = NULL; u8 ts_remain = 0, how_much = 0, new_ts = 1; struct ethhdr *ethh = NULL; + bool error = false; #ifdef ULE_DEBUG /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ @@ -459,10 +460,16 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) /* Drop partly decoded SNDU, reset state, resync on PUSI. */ if (priv->ule_skb) { - dev_kfree_skb( priv->ule_skb ); + error = true; + dev_kfree_skb(priv->ule_skb); + } + + if (error || priv->ule_sndu_remain) { dev->stats.rx_errors++; dev->stats.rx_frame_errors++; + error = false; } + reset_ule(priv); priv->need_pusi = 1; continue; @@ -534,6 +541,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) from_where += 2; } + priv->ule_sndu_remain = priv->ule_sndu_len + 2; /* * State of current TS: * ts_remain (remaining bytes in the current TS cell) @@ -543,6 +551,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) */ switch (ts_remain) { case 1: + priv->ule_sndu_remain--; priv->ule_sndu_type = from_where[0] << 8; priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ ts_remain -= 1; from_where += 1; @@ -556,6 +565,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) default: /* complete ULE header is present in current TS. */ /* Extract ULE type field. */ if (priv->ule_sndu_type_1) { + priv->ule_sndu_type_1 = 0; priv->ule_sndu_type |= from_where[0]; from_where += 1; /* points to payload start. */ ts_remain -= 1; |