diff options
| -rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 32 | ||||
| -rw-r--r-- | include/uapi/rdma/ib_user_verbs.h | 1 |
2 files changed, 16 insertions, 17 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 2f0f01b70e3b..26ee2d2a8c52 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
| @@ -2657,7 +2657,6 @@ ssize_t ib_uverbs_create_flow(struct ib_uverbs_file *file, | |||
| 2657 | void *kern_spec; | 2657 | void *kern_spec; |
| 2658 | void *ib_spec; | 2658 | void *ib_spec; |
| 2659 | int i; | 2659 | int i; |
| 2660 | int kern_attr_size; | ||
| 2661 | 2660 | ||
| 2662 | if (out_len < sizeof(resp)) | 2661 | if (out_len < sizeof(resp)) |
| 2663 | return -ENOSPC; | 2662 | return -ENOSPC; |
| @@ -2672,32 +2671,28 @@ ssize_t ib_uverbs_create_flow(struct ib_uverbs_file *file, | |||
| 2672 | !capable(CAP_NET_ADMIN)) || !capable(CAP_NET_RAW)) | 2671 | !capable(CAP_NET_ADMIN)) || !capable(CAP_NET_RAW)) |
| 2673 | return -EPERM; | 2672 | return -EPERM; |
| 2674 | 2673 | ||
| 2675 | if (cmd.flow_attr.num_of_specs < 0 || | 2674 | if (cmd.flow_attr.num_of_specs > IB_FLOW_SPEC_SUPPORT_LAYERS) |
| 2676 | cmd.flow_attr.num_of_specs > IB_FLOW_SPEC_SUPPORT_LAYERS) | ||
| 2677 | return -EINVAL; | 2675 | return -EINVAL; |
| 2678 | 2676 | ||
| 2679 | kern_attr_size = cmd.flow_attr.size - sizeof(cmd) - | 2677 | if (cmd.flow_attr.size > (in_len - sizeof(cmd)) || |
| 2680 | sizeof(struct ib_uverbs_cmd_hdr_ex); | 2678 | cmd.flow_attr.size > |
| 2681 | |||
| 2682 | if (cmd.flow_attr.size < 0 || cmd.flow_attr.size > in_len || | ||
| 2683 | kern_attr_size < 0 || kern_attr_size > | ||
| 2684 | (cmd.flow_attr.num_of_specs * sizeof(struct ib_kern_spec))) | 2679 | (cmd.flow_attr.num_of_specs * sizeof(struct ib_kern_spec))) |
| 2685 | return -EINVAL; | 2680 | return -EINVAL; |
| 2686 | 2681 | ||
| 2687 | if (cmd.flow_attr.num_of_specs) { | 2682 | if (cmd.flow_attr.num_of_specs) { |
| 2688 | kern_flow_attr = kmalloc(cmd.flow_attr.size, GFP_KERNEL); | 2683 | kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size, |
| 2684 | GFP_KERNEL); | ||
| 2689 | if (!kern_flow_attr) | 2685 | if (!kern_flow_attr) |
| 2690 | return -ENOMEM; | 2686 | return -ENOMEM; |
| 2691 | 2687 | ||
| 2692 | memcpy(kern_flow_attr, &cmd.flow_attr, sizeof(*kern_flow_attr)); | 2688 | memcpy(kern_flow_attr, &cmd.flow_attr, sizeof(*kern_flow_attr)); |
| 2693 | if (copy_from_user(kern_flow_attr + 1, buf + sizeof(cmd), | 2689 | if (copy_from_user(kern_flow_attr + 1, buf + sizeof(cmd), |
| 2694 | kern_attr_size)) { | 2690 | cmd.flow_attr.size)) { |
| 2695 | err = -EFAULT; | 2691 | err = -EFAULT; |
| 2696 | goto err_free_attr; | 2692 | goto err_free_attr; |
| 2697 | } | 2693 | } |
| 2698 | } else { | 2694 | } else { |
| 2699 | kern_flow_attr = &cmd.flow_attr; | 2695 | kern_flow_attr = &cmd.flow_attr; |
| 2700 | kern_attr_size = sizeof(cmd.flow_attr); | ||
| 2701 | } | 2696 | } |
| 2702 | 2697 | ||
| 2703 | uobj = kmalloc(sizeof(*uobj), GFP_KERNEL); | 2698 | uobj = kmalloc(sizeof(*uobj), GFP_KERNEL); |
| @@ -2714,7 +2709,7 @@ ssize_t ib_uverbs_create_flow(struct ib_uverbs_file *file, | |||
| 2714 | goto err_uobj; | 2709 | goto err_uobj; |
| 2715 | } | 2710 | } |
| 2716 | 2711 | ||
| 2717 | flow_attr = kmalloc(cmd.flow_attr.size, GFP_KERNEL); | 2712 | flow_attr = kmalloc(sizeof(*flow_attr) + cmd.flow_attr.size, GFP_KERNEL); |
| 2718 | if (!flow_attr) { | 2713 | if (!flow_attr) { |
| 2719 | err = -ENOMEM; | 2714 | err = -ENOMEM; |
| 2720 | goto err_put; | 2715 | goto err_put; |
| @@ -2729,19 +2724,22 @@ ssize_t ib_uverbs_create_flow(struct ib_uverbs_file *file, | |||
| 2729 | 2724 | ||
| 2730 | kern_spec = kern_flow_attr + 1; | 2725 | kern_spec = kern_flow_attr + 1; |
| 2731 | ib_spec = flow_attr + 1; | 2726 | ib_spec = flow_attr + 1; |
| 2732 | for (i = 0; i < flow_attr->num_of_specs && kern_attr_size > 0; i++) { | 2727 | for (i = 0; i < flow_attr->num_of_specs && |
| 2728 | cmd.flow_attr.size > offsetof(struct ib_kern_spec, reserved) && | ||
| 2729 | cmd.flow_attr.size >= | ||
| 2730 | ((struct ib_kern_spec *)kern_spec)->size; i++) { | ||
| 2733 | err = kern_spec_to_ib_spec(kern_spec, ib_spec); | 2731 | err = kern_spec_to_ib_spec(kern_spec, ib_spec); |
| 2734 | if (err) | 2732 | if (err) |
| 2735 | goto err_free; | 2733 | goto err_free; |
| 2736 | flow_attr->size += | 2734 | flow_attr->size += |
| 2737 | ((union ib_flow_spec *) ib_spec)->size; | 2735 | ((union ib_flow_spec *) ib_spec)->size; |
| 2738 | kern_attr_size -= ((struct ib_kern_spec *) kern_spec)->size; | 2736 | cmd.flow_attr.size -= ((struct ib_kern_spec *)kern_spec)->size; |
| 2739 | kern_spec += ((struct ib_kern_spec *) kern_spec)->size; | 2737 | kern_spec += ((struct ib_kern_spec *) kern_spec)->size; |
| 2740 | ib_spec += ((union ib_flow_spec *) ib_spec)->size; | 2738 | ib_spec += ((union ib_flow_spec *) ib_spec)->size; |
| 2741 | } | 2739 | } |
| 2742 | if (kern_attr_size) { | 2740 | if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) { |
| 2743 | pr_warn("create flow failed, %d bytes left from uverb cmd\n", | 2741 | pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n", |
| 2744 | kern_attr_size); | 2742 | i, cmd.flow_attr.size); |
| 2745 | goto err_free; | 2743 | goto err_free; |
| 2746 | } | 2744 | } |
| 2747 | flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER); | 2745 | flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER); |
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h index e3ddd86c90a6..99a58bdc1c64 100644 --- a/include/uapi/rdma/ib_user_verbs.h +++ b/include/uapi/rdma/ib_user_verbs.h | |||
| @@ -771,6 +771,7 @@ struct ib_kern_flow_attr { | |||
| 771 | 771 | ||
| 772 | struct ib_uverbs_create_flow { | 772 | struct ib_uverbs_create_flow { |
| 773 | __u32 comp_mask; | 773 | __u32 comp_mask; |
| 774 | __u32 reserved; | ||
| 774 | __u64 response; | 775 | __u64 response; |
| 775 | __u32 qp_handle; | 776 | __u32 qp_handle; |
| 776 | struct ib_kern_flow_attr flow_attr; | 777 | struct ib_kern_flow_attr flow_attr; |
