Skip to content

Commit 16b8703

Browse files
BernardMetzlerrleon
authored andcommitted
RDMA/siw: Remove direct link to net_device
Do not manage a per device direct link to net_device. Rely on associated ib_devices net_device management, not doubling the effort locally. A badly managed local link to net_device was causing a 'KASAN: slab-use-after-free' exception during siw_query_port() call. Fixes: bdcf26b ("rdma/siw: network and RDMA core interface") Reported-by: syzbot+4b87489410b4efd181bf@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=4b87489410b4efd181bf Signed-off-by: Bernard Metzler <bmt@zurich.ibm.com> Link: https://patch.msgid.link/20241212151848.564872-1-bmt@zurich.ibm.com Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev> Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent 13a6691 commit 16b8703

File tree

4 files changed

+49
-35
lines changed

4 files changed

+49
-35
lines changed

drivers/infiniband/sw/siw/siw.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
*/
4747
#define SIW_IRQ_MAXBURST_SQ_ACTIVE 4
4848

49+
/* There is always only a port 1 per siw device */
50+
#define SIW_PORT 1
51+
4952
struct siw_dev_cap {
5053
int max_qp;
5154
int max_qp_wr;
@@ -69,16 +72,12 @@ struct siw_pd {
6972

7073
struct siw_device {
7174
struct ib_device base_dev;
72-
struct net_device *netdev;
7375
struct siw_dev_cap attrs;
7476

7577
u32 vendor_part_id;
7678
int numa_node;
7779
char raw_gid[ETH_ALEN];
7880

79-
/* physical port state (only one port per device) */
80-
enum ib_port_state state;
81-
8281
spinlock_t lock;
8382

8483
struct xarray qp_xa;

drivers/infiniband/sw/siw/siw_cm.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,6 +1759,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
17591759
{
17601760
struct socket *s;
17611761
struct siw_cep *cep = NULL;
1762+
struct net_device *ndev = NULL;
17621763
struct siw_device *sdev = to_siw_dev(id->device);
17631764
int addr_family = id->local_addr.ss_family;
17641765
int rv = 0;
@@ -1779,9 +1780,15 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
17791780
struct sockaddr_in *laddr = &to_sockaddr_in(id->local_addr);
17801781

17811782
/* For wildcard addr, limit binding to current device only */
1782-
if (ipv4_is_zeronet(laddr->sin_addr.s_addr))
1783-
s->sk->sk_bound_dev_if = sdev->netdev->ifindex;
1784-
1783+
if (ipv4_is_zeronet(laddr->sin_addr.s_addr)) {
1784+
ndev = ib_device_get_netdev(id->device, SIW_PORT);
1785+
if (ndev) {
1786+
s->sk->sk_bound_dev_if = ndev->ifindex;
1787+
} else {
1788+
rv = -ENODEV;
1789+
goto error;
1790+
}
1791+
}
17851792
rv = s->ops->bind(s, (struct sockaddr *)laddr,
17861793
sizeof(struct sockaddr_in));
17871794
} else {
@@ -1797,9 +1804,15 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
17971804
}
17981805

17991806
/* For wildcard addr, limit binding to current device only */
1800-
if (ipv6_addr_any(&laddr->sin6_addr))
1801-
s->sk->sk_bound_dev_if = sdev->netdev->ifindex;
1802-
1807+
if (ipv6_addr_any(&laddr->sin6_addr)) {
1808+
ndev = ib_device_get_netdev(id->device, SIW_PORT);
1809+
if (ndev) {
1810+
s->sk->sk_bound_dev_if = ndev->ifindex;
1811+
} else {
1812+
rv = -ENODEV;
1813+
goto error;
1814+
}
1815+
}
18031816
rv = s->ops->bind(s, (struct sockaddr *)laddr,
18041817
sizeof(struct sockaddr_in6));
18051818
}
@@ -1860,6 +1873,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
18601873
}
18611874
list_add_tail(&cep->listenq, (struct list_head *)id->provider_data);
18621875
cep->state = SIW_EPSTATE_LISTENING;
1876+
dev_put(ndev);
18631877

18641878
siw_dbg(id->device, "Listen at laddr %pISp\n", &id->local_addr);
18651879

@@ -1879,6 +1893,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
18791893
siw_cep_set_free_and_put(cep);
18801894
}
18811895
sock_release(s);
1896+
dev_put(ndev);
18821897

18831898
return rv;
18841899
}

drivers/infiniband/sw/siw/siw_main.c

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,6 @@ static struct siw_device *siw_device_create(struct net_device *netdev)
287287
return NULL;
288288

289289
base_dev = &sdev->base_dev;
290-
sdev->netdev = netdev;
291290

