Loading drivers/infiniband/core/iwcm.c +9 −2 Original line number Diff line number Diff line Loading @@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id) static void rem_ref(struct iw_cm_id *cm_id) { struct iwcm_id_private *cm_id_priv; int cb_destroy; cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); if (iwcm_deref_id(cm_id_priv) && test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) { /* * Test bit before deref in case the cm_id gets freed on another * thread. */ cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags); if (iwcm_deref_id(cm_id_priv) && cb_destroy) { BUG_ON(!list_empty(&cm_id_priv->work_list)); free_cm_id(cm_id_priv); } Loading drivers/infiniband/core/uverbs.h +9 −1 Original line number Diff line number Diff line Loading @@ -49,12 +49,20 @@ #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ do { \ (udata)->inbuf = (void __user *) (ibuf); \ (udata)->inbuf = (const void __user *) (ibuf); \ (udata)->outbuf = (void __user *) (obuf); \ (udata)->inlen = (ilen); \ (udata)->outlen = (olen); \ } while (0) #define INIT_UDATA_BUF_OR_NULL(udata, ibuf, obuf, ilen, olen) \ do { \ (udata)->inbuf = (ilen) ? (const void __user *) (ibuf) : NULL; \ (udata)->outbuf = (olen) ? (void __user *) (obuf) : NULL; \ (udata)->inlen = (ilen); \ (udata)->outlen = (olen); \ } while (0) /* * Our lifetime rules for these structs are the following: * Loading drivers/infiniband/core/uverbs_cmd.c +17 −0 Original line number Diff line number Diff line Loading @@ -2593,6 +2593,9 @@ out_put: static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec, union ib_flow_spec *ib_spec) { if (kern_spec->reserved) return -EINVAL; ib_spec->type = kern_spec->type; switch (ib_spec->type) { Loading Loading @@ -2646,6 +2649,9 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, void *ib_spec; int i; if (ucore->inlen < sizeof(cmd)) return -EINVAL; if (ucore->outlen < sizeof(resp)) return -ENOSPC; Loading @@ -2671,6 +2677,10 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec))) return -EINVAL; if (cmd.flow_attr.reserved[0] || cmd.flow_attr.reserved[1]) return -EINVAL; if (cmd.flow_attr.num_of_specs) { kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size, GFP_KERNEL); Loading Loading @@ -2731,6 +2741,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) { pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n", i, cmd.flow_attr.size); err = -EINVAL; goto err_free; } flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER); Loading Loading @@ -2791,10 +2802,16 @@ int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file, struct ib_uobject *uobj; int ret; if (ucore->inlen < sizeof(cmd)) return -EINVAL; ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); if (ret) return ret; if (cmd.comp_mask) return -EINVAL; uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle, file->ucontext); if (!uobj) Loading drivers/infiniband/core/uverbs_main.c +16 −11 Original line number Diff line number Diff line Loading @@ -668,23 +668,28 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count) return -EINVAL; if (ex_hdr.cmd_hdr_reserved) return -EINVAL; if (ex_hdr.response) { if (!hdr.out_words && !ex_hdr.provider_out_words) return -EINVAL; if (!access_ok(VERIFY_WRITE, (void __user *) (unsigned long) ex_hdr.response, (hdr.out_words + ex_hdr.provider_out_words) * 8)) return -EFAULT; } else { if (hdr.out_words || ex_hdr.provider_out_words) return -EINVAL; } INIT_UDATA(&ucore, (hdr.in_words) ? buf : 0, (unsigned long)ex_hdr.response, hdr.in_words * 8, hdr.out_words * 8); INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response, hdr.in_words * 8, hdr.out_words * 8); INIT_UDATA(&uhw, (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0, (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0, INIT_UDATA_BUF_OR_NULL(&uhw, buf + ucore.inlen, (unsigned long) ex_hdr.response + ucore.outlen, ex_hdr.provider_in_words * 8, ex_hdr.provider_out_words * 8); Loading include/rdma/ib_verbs.h +1 −1 Original line number Diff line number Diff line Loading @@ -978,7 +978,7 @@ struct ib_uobject { }; struct ib_udata { void __user *inbuf; const void __user *inbuf; void __user *outbuf; size_t inlen; size_t outlen; Loading Loading
drivers/infiniband/core/iwcm.c +9 −2 Original line number Diff line number Diff line Loading @@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id) static void rem_ref(struct iw_cm_id *cm_id) { struct iwcm_id_private *cm_id_priv; int cb_destroy; cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); if (iwcm_deref_id(cm_id_priv) && test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) { /* * Test bit before deref in case the cm_id gets freed on another * thread. */ cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags); if (iwcm_deref_id(cm_id_priv) && cb_destroy) { BUG_ON(!list_empty(&cm_id_priv->work_list)); free_cm_id(cm_id_priv); } Loading
drivers/infiniband/core/uverbs.h +9 −1 Original line number Diff line number Diff line Loading @@ -49,12 +49,20 @@ #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ do { \ (udata)->inbuf = (void __user *) (ibuf); \ (udata)->inbuf = (const void __user *) (ibuf); \ (udata)->outbuf = (void __user *) (obuf); \ (udata)->inlen = (ilen); \ (udata)->outlen = (olen); \ } while (0) #define INIT_UDATA_BUF_OR_NULL(udata, ibuf, obuf, ilen, olen) \ do { \ (udata)->inbuf = (ilen) ? (const void __user *) (ibuf) : NULL; \ (udata)->outbuf = (olen) ? (void __user *) (obuf) : NULL; \ (udata)->inlen = (ilen); \ (udata)->outlen = (olen); \ } while (0) /* * Our lifetime rules for these structs are the following: * Loading
drivers/infiniband/core/uverbs_cmd.c +17 −0 Original line number Diff line number Diff line Loading @@ -2593,6 +2593,9 @@ out_put: static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec, union ib_flow_spec *ib_spec) { if (kern_spec->reserved) return -EINVAL; ib_spec->type = kern_spec->type; switch (ib_spec->type) { Loading Loading @@ -2646,6 +2649,9 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, void *ib_spec; int i; if (ucore->inlen < sizeof(cmd)) return -EINVAL; if (ucore->outlen < sizeof(resp)) return -ENOSPC; Loading @@ -2671,6 +2677,10 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec))) return -EINVAL; if (cmd.flow_attr.reserved[0] || cmd.flow_attr.reserved[1]) return -EINVAL; if (cmd.flow_attr.num_of_specs) { kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size, GFP_KERNEL); Loading Loading @@ -2731,6 +2741,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) { pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n", i, cmd.flow_attr.size); err = -EINVAL; goto err_free; } flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER); Loading Loading @@ -2791,10 +2802,16 @@ int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file, struct ib_uobject *uobj; int ret; if (ucore->inlen < sizeof(cmd)) return -EINVAL; ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd)); if (ret) return ret; if (cmd.comp_mask) return -EINVAL; uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle, file->ucontext); if (!uobj) Loading
drivers/infiniband/core/uverbs_main.c +16 −11 Original line number Diff line number Diff line Loading @@ -668,23 +668,28 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count) return -EINVAL; if (ex_hdr.cmd_hdr_reserved) return -EINVAL; if (ex_hdr.response) { if (!hdr.out_words && !ex_hdr.provider_out_words) return -EINVAL; if (!access_ok(VERIFY_WRITE, (void __user *) (unsigned long) ex_hdr.response, (hdr.out_words + ex_hdr.provider_out_words) * 8)) return -EFAULT; } else { if (hdr.out_words || ex_hdr.provider_out_words) return -EINVAL; } INIT_UDATA(&ucore, (hdr.in_words) ? buf : 0, (unsigned long)ex_hdr.response, hdr.in_words * 8, hdr.out_words * 8); INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response, hdr.in_words * 8, hdr.out_words * 8); INIT_UDATA(&uhw, (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0, (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0, INIT_UDATA_BUF_OR_NULL(&uhw, buf + ucore.inlen, (unsigned long) ex_hdr.response + ucore.outlen, ex_hdr.provider_in_words * 8, ex_hdr.provider_out_words * 8); Loading
include/rdma/ib_verbs.h +1 −1 Original line number Diff line number Diff line Loading @@ -978,7 +978,7 @@ struct ib_uobject { }; struct ib_udata { void __user *inbuf; const void __user *inbuf; void __user *outbuf; size_t inlen; size_t outlen; Loading