[PATCH net 2/2] can: j1939: validate the DPO packet number
From: Xue Boyang
Date: Thu Sep 17 2026 - 22:58:15 EST
j1939_xtp_rx_dpo_one() copies the 18-bit packet number of the ETP.CM_DPO
command into session->pkt.dpo without any sanity check. The value is
later used as a byte offset (pkt.dpo * 7) by
j1939_session_skb_get_by_offset(), both for TP.DT placement (combined
with dat[0] - 1) and for the final message distribution in
j1939_session_completed().
A DPO pointing past the end of the transfer has no valid meaning:
every legal window rebase satisfies pkt.dpo <= pkt.total. Reject
out-of-range values and abort the session with J1939_XTP_ABORT_FAULT
instead of carrying them around, mirroring the error handling of
j1939_xtp_rx_dat_one().
Note that pkt.dpo == pkt.total combined with a DT frame of
dat[0] == 0 still encodes the final packet (dat[0] - 1 + pkt.dpo ==
pkt.total - 1) and therefore stays accepted by design; the NULL
handling in j1939_session_completed() from the previous patch covers
this case. This patch only discards the clearly bogus values, so the
receive path no longer operates on offsets far outside the buffer.
Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol")
Signed-off-by: Xue Boyang <m18335910246@xxxxxxx>
---
net/can/j1939/transport.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index ecf7f245f837..b09983d9c19c 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -1833,6 +1833,11 @@ static void j1939_xtp_rx_dpo_one(struct j1939_session *session,
/* transmitted without problems */
session->pkt.dpo = j1939_etp_ctl_to_packet(skb->data);
+ if (session->pkt.dpo > session->pkt.total) {
+ j1939_session_timers_cancel(session);
+ j1939_session_cancel(session, J1939_XTP_ABORT_FAULT);
+ return;
+ }
session->last_cmd = dat[0];
j1939_tp_set_rxtimeout(session, 750);
--
2.53.0