292291
if (netdev->addr_len) {
293292
memcpy(sdev->raw_gid, netdev->dev_addr,
@@ -381,12 +380,10 @@ static int siw_netdev_event(struct notifier_block *nb, unsigned long event,
381380

382381
switch (event) {
383382
case NETDEV_UP:
384-
sdev->state = IB_PORT_ACTIVE;
385383
siw_port_event(sdev, 1, IB_EVENT_PORT_ACTIVE);
386384
break;
387385

388386
case NETDEV_DOWN:
389-
sdev->state = IB_PORT_DOWN;
390387
siw_port_event(sdev, 1, IB_EVENT_PORT_ERR);
391388
break;
392389

@@ -407,12 +404,8 @@ static int siw_netdev_event(struct notifier_block *nb, unsigned long event,
407404
siw_port_event(sdev, 1, IB_EVENT_LID_CHANGE);
408405
break;
409406
/*
410-
* Todo: Below netdev events are currently not handled.
407+
* All other events are not handled
411408
*/
412-
case NETDEV_CHANGEMTU:
413-
case NETDEV_CHANGE:
414-
break;
415-
416409
default:
417410
break;
418411
}
@@ -442,12 +435,6 @@ static int siw_newlink(const char *basedev_name, struct net_device *netdev)
442435
sdev = siw_device_create(netdev);
443436
if (sdev) {
444437
dev_dbg(&netdev->dev, "siw: new device\n");
445-
446-
if (netif_running(netdev) && netif_carrier_ok(netdev))
447-
sdev->state = IB_PORT_ACTIVE;
448-
else
449-
sdev->state = IB_PORT_DOWN;
450-
451438
ib_mark_name_assigned_by_user(&sdev->base_dev);
452439
rv = siw_device_register(sdev, basedev_name);
453440
if (rv)

drivers/infiniband/sw/siw/siw_verbs.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,21 +171,29 @@ int siw_query_device(struct ib_device *base_dev, struct ib_device_attr *attr,
171171
int siw_query_port(struct ib_device *base_dev, u32 port,
172172
struct ib_port_attr *attr)
173173
{
174-
struct siw_device *sdev = to_siw_dev(base_dev);
174+
struct net_device *ndev;
175175
int rv;
176176

177177
memset(attr, 0, sizeof(*attr));
178178

179179
rv = ib_get_eth_speed(base_dev, port, &attr->active_speed,
180180
&attr->active_width);
181+
if (rv)
182+
return rv;
183+
184+
ndev = ib_device_get_netdev(base_dev, SIW_PORT);
185+
if (!ndev)
186+
return -ENODEV;
187+
181188
attr->gid_tbl_len = 1;
182189
attr->max_msg_sz = -1;
183-
attr->max_mtu = ib_mtu_int_to_enum(sdev->netdev->mtu);
184-
attr->active_mtu = ib_mtu_int_to_enum(sdev->netdev->mtu);
185-
attr->phys_state = sdev->state == IB_PORT_ACTIVE ?
190+
attr->max_mtu = ib_mtu_int_to_enum(ndev->max_mtu);
191+
attr->active_mtu = ib_mtu_int_to_enum(READ_ONCE(ndev->mtu));
192+
attr->phys_state = (netif_running(ndev) && netif_carrier_ok(ndev)) ?
186193
IB_PORT_PHYS_STATE_LINK_UP : IB_PORT_PHYS_STATE_DISABLED;
194+
attr->state = attr->phys_state == IB_PORT_PHYS_STATE_LINK_UP ?
195+
IB_PORT_ACTIVE : IB_PORT_DOWN;
187196
attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP;
188-
attr->state = sdev->state;
189197
/*
190198
* All zero
191199
*
@@ -199,6 +207,7 @@ int siw_query_port(struct ib_device *base_dev, u32 port,
199207
* attr->subnet_timeout = 0;
200208
* attr->init_type_repy = 0;
201209
*/
210+
dev_put(ndev);
202211
return rv;
203212
}
204213

@@ -505,21 +514,24 @@ int siw_query_qp(struct ib_qp *base_qp, struct ib_qp_attr *qp_attr,
505514
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
506515
{
507516
struct siw_qp *qp;
508-
struct siw_device *sdev;
517+
struct net_device *ndev;
509518

510-
if (base_qp && qp_attr && qp_init_attr) {
519+
if (base_qp && qp_attr && qp_init_attr)
511520
qp = to_siw_qp(base_qp);
512-
sdev = to_siw_dev(base_qp->device);
513-
} else {
521+
else
514522
return -EINVAL;
515-
}
523+
524+
ndev = ib_device_get_netdev(base_qp->device, SIW_PORT);
525+
if (!ndev)
526+
return -ENODEV;
527+
516528
qp_attr->qp_state = siw_qp_state_to_ib_qp_state[qp->attrs.state];
517529
qp_attr->cap.max_inline_data = SIW_MAX_INLINE;
518530
qp_attr->cap.max_send_wr = qp->attrs.sq_size;
519531
qp_attr->cap.max_send_sge = qp->attrs.sq_max_sges;
520532
qp_attr->cap.max_recv_wr = qp->attrs.rq_size;
521533
qp_attr->cap.max_recv_sge = qp->attrs.rq_max_sges;
522-
qp_attr->path_mtu = ib_mtu_int_to_enum(sdev->netdev->mtu);
534+
qp_attr->path_mtu = ib_mtu_int_to_enum(READ_ONCE(ndev->mtu));
523535
qp_attr->max_rd_atomic = qp->attrs.irq_size;
524536
qp_attr->max_dest_rd_atomic = qp->attrs.orq_size;
525537

@@ -534,6 +546,7 @@ int siw_query_qp(struct ib_qp *base_qp, struct ib_qp_attr *qp_attr,
534546

535547
qp_init_attr->cap = qp_attr->cap;
536548

549+
dev_put(ndev);
537550
return 0;
538551
}
539552

0 commit comments

Comments
 (0)