Skip to content

Commit 8919477

Browse files
gopi487krishnaRob Clark
authored andcommitted
drm/msm: Add NULL check in vm_op_enqueue()
vm_op_enqueue() allocates an msm_vm_op struct with kmalloc, but the return value is not checked for NULL value which can be returned by kmalloc under low-memory conditions. This can result in NULL pointer dereference when the pointer is dereferenced. Add NULL check after the allocation and propagate -ENOMEM back to the caller in case of a failure. Signed-off-by: Gopi Krishna Menon <krishnagopi487@gmail.com> Patchwork: https://patchwork.freedesktop.org/patch/678416/ Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
1 parent e2f085a commit 8919477

1 file changed

Lines changed: 22 additions & 6 deletions

File tree

drivers/gpu/drm/msm/msm_gem_vma.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -462,15 +462,20 @@ struct op_arg {
462462
bool kept;
463463
};
464464

465-
static void
465+
static int
466466
vm_op_enqueue(struct op_arg *arg, struct msm_vm_op _op)
467467
{
468468
struct msm_vm_op *op = kmalloc(sizeof(*op), GFP_KERNEL);
469+
if (!op)
470+
return -ENOMEM;
471+
469472
*op = _op;
470473
list_add_tail(&op->node, &arg->job->vm_ops);
471474

472475
if (op->obj)
473476
drm_gem_object_get(op->obj);
477+
478+
return 0;
474479
}
475480

476481
static struct drm_gpuva *
@@ -489,6 +494,7 @@ msm_gem_vm_sm_step_map(struct drm_gpuva_op *op, void *_arg)
489494
struct drm_gpuva *vma;
490495
struct sg_table *sgt;
491496
unsigned prot;
497+
int ret;
492498

493499
if (arg->kept)
494500
return 0;
@@ -500,8 +506,6 @@ msm_gem_vm_sm_step_map(struct drm_gpuva_op *op, void *_arg)
500506
vm_dbg("%p:%p:%p: %016llx %016llx", vma->vm, vma, vma->gem.obj,
501507
vma->va.addr, vma->va.range);
502508

503-
vma->flags = ((struct op_arg *)arg)->flags;
504-
505509
if (obj) {
506510
sgt = to_msm_bo(obj)->sgt;
507511
prot = msm_gem_prot(obj);
@@ -510,7 +514,7 @@ msm_gem_vm_sm_step_map(struct drm_gpuva_op *op, void *_arg)
510514
prot = IOMMU_READ | IOMMU_WRITE;
511515
}
512516

513-
vm_op_enqueue(arg, (struct msm_vm_op){
517+
ret = vm_op_enqueue(arg, (struct msm_vm_op){
514518
.op = MSM_VM_OP_MAP,
515519
.map = {
516520
.sgt = sgt,
@@ -523,6 +527,10 @@ msm_gem_vm_sm_step_map(struct drm_gpuva_op *op, void *_arg)
523527
.obj = vma->gem.obj,
524528
});
525529

530+
if (ret)
531+
return ret;
532+
533+
vma->flags = ((struct op_arg *)arg)->flags;
526534
to_msm_vma(vma)->mapped = true;
527535

528536
return 0;
@@ -538,6 +546,7 @@ msm_gem_vm_sm_step_remap(struct drm_gpuva_op *op, void *arg)
538546
struct drm_gpuvm_bo *vm_bo = orig_vma->vm_bo;
539547
bool mapped = to_msm_vma(orig_vma)->mapped;
540548
unsigned flags;
549+
int ret;
541550

542551
vm_dbg("orig_vma: %p:%p:%p: %016llx %016llx", vm, orig_vma,
543552
orig_vma->gem.obj, orig_vma->va.addr, orig_vma->va.range);
@@ -547,7 +556,7 @@ msm_gem_vm_sm_step_remap(struct drm_gpuva_op *op, void *arg)
547556

548557
drm_gpuva_op_remap_to_unmap_range(&op->remap, &unmap_start, &unmap_range);
549558

550-
vm_op_enqueue(arg, (struct msm_vm_op){
559+
ret = vm_op_enqueue(arg, (struct msm_vm_op){
551560
.op = MSM_VM_OP_UNMAP,
552561
.unmap = {
553562
.iova = unmap_start,
@@ -557,6 +566,9 @@ msm_gem_vm_sm_step_remap(struct drm_gpuva_op *op, void *arg)
557566
.obj = orig_vma->gem.obj,
558567
});
559568

569+
if (ret)
570+
return ret;
571+
560572
/*
561573
* Part of this GEM obj is still mapped, but we're going to kill the
562574
* existing VMA and replace it with one or two new ones (ie. two if
@@ -618,6 +630,7 @@ msm_gem_vm_sm_step_unmap(struct drm_gpuva_op *op, void *_arg)
618630
struct msm_vm_bind_job *job = arg->job;
619631
struct drm_gpuva *vma = op->unmap.va;
620632
struct msm_gem_vma *msm_vma = to_msm_vma(vma);
633+
int ret;
621634

622635
vm_dbg("%p:%p:%p: %016llx %016llx", vma->vm, vma, vma->gem.obj,
623636
vma->va.addr, vma->va.range);
@@ -650,7 +663,7 @@ msm_gem_vm_sm_step_unmap(struct drm_gpuva_op *op, void *_arg)
650663
if (!msm_vma->mapped)
651664
goto out_close;
652665

653-
vm_op_enqueue(arg, (struct msm_vm_op){
666+
ret = vm_op_enqueue(arg, (struct msm_vm_op){
654667
.op = MSM_VM_OP_UNMAP,
655668
.unmap = {
656669
.iova = vma->va.addr,
@@ -660,6 +673,9 @@ msm_gem_vm_sm_step_unmap(struct drm_gpuva_op *op, void *_arg)
660673
.obj = vma->gem.obj,
661674
});
662675

676+
if (ret)
677+
return ret;
678+
663679
msm_vma->mapped = false;
664680

665681
out_close:

0 commit comments

Comments
 (0)