* [PATCH net 1/7] can: j1939: Fix UAF in j1939_sk_match_filter during setsockopt(SO_J1939_FILTER)
[not found] <20231005094639.387019-1-mkl@pengutronix.de>
@ 2023-10-05 9:46 ` Marc Kleine-Budde
2023-10-05 16:44 ` Jakub Kicinski
2023-10-05 9:46 ` [PATCH net 4/7] can: sja1000: Always restart the Tx queue after an overrun Marc Kleine-Budde
1 sibling, 1 reply; 4+ messages in thread
From: Marc Kleine-Budde @ 2023-10-05 9:46 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Oleksij Rempel, Sili Luo, stable,
Marc Kleine-Budde
From: Oleksij Rempel <o.rempel@pengutronix.de>
Lock jsk->sk to prevent UAF when setsockopt(..., SO_J1939_FILTER, ...)
modifies jsk->filters while receiving packets.
Following trace was seen on affected system:
==================================================================
BUG: KASAN: slab-use-after-free in j1939_sk_recv_match_one+0x1af/0x2d0 [can_j1939]
Read of size 4 at addr ffff888012144014 by task j1939/350
CPU: 0 PID: 350 Comm: j1939 Tainted: G W OE 6.5.0-rc5 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
print_report+0xd3/0x620
? kasan_complete_mode_report_info+0x7d/0x200
? j1939_sk_recv_match_one+0x1af/0x2d0 [can_j1939]
kasan_report+0xc2/0x100
? j1939_sk_recv_match_one+0x1af/0x2d0 [can_j1939]
__asan_load4+0x84/0xb0
j1939_sk_recv_match_one+0x1af/0x2d0 [can_j1939]
j1939_sk_recv+0x20b/0x320 [can_j1939]
? __kasan_check_write+0x18/0x20
? __pfx_j1939_sk_recv+0x10/0x10 [can_j1939]
? j1939_simple_recv+0x69/0x280 [can_j1939]
? j1939_ac_recv+0x5e/0x310 [can_j1939]
j1939_can_recv+0x43f/0x580 [can_j1939]
? __pfx_j1939_can_recv+0x10/0x10 [can_j1939]
? raw_rcv+0x42/0x3c0 [can_raw]
? __pfx_j1939_can_recv+0x10/0x10 [can_j1939]
can_rcv_filter+0x11f/0x350 [can]
can_receive+0x12f/0x190 [can]
? __pfx_can_rcv+0x10/0x10 [can]
can_rcv+0xdd/0x130 [can]
? __pfx_can_rcv+0x10/0x10 [can]
__netif_receive_skb_one_core+0x13d/0x150
? __pfx___netif_receive_skb_one_core+0x10/0x10
? __kasan_check_write+0x18/0x20
? _raw_spin_lock_irq+0x8c/0xe0
__netif_receive_skb+0x23/0xb0
process_backlog+0x107/0x260
__napi_poll+0x69/0x310
net_rx_action+0x2a1/0x580
? __pfx_net_rx_action+0x10/0x10
? __pfx__raw_spin_lock+0x10/0x10
? handle_irq_event+0x7d/0xa0
__do_softirq+0xf3/0x3f8
do_softirq+0x53/0x80
</IRQ>
<TASK>
__local_bh_enable_ip+0x6e/0x70
netif_rx+0x16b/0x180
can_send+0x32b/0x520 [can]
? __pfx_can_send+0x10/0x10 [can]
? __check_object_size+0x299/0x410
raw_sendmsg+0x572/0x6d0 [can_raw]
? __pfx_raw_sendmsg+0x10/0x10 [can_raw]
? apparmor_socket_sendmsg+0x2f/0x40
? __pfx_raw_sendmsg+0x10/0x10 [can_raw]
sock_sendmsg+0xef/0x100
sock_write_iter+0x162/0x220
? __pfx_sock_write_iter+0x10/0x10
? __rtnl_unlock+0x47/0x80
? security_file_permission+0x54/0x320
vfs_write+0x6ba/0x750
? __pfx_vfs_write+0x10/0x10
? __fget_light+0x1ca/0x1f0
? __rcu_read_unlock+0x5b/0x280
ksys_write+0x143/0x170
? __pfx_ksys_write+0x10/0x10
? __kasan_check_read+0x15/0x20
? fpregs_assert_state_consistent+0x62/0x70
__x64_sys_write+0x47/0x60
do_syscall_64+0x60/0x90
? do_syscall_64+0x6d/0x90
? irqentry_exit+0x3f/0x50
? exc_page_fault+0x79/0xf0
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Allocated by task 348:
kasan_save_stack+0x2a/0x50
kasan_set_track+0x29/0x40
kasan_save_alloc_info+0x1f/0x30
__kasan_kmalloc+0xb5/0xc0
__kmalloc_node_track_caller+0x67/0x160
j1939_sk_setsockopt+0x284/0x450 [can_j1939]
__sys_setsockopt+0x15c/0x2f0
__x64_sys_setsockopt+0x6b/0x80
do_syscall_64+0x60/0x90
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Freed by task 349:
kasan_save_stack+0x2a/0x50
kasan_set_track+0x29/0x40
kasan_save_free_info+0x2f/0x50
__kasan_slab_free+0x12e/0x1c0
__kmem_cache_free+0x1b9/0x380
kfree+0x7a/0x120
j1939_sk_setsockopt+0x3b2/0x450 [can_j1939]
__sys_setsockopt+0x15c/0x2f0
__x64_sys_setsockopt+0x6b/0x80
do_syscall_64+0x60/0x90
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Fixes: 9d71dd0c70099 ("can: add support of SAE J1939 protocol")
Reported-by: Sili Luo <rootlab@huawei.com>
Suggested-by: Sili Luo <rootlab@huawei.com>
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: stable@vger.kernel.org
Tested-by: Sili Luo <rootlab@huawei.com>
Link: https://lore.kernel.org/all/20230927161456.82772-1-o.rempel@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
net/can/j1939/socket.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
index b28c976f52a0..2ce24bf78c72 100644
--- a/net/can/j1939/socket.c
+++ b/net/can/j1939/socket.c
@@ -262,12 +262,17 @@ static bool j1939_sk_match_dst(struct j1939_sock *jsk,
static bool j1939_sk_match_filter(struct j1939_sock *jsk,
const struct j1939_sk_buff_cb *skcb)
{
- const struct j1939_filter *f = jsk->filters;
- int nfilter = jsk->nfilters;
+ const struct j1939_filter *f;
+ int nfilter;
+
+ lock_sock(&jsk->sk);
+
+ f = jsk->filters;
+ nfilter = jsk->nfilters;
if (!nfilter)
/* receive all when no filters are assigned */
- return true;
+ goto filter_match_found;
for (; nfilter; ++f, --nfilter) {
if ((skcb->addr.pgn & f->pgn_mask) != f->pgn)
@@ -276,9 +281,15 @@ static bool j1939_sk_match_filter(struct j1939_sock *jsk,
continue;
if ((skcb->addr.src_name & f->name_mask) != f->name)
continue;
- return true;
+ goto filter_match_found;
}
+
+ release_sock(&jsk->sk);
return false;
+
+filter_match_found:
+ release_sock(&jsk->sk);
+ return true;
}
static bool j1939_sk_recv_match_one(struct j1939_sock *jsk,
base-commit: d0f95894fda7d4f895b29c1097f92d7fee278cb2
--
2.40.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH net 4/7] can: sja1000: Always restart the Tx queue after an overrun
[not found] <20231005094639.387019-1-mkl@pengutronix.de>
2023-10-05 9:46 ` [PATCH net 1/7] can: j1939: Fix UAF in j1939_sk_match_filter during setsockopt(SO_J1939_FILTER) Marc Kleine-Budde
@ 2023-10-05 9:46 ` Marc Kleine-Budde
1 sibling, 0 replies; 4+ messages in thread
From: Marc Kleine-Budde @ 2023-10-05 9:46 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Miquel Raynal, stable,
Marc Kleine-Budde
From: Miquel Raynal <miquel.raynal@bootlin.com>
Upstream commit 717c6ec241b5 ("can: sja1000: Prevent overrun stalls with
a soft reset on Renesas SoCs") fixes an issue with Renesas own SJA1000
CAN controller reception: the Rx buffer is only 5 messages long, so when
the bus loaded (eg. a message every 50us), overrun may easily
happen. Upon an overrun situation, due to a possible internal crosstalk
situation, the controller enters a frozen state which only can be
unlocked with a soft reset (experimentally). The solution was to offload
a call to sja1000_start() in a threaded handler. This needs to happen in
process context as this operation requires to sleep. sja1000_start()
basically enters "reset mode", performs a proper software reset and
returns back into "normal mode".
Since this fix was introduced, we no longer observe any stalls in
reception. However it was sporadically observed that the transmit path
would now freeze. Further investigation blamed the fix mentioned above,
and especially the reset operation. Reproducing the reset in a loop
helped identifying what could possibly go wrong. The sja1000 is a single
Tx queue device, which leverages the netdev helpers to process one Tx
message at a time. The logic is: the queue is stopped, the message sent
to the transceiver, once properly transmitted the controller sets a
status bit which triggers an interrupt, in the interrupt handler the
transmission status is checked and the queue woken up. Unfortunately, if
an overrun happens, we might perform the soft reset precisely between
the transmission of the buffer to the transceiver and the advent of the
transmission status bit. We would then stop the transmission operation
without re-enabling the queue, leading to all further transmissions to
be ignored.
The reset interrupt can only happen while the device is "open", and
after a reset we anyway want to resume normal operations, no matter if a
packet to transmit got dropped in the process, so we shall wake up the
queue. Restarting the device and waking-up the queue is exactly what
sja1000_set_mode(CAN_MODE_START) does. In order to be consistent about
the queue state, we must acquire a lock both in the reset handler and in
the transmit path to ensure serialization of both operations. It turns
out, a lock is already held when entering the transmit path, so we can
just acquire/release it as well with the regular net helpers inside the
threaded interrupt handler and this way we should be safe. As the
reset handler might still be called after the transmission of a frame to
the transceiver but before it actually gets transmitted, we must ensure
we don't leak the skb, so we free it (the behavior is consistent, no
matter if there was an skb on the stack or not).
Fixes: 717c6ec241b5 ("can: sja1000: Prevent overrun stalls with a soft reset on Renesas SoCs")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/all/20231002160206.190953-1-miquel.raynal@bootlin.com
[mkl: fixed call to can_free_echo_skb()]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/sja1000/sja1000.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 0ada0e160e93..743c2eb62b87 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -392,7 +392,13 @@ static irqreturn_t sja1000_reset_interrupt(int irq, void *dev_id)
struct net_device *dev = (struct net_device *)dev_id;
netdev_dbg(dev, "performing a soft reset upon overrun\n");
- sja1000_start(dev);
+
+ netif_tx_lock(dev);
+
+ can_free_echo_skb(dev, 0, NULL);
+ sja1000_set_mode(dev, CAN_MODE_START);
+
+ netif_tx_unlock(dev);
return IRQ_HANDLED;
}
--
2.40.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH net 1/7] can: j1939: Fix UAF in j1939_sk_match_filter during setsockopt(SO_J1939_FILTER)
2023-10-05 9:46 ` [PATCH net 1/7] can: j1939: Fix UAF in j1939_sk_match_filter during setsockopt(SO_J1939_FILTER) Marc Kleine-Budde
@ 2023-10-05 16:44 ` Jakub Kicinski
2023-10-06 10:33 ` Oleksij Rempel
0 siblings, 1 reply; 4+ messages in thread
From: Jakub Kicinski @ 2023-10-05 16:44 UTC (permalink / raw)
To: Marc Kleine-Budde, Oleksij Rempel
Cc: netdev, davem, linux-can, kernel, Sili Luo, stable
On Thu, 5 Oct 2023 11:46:33 +0200 Marc Kleine-Budde wrote:
> Lock jsk->sk to prevent UAF when setsockopt(..., SO_J1939_FILTER, ...)
> modifies jsk->filters while receiving packets.
Doesn't it potentially introduce sleep in atomic?
j1939_sk_recv_match()
spin_lock_bh(&priv->j1939_socks_lock);
j1939_sk_recv_match_one()
j1939_sk_match_filter()
lock_sock()
sleep
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net 1/7] can: j1939: Fix UAF in j1939_sk_match_filter during setsockopt(SO_J1939_FILTER)
2023-10-05 16:44 ` Jakub Kicinski
@ 2023-10-06 10:33 ` Oleksij Rempel
0 siblings, 0 replies; 4+ messages in thread
From: Oleksij Rempel @ 2023-10-06 10:33 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Marc Kleine-Budde, netdev, stable, linux-can, kernel, Sili Luo,
davem
Hi Jakub,
On Thu, Oct 05, 2023 at 09:44:21AM -0700, Jakub Kicinski wrote:
> On Thu, 5 Oct 2023 11:46:33 +0200 Marc Kleine-Budde wrote:
> > Lock jsk->sk to prevent UAF when setsockopt(..., SO_J1939_FILTER, ...)
> > modifies jsk->filters while receiving packets.
>
> Doesn't it potentially introduce sleep in atomic?
>
> j1939_sk_recv_match()
> spin_lock_bh(&priv->j1939_socks_lock);
> j1939_sk_recv_match_one()
> j1939_sk_match_filter()
> lock_sock()
> sleep
Good point! Thank you for the review.
@Sili Luo, can you please take a look at this?
Regards,
Oleksij
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-10-06 10:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20231005094639.387019-1-mkl@pengutronix.de>
2023-10-05 9:46 ` [PATCH net 1/7] can: j1939: Fix UAF in j1939_sk_match_filter during setsockopt(SO_J1939_FILTER) Marc Kleine-Budde
2023-10-05 16:44 ` Jakub Kicinski
2023-10-06 10:33 ` Oleksij Rempel
2023-10-05 9:46 ` [PATCH net 4/7] can: sja1000: Always restart the Tx queue after an overrun Marc Kleine-Budde
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox