Skip to content

Commit 7b2c3ea

Browse files
hartkoppmarckleinebudde
authored andcommitted
can: bcm: add missing rcu list annotations and operations
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: dac5e62 ("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>
1 parent e6c24ba commit 7b2c3ea

1 file changed

Lines changed: 16 additions & 9 deletions

File tree

net/can/bcm.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
265265
(reduction == 100) ? "near " : "", reduction);
266266
}
267267

268-
list_for_each_entry(op, &bo->tx_ops, list) {
268+
list_for_each_entry_rcu(op, &bo->tx_ops, list) {
269269

270270
seq_printf(m, "tx_op: %03X %s ", op->can_id,
271271
bcm_proc_getifname(net, ifname, op->ifindex));
@@ -1017,6 +1017,7 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
10171017
struct bcm_sock *bo = bcm_sk(sk);
10181018
struct bcm_op *op;
10191019
struct canfd_frame *cf;
1020+
bool add_op_to_list = false;
10201021
unsigned int i;
10211022
int err;
10221023

@@ -1158,8 +1159,7 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
11581159
hrtimer_setup(&op->thrtimer, hrtimer_dummy_timeout, CLOCK_MONOTONIC,
11591160
HRTIMER_MODE_REL_SOFT);
11601161

1161-
/* add this bcm_op to the list of the tx_ops */
1162-
list_add(&op->list, &bo->tx_ops);
1162+
add_op_to_list = true;
11631163

11641164
} /* if ((op = bcm_find_op(&bo->tx_ops, msg_head->can_id, ifindex))) */
11651165

@@ -1181,6 +1181,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
11811181
op->flags |= TX_ANNOUNCE;
11821182
}
11831183

1184+
/* add this bcm_op to the list of the tx_ops? */
1185+
if (add_op_to_list)
1186+
list_add_rcu(&op->list, &bo->tx_ops);
1187+
11841188
if (op->flags & TX_ANNOUNCE)
11851189
bcm_can_tx(op, NULL);
11861190

@@ -1373,9 +1377,6 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
13731377
hrtimer_setup(&op->thrtimer, bcm_rx_thr_handler, CLOCK_MONOTONIC,
13741378
HRTIMER_MODE_REL_SOFT);
13751379

1376-
/* add this bcm_op to the list of the rx_ops */
1377-
list_add(&op->list, &bo->rx_ops);
1378-
13791380
/* call can_rx_register() */
13801381
do_rx_register = 1;
13811382

@@ -1449,10 +1450,12 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
14491450
bcm_rx_handler, op, "bcm", sk);
14501451
if (err) {
14511452
/* this bcm rx op is broken -> remove it */
1452-
list_del_rcu(&op->list);
14531453
bcm_remove_op(op);
14541454
return err;
14551455
}
1456+
1457+
/* add this bcm_op to the list of the rx_ops */
1458+
list_add_rcu(&op->list, &bo->rx_ops);
14561459
}
14571460

14581461
return msg_head->nframes * op->cfsiz + MHSIZ;
@@ -1786,8 +1789,10 @@ static int bcm_release(struct socket *sock)
17861789
remove_proc_entry(bo->procname, net->can.bcmproc_dir);
17871790
#endif /* CONFIG_PROC_FS */
17881791

1789-
list_for_each_entry_safe(op, next, &bo->tx_ops, list)
1792+
list_for_each_entry_safe(op, next, &bo->tx_ops, list) {
1793+
list_del_rcu(&op->list);
17901794
bcm_remove_op(op);
1795+
}
17911796

17921797
list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
17931798
/*
@@ -1818,8 +1823,10 @@ static int bcm_release(struct socket *sock)
18181823

18191824
synchronize_rcu();
18201825

1821-
list_for_each_entry_safe(op, next, &bo->rx_ops, list)
1826+
list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
1827+
list_del_rcu(&op->list);
18221828
bcm_remove_op(op);
1829+
}
18231830

18241831
/* remove device reference */
18251832
if (bo->bound) {

0 commit comments

Comments
 (0)