Gustavo A. R. Silva
2018-Feb-13  15:40 UTC
[Nouveau] [drm-nouveau-mmu] question about potential NULL pointer dereference
Hi all,
While doing some static analysis I ran into the following piece of  
code at drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c:957:
  957#define node(root, dir) ((root)->head.dir == &vmm->list) ? NULL :
              \
  958        list_entry((root)->head.dir, struct nvkm_vma, head)
  959
  960void
  961nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
  962{
  963        struct nvkm_vma *next;
  964
  965        nvkm_memory_tags_put(vma->memory,  
vmm->mmu->subdev.device, &vma->tags);
  966        nvkm_memory_unref(&vma->memory);
  967
  968        if (vma->part) {
  969                struct nvkm_vma *prev = node(vma, prev);
  970                if (!prev->memory) {
  971                        prev->size += vma->size;
  972                        rb_erase(&vma->tree, &vmm->root);
  973                        list_del(&vma->head);
  974                        kfree(vma);
  975                        vma = prev;
  976                }
  977        }
  978
  979        next = node(vma, next);
  980        if (next && next->part) {
  981                if (!next->memory) {
  982                        vma->size += next->size;
  983                        rb_erase(&next->tree, &vmm->root);
  984                        list_del(&next->head);
  985                        kfree(next);
  986                }
  987        }
  988}
The issue here is that in case _node_ returns NULL, _prev_ is not  
being null checked, hence there is a potential null pointer  
dereference at line 970.
Notice that _next_ is being null checked at line 980, so I wonder if  
_prev_ should be checked the same as _next_.
The fact that both _next_ and next->part are null checked, makes me  
wonder if in case _prev_ actually needs to be checked, there is  
another pointer contained into _prev_ to be validated as well? I'm  
sorry, this is not clear to me at this moment.
I appreciate your feedback
Thank you
--
Gustavo
Ben Skeggs
2018-Feb-13  22:57 UTC
[Nouveau] [drm-nouveau-mmu] question about potential NULL pointer dereference
On Wed, Feb 14, 2018 at 1:40 AM, Gustavo A. R. Silva <garsilva at embeddedor.com> wrote:> > Hi all, > > While doing some static analysis I ran into the following piece of code at > drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c:957: > > 957#define node(root, dir) ((root)->head.dir == &vmm->list) ? NULL : > \ > 958 list_entry((root)->head.dir, struct nvkm_vma, head) > 959 > 960void > 961nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma) > 962{ > 963 struct nvkm_vma *next; > 964 > 965 nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, > &vma->tags); > 966 nvkm_memory_unref(&vma->memory); > 967 > 968 if (vma->part) { > 969 struct nvkm_vma *prev = node(vma, prev); > 970 if (!prev->memory) { > 971 prev->size += vma->size; > 972 rb_erase(&vma->tree, &vmm->root); > 973 list_del(&vma->head); > 974 kfree(vma); > 975 vma = prev; > 976 } > 977 } > 978 > 979 next = node(vma, next); > 980 if (next && next->part) { > 981 if (!next->memory) { > 982 vma->size += next->size; > 983 rb_erase(&next->tree, &vmm->root); > 984 list_del(&next->head); > 985 kfree(next); > 986 } > 987 } > 988} > > The issue here is that in case _node_ returns NULL, _prev_ is not being null > checked, hence there is a potential null pointer dereference at line 970. > > Notice that _next_ is being null checked at line 980, so I wonder if _prev_ > should be checked the same as _next_. > > The fact that both _next_ and next->part are null checked, makes me wonder > if in case _prev_ actually needs to be checked, there is another pointer > contained into _prev_ to be validated as well? I'm sorry, this is not clear > to me at this moment.It's not checked because it can't happen. If vma->part is set, there will be a previous node that it was split from. Ben.> > I appreciate your feedback > Thank you > -- > Gustavo > > > > > >
Gustavo A. R. Silva
2018-Feb-13  23:00 UTC
[Nouveau] [drm-nouveau-mmu] question about potential NULL pointer dereference
Quoting Ben Skeggs <bskeggs at redhat.com>:> On Wed, Feb 14, 2018 at 1:40 AM, Gustavo A. R. Silva > <garsilva at embeddedor.com> wrote: >> >> Hi all, >> >> While doing some static analysis I ran into the following piece of code at >> drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c:957: >> >> 957#define node(root, dir) ((root)->head.dir == &vmm->list) ? NULL : >> \ >> 958 list_entry((root)->head.dir, struct nvkm_vma, head) >> 959 >> 960void >> 961nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma) >> 962{ >> 963 struct nvkm_vma *next; >> 964 >> 965 nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, >> &vma->tags); >> 966 nvkm_memory_unref(&vma->memory); >> 967 >> 968 if (vma->part) { >> 969 struct nvkm_vma *prev = node(vma, prev); >> 970 if (!prev->memory) { >> 971 prev->size += vma->size; >> 972 rb_erase(&vma->tree, &vmm->root); >> 973 list_del(&vma->head); >> 974 kfree(vma); >> 975 vma = prev; >> 976 } >> 977 } >> 978 >> 979 next = node(vma, next); >> 980 if (next && next->part) { >> 981 if (!next->memory) { >> 982 vma->size += next->size; >> 983 rb_erase(&next->tree, &vmm->root); >> 984 list_del(&next->head); >> 985 kfree(next); >> 986 } >> 987 } >> 988} >> >> The issue here is that in case _node_ returns NULL, _prev_ is not being null >> checked, hence there is a potential null pointer dereference at line 970. >> >> Notice that _next_ is being null checked at line 980, so I wonder if _prev_ >> should be checked the same as _next_. >> >> The fact that both _next_ and next->part are null checked, makes me wonder >> if in case _prev_ actually needs to be checked, there is another pointer >> contained into _prev_ to be validated as well? I'm sorry, this is not clear >> to me at this moment. > It's not checked because it can't happen. If vma->part is set, there > will be a previous node that it was split from. >I got it. Thanks, Ben. -- Gustavo
Seemingly Similar Threads
- [drm-nouveau-mmu] question about potential NULL pointer dereference
- [RFC PATCH 00/13] SVM (share virtual memory) with HMM in nouveau
- [RESEND PATCH 0/3] nouveau: fixes for SVM
- [PATCH 3/6] mmu: map small pages into big pages(s) by IOMMU if possible
- [PATCH 3/6] mmu: map small pages into big pages(s) by IOMMU if possible