diff --git a/net/can/isotp.c b/net/can/isotp.c index c48b4a818297e2a1348a2b64016d0f4ff613e683..112c4ec3011c5e36cfafb2b86306ab466fabc799 100644 --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -1266,7 +1266,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l struct isotp_sock *so = isotp_sk(sk); struct net *net = sock_net(sk); int ifindex; - struct net_device *dev; + struct net_device *dev = NULL; canid_t tx_id = addr->can_addr.tp.tx_id; canid_t rx_id = addr->can_addr.tp.rx_id; int err = 0; @@ -1322,12 +1322,10 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l goto out; } if (dev->type != ARPHRD_CAN) { - dev_put(dev); err = -ENODEV; goto out; } if (READ_ONCE(dev->mtu) < so->ll.mtu) { - dev_put(dev); err = -EINVAL; goto out; } @@ -1336,26 +1334,33 @@ static int isotp_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int l ifindex = dev->ifindex; - if (isotp_register_rxid(so)) - can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id), - isotp_rcv, sk, "isotp", sk); + if (isotp_register_rxid(so)) { + err = can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id), + isotp_rcv, sk, "isotp", sk); + if (err) + goto out; + } /* no consecutive frame echo skb in flight */ so->cfecho = 0; /* register for echo skb's */ - can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id), - isotp_rcv_echo, sk, "isotpe", sk); - - dev_put(dev); - - /* switch to new settings */ - so->ifindex = ifindex; - so->rxid = rx_id; - so->txid = tx_id; - so->bound = 1; + err = can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id), + isotp_rcv_echo, sk, "isotpe", sk); + if (err) { + if (isotp_register_rxid(so)) + can_rx_unregister(net, dev, rx_id, SINGLE_MASK(rx_id), + isotp_rcv, sk); + } else { + /* switch to new settings */ + so->ifindex = ifindex; + so->rxid = rx_id; + so->txid = tx_id; + so->bound = 1; + } out: + dev_put(dev); release_sock(sk); if (notify_enetdown) {