Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'linux-can-fixes-for-7.0-20260323' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2026-03-23

this is a pull request of 5 patches for net/main.

The first patch is by me and adds missing error handling to the CAN
netlink device configuration code.

Wenyuan Li contributes a patch for the mcp251x drier to add missing
error handling for power enabling in th open and resume functions.

Oliver Hartkopp's patch adds missing atomic access in hot path for the
CAN procfs statistics.

A series by Ali Norouzi and Oliver Hartkopp fix a can-Out-of-Bounds
Heap R/W in the can-gw protocol and a UAF in the CAN isotp protocol.

linux-can-fixes-for-7.0-20260323

* tag 'linux-can-fixes-for-7.0-20260323' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
can: isotp: fix tx.buf use-after-free in isotp_sendmsg()
can: gw: fix OOB heap access in cgw_csum_crc8_rel()
can: statistics: add missing atomic access in hot path
can: mcp251x: add error handling for power enable in open and resume
can: netlink: can_changelink(): add missing error handling to call can_ctrlmode_changelink()
====================

Link: https://patch.msgid.link/20260323103224.218099-1-mkl@pengutronix.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+53 -19
+3 -1
drivers/net/can/dev/netlink.c
··· 601 601 /* We need synchronization with dev->stop() */ 602 602 ASSERT_RTNL(); 603 603 604 - can_ctrlmode_changelink(dev, data, extack); 604 + err = can_ctrlmode_changelink(dev, data, extack); 605 + if (err) 606 + return err; 605 607 606 608 if (data[IFLA_CAN_BITTIMING]) { 607 609 struct can_bittiming bt;
+24 -5
drivers/net/can/spi/mcp251x.c
··· 1225 1225 } 1226 1226 1227 1227 mutex_lock(&priv->mcp_lock); 1228 - mcp251x_power_enable(priv->transceiver, 1); 1228 + ret = mcp251x_power_enable(priv->transceiver, 1); 1229 + if (ret) { 1230 + dev_err(&spi->dev, "failed to enable transceiver power: %pe\n", ERR_PTR(ret)); 1231 + goto out_close_candev; 1232 + } 1229 1233 1230 1234 priv->force_quit = 0; 1231 1235 priv->tx_skb = NULL; ··· 1276 1272 mcp251x_hw_sleep(spi); 1277 1273 out_close: 1278 1274 mcp251x_power_enable(priv->transceiver, 0); 1275 + out_close_candev: 1279 1276 close_candev(net); 1280 1277 mutex_unlock(&priv->mcp_lock); 1281 1278 if (release_irq) ··· 1521 1516 { 1522 1517 struct spi_device *spi = to_spi_device(dev); 1523 1518 struct mcp251x_priv *priv = spi_get_drvdata(spi); 1519 + int ret = 0; 1524 1520 1525 - if (priv->after_suspend & AFTER_SUSPEND_POWER) 1526 - mcp251x_power_enable(priv->power, 1); 1527 - if (priv->after_suspend & AFTER_SUSPEND_UP) 1528 - mcp251x_power_enable(priv->transceiver, 1); 1521 + if (priv->after_suspend & AFTER_SUSPEND_POWER) { 1522 + ret = mcp251x_power_enable(priv->power, 1); 1523 + if (ret) { 1524 + dev_err(dev, "failed to restore power: %pe\n", ERR_PTR(ret)); 1525 + return ret; 1526 + } 1527 + } 1528 + 1529 + if (priv->after_suspend & AFTER_SUSPEND_UP) { 1530 + ret = mcp251x_power_enable(priv->transceiver, 1); 1531 + if (ret) { 1532 + dev_err(dev, "failed to restore transceiver power: %pe\n", ERR_PTR(ret)); 1533 + if (priv->after_suspend & AFTER_SUSPEND_POWER) 1534 + mcp251x_power_enable(priv->power, 0); 1535 + return ret; 1536 + } 1537 + } 1529 1538 1530 1539 if (priv->after_suspend & (AFTER_SUSPEND_POWER | AFTER_SUSPEND_UP)) 1531 1540 queue_work(priv->wq, &priv->restart_work);
+2 -2
net/can/af_can.c
··· 469 469 470 470 rcv->can_id = can_id; 471 471 rcv->mask = mask; 472 - rcv->matches = 0; 472 + atomic_long_set(&rcv->matches, 0); 473 473 rcv->func = func; 474 474 rcv->data = data; 475 475 rcv->ident = ident; ··· 573 573 static inline void deliver(struct sk_buff *skb, struct receiver *rcv) 574 574 { 575 575 rcv->func(skb, rcv->data); 576 - rcv->matches++; 576 + atomic_long_inc(&rcv->matches); 577 577 } 578 578 579 579 static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb)
+1 -1
net/can/af_can.h
··· 52 52 struct hlist_node list; 53 53 canid_t can_id; 54 54 canid_t mask; 55 - unsigned long matches; 55 + atomic_long_t matches; 56 56 void (*func)(struct sk_buff *skb, void *data); 57 57 void *data; 58 58 char *ident;
+3 -3
net/can/gw.c
··· 375 375 return; 376 376 377 377 if (from <= to) { 378 - for (i = crc8->from_idx; i <= crc8->to_idx; i++) 378 + for (i = from; i <= to; i++) 379 379 crc = crc8->crctab[crc ^ cf->data[i]]; 380 380 } else { 381 - for (i = crc8->from_idx; i >= crc8->to_idx; i--) 381 + for (i = from; i >= to; i--) 382 382 crc = crc8->crctab[crc ^ cf->data[i]]; 383 383 } 384 384 ··· 397 397 break; 398 398 } 399 399 400 - cf->data[crc8->result_idx] = crc ^ crc8->final_xor_val; 400 + cf->data[res] = crc ^ crc8->final_xor_val; 401 401 } 402 402 403 403 static void cgw_csum_crc8_pos(struct canfd_frame *cf,
+18 -6
net/can/isotp.c
··· 1248 1248 so->ifindex = 0; 1249 1249 so->bound = 0; 1250 1250 1251 - if (so->rx.buf != so->rx.sbuf) 1252 - kfree(so->rx.buf); 1253 - 1254 - if (so->tx.buf != so->tx.sbuf) 1255 - kfree(so->tx.buf); 1256 - 1257 1251 sock_orphan(sk); 1258 1252 sock->sk = NULL; 1259 1253 ··· 1616 1622 return NOTIFY_DONE; 1617 1623 } 1618 1624 1625 + static void isotp_sock_destruct(struct sock *sk) 1626 + { 1627 + struct isotp_sock *so = isotp_sk(sk); 1628 + 1629 + /* do the standard CAN sock destruct work */ 1630 + can_sock_destruct(sk); 1631 + 1632 + /* free potential extended PDU buffers */ 1633 + if (so->rx.buf != so->rx.sbuf) 1634 + kfree(so->rx.buf); 1635 + 1636 + if (so->tx.buf != so->tx.sbuf) 1637 + kfree(so->tx.buf); 1638 + } 1639 + 1619 1640 static int isotp_init(struct sock *sk) 1620 1641 { 1621 1642 struct isotp_sock *so = isotp_sk(sk); ··· 1674 1665 spin_lock(&isotp_notifier_lock); 1675 1666 list_add_tail(&so->notifier, &isotp_notifier_list); 1676 1667 spin_unlock(&isotp_notifier_lock); 1668 + 1669 + /* re-assign default can_sock_destruct() reference */ 1670 + sk->sk_destruct = isotp_sock_destruct; 1677 1671 1678 1672 return 0; 1679 1673 }
+2 -1
net/can/proc.c
··· 196 196 " %-5s %03x %08x %pK %pK %8ld %s\n"; 197 197 198 198 seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, 199 - r->func, r->data, r->matches, r->ident); 199 + r->func, r->data, atomic_long_read(&r->matches), 200 + r->ident); 200 201 } 201 202 } 202 203