Decode the SNR exponent as a signed value instead of storing it in a u32. Subtracting 0x40 from the unsigned exponent currently causes it to wrap around when the encoded value represents a negative number. Keep the signal and noise mantissas unsigned, as they are used in unsigned fixed-point arithmetic. Check exponent values before shifting by check_shl_overflow(). Return the existing invalid SNR value when the exponent cannot be represented safely. Fixes: 77e2c0f5d471 ("V4L/DVB (12900): DiB8000: added support for DiBcom ISDB-T/ISDB-Tsb demodulator DiB8000") Cc: stable@vger.kernel.org Signed-off-by: Ilya Krutskih --- drivers/media/dvb-frontends/dib8000.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index d291113291e0..442ec06e34dc 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -3873,7 +3874,8 @@ static u32 dib8000_get_snr(struct dvb_frontend *fe) exp = (val & 0x3f); if ((exp & 0x20) != 0) exp -= 0x40; - n <<= exp+16; + if (check_shl_overflow(n, exp + 16, &n)) + return 0xffffffff; if (state->revision != 0x8090) val = dib8000_read_word(state, 543); @@ -3883,7 +3885,8 @@ static u32 dib8000_get_snr(struct dvb_frontend *fe) exp = (val & 0x3f); if ((exp & 0x20) != 0) exp -= 0x40; - s <<= exp+16; + if (check_shl_overflow(s, exp + 16, &s)) + return 0xffffffff; if (n > 0) { u32 t = (s/n) << 16; -- 2.43.0