
From: Zhushuai Yin <yinzhushuai@huawei.com> When the buffer size is configured to be less than 10, gzip will core dump. The root cause is that the access to the head size is not intercepted, leading to subsequent access overflow. Signed-off-by: Zhushuai Yin <yinzhushuai@huawei.com> Signed-off-by: Qi Tao <taoqi10@huawei.com> --- wd_comp.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/wd_comp.c b/wd_comp.c index 58f6e451..0871abf6 100644 --- a/wd_comp.c +++ b/wd_comp.c @@ -17,6 +17,8 @@ #define HW_CTX_SIZE (64 * 1024) #define STREAM_CHUNK (128 * 1024) +#define WD_ZLIB_HEADER_SZ 2 +#define WD_GZIP_HEADER_SZ 10 #define swap_byte(x) \ ((((x) & 0x000000ff) << 24) | \ @@ -522,7 +524,42 @@ static void fill_comp_msg(struct wd_comp_sess *sess, struct wd_comp_msg *msg, msg->req.last = 1; } -static int wd_comp_check_buffer(struct wd_comp_req *req) +static int wd_check_alg_buff_size(__u32 dst_len, __u32 src_len, + enum wd_comp_alg_type alg_type, enum wd_comp_op_type op_type) +{ + if (!dst_len) { + WD_ERR("invalid: dst_len is 0!\n"); + return -WD_EINVAL; + } + + if (alg_type == WD_ZLIB) { + if (dst_len <= WD_ZLIB_HEADER_SZ && op_type == WD_DIR_COMPRESS) { + WD_ERR("invalid: zlib dst_len(%u) is too samll!\n", dst_len); + return -WD_EINVAL; + } + + if (src_len <= WD_ZLIB_HEADER_SZ && op_type == WD_DIR_DECOMPRESS) { + WD_ERR("invalid: zlib src_len(%u) is too samll!\n", src_len); + return -WD_EINVAL; + } + } + + if (alg_type == WD_GZIP) { + if (dst_len <= WD_GZIP_HEADER_SZ && op_type == WD_DIR_COMPRESS) { + WD_ERR("invalid: gzip dst_len(%u) is too samll!\n", dst_len); + return -WD_EINVAL; + } + + if (src_len <= WD_GZIP_HEADER_SZ && op_type == WD_DIR_DECOMPRESS) { + WD_ERR("invalid: gzip src_len(%u) is too samll!\n", src_len); + return -WD_EINVAL; + } + } + + return 0; +} + +static int wd_comp_check_buffer(struct wd_comp_req *req, enum wd_comp_alg_type alg_type) { if (req->data_fmt == WD_FLAT_BUF) { if (unlikely(!req->src || !req->dst)) { @@ -536,12 +573,7 @@ static int wd_comp_check_buffer(struct wd_comp_req *req) } } - if (!req->dst_len) { - WD_ERR("invalid: dst_len is 0!\n"); - return -WD_EINVAL; - } - - return 0; + return wd_check_alg_buff_size(req->dst_len, req->src_len, alg_type, req->op_type); } static int wd_comp_check_params(struct wd_comp_sess *sess, @@ -560,7 +592,7 @@ static int wd_comp_check_params(struct wd_comp_sess *sess, return -WD_EINVAL; } - ret = wd_comp_check_buffer(req); + ret = wd_comp_check_buffer(req, sess->alg_type); if (unlikely(ret)) return ret; -- 2.33.0