Skip to content

Commit d9c2a50

Browse files
author
Paolo Abeni
committed
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/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents eb8c426 + cce598f commit d9c2a50

7 files changed

Lines changed: 53 additions & 19 deletions

File tree

drivers/net/can/dev/netlink.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,9 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
601601
/* We need synchronization with dev->stop() */
602602
ASSERT_RTNL();
603603

604-
can_ctrlmode_changelink(dev, data, extack);
604+
err = can_ctrlmode_changelink(dev, data, extack);
605+
if (err)
606+
return err;
605607

606608
if (data[IFLA_CAN_BITTIMING]) {
607609
struct can_bittiming bt;

drivers/net/can/spi/mcp251x.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,11 @@ static int mcp251x_open(struct net_device *net)
12251225
}
12261226

12271227
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+
}
12291233

12301234
priv->force_quit = 0;
12311235
priv->tx_skb = NULL;
@@ -1272,6 +1276,7 @@ static int mcp251x_open(struct net_device *net)
12721276
mcp251x_hw_sleep(spi);
12731277
out_close:
12741278
mcp251x_power_enable(priv->transceiver, 0);
1279+
out_close_candev:
12751280
close_candev(net);
12761281
mutex_unlock(&priv->mcp_lock);
12771282
if (release_irq)
@@ -1516,11 +1521,25 @@ static int __maybe_unused mcp251x_can_resume(struct device *dev)
15161521
{
15171522
struct spi_device *spi = to_spi_device(dev);
15181523
struct mcp251x_priv *priv = spi_get_drvdata(spi);
1524+
int ret = 0;
15191525

1520-
if (priv->after_suspend & AFTER_SUSPEND_POWER)
1521-
mcp251x_power_enable(priv->power, 1);
1522-
if (priv->after_suspend & AFTER_SUSPEND_UP)
1523-
mcp251x_power_enable(priv->transceiver, 1);
1526+
if (priv->after_suspend & AFTER_SUSPEND_POWER) {
1527+
ret = mcp251x_power_enable(priv->power, 1);
1528+
if (ret) {
1529+
dev_err(dev, "failed to restore power: %pe\n", ERR_PTR(ret));
1530+
return ret;
1531+
}
1532+
}
1533+
1534+
if (priv->after_suspend & AFTER_SUSPEND_UP) {
1535+
ret = mcp251x_power_enable(priv->transceiver, 1);
1536+
if (ret) {
1537+
dev_err(dev, "failed to restore transceiver power: %pe\n", ERR_PTR(ret));
1538+
if (priv->after_suspend & AFTER_SUSPEND_POWER)
1539+
mcp251x_power_enable(priv->power, 0);
1540+
return ret;
1541+
}
1542+
}
15241543

15251544
if (priv->after_suspend & (AFTER_SUSPEND_POWER | AFTER_SUSPEND_UP))
15261545
queue_work(priv->wq, &priv->restart_work);

net/can/af_can.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
469469

470470
rcv->can_id = can_id;
471471
rcv->mask = mask;
472-
rcv->matches = 0;
472+
atomic_long_set(&rcv->matches, 0);
473473
rcv->func = func;
474474
rcv->data = data;
475475
rcv->ident = ident;
@@ -573,7 +573,7 @@ EXPORT_SYMBOL(can_rx_unregister);
573573
static inline void deliver(struct sk_buff *skb, struct receiver *rcv)
574574
{
575575
rcv->func(skb, rcv->data);
576-
rcv->matches++;
576+
atomic_long_inc(&rcv->matches);
577577
}
578578

579579
static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb)

net/can/af_can.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct receiver {
5252
struct hlist_node list;
5353
canid_t can_id;
5454
canid_t mask;
55-
unsigned long matches;
55+
atomic_long_t matches;
5656
void (*func)(struct sk_buff *skb, void *data);
5757
void *data;
5858
char *ident;

net/can/gw.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,10 @@ static void cgw_csum_crc8_rel(struct canfd_frame *cf,
375375
return;
376376

377377
if (from <= to) {
378-
for (i = crc8->from_idx; i <= crc8->to_idx; i++)
378+
for (i = from; i <= to; i++)
379379
crc = crc8->crctab[crc ^ cf->data[i]];
380380
} else {
381-
for (i = crc8->from_idx; i >= crc8->to_idx; i--)
381+
for (i = from; i >= to; i--)
382382
crc = crc8->crctab[crc ^ cf->data[i]];
383383
}
384384

@@ -397,7 +397,7 @@ static void cgw_csum_crc8_rel(struct canfd_frame *cf,
397397
break;
398398
}
399399

400-
cf->data[crc8->result_idx] = crc ^ crc8->final_xor_val;
400+
cf->data[res] = crc ^ crc8->final_xor_val;
401401
}
402402

403403
static void cgw_csum_crc8_pos(struct canfd_frame *cf,

net/can/isotp.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,12 +1248,6 @@ static int isotp_release(struct socket *sock)
12481248
so->ifindex = 0;
12491249
so->bound = 0;
12501250

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-
12571251
sock_orphan(sk);
12581252
sock->sk = NULL;
12591253

@@ -1622,6 +1616,21 @@ static int isotp_notifier(struct notifier_block *nb, unsigned long msg,
16221616
return NOTIFY_DONE;
16231617
}
16241618

1619+
static void isotp_sock_destruct(struct sock *sk)
1620+
{
1621+
struct isotp_sock *so = isotp_sk(sk);
1622+
1623+
/* do the standard CAN sock destruct work */
1624+
can_sock_destruct(sk);
1625+
1626+
/* free potential extended PDU buffers */
1627+
if (so->rx.buf != so->rx.sbuf)
1628+
kfree(so->rx.buf);
1629+
1630+
if (so->tx.buf != so->tx.sbuf)
1631+
kfree(so->tx.buf);
1632+
}
1633+
16251634
static int isotp_init(struct sock *sk)
16261635
{
16271636
struct isotp_sock *so = isotp_sk(sk);
@@ -1666,6 +1675,9 @@ static int isotp_init(struct sock *sk)
16661675
list_add_tail(&so->notifier, &isotp_notifier_list);
16671676
spin_unlock(&isotp_notifier_lock);
16681677

1678+
/* re-assign default can_sock_destruct() reference */
1679+
sk->sk_destruct = isotp_sock_destruct;
1680+
16691681
return 0;
16701682
}
16711683

net/can/proc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
196196
" %-5s %03x %08x %pK %pK %8ld %s\n";
197197

198198
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);
200201
}
201202
}
202203

0 commit comments

Comments
 (0)