video: tegra: nvmap: Fix data race

Consider the following execution scenario, it can lead to a data race

Thread 1                    Thread 2
-------------------------------------------------------
NvRmMemHandleAllocAttr
NvRmMemGetFd
NvRmMemHandleFromFd         close(fd), NvRmMemHandleFree

When thread 1 is executing NvRmMemHandleFromFd while thread 2 is closing
the fd and freeing the handle, then following sequence will lead to
accessing a freed dma-buf and may lead to dereference issue.

- TH1: Get handle from fd and increment handle's refcount.
- TH2: Close the fd and start execution of NvRmMemHandleFree.
- TH2: Decrement ref's dup count, it will become 0, hence ref would be
freed and dma-buf as well, but as handle's refcount is incremented in
step 1, handle won't be freed.
- TH1: Resume HandleFromFd part, call to nvmap_duplicate_handle. Ref is
already freed, so generate new ref and increment dma-buf's count but as
dma-buf is freed already, accessing dma-buf will lead to dereferene
issue. Hence, we need to add a null check here and return error value in
such scenario.

Also, add check for return value of nvmap_handle_get, at missing places.

Bug 4214453

Change-Id: Ib6ef66b4a7126bef2ed1dbb48643445a4ded1bab
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2994962
(cherry picked from commit 7ba6a3abfe65f7cffeeb4004cf0868468121fc32)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2994440
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Ketan Patil
2023-10-10 12:17:39 +00:00
committed by mobile promotions
parent 383e589822
commit 5c59fead46
3 changed files with 18 additions and 3 deletions

View File

@@ -403,9 +403,13 @@ struct nvmap_handle_ref *nvmap_duplicate_handle(struct nvmap_client *client,
if (is_ro) {
ref->is_ro = true;
if (!h->dmabuf_ro)
goto exit;
get_dma_buf(h->dmabuf_ro);
} else {
ref->is_ro = false;
if (!h->dmabuf)
goto exit;
get_dma_buf(h->dmabuf);
}
@@ -413,6 +417,11 @@ out:
NVMAP_TAG_TRACE(trace_nvmap_duplicate_handle,
NVMAP_TP_ARGS_CHR(client, h, ref));
return ref;
exit:
pr_err("dmabuf is NULL\n");
kfree(ref);
return ERR_PTR(-EINVAL);
}
struct nvmap_handle_ref *nvmap_create_handle_from_id(