mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
can: bcm: add missing rcu list annotations and operations
commit7b2c3eabc4upstream. sashiko-bot remarked the missing use of list_add_rcu() in bcm_[rx|tx]_setup() to have a proper initialized bcm_op structure when bcm_proc_show() traverses the bcm_op's under rcu_read_lock(). To cover all initial settings of the bcm_op's the list_add_rcu() calls are moved to the end of the setup code. While at it, also fix the mirroring removal side: bcm_release() called bcm_remove_op() - which frees the op via call_rcu() - on ops that were still linked in bo->tx_ops/bo->rx_ops, without list_del_rcu() first. Unlink each op with list_del_rcu() before handing it to bcm_remove_op(), matching the existing pattern in bcm_delete_tx_op()/bcm_delete_rx_op(). Reported-by: sashiko-reviews@lists.linux.dev Closes: https://lore.kernel.org/linux-can/20260610094654.A1FFE1F00893@smtp.kernel.org/ Fixes:dac5e62491("can: bcm: add missing rcu read protection for procfs content") Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Link: https://patch.msgid.link/20260714-bcm_fixes-v15-5-562f7e3e42da@hartkopp.net Cc: stable@kernel.org Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
0f6f9f9529
commit
f53bdab85e
+16
-9
@@ -248,7 +248,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
|
||||
(reduction == 100) ? "near " : "", reduction);
|
||||
}
|
||||
|
||||
list_for_each_entry(op, &bo->tx_ops, list) {
|
||||
list_for_each_entry_rcu(op, &bo->tx_ops, list) {
|
||||
|
||||
seq_printf(m, "tx_op: %03X %s ", op->can_id,
|
||||
bcm_proc_getifname(net, ifname, op->ifindex));
|
||||
@@ -903,6 +903,7 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
|
||||
struct bcm_sock *bo = bcm_sk(sk);
|
||||
struct bcm_op *op;
|
||||
struct canfd_frame *cf;
|
||||
bool add_op_to_list = false;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
@@ -1045,8 +1046,7 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
|
||||
hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
|
||||
/* add this bcm_op to the list of the tx_ops */
|
||||
list_add(&op->list, &bo->tx_ops);
|
||||
add_op_to_list = true;
|
||||
|
||||
} /* if ((op = bcm_find_op(&bo->tx_ops, msg_head->can_id, ifindex))) */
|
||||
|
||||
@@ -1068,6 +1068,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
|
||||
op->flags |= TX_ANNOUNCE;
|
||||
}
|
||||
|
||||
/* add this bcm_op to the list of the tx_ops? */
|
||||
if (add_op_to_list)
|
||||
list_add_rcu(&op->list, &bo->tx_ops);
|
||||
|
||||
if (op->flags & TX_ANNOUNCE)
|
||||
bcm_can_tx(op);
|
||||
|
||||
@@ -1211,9 +1215,6 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
op->thrtimer.function = bcm_rx_thr_handler;
|
||||
|
||||
/* add this bcm_op to the list of the rx_ops */
|
||||
list_add(&op->list, &bo->rx_ops);
|
||||
|
||||
/* call can_rx_register() */
|
||||
do_rx_register = 1;
|
||||
|
||||
@@ -1292,10 +1293,12 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
|
||||
bcm_rx_handler, op, "bcm", sk);
|
||||
if (err) {
|
||||
/* this bcm rx op is broken -> remove it */
|
||||
list_del_rcu(&op->list);
|
||||
bcm_remove_op(op);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* add this bcm_op to the list of the rx_ops */
|
||||
list_add_rcu(&op->list, &bo->rx_ops);
|
||||
}
|
||||
|
||||
return msg_head->nframes * op->cfsiz + MHSIZ;
|
||||
@@ -1625,8 +1628,10 @@ static int bcm_release(struct socket *sock)
|
||||
remove_proc_entry(bo->procname, net->can.bcmproc_dir);
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
list_for_each_entry_safe(op, next, &bo->tx_ops, list)
|
||||
list_for_each_entry_safe(op, next, &bo->tx_ops, list) {
|
||||
list_del_rcu(&op->list);
|
||||
bcm_remove_op(op);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
|
||||
/*
|
||||
@@ -1657,8 +1662,10 @@ static int bcm_release(struct socket *sock)
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
list_for_each_entry_safe(op, next, &bo->rx_ops, list)
|
||||
list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
|
||||
list_del_rcu(&op->list);
|
||||
bcm_remove_op(op);
|
||||
}
|
||||
|
||||
/* remove device reference */
|
||||
if (bo->bound) {
|
||||
|
||||
Reference in New Issue
Block a user