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

can: slcan: allow reception of short error messages

Allows slcan to receive short messages (typically errors) from the serial
interface.

When error support was added to slcan protocol in
b32ff4668544e1333b694fcc7812b2d7397b4d6a ("can: slcan: extend the protocol
with error info") the minimum valid message size changed from 5 (minimum
standard can frame tIII0) to 3 ("e1a" is a valid protocol message, it is
one of the examples given in the comments for slcan_bump_err() ), but the
check for minimum message length prodicating all decoding was not adjusted.
This makes short error messages discarded and error frames not being
generated.

This patch changes the minimum length to the new minimum (3 characters,
excluding terminator, is now a valid message).

Signed-off-by: Carlos Sanchez <carlossanchez@geotab.com>
Fixes: b32ff4668544 ("can: slcan: extend the protocol with error info")
Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Link: https://patch.msgid.link/20250520102305.1097494-1-carlossanchez@geotab.com
Cc: stable@vger.kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Carlos Sanchez and committed by
Marc Kleine-Budde
ef0841e4 be19a922

+20 -6
+20 -6
drivers/net/can/slcan/slcan-core.c
··· 71 71 #define SLCAN_CMD_LEN 1 72 72 #define SLCAN_SFF_ID_LEN 3 73 73 #define SLCAN_EFF_ID_LEN 8 74 + #define SLCAN_DATA_LENGTH_LEN 1 75 + #define SLCAN_ERROR_LEN 1 74 76 #define SLCAN_STATE_LEN 1 75 77 #define SLCAN_STATE_BE_RXCNT_LEN 3 76 78 #define SLCAN_STATE_BE_TXCNT_LEN 3 77 - #define SLCAN_STATE_FRAME_LEN (1 + SLCAN_CMD_LEN + \ 78 - SLCAN_STATE_BE_RXCNT_LEN + \ 79 - SLCAN_STATE_BE_TXCNT_LEN) 79 + #define SLCAN_STATE_MSG_LEN (SLCAN_CMD_LEN + \ 80 + SLCAN_STATE_LEN + \ 81 + SLCAN_STATE_BE_RXCNT_LEN + \ 82 + SLCAN_STATE_BE_TXCNT_LEN) 83 + #define SLCAN_ERROR_MSG_LEN_MIN (SLCAN_CMD_LEN + \ 84 + SLCAN_ERROR_LEN + \ 85 + SLCAN_DATA_LENGTH_LEN) 86 + #define SLCAN_FRAME_MSG_LEN_MIN (SLCAN_CMD_LEN + \ 87 + SLCAN_SFF_ID_LEN + \ 88 + SLCAN_DATA_LENGTH_LEN) 80 89 struct slcan { 81 90 struct can_priv can; 82 91 ··· 184 175 int i, tmp; 185 176 u32 tmpid; 186 177 char *cmd = sl->rbuff; 178 + 179 + if (sl->rcount < SLCAN_FRAME_MSG_LEN_MIN) 180 + return; 187 181 188 182 skb = alloc_can_skb(sl->dev, &cf); 189 183 if (unlikely(!skb)) { ··· 293 281 return; 294 282 } 295 283 296 - if (state == sl->can.state || sl->rcount < SLCAN_STATE_FRAME_LEN) 284 + if (state == sl->can.state || sl->rcount != SLCAN_STATE_MSG_LEN) 297 285 return; 298 286 299 287 cmd += SLCAN_STATE_BE_RXCNT_LEN + SLCAN_CMD_LEN + 1; ··· 339 327 char *cmd = sl->rbuff; 340 328 bool rx_errors = false, tx_errors = false, rx_over_errors = false; 341 329 int i, len; 330 + 331 + if (sl->rcount < SLCAN_ERROR_MSG_LEN_MIN) 332 + return; 342 333 343 334 /* get len from sanitized ASCII value */ 344 335 len = cmd[1]; ··· 471 456 static void slcan_unesc(struct slcan *sl, unsigned char s) 472 457 { 473 458 if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */ 474 - if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && 475 - sl->rcount > 4) 459 + if (!test_and_clear_bit(SLF_ERROR, &sl->flags)) 476 460 slcan_bump(sl); 477 461 478 462 sl->rcount = 0;