aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_main.c
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2005-09-26 13:01:03 -0700
committerRoland Dreier <rolandd@cisco.com>2005-09-26 13:01:03 -0700
commit63c47c286d062d93e0501d60797274c84a587e97 (patch)
tree7be7c3402e456ed857c5041cd5ee6a699f772701 /drivers/infiniband/core/uverbs_main.c
parent[IB] mthca: Fix off by one bug in mthca_map_cmd (diff)
downloadlinux-dev-63c47c286d062d93e0501d60797274c84a587e97.tar.xz
linux-dev-63c47c286d062d93e0501d60797274c84a587e97.zip
[IB] uverbs: Close some exploitable races
Al Viro pointed out that the current IB userspace verbs interface allows userspace to cause mischief by closing file descriptors before we're ready, or issuing the same command twice at the same time. This patch closes those races, and fixes other obvious problems such as a module reference leak. Some other interface bogosities will require an ABI change to fix properly, so I'm deferring those fixes until 2.6.15. Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core/uverbs_main.c')
-rw-r--r--drivers/infiniband/core/uverbs_main.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index ce5bdb7af306..12511808de21 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -448,7 +448,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (hdr.in_words * 4 != count)
return -EINVAL;
- if (hdr.command < 0 || hdr.command >= ARRAY_SIZE(uverbs_cmd_table))
+ if (hdr.command < 0 ||
+ hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+ !uverbs_cmd_table[hdr.command])
return -EINVAL;
if (!file->ucontext &&
@@ -484,27 +486,29 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
file = kmalloc(sizeof *file +
(dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
GFP_KERNEL);
- if (!file)
- return -ENOMEM;
+ if (!file) {
+ ret = -ENOMEM;
+ goto err;
+ }
file->device = dev;
kref_init(&file->ref);
+ init_MUTEX(&file->mutex);
file->ucontext = NULL;
+ kref_get(&file->ref);
ret = ib_uverbs_event_init(&file->async_file, file);
if (ret)
- goto err;
+ goto err_kref;
file->async_file.is_async = 1;
- kref_get(&file->ref);
-
for (i = 0; i < dev->num_comp; ++i) {
+ kref_get(&file->ref);
ret = ib_uverbs_event_init(&file->comp_file[i], file);
if (ret)
goto err_async;
- kref_get(&file->ref);
file->comp_file[i].is_async = 0;
}
@@ -524,9 +528,16 @@ err_async:
ib_uverbs_event_release(&file->async_file);
-err:
+err_kref:
+ /*
+ * One extra kref_put() because we took a reference before the
+ * event file creation that failed and got us here.
+ */
+ kref_put(&file->ref, ib_uverbs_release_file);
kref_put(&file->ref, ib_uverbs_release_file);
+err:
+ module_put(dev->ib_dev->owner);
return ret;
}