mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 05:17:10 +09:00
video: tegra: nvmap: fix read failures, super user and noref pinning
a >= vs > error when checking the operating region of the read and write ioctls was causing failures when reading the last byte of a handle. the super-user node (knvmap) wasn't registered correctly due to a cut- and-paste error, and the regular user node was assigned super-user priveleges. noref pinning wasn't correctly validating that the specified handle existed before pinning it, which caused the reference count for the handle to become imbalanced on a subsequent unpin Change-Id: I9985b85023705b00389a53fb962c3b60d62da6b8 Signed-off-by: Gary King <gking@nvidia.com>
This commit is contained in:
@@ -225,12 +225,17 @@ int nvmap_pin_ids(struct nvmap_client *client,
|
||||
if (ref) {
|
||||
atomic_inc(&ref->pin);
|
||||
nvmap_handle_get(h[i]);
|
||||
} else if (!client->super && (h[i]->owner != client) &&
|
||||
!h[i]->global) {
|
||||
ret = -EPERM;
|
||||
} else {
|
||||
nvmap_warn(client, "%s pinning unreferenced handle "
|
||||
"%p\n", current->group_leader->comm, h[i]);
|
||||
struct nvmap_handle *verify;
|
||||
nvmap_ref_unlock(client);
|
||||
verify = nvmap_validate_get(client, ids[i]);
|
||||
if (verify)
|
||||
nvmap_warn(client, "%s pinning unreferenced "
|
||||
"handle %p\n",
|
||||
current->group_leader->comm, h[i]);
|
||||
else
|
||||
ret = -EPERM;
|
||||
nvmap_ref_lock(client);
|
||||
}
|
||||
}
|
||||
nvmap_ref_unlock(client);
|
||||
|
||||
@@ -353,6 +353,8 @@ struct nvmap_handle *nvmap_validate_get(struct nvmap_client *client,
|
||||
if ((unsigned long)h == id) {
|
||||
if (client->super || h->global || (h->owner == client))
|
||||
h = nvmap_handle_get(h);
|
||||
else
|
||||
h = NULL;
|
||||
spin_unlock(&client->dev->handle_lock);
|
||||
return h;
|
||||
}
|
||||
@@ -696,9 +698,9 @@ static int nvmap_probe(struct platform_device *pdev)
|
||||
dev->dev_user.parent = &pdev->dev;
|
||||
|
||||
dev->dev_super.minor = MISC_DYNAMIC_MINOR;
|
||||
dev->dev_super.name = "kvmap";
|
||||
dev->dev_user.fops = &nvmap_super_fops;
|
||||
dev->dev_user.parent = &pdev->dev;
|
||||
dev->dev_super.name = "knvmap";
|
||||
dev->dev_super.fops = &nvmap_super_fops;
|
||||
dev->dev_super.parent = &pdev->dev;
|
||||
|
||||
dev->handles = RB_ROOT;
|
||||
|
||||
|
||||
@@ -459,7 +459,8 @@ static int cache_maint(struct nvmap_client *client, struct nvmap_handle *h,
|
||||
}
|
||||
|
||||
if (h->flags == NVMAP_HANDLE_UNCACHEABLE ||
|
||||
h->flags == NVMAP_HANDLE_WRITE_COMBINE)
|
||||
h->flags == NVMAP_HANDLE_WRITE_COMBINE ||
|
||||
start == end)
|
||||
goto out;
|
||||
|
||||
if (WARN_ON_ONCE(op == NVMAP_CACHE_OP_WB_INV))
|
||||
@@ -607,7 +608,7 @@ static ssize_t rw_handle(struct nvmap_client *client, struct nvmap_handle *h,
|
||||
return PTR_ERR(pte);
|
||||
|
||||
while (count--) {
|
||||
if (h_offs + elem_size >= h->size) {
|
||||
if (h_offs + elem_size > h->size) {
|
||||
nvmap_warn(client, "read/write outside of handle\n");
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user