summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnssi Kalliolahti <akalliolahti@nvidia.com>2010-05-20 14:45:03 +0300
committerGary King <gking@nvidia.com>2010-06-11 16:35:44 -0700
commitc7d7d2960d9f46b6b0cb4f0041a91779ffacc12e (patch)
treeb816560cb8eec362dad043430deb297486aaf1b0
parent0ad0f96d590c15c8bbe1165ed8da250edc222a6f (diff)
nvmap: tighten handle validation before pinning
Added check for handle poison before pinning. This prevents panic (BUG_ON in _nvmap_handle_pin_locked) when trying to pin already freed handle. Bug 684375 Change-Id: I85ba4b37b2f193c19782edeaa562b7f77915cfc4 Reviewed-on: http://git-master/r/2478 Tested-by: Anssi Kalliolahti <akalliolahti@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
-rw-r--r--drivers/char/nvmap.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/char/nvmap.c b/drivers/char/nvmap.c
index dbd60a1a0d3a..6e1830862b64 100644
--- a/drivers/char/nvmap.c
+++ b/drivers/char/nvmap.c
@@ -1372,6 +1372,12 @@ struct nvmap_handle_ref *_nvmap_ref_lookup_locked(
struct nvmap_file_priv *priv, unsigned long ref)
{
struct rb_node *n = priv->handle_refs.rb_node;
+ struct nvmap_handle *h = (struct nvmap_handle *)ref;
+
+ if (unlikely(h->poison != NVDA_POISON)) {
+ pr_err("%s: handle is poisoned\n", __func__);
+ return NULL;
+ }
while (n) {
struct nvmap_handle_ref *r;
@@ -1551,16 +1557,19 @@ static int _nvmap_do_pin(struct nvmap_file_priv *priv,
spin_lock(&priv->ref_lock);
for (i=0; i<nr && !ret; i++) {
r = _nvmap_ref_lookup_locked(priv, refs[i]);
- if (!r && (!(priv->su || h[i]->global ||
- current->group_leader == h[i]->owner)))
- ret = -EPERM;
- else if (r) atomic_inc(&r->pin);
+ if (r) atomic_inc(&r->pin);
else {
- pr_err("%s: %s pinning %s's %uB handle without "
- "local context\n", __func__,
- current->group_leader->comm,
- h[i]->owner->comm, h[i]->orig_size);
- }
+ if ((h[i]->poison != NVDA_POISON) ||
+ (!(priv->su || h[i]->global ||
+ current->group_leader == h[i]->owner)))
+ ret = -EPERM;
+ else {
+ pr_err("%s: %s pinning %s's %uB handle without "
+ "local context\n", __func__,
+ current->group_leader->comm,
+ h[i]->owner->comm, h[i]->orig_size);
+ }
+ }
}
while (ret && i--) {