aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/core/uverbs_main.c62
1 files changed, 32 insertions, 30 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 20797a1c77f3..906fcceb9ea4 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -660,6 +660,29 @@ static bool verify_command_idx(u32 command, bool extended)
uverbs_cmd_table[command];
}
+static ssize_t process_hdr(struct ib_uverbs_cmd_hdr *hdr,
+ __u32 *command, bool *extended)
+{
+ __u32 flags;
+
+ if (hdr->command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK |
+ IB_USER_VERBS_CMD_COMMAND_MASK))
+ return -EINVAL;
+
+ *command = hdr->command & IB_USER_VERBS_CMD_COMMAND_MASK;
+ flags = (hdr->command &
+ IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT;
+
+ *extended = flags & IB_USER_VERBS_CMD_FLAG_EXTENDED;
+ if (flags & ~IB_USER_VERBS_CMD_FLAG_EXTENDED)
+ return -EINVAL;
+
+ if (!verify_command_idx(*command, *extended))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
size_t count, loff_t *pos)
{
@@ -667,9 +690,8 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
struct ib_uverbs_ex_cmd_hdr ex_hdr;
struct ib_device *ib_dev;
struct ib_uverbs_cmd_hdr hdr;
- bool extended_command;
+ bool extended;
__u32 command;
- __u32 flags;
int srcu_key;
ssize_t ret;
@@ -685,6 +707,13 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT;
+ ret = process_hdr(&hdr, &command, &extended);
+ if (ret)
+ return ret;
+
+ if (extended && count < (sizeof(hdr) + sizeof(ex_hdr)))
+ return -EINVAL;
+
srcu_key = srcu_read_lock(&file->device->disassociate_srcu);
ib_dev = srcu_dereference(file->device->ib_dev,
&file->device->disassociate_srcu);
@@ -693,33 +722,6 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
goto out;
}
- if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK |
- IB_USER_VERBS_CMD_COMMAND_MASK)) {
- ret = -EINVAL;
- goto out;
- }
-
- command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK;
- flags = (hdr.command &
- IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT;
-
- extended_command = flags & IB_USER_VERBS_CMD_FLAG_EXTENDED;
- if (flags & ~IB_USER_VERBS_CMD_FLAG_EXTENDED) {
- ret = -EINVAL;
- goto out;
- }
-
- if (extended_command &&
- count < (sizeof(hdr) + sizeof(ex_hdr))) {
- ret = -EINVAL;
- goto out;
- }
-
- if (!verify_command_idx(command, extended_command)) {
- ret = -EOPNOTSUPP;
- goto out;
- }
-
if (!verify_command_mask(ib_dev, command)) {
ret = -EOPNOTSUPP;
goto out;
@@ -731,7 +733,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
goto out;
}
- if (!flags) {
+ if (!extended) {
if (hdr.in_words * 4 != count) {
ret = -EINVAL;
goto out;