linux-can-fixes-for-5.13-20210619
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAmDOZ38THG1rbEBwZW5n dXRyb25peC5kZQAKCRCpyVqK+u3vqf9CCACcVoZsa+47buGmvQmRpyhbA+/a3LFF h5kBpts+igtZ2HnB5ODSu+SeqphYtE+eJeLLxbaw8riig0Vz+ogNJUMoalodYIwx B1jUTKYHg6wxDq6cAqZrG2KpOdIucXEFcugccPF0tjRthet0vZyWxbx66XWzFrp8 +UGK5H/diGihaRqguJwN3P9Mw3SYw4VWo2J2iYQ8WkGT1sy1UO4XuO9U6KqNBHmA 3a48VrgtwC4yZI7+Ar36SNMnL9P3qArE6UlqtpYDudmqpSCX08A4itM5rJ4UGSKk PwetFCvjhjsxFs081ILaBe2Ktu3fl3i+FsZF/hwv99p45l4OCaYBEwfw =xYM1 -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-5.13-20210619' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== pull-request: can 2021-06-19 this is a pull request of 5 patches for net/master. The first patch is by Thadeu Lima de Souza Cascardo and fixes a potential use-after-free in the CAN broadcast manager socket, by delaying the release of struct bcm_op after synchronize_rcu(). Oliver Hartkopp's patch fixes a similar potential user-after-free in the CAN gateway socket by synchronizing RCU operations before removing gw job entry. Another patch by Oliver Hartkopp fixes a potential use-after-free in the ISOTP socket by omitting unintended hrtimer restarts on socket release. Oleksij Rempel's patch for the j1939 socket fixes a potential use-after-free by setting the SOCK_RCU_FREE flag on the socket. The last patch is by Pavel Skripkin and fixes a use-after-free in the ems_usb CAN driver. All patches are intended for stable and have stable@v.k.o on Cc. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
d52f9b22d5
|
@ -1053,7 +1053,6 @@ static void ems_usb_disconnect(struct usb_interface *intf)
|
|||
|
||||
if (dev) {
|
||||
unregister_netdev(dev->netdev);
|
||||
free_candev(dev->netdev);
|
||||
|
||||
unlink_all_urbs(dev);
|
||||
|
||||
|
@ -1061,6 +1060,8 @@ static void ems_usb_disconnect(struct usb_interface *intf)
|
|||
|
||||
kfree(dev->intr_in_buffer);
|
||||
kfree(dev->tx_msg_buffer);
|
||||
|
||||
free_candev(dev->netdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -785,6 +785,7 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
|
|||
bcm_rx_handler, op);
|
||||
|
||||
list_del(&op->list);
|
||||
synchronize_rcu();
|
||||
bcm_remove_op(op);
|
||||
return 1; /* done */
|
||||
}
|
||||
|
@ -1533,9 +1534,13 @@ static int bcm_release(struct socket *sock)
|
|||
REGMASK(op->can_id),
|
||||
bcm_rx_handler, op);
|
||||
|
||||
bcm_remove_op(op);
|
||||
}
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
list_for_each_entry_safe(op, next, &bo->rx_ops, list)
|
||||
bcm_remove_op(op);
|
||||
|
||||
#if IS_ENABLED(CONFIG_PROC_FS)
|
||||
/* remove procfs entry */
|
||||
if (net->can.bcmproc_dir && bo->bcm_proc_read)
|
||||
|
|
|
@ -596,6 +596,7 @@ static int cgw_notifier(struct notifier_block *nb,
|
|||
if (gwj->src.dev == dev || gwj->dst.dev == dev) {
|
||||
hlist_del(&gwj->list);
|
||||
cgw_unregister_filter(net, gwj);
|
||||
synchronize_rcu();
|
||||
kmem_cache_free(cgw_cache, gwj);
|
||||
}
|
||||
}
|
||||
|
@ -1154,6 +1155,7 @@ static void cgw_remove_all_jobs(struct net *net)
|
|||
hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) {
|
||||
hlist_del(&gwj->list);
|
||||
cgw_unregister_filter(net, gwj);
|
||||
synchronize_rcu();
|
||||
kmem_cache_free(cgw_cache, gwj);
|
||||
}
|
||||
}
|
||||
|
@ -1222,6 +1224,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
|
||||
hlist_del(&gwj->list);
|
||||
cgw_unregister_filter(net, gwj);
|
||||
synchronize_rcu();
|
||||
kmem_cache_free(cgw_cache, gwj);
|
||||
err = 0;
|
||||
break;
|
||||
|
|
|
@ -1028,9 +1028,6 @@ static int isotp_release(struct socket *sock)
|
|||
|
||||
lock_sock(sk);
|
||||
|
||||
hrtimer_cancel(&so->txtimer);
|
||||
hrtimer_cancel(&so->rxtimer);
|
||||
|
||||
/* remove current filters & unregister */
|
||||
if (so->bound && (!(so->opt.flags & CAN_ISOTP_SF_BROADCAST))) {
|
||||
if (so->ifindex) {
|
||||
|
@ -1042,10 +1039,14 @@ static int isotp_release(struct socket *sock)
|
|||
SINGLE_MASK(so->rxid),
|
||||
isotp_rcv, sk);
|
||||
dev_put(dev);
|
||||
synchronize_rcu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hrtimer_cancel(&so->txtimer);
|
||||
hrtimer_cancel(&so->rxtimer);
|
||||
|
||||
so->ifindex = 0;
|
||||
so->bound = 0;
|
||||
|
||||
|
|
|
@ -193,6 +193,10 @@ static void j1939_can_rx_unregister(struct j1939_priv *priv)
|
|||
can_rx_unregister(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
|
||||
j1939_can_recv, priv);
|
||||
|
||||
/* The last reference of priv is dropped by the RCU deferred
|
||||
* j1939_sk_sock_destruct() of the last socket, so we can
|
||||
* safely drop this reference here.
|
||||
*/
|
||||
j1939_priv_put(priv);
|
||||
}
|
||||
|
||||
|
|
|
@ -398,6 +398,9 @@ static int j1939_sk_init(struct sock *sk)
|
|||
atomic_set(&jsk->skb_pending, 0);
|
||||
spin_lock_init(&jsk->sk_session_queue_lock);
|
||||
INIT_LIST_HEAD(&jsk->sk_session_queue);
|
||||
|
||||
/* j1939_sk_sock_destruct() depends on SOCK_RCU_FREE flag */
|
||||
sock_set_flag(sk, SOCK_RCU_FREE);
|
||||
sk->sk_destruct = j1939_sk_sock_destruct;
|
||||
sk->sk_protocol = CAN_J1939;
|
||||
|
||||
|
|
Loading…
Reference in New Issue