Commit 22f12c60e12a4112fdca31582e66fe501600ee2b
Exists in
master
and in
16 other branches
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, |