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

can: xilinx_can: xcan_write_frame(): fix use-after-free of transmitted SKB

can_put_echo_skb() takes ownership of the SKB and it may be freed
during or after the call.

However, xilinx_can xcan_write_frame() keeps using SKB after the call.

Fix that by only calling can_put_echo_skb() after the code is done
touching the SKB.

The tx_lock is held for the entire xcan_write_frame() execution and
also on the can_get_echo_skb() side so the order of operations does not
matter.

An earlier fix commit 3d3c817c3a40 ("can: xilinx_can: Fix usage of skb
memory") did not move the can_put_echo_skb() call far enough.

Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
Fixes: 1598efe57b3e ("can: xilinx_can: refactor code in preparation for CAN FD support")
Link: https://patch.msgid.link/20250822095002.168389-1-anssi.hannula@bitwise.fi
[mkl: add "commit" in front of sha1 in patch description]
[mkl: fix indention]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Anssi Hannula and committed by
Marc Kleine-Budde
ef79f00b 06e02da2

+8 -8
+8 -8
drivers/net/can/xilinx_can.c
··· 690 690 dlc |= XCAN_DLCR_EDL_MASK; 691 691 } 692 692 693 - if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) && 694 - (priv->devtype.flags & XCAN_FLAG_TXFEMP)) 695 - can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0); 696 - else 697 - can_put_echo_skb(skb, ndev, 0, 0); 698 - 699 - priv->tx_head++; 700 - 701 693 priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id); 702 694 /* If the CAN frame is RTR frame this write triggers transmission 703 695 * (not on CAN FD) ··· 722 730 data[1]); 723 731 } 724 732 } 733 + 734 + if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) && 735 + (priv->devtype.flags & XCAN_FLAG_TXFEMP)) 736 + can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0); 737 + else 738 + can_put_echo_skb(skb, ndev, 0, 0); 739 + 740 + priv->tx_head++; 725 741 } 726 742 727 743 /**