Commit f863f222 authored by Dafna Hirschfeld's avatar Dafna Hirschfeld Committed by Mauro Carvalho Chehab

media: vicodec: ensure comp frame pointer kept in range

Make sure that the pointer to the compressed frame does not
get out of the buffer.
Signed-off-by: default avatarDafna Hirschfeld <dafna3@gmail.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 3b15f68e
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include "codec-fwht.h" #include "codec-fwht.h"
#define OVERFLOW_BIT BIT(14)
/* /*
* Note: bit 0 of the header must always be 0. Otherwise it cannot * Note: bit 0 of the header must always be 0. Otherwise it cannot
* be guaranteed that the magic 8 byte sequence (see below) can * be guaranteed that the magic 8 byte sequence (see below) can
...@@ -104,16 +106,21 @@ static int rlc(const s16 *in, __be16 *output, int blocktype) ...@@ -104,16 +106,21 @@ static int rlc(const s16 *in, __be16 *output, int blocktype)
* This function will worst-case increase rlc_in by 65*2 bytes: * This function will worst-case increase rlc_in by 65*2 bytes:
* one s16 value for the header and 8 * 8 coefficients of type s16. * one s16 value for the header and 8 * 8 coefficients of type s16.
*/ */
static s16 derlc(const __be16 **rlc_in, s16 *dwht_out) static u16 derlc(const __be16 **rlc_in, s16 *dwht_out,
const __be16 *end_of_input)
{ {
/* header */ /* header */
const __be16 *input = *rlc_in; const __be16 *input = *rlc_in;
s16 ret = ntohs(*input++); u16 stat;
int dec_count = 0; int dec_count = 0;
s16 block[8 * 8 + 16]; s16 block[8 * 8 + 16];
s16 *wp = block; s16 *wp = block;
int i; int i;
if (input > end_of_input)
return OVERFLOW_BIT;
stat = ntohs(*input++);
/* /*
* Now de-compress, it expands one byte to up to 15 bytes * Now de-compress, it expands one byte to up to 15 bytes
* (or fills the remainder of the 64 bytes with zeroes if it * (or fills the remainder of the 64 bytes with zeroes if it
...@@ -123,9 +130,15 @@ static s16 derlc(const __be16 **rlc_in, s16 *dwht_out) ...@@ -123,9 +130,15 @@ static s16 derlc(const __be16 **rlc_in, s16 *dwht_out)
* allow for overflow if the incoming data was malformed. * allow for overflow if the incoming data was malformed.
*/ */
while (dec_count < 8 * 8) { while (dec_count < 8 * 8) {
s16 in = ntohs(*input++); s16 in;
int length = in & 0xf; int length;
int coeff = in >> 4; int coeff;
if (input > end_of_input)
return OVERFLOW_BIT;
in = ntohs(*input++);
length = in & 0xf;
coeff = in >> 4;
/* fill remainder with zeros */ /* fill remainder with zeros */
if (length == 15) { if (length == 15) {
...@@ -150,7 +163,7 @@ static s16 derlc(const __be16 **rlc_in, s16 *dwht_out) ...@@ -150,7 +163,7 @@ static s16 derlc(const __be16 **rlc_in, s16 *dwht_out)
dwht_out[x + y * 8] = *wp++; dwht_out[x + y * 8] = *wp++;
} }
*rlc_in = input; *rlc_in = input;
return ret; return stat;
} }
static const int quant_table[] = { static const int quant_table[] = {
...@@ -808,22 +821,24 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm, ...@@ -808,22 +821,24 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
return encoding; return encoding;
} }
static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
u32 height, u32 width, u32 coded_width, u32 height, u32 width, u32 coded_width,
bool uncompressed) bool uncompressed, const __be16 *end_of_rlco_buf)
{ {
unsigned int copies = 0; unsigned int copies = 0;
s16 copy[8 * 8]; s16 copy[8 * 8];
s16 stat; u16 stat;
unsigned int i, j; unsigned int i, j;
width = round_up(width, 8); width = round_up(width, 8);
height = round_up(height, 8); height = round_up(height, 8);
if (uncompressed) { if (uncompressed) {
if (end_of_rlco_buf + 1 < *rlco + width * height / 2)
return false;
memcpy(ref, *rlco, width * height); memcpy(ref, *rlco, width * height);
*rlco += width * height / 2; *rlco += width * height / 2;
return; return true;
} }
/* /*
...@@ -847,8 +862,9 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, ...@@ -847,8 +862,9 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
continue; continue;
} }
stat = derlc(rlco, cf->coeffs); stat = derlc(rlco, cf->coeffs, end_of_rlco_buf);
if (stat & OVERFLOW_BIT)
return false;
if (stat & PFRAME_BIT) if (stat & PFRAME_BIT)
dequantize_inter(cf->coeffs); dequantize_inter(cf->coeffs);
else else
...@@ -865,17 +881,22 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, ...@@ -865,17 +881,22 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
fill_decoder_block(refp, cf->de_fwht, coded_width); fill_decoder_block(refp, cf->de_fwht, coded_width);
} }
} }
return true;
} }
void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, bool fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
u32 hdr_flags, unsigned int components_num, u32 hdr_flags, unsigned int components_num,
unsigned int width, unsigned int height, unsigned int width, unsigned int height,
unsigned int coded_width) unsigned int coded_width)
{ {
const __be16 *rlco = cf->rlc_data; const __be16 *rlco = cf->rlc_data;
const __be16 *end_of_rlco_buf = cf->rlc_data +
(cf->size / sizeof(*rlco)) - 1;
decode_plane(cf, &rlco, ref->luma, height, width, coded_width, if (!decode_plane(cf, &rlco, ref->luma, height, width, coded_width,
hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED); hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED,
end_of_rlco_buf))
return false;
if (components_num >= 3) { if (components_num >= 3) {
u32 h = height; u32 h = height;
...@@ -888,13 +909,21 @@ void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, ...@@ -888,13 +909,21 @@ void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
w /= 2; w /= 2;
c /= 2; c /= 2;
} }
decode_plane(cf, &rlco, ref->cb, h, w, c, if (!decode_plane(cf, &rlco, ref->cb, h, w, c,
hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED); hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED,
decode_plane(cf, &rlco, ref->cr, h, w, c, end_of_rlco_buf))
hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED); return false;
if (!decode_plane(cf, &rlco, ref->cr, h, w, c,
hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED,
end_of_rlco_buf))
return false;
} }
if (components_num == 4) if (components_num == 4)
decode_plane(cf, &rlco, ref->alpha, height, width, coded_width, if (!decode_plane(cf, &rlco, ref->alpha, height, width,
hdr_flags & FWHT_FL_ALPHA_IS_UNCOMPRESSED); coded_width,
hdr_flags & FWHT_FL_ALPHA_IS_UNCOMPRESSED,
end_of_rlco_buf))
return false;
return true;
} }
...@@ -139,7 +139,7 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm, ...@@ -139,7 +139,7 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
bool is_intra, bool next_is_intra, bool is_intra, bool next_is_intra,
unsigned int width, unsigned int height, unsigned int width, unsigned int height,
unsigned int stride, unsigned int chroma_stride); unsigned int stride, unsigned int chroma_stride);
void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, bool fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
u32 hdr_flags, unsigned int components_num, u32 hdr_flags, unsigned int components_num,
unsigned int width, unsigned int height, unsigned int width, unsigned int height,
unsigned int coded_width); unsigned int coded_width);
......
...@@ -280,6 +280,7 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) ...@@ -280,6 +280,7 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
state->ycbcr_enc = ntohl(state->header.ycbcr_enc); state->ycbcr_enc = ntohl(state->header.ycbcr_enc);
state->quantization = ntohl(state->header.quantization); state->quantization = ntohl(state->header.quantization);
cf.rlc_data = (__be16 *)p_in; cf.rlc_data = (__be16 *)p_in;
cf.size = ntohl(state->header.size);
hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2; hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2; hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
...@@ -287,9 +288,10 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) ...@@ -287,9 +288,10 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
hdr_height_div != info->height_div) hdr_height_div != info->height_div)
return -EINVAL; return -EINVAL;
fwht_decode_frame(&cf, &state->ref_frame, flags, components_num, if (!fwht_decode_frame(&cf, &state->ref_frame, flags, components_num,
state->visible_width, state->visible_height, state->visible_width, state->visible_height,
state->coded_width); state->coded_width))
return -EINVAL;
/* /*
* TODO - handle the case where the compressed stream encodes a * TODO - handle the case where the compressed stream encodes a
......
...@@ -186,6 +186,10 @@ static int device_process(struct vicodec_ctx *ctx, ...@@ -186,6 +186,10 @@ static int device_process(struct vicodec_ctx *ctx,
return ret; return ret;
vb2_set_plane_payload(&dst_vb->vb2_buf, 0, ret); vb2_set_plane_payload(&dst_vb->vb2_buf, 0, ret);
} else { } else {
unsigned int comp_frame_size = ntohl(ctx->state.header.size);
if (comp_frame_size > ctx->comp_max_size)
return -EINVAL;
state->info = q_dst->info; state->info = q_dst->info;
ret = v4l2_fwht_decode(state, p_src, p_dst); ret = v4l2_fwht_decode(state, p_src, p_dst);
if (ret < 0) if (ret < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment