Commit 22f12c60e12a4112fdca31582e66fe501600ee2b

Authored by Roland Dreier

Merge branches 'cxgb4', 'flowsteer' and 'misc' into for-linus

Showing 5 changed files Side-by-side Diff

drivers/infiniband/core/iwcm.c
... ... @@ -181,9 +181,16 @@
181 181 static void rem_ref(struct iw_cm_id *cm_id)
182 182 {
183 183 struct iwcm_id_private *cm_id_priv;
  184 + int cb_destroy;
  185 +
184 186 cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
185   - if (iwcm_deref_id(cm_id_priv) &&
186   - test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
  187 +
  188 + /*
  189 + * Test bit before deref in case the cm_id gets freed on another
  190 + * thread.
  191 + */
  192 + cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
  193 + if (iwcm_deref_id(cm_id_priv) && cb_destroy) {
187 194 BUG_ON(!list_empty(&cm_id_priv->work_list));
188 195 free_cm_id(cm_id_priv);
189 196 }
drivers/infiniband/core/uverbs.h
... ... @@ -49,10 +49,18 @@
49 49  
50 50 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
51 51 do { \
52   - (udata)->inbuf = (void __user *) (ibuf); \
  52 + (udata)->inbuf = (const void __user *) (ibuf); \
53 53 (udata)->outbuf = (void __user *) (obuf); \
54 54 (udata)->inlen = (ilen); \
55 55 (udata)->outlen = (olen); \
  56 + } while (0)
  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); \
56 64 } while (0)
57 65  
58 66 /*
drivers/infiniband/core/uverbs_cmd.c
... ... @@ -2593,6 +2593,9 @@
2593 2593 static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
2594 2594 union ib_flow_spec *ib_spec)
2595 2595 {
  2596 + if (kern_spec->reserved)
  2597 + return -EINVAL;
  2598 +
2596 2599 ib_spec->type = kern_spec->type;
2597 2600  
2598 2601 switch (ib_spec->type) {
... ... @@ -2646,6 +2649,9 @@
2646 2649 void *ib_spec;
2647 2650 int i;
2648 2651  
  2652 + if (ucore->inlen < sizeof(cmd))
  2653 + return -EINVAL;
  2654 +
2649 2655 if (ucore->outlen < sizeof(resp))
2650 2656 return -ENOSPC;
2651 2657  
... ... @@ -2671,6 +2677,10 @@
2671 2677 (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec)))
2672 2678 return -EINVAL;
2673 2679  
  2680 + if (cmd.flow_attr.reserved[0] ||
  2681 + cmd.flow_attr.reserved[1])
  2682 + return -EINVAL;
  2683 +
2674 2684 if (cmd.flow_attr.num_of_specs) {
2675 2685 kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size,
2676 2686 GFP_KERNEL);
... ... @@ -2731,6 +2741,7 @@
2731 2741 if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) {
2732 2742 pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n",
2733 2743 i, cmd.flow_attr.size);
  2744 + err = -EINVAL;
2734 2745 goto err_free;
2735 2746 }
2736 2747 flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER);
2737 2748  
... ... @@ -2791,9 +2802,15 @@
2791 2802 struct ib_uobject *uobj;
2792 2803 int ret;
2793 2804  
  2805 + if (ucore->inlen < sizeof(cmd))
  2806 + return -EINVAL;
  2807 +
2794 2808 ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
2795 2809 if (ret)
2796 2810 return ret;
  2811 +
  2812 + if (cmd.comp_mask)
  2813 + return -EINVAL;
2797 2814  
2798 2815 uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle,
2799 2816 file->ucontext);
drivers/infiniband/core/uverbs_main.c
... ... @@ -668,25 +668,30 @@
668 668 if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count)
669 669 return -EINVAL;
670 670  
  671 + if (ex_hdr.cmd_hdr_reserved)
  672 + return -EINVAL;
  673 +
671 674 if (ex_hdr.response) {
672 675 if (!hdr.out_words && !ex_hdr.provider_out_words)
673 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 682 } else {
675 683 if (hdr.out_words || ex_hdr.provider_out_words)
676 684 return -EINVAL;
677 685 }
678 686  
679   - INIT_UDATA(&ucore,
680   - (hdr.in_words) ? buf : 0,
681   - (unsigned long)ex_hdr.response,
682   - hdr.in_words * 8,
683   - hdr.out_words * 8);
  687 + INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response,
  688 + hdr.in_words * 8, hdr.out_words * 8);
684 689  
685   - INIT_UDATA(&uhw,
686   - (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0,
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 + INIT_UDATA_BUF_OR_NULL(&uhw,
  691 + buf + ucore.inlen,
  692 + (unsigned long) ex_hdr.response + ucore.outlen,
  693 + ex_hdr.provider_in_words * 8,
  694 + ex_hdr.provider_out_words * 8);
690 695  
691 696 err = uverbs_ex_cmd_table[command](file,
692 697 &ucore,
include/rdma/ib_verbs.h
... ... @@ -978,7 +978,7 @@
978 978 };
979 979  
980 980 struct ib_udata {
981   - void __user *inbuf;
  981 + const void __user *inbuf;
982 982 void __user *outbuf;
983 983 size_t inlen;
984 984 size_t outlen;