msm: eva: Enhance WarpNCC buffer validation
Add dmabuf-based WarpNCC metadata buffer size validation to prevent fault in case of erroneous OOB buffer content. Change-Id: Iaa89e6c52d2c262d2266bdc3151b5b3feee79c5a Signed-off-by: Sabharsh Sidhu <quic_ssidhu@quicinc.com>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
23e1f8be28
commit
0deded3f88
@@ -46,7 +46,7 @@ struct cvp_oob_pool wncc_buf_pool;
|
|||||||
|
|
||||||
static void _wncc_print_cvpwnccbufs_table(struct msm_cvp_inst* inst);
|
static void _wncc_print_cvpwnccbufs_table(struct msm_cvp_inst* inst);
|
||||||
static int _wncc_unmap_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
static int _wncc_unmap_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
||||||
unsigned int num_layers, unsigned int metadata_bufs_offset,
|
struct eva_kmd_oob_wncc *wncc_oob,
|
||||||
struct eva_kmd_wncc_metadata** wncc_metadata);
|
struct eva_kmd_wncc_metadata** wncc_metadata);
|
||||||
|
|
||||||
void msm_cvp_print_inst_bufs(struct msm_cvp_inst *inst, bool log);
|
void msm_cvp_print_inst_bufs(struct msm_cvp_inst *inst, bool log);
|
||||||
@@ -887,19 +887,26 @@ static int _wncc_copy_oob_from_user(struct eva_kmd_hfi_packet* in_pkt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int _wncc_map_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
static int _wncc_map_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
||||||
unsigned int num_layers, unsigned int metadata_bufs_offset,
|
struct eva_kmd_oob_wncc *wncc_oob,
|
||||||
struct eva_kmd_wncc_metadata** wncc_metadata)
|
struct eva_kmd_wncc_metadata** wncc_metadata)
|
||||||
{
|
{
|
||||||
int rc = 0, i;
|
int rc = 0, i;
|
||||||
struct cvp_buf_type* wncc_metadata_bufs;
|
struct cvp_buf_type* wncc_metadata_bufs;
|
||||||
struct dma_buf* dmabuf;
|
struct dma_buf* dmabuf;
|
||||||
struct eva_buf_map map;
|
struct eva_buf_map map;
|
||||||
|
__u32 num_layers, metadata_bufs_offset;
|
||||||
|
|
||||||
if (!in_pkt || !wncc_metadata ||
|
if (!in_pkt || !wncc_metadata || !wncc_oob) {
|
||||||
num_layers < 1 || num_layers > EVA_KMD_WNCC_MAX_LAYERS) {
|
|
||||||
dprintk(CVP_ERR, "%s: invalid params", __func__);
|
dprintk(CVP_ERR, "%s: invalid params", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
num_layers = wncc_oob->num_layers;
|
||||||
|
metadata_bufs_offset = wncc_oob->metadata_bufs_offset;
|
||||||
|
if (num_layers < 1 || num_layers > EVA_KMD_WNCC_MAX_LAYERS) {
|
||||||
|
dprintk(CVP_ERR, "%s: invalid wncc num layers", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
if (metadata_bufs_offset > ((sizeof(in_pkt->pkt_data)
|
if (metadata_bufs_offset > ((sizeof(in_pkt->pkt_data)
|
||||||
- sizeof(struct cvp_buf_type)) / sizeof(__u32))) {
|
- sizeof(struct cvp_buf_type)) / sizeof(__u32))) {
|
||||||
dprintk(CVP_ERR, "%s: invalid wncc metadata bufs offset",
|
dprintk(CVP_ERR, "%s: invalid wncc metadata bufs offset",
|
||||||
@@ -920,6 +927,16 @@ static int _wncc_map_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dmabuf->size < wncc_oob->layers[i].num_addrs *
|
||||||
|
sizeof(struct eva_kmd_wncc_metadata)) {
|
||||||
|
dprintk(CVP_ERR,
|
||||||
|
"%s: wncc_metadata_bufs[%d] size insufficient for num addrs in oob",
|
||||||
|
__func__, i);
|
||||||
|
dma_buf_put(dmabuf);
|
||||||
|
rc = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
rc = dma_buf_begin_cpu_access(dmabuf, DMA_TO_DEVICE);
|
rc = dma_buf_begin_cpu_access(dmabuf, DMA_TO_DEVICE);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
@@ -949,26 +966,32 @@ static int _wncc_map_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
_wncc_unmap_metadata_bufs(in_pkt, i, metadata_bufs_offset,
|
_wncc_unmap_metadata_bufs(in_pkt, wncc_oob, wncc_metadata);
|
||||||
wncc_metadata);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _wncc_unmap_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
static int _wncc_unmap_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
||||||
unsigned int num_layers, unsigned int metadata_bufs_offset,
|
struct eva_kmd_oob_wncc *wncc_oob,
|
||||||
struct eva_kmd_wncc_metadata** wncc_metadata)
|
struct eva_kmd_wncc_metadata** wncc_metadata)
|
||||||
{
|
{
|
||||||
int rc = 0, i;
|
int rc = 0, i;
|
||||||
struct cvp_buf_type* wncc_metadata_bufs;
|
struct cvp_buf_type* wncc_metadata_bufs;
|
||||||
struct dma_buf* dmabuf;
|
struct dma_buf* dmabuf;
|
||||||
struct eva_buf_map map;
|
struct eva_buf_map map;
|
||||||
|
__u32 num_layers, metadata_bufs_offset;
|
||||||
|
|
||||||
if (!in_pkt || !wncc_metadata ||
|
if (!in_pkt || !wncc_metadata || !wncc_oob) {
|
||||||
num_layers < 1 || num_layers > EVA_KMD_WNCC_MAX_LAYERS) {
|
|
||||||
dprintk(CVP_ERR, "%s: invalid params", __func__);
|
dprintk(CVP_ERR, "%s: invalid params", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
num_layers = wncc_oob->num_layers;
|
||||||
|
metadata_bufs_offset = wncc_oob->metadata_bufs_offset;
|
||||||
|
if (num_layers < 1 || num_layers > EVA_KMD_WNCC_MAX_LAYERS) {
|
||||||
|
dprintk(CVP_ERR, "%s: invalid wncc num layers", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
if (metadata_bufs_offset > ((sizeof(in_pkt->pkt_data)
|
if (metadata_bufs_offset > ((sizeof(in_pkt->pkt_data)
|
||||||
- sizeof(struct cvp_buf_type)) / sizeof(__u32))) {
|
- sizeof(struct cvp_buf_type)) / sizeof(__u32))) {
|
||||||
dprintk(CVP_ERR, "%s: invalid wncc metadata bufs offset",
|
dprintk(CVP_ERR, "%s: invalid wncc metadata bufs offset",
|
||||||
@@ -980,8 +1003,7 @@ static int _wncc_unmap_metadata_bufs(struct eva_kmd_hfi_packet* in_pkt,
|
|||||||
&in_pkt->pkt_data[metadata_bufs_offset];
|
&in_pkt->pkt_data[metadata_bufs_offset];
|
||||||
for (i = 0; i < num_layers; i++) {
|
for (i = 0; i < num_layers; i++) {
|
||||||
if (!wncc_metadata[i]) {
|
if (!wncc_metadata[i]) {
|
||||||
rc = -EINVAL;
|
continue;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dmabuf = dma_buf_get(wncc_metadata_bufs[i].fd);
|
dmabuf = dma_buf_get(wncc_metadata_bufs[i].fd);
|
||||||
@@ -1116,9 +1138,9 @@ static int msm_cvp_proc_oob_wncc(struct msm_cvp_inst* inst,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _wncc_map_metadata_bufs(in_pkt,
|
memset(wncc_metadata, 0,
|
||||||
wncc_oob->num_layers, wncc_oob->metadata_bufs_offset,
|
sizeof(*wncc_metadata) * EVA_KMD_WNCC_MAX_LAYERS);
|
||||||
wncc_metadata);
|
rc = _wncc_map_metadata_bufs(in_pkt, wncc_oob, wncc_metadata);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR, "%s: failed to map wncc metadata bufs",
|
dprintk(CVP_ERR, "%s: failed to map wncc metadata bufs",
|
||||||
__func__);
|
__func__);
|
||||||
@@ -1186,9 +1208,7 @@ static int msm_cvp_proc_oob_wncc(struct msm_cvp_inst* inst,
|
|||||||
_wncc_print_metadata_buf(wncc_oob->num_layers,
|
_wncc_print_metadata_buf(wncc_oob->num_layers,
|
||||||
wncc_oob->layers[0].num_addrs, wncc_metadata);
|
wncc_oob->layers[0].num_addrs, wncc_metadata);
|
||||||
|
|
||||||
if (_wncc_unmap_metadata_bufs(in_pkt,
|
if (_wncc_unmap_metadata_bufs(in_pkt, wncc_oob, wncc_metadata)) {
|
||||||
wncc_oob->num_layers, wncc_oob->metadata_bufs_offset,
|
|
||||||
wncc_metadata)) {
|
|
||||||
dprintk(CVP_ERR, "%s: failed to unmap wncc metadata bufs",
|
dprintk(CVP_ERR, "%s: failed to unmap wncc metadata bufs",
|
||||||
__func__);
|
__func__);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user