aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/uverbs.h10
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c17
-rw-r--r--drivers/infiniband/core/uverbs_main.c27
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c2
-rw-r--r--include/rdma/ib_verbs.h2
5 files changed, 44 insertions, 14 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index bdc842e9faef..a283274a5a09 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -49,12 +49,20 @@
49 49
50#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ 50#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
51 do { \ 51 do { \
52 (udata)->inbuf = (void __user *) (ibuf); \ 52 (udata)->inbuf = (const void __user *) (ibuf); \
53 (udata)->outbuf = (void __user *) (obuf); \ 53 (udata)->outbuf = (void __user *) (obuf); \
54 (udata)->inlen = (ilen); \ 54 (udata)->inlen = (ilen); \
55 (udata)->outlen = (olen); \ 55 (udata)->outlen = (olen); \
56 } while (0) 56 } while (0)
57 57
58#define INIT_UDATA_BUF_OR_NULL(udata, ibuf, obuf, ilen, olen) \
59 do { \
60 (udata)->inbuf = (ilen) ? (const void __user *) (ibuf) : NULL; \
61 (udata)->outbuf = (olen) ? (void __user *) (obuf) : NULL; \
62 (udata)->inlen = (ilen); \
63 (udata)->outlen = (olen); \
64 } while (0)
65
58/* 66/*
59 * Our lifetime rules for these structs are the following: 67 * Our lifetime rules for these structs are the following:
60 * 68 *
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 65f6e7dc380c..f1cc83855af6 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -2593,6 +2593,9 @@ out_put:
2593static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec, 2593static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
2594 union ib_flow_spec *ib_spec) 2594 union ib_flow_spec *ib_spec)
2595{ 2595{
2596 if (kern_spec->reserved)
2597 return -EINVAL;
2598
2596 ib_spec->type = kern_spec->type; 2599 ib_spec->type = kern_spec->type;
2597 2600
2598 switch (ib_spec->type) { 2601 switch (ib_spec->type) {
@@ -2646,6 +2649,9 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
2646 void *ib_spec; 2649 void *ib_spec;
2647 int i; 2650 int i;
2648 2651
2652 if (ucore->inlen < sizeof(cmd))
2653 return -EINVAL;
2654
2649 if (ucore->outlen < sizeof(resp)) 2655 if (ucore->outlen < sizeof(resp))
2650 return -ENOSPC; 2656 return -ENOSPC;
2651 2657
@@ -2671,6 +2677,10 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
2671 (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec))) 2677 (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec)))
2672 return -EINVAL; 2678 return -EINVAL;
2673 2679
2680 if (cmd.flow_attr.reserved[0] ||
2681 cmd.flow_attr.reserved[1])
2682 return -EINVAL;
2683
2674 if (cmd.flow_attr.num_of_specs) { 2684 if (cmd.flow_attr.num_of_specs) {
2675 kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size, 2685 kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size,
2676 GFP_KERNEL); 2686 GFP_KERNEL);
@@ -2731,6 +2741,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
2731 if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) { 2741 if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) {
2732 pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n", 2742 pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n",
2733 i, cmd.flow_attr.size); 2743 i, cmd.flow_attr.size);
2744 err = -EINVAL;
2734 goto err_free; 2745 goto err_free;
2735 } 2746 }
2736 flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER); 2747 flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER);
@@ -2791,10 +2802,16 @@ int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file,
2791 struct ib_uobject *uobj; 2802 struct ib_uobject *uobj;
2792 int ret; 2803 int ret;
2793 2804
2805 if (ucore->inlen < sizeof(cmd))
2806 return -EINVAL;
2807
2794 ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); 2808 ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
2795 if (ret) 2809 if (ret)
2796 return ret; 2810 return ret;
2797 2811
2812 if (cmd.comp_mask)
2813 return -EINVAL;
2814
2798 uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle, 2815 uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle,
2799 file->ucontext); 2816 file->ucontext);
2800 if (!uobj) 2817 if (!uobj)
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 34386943ebcf..08219fb3338b 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -668,25 +668,30 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
668 if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count) 668 if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count)
669 return -EINVAL; 669 return -EINVAL;
670 670
671 if (ex_hdr.cmd_hdr_reserved)
672 return -EINVAL;
673
671 if (ex_hdr.response) { 674 if (ex_hdr.response) {
672 if (!hdr.out_words && !ex_hdr.provider_out_words) 675 if (!hdr.out_words && !ex_hdr.provider_out_words)
673 return -EINVAL; 676 return -EINVAL;
677
678 if (!access_ok(VERIFY_WRITE,
679 (void __user *) (unsigned long) ex_hdr.response,
680 (hdr.out_words + ex_hdr.provider_out_words) * 8))
681 return -EFAULT;
674 } else { 682 } else {
675 if (hdr.out_words || ex_hdr.provider_out_words) 683 if (hdr.out_words || ex_hdr.provider_out_words)
676 return -EINVAL; 684 return -EINVAL;
677 } 685 }
678 686
679 INIT_UDATA(&ucore, 687 INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response,
680 (hdr.in_words) ? buf : 0, 688 hdr.in_words * 8, hdr.out_words * 8);
681 (unsigned long)ex_hdr.response, 689
682 hdr.in_words * 8, 690 INIT_UDATA_BUF_OR_NULL(&uhw,
683 hdr.out_words * 8); 691 buf + ucore.inlen,
684 692 (unsigned long) ex_hdr.response + ucore.outlen,
685 INIT_UDATA(&uhw, 693 ex_hdr.provider_in_words * 8,
686 (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0, 694 ex_hdr.provider_out_words * 8);
687 (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0,
688 ex_hdr.provider_in_words * 8,
689 ex_hdr.provider_out_words * 8);
690 695
691 err = uverbs_ex_cmd_table[command](file, 696 err = uverbs_ex_cmd_table[command](file,
692 &ucore, 697 &ucore,
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 4cb8eb24497c..84e45006451c 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -173,7 +173,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
173 return ret; 173 return ret;
174} 174}
175 175
176int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data) 176static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
177{ 177{
178 u32 remain = len; 178 u32 remain = len;
179 u32 dmalen; 179 u32 dmalen;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 979874c627ee..61e1935c91b1 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -978,7 +978,7 @@ struct ib_uobject {
978}; 978};
979 979
980struct ib_udata { 980struct ib_udata {
981 void __user *inbuf; 981 const void __user *inbuf;
982 void __user *outbuf; 982 void __user *outbuf;
983 size_t inlen; 983 size_t inlen;
984 size_t outlen; 984 size_t outlen;