Commit ca745723 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma

Pull rdma fixes from Jason Gunthorpe:

 - Older "does not even boot" regression in qib from July

 - Bug fixes for error unwind in rtrs

 - Avoid a deadlock syzkaller found in srp

 - Fix another UAF syzkaller found in cma

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/cma: Do not change route.addr.src_addr outside state checks
  RDMA/ib_srp: Fix a deadlock
  RDMA/rtrs-clt: Move free_permit from free_clt to rtrs_clt_close
  RDMA/rtrs-clt: Fix possible double free in error case
  IB/qib: Fix duplicate sysfs directory name
parents 115ccd22 22e9f710
...@@ -3370,22 +3370,30 @@ static int cma_resolve_ib_addr(struct rdma_id_private *id_priv) ...@@ -3370,22 +3370,30 @@ static int cma_resolve_ib_addr(struct rdma_id_private *id_priv)
static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
const struct sockaddr *dst_addr) const struct sockaddr *dst_addr)
{ {
if (!src_addr || !src_addr->sa_family) { struct sockaddr_storage zero_sock = {};
src_addr = (struct sockaddr *) &id->route.addr.src_addr;
src_addr->sa_family = dst_addr->sa_family; if (src_addr && src_addr->sa_family)
if (IS_ENABLED(CONFIG_IPV6) && return rdma_bind_addr(id, src_addr);
dst_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *src_addr6 = (struct sockaddr_in6 *) src_addr; /*
struct sockaddr_in6 *dst_addr6 = (struct sockaddr_in6 *) dst_addr; * When the src_addr is not specified, automatically supply an any addr
src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id; */
if (ipv6_addr_type(&dst_addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL) zero_sock.ss_family = dst_addr->sa_family;
id->route.addr.dev_addr.bound_dev_if = dst_addr6->sin6_scope_id; if (IS_ENABLED(CONFIG_IPV6) && dst_addr->sa_family == AF_INET6) {
} else if (dst_addr->sa_family == AF_IB) { struct sockaddr_in6 *src_addr6 =
((struct sockaddr_ib *) src_addr)->sib_pkey = (struct sockaddr_in6 *)&zero_sock;
((struct sockaddr_ib *) dst_addr)->sib_pkey; struct sockaddr_in6 *dst_addr6 =
} (struct sockaddr_in6 *)dst_addr;
}
return rdma_bind_addr(id, src_addr); src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id;
if (ipv6_addr_type(&dst_addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
id->route.addr.dev_addr.bound_dev_if =
dst_addr6->sin6_scope_id;
} else if (dst_addr->sa_family == AF_IB) {
((struct sockaddr_ib *)&zero_sock)->sib_pkey =
((struct sockaddr_ib *)dst_addr)->sib_pkey;
}
return rdma_bind_addr(id, (struct sockaddr *)&zero_sock);
} }
/* /*
......
...@@ -541,7 +541,7 @@ static struct attribute *port_diagc_attributes[] = { ...@@ -541,7 +541,7 @@ static struct attribute *port_diagc_attributes[] = {
}; };
static const struct attribute_group port_diagc_group = { static const struct attribute_group port_diagc_group = {
.name = "linkcontrol", .name = "diag_counters",
.attrs = port_diagc_attributes, .attrs = port_diagc_attributes,
}; };
......
...@@ -2682,6 +2682,8 @@ static void rtrs_clt_dev_release(struct device *dev) ...@@ -2682,6 +2682,8 @@ static void rtrs_clt_dev_release(struct device *dev)
struct rtrs_clt_sess *clt = container_of(dev, struct rtrs_clt_sess, struct rtrs_clt_sess *clt = container_of(dev, struct rtrs_clt_sess,
dev); dev);
mutex_destroy(&clt->paths_ev_mutex);
mutex_destroy(&clt->paths_mutex);
kfree(clt); kfree(clt);
} }
...@@ -2711,6 +2713,8 @@ static struct rtrs_clt_sess *alloc_clt(const char *sessname, size_t paths_num, ...@@ -2711,6 +2713,8 @@ static struct rtrs_clt_sess *alloc_clt(const char *sessname, size_t paths_num,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
clt->dev.class = rtrs_clt_dev_class;
clt->dev.release = rtrs_clt_dev_release;
uuid_gen(&clt->paths_uuid); uuid_gen(&clt->paths_uuid);
INIT_LIST_HEAD_RCU(&clt->paths_list); INIT_LIST_HEAD_RCU(&clt->paths_list);
clt->paths_num = paths_num; clt->paths_num = paths_num;
...@@ -2727,53 +2731,51 @@ static struct rtrs_clt_sess *alloc_clt(const char *sessname, size_t paths_num, ...@@ -2727,53 +2731,51 @@ static struct rtrs_clt_sess *alloc_clt(const char *sessname, size_t paths_num,
init_waitqueue_head(&clt->permits_wait); init_waitqueue_head(&clt->permits_wait);
mutex_init(&clt->paths_ev_mutex); mutex_init(&clt->paths_ev_mutex);
mutex_init(&clt->paths_mutex); mutex_init(&clt->paths_mutex);
device_initialize(&clt->dev);
clt->dev.class = rtrs_clt_dev_class;
clt->dev.release = rtrs_clt_dev_release;
err = dev_set_name(&clt->dev, "%s", sessname); err = dev_set_name(&clt->dev, "%s", sessname);
if (err) if (err)
goto err; goto err_put;
/* /*
* Suppress user space notification until * Suppress user space notification until
* sysfs files are created * sysfs files are created
*/ */
dev_set_uevent_suppress(&clt->dev, true); dev_set_uevent_suppress(&clt->dev, true);
err = device_register(&clt->dev); err = device_add(&clt->dev);
if (err) { if (err)
put_device(&clt->dev); goto err_put;
goto err;
}
clt->kobj_paths = kobject_create_and_add("paths", &clt->dev.kobj); clt->kobj_paths = kobject_create_and_add("paths", &clt->dev.kobj);
if (!clt->kobj_paths) { if (!clt->kobj_paths) {
err = -ENOMEM; err = -ENOMEM;
goto err_dev; goto err_del;
} }
err = rtrs_clt_create_sysfs_root_files(clt); err = rtrs_clt_create_sysfs_root_files(clt);
if (err) { if (err) {
kobject_del(clt->kobj_paths); kobject_del(clt->kobj_paths);
kobject_put(clt->kobj_paths); kobject_put(clt->kobj_paths);
goto err_dev; goto err_del;
} }
dev_set_uevent_suppress(&clt->dev, false); dev_set_uevent_suppress(&clt->dev, false);
kobject_uevent(&clt->dev.kobj, KOBJ_ADD); kobject_uevent(&clt->dev.kobj, KOBJ_ADD);
return clt; return clt;
err_dev: err_del:
device_unregister(&clt->dev); device_del(&clt->dev);
err: err_put:
free_percpu(clt->pcpu_path); free_percpu(clt->pcpu_path);
kfree(clt); put_device(&clt->dev);
return ERR_PTR(err); return ERR_PTR(err);
} }
static void free_clt(struct rtrs_clt_sess *clt) static void free_clt(struct rtrs_clt_sess *clt)
{ {
free_permits(clt);
free_percpu(clt->pcpu_path); free_percpu(clt->pcpu_path);
mutex_destroy(&clt->paths_ev_mutex);
mutex_destroy(&clt->paths_mutex); /*
/* release callback will free clt in last put */ * release callback will free clt and destroy mutexes in last put
*/
device_unregister(&clt->dev); device_unregister(&clt->dev);
} }
...@@ -2890,6 +2892,7 @@ void rtrs_clt_close(struct rtrs_clt_sess *clt) ...@@ -2890,6 +2892,7 @@ void rtrs_clt_close(struct rtrs_clt_sess *clt)
rtrs_clt_destroy_path_files(clt_path, NULL); rtrs_clt_destroy_path_files(clt_path, NULL);
kobject_put(&clt_path->kobj); kobject_put(&clt_path->kobj);
} }
free_permits(clt);
free_clt(clt); free_clt(clt);
} }
EXPORT_SYMBOL(rtrs_clt_close); EXPORT_SYMBOL(rtrs_clt_close);
......
...@@ -4047,9 +4047,11 @@ static void srp_remove_one(struct ib_device *device, void *client_data) ...@@ -4047,9 +4047,11 @@ static void srp_remove_one(struct ib_device *device, void *client_data)
spin_unlock(&host->target_lock); spin_unlock(&host->target_lock);
/* /*
* Wait for tl_err and target port removal tasks. * srp_queue_remove_work() queues a call to
* srp_remove_target(). The latter function cancels
* target->tl_err_work so waiting for the remove works to
* finish is sufficient.
*/ */
flush_workqueue(system_long_wq);
flush_workqueue(srp_remove_wq); flush_workqueue(srp_remove_wq);
kfree(host); kfree(host);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment