From: Greg Kroah-Hartman Date: Mon, 6 Nov 2023 11:19:28 +0000 (+0100) Subject: 5.15-stable patches X-Git-Tag: v4.14.329~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=67368317bd19a27ce954a483759c34de904552aa;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: can-isotp-add-local-echo-tx-processing-and-tx-without-fc.patch can-isotp-check-can-address-family-in-isotp_bind.patch can-isotp-handle-wait_event_interruptible-return-values.patch can-isotp-isotp_bind-do-not-validate-unused-address-information.patch can-isotp-isotp_bind-return-einval-on-incorrect-can-id-formatting.patch can-isotp-isotp_sendmsg-fix-tx-state-detection-and-wait-behavior.patch can-isotp-set-max-pdu-size-to-64-kbyte.patch --- diff --git a/queue-5.15/can-isotp-add-local-echo-tx-processing-and-tx-without-fc.patch b/queue-5.15/can-isotp-add-local-echo-tx-processing-and-tx-without-fc.patch new file mode 100644 index 00000000000..6232ccd5404 --- /dev/null +++ b/queue-5.15/can-isotp-add-local-echo-tx-processing-and-tx-without-fc.patch @@ -0,0 +1,720 @@ +From stable-owner@vger.kernel.org Tue Oct 31 10:31:04 2023 +From: Oliver Hartkopp +Date: Tue, 31 Oct 2023 10:30:23 +0100 +Subject: can: isotp: add local echo tx processing and tx without FC +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, sashal@kernel.org +Cc: linux-can@vger.kernel.org, lukas.magel@posteo.net, patches@lists.linux.dev, maxime.jayat@mobile-devices.fr, mkl@pengutronix.de, michal.sojka@cvut.cz, Oliver Hartkopp +Message-ID: <20231031093025.2699-6-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +commit 4b7fe92c06901f4563af0e36d25223a5ab343782 upstream +commit 9f39d36530e5678d092d53c5c2c60d82b4dcc169 upstream +commit 051737439eaee5bdd03d3c2ef5510d54a478fd05 upstream + +Due to the existing patch order applied to isotp.c in the stable kernel the +original order of depending patches the three original patches +4b7fe92c0690 ("can: isotp: add local echo tx processing for consecutive frames") +9f39d36530e5 ("can: isotp: add support for transmission without flow control") +051737439eae ("can: isotp: fix race between isotp_sendsmg() and isotp_release()") +can not be split into different patches that can be applied in working steps +to the stable tree. + +Signed-off-by: Oliver Hartkopp +Signed-off-by: Greg Kroah-Hartman +--- + include/uapi/linux/can/isotp.h | 25 +- + net/can/isotp.c | 406 ++++++++++++++++++++++++++--------------- + 2 files changed, 271 insertions(+), 160 deletions(-) + +--- a/include/uapi/linux/can/isotp.h ++++ b/include/uapi/linux/can/isotp.h +@@ -124,18 +124,19 @@ struct can_isotp_ll_options { + + /* flags for isotp behaviour */ + +-#define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */ +-#define CAN_ISOTP_EXTEND_ADDR 0x002 /* enable extended addressing */ +-#define CAN_ISOTP_TX_PADDING 0x004 /* enable CAN frame padding tx path */ +-#define CAN_ISOTP_RX_PADDING 0x008 /* enable CAN frame padding rx path */ +-#define CAN_ISOTP_CHK_PAD_LEN 0x010 /* check received CAN frame padding */ +-#define CAN_ISOTP_CHK_PAD_DATA 0x020 /* check received CAN frame padding */ +-#define CAN_ISOTP_HALF_DUPLEX 0x040 /* half duplex error state handling */ +-#define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */ +-#define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */ +-#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */ +-#define CAN_ISOTP_WAIT_TX_DONE 0x400 /* wait for tx completion */ +-#define CAN_ISOTP_SF_BROADCAST 0x800 /* 1-to-N functional addressing */ ++#define CAN_ISOTP_LISTEN_MODE 0x0001 /* listen only (do not send FC) */ ++#define CAN_ISOTP_EXTEND_ADDR 0x0002 /* enable extended addressing */ ++#define CAN_ISOTP_TX_PADDING 0x0004 /* enable CAN frame padding tx path */ ++#define CAN_ISOTP_RX_PADDING 0x0008 /* enable CAN frame padding rx path */ ++#define CAN_ISOTP_CHK_PAD_LEN 0x0010 /* check received CAN frame padding */ ++#define CAN_ISOTP_CHK_PAD_DATA 0x0020 /* check received CAN frame padding */ ++#define CAN_ISOTP_HALF_DUPLEX 0x0040 /* half duplex error state handling */ ++#define CAN_ISOTP_FORCE_TXSTMIN 0x0080 /* ignore stmin from received FC */ ++#define CAN_ISOTP_FORCE_RXSTMIN 0x0100 /* ignore CFs depending on rx stmin */ ++#define CAN_ISOTP_RX_EXT_ADDR 0x0200 /* different rx extended addressing */ ++#define CAN_ISOTP_WAIT_TX_DONE 0x0400 /* wait for tx completion */ ++#define CAN_ISOTP_SF_BROADCAST 0x0800 /* 1-to-N functional addressing */ ++#define CAN_ISOTP_CF_BROADCAST 0x1000 /* 1-to-N transmission w/o FC */ + + /* protocol machine default values */ + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -14,7 +14,6 @@ + * - use CAN_ISOTP_WAIT_TX_DONE flag to block the caller until the PDU is sent + * - as we have static buffers the check whether the PDU fits into the buffer + * is done at FF reception time (no support for sending 'wait frames') +- * - take care of the tx-queue-len as traffic shaping is still on the TODO list + * + * Copyright (c) 2020 Volkswagen Group Electronic Research + * All rights reserved. +@@ -105,18 +104,23 @@ MODULE_ALIAS("can-proto-6"); + #define FC_CONTENT_SZ 3 /* flow control content size in byte (FS/BS/STmin) */ + + #define ISOTP_CHECK_PADDING (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA) ++#define ISOTP_ALL_BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST) + + /* Flow Status given in FC frame */ + #define ISOTP_FC_CTS 0 /* clear to send */ + #define ISOTP_FC_WT 1 /* wait */ + #define ISOTP_FC_OVFLW 2 /* overflow */ + ++#define ISOTP_FC_TIMEOUT 1 /* 1 sec */ ++#define ISOTP_ECHO_TIMEOUT 2 /* 2 secs */ ++ + enum { + ISOTP_IDLE = 0, + ISOTP_WAIT_FIRST_FC, + ISOTP_WAIT_FC, + ISOTP_WAIT_DATA, +- ISOTP_SENDING ++ ISOTP_SENDING, ++ ISOTP_SHUTDOWN, + }; + + struct tpcon { +@@ -137,13 +141,14 @@ struct isotp_sock { + canid_t rxid; + ktime_t tx_gap; + ktime_t lastrxcf_tstamp; +- struct hrtimer rxtimer, txtimer; ++ struct hrtimer rxtimer, txtimer, txfrtimer; + struct can_isotp_options opt; + struct can_isotp_fc_options rxfc, txfc; + struct can_isotp_ll_options ll; + u32 frame_txtime; + u32 force_tx_stmin; + u32 force_rx_stmin; ++ u32 cfecho; /* consecutive frame echo tag */ + struct tpcon rx, tx; + struct list_head notifier; + wait_queue_head_t wait; +@@ -159,6 +164,17 @@ static inline struct isotp_sock *isotp_s + return (struct isotp_sock *)sk; + } + ++static u32 isotp_bc_flags(struct isotp_sock *so) ++{ ++ return so->opt.flags & ISOTP_ALL_BC_FLAGS; ++} ++ ++static bool isotp_register_rxid(struct isotp_sock *so) ++{ ++ /* no broadcast modes => register rx_id for FC frame reception */ ++ return (isotp_bc_flags(so) == 0); ++} ++ + static enum hrtimer_restart isotp_rx_timer_handler(struct hrtimer *hrtimer) + { + struct isotp_sock *so = container_of(hrtimer, struct isotp_sock, +@@ -240,7 +256,8 @@ static int isotp_send_fc(struct sock *sk + so->lastrxcf_tstamp = ktime_set(0, 0); + + /* start rx timeout watchdog */ +- hrtimer_start(&so->rxtimer, ktime_set(1, 0), HRTIMER_MODE_REL_SOFT); ++ hrtimer_start(&so->rxtimer, ktime_set(ISOTP_FC_TIMEOUT, 0), ++ HRTIMER_MODE_REL_SOFT); + return 0; + } + +@@ -326,6 +343,8 @@ static int check_pad(struct isotp_sock * + return 0; + } + ++static void isotp_send_cframe(struct isotp_sock *so); ++ + static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae) + { + struct sock *sk = &so->sk; +@@ -380,14 +399,15 @@ static int isotp_rcv_fc(struct isotp_soc + case ISOTP_FC_CTS: + so->tx.bs = 0; + so->tx.state = ISOTP_SENDING; +- /* start cyclic timer for sending CF frame */ +- hrtimer_start(&so->txtimer, so->tx_gap, ++ /* send CF frame and enable echo timeout handling */ ++ hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0), + HRTIMER_MODE_REL_SOFT); ++ isotp_send_cframe(so); + break; + + case ISOTP_FC_WT: + /* start timer to wait for next FC frame */ +- hrtimer_start(&so->txtimer, ktime_set(1, 0), ++ hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0), + HRTIMER_MODE_REL_SOFT); + break; + +@@ -582,7 +602,7 @@ static int isotp_rcv_cf(struct sock *sk, + /* perform blocksize handling, if enabled */ + if (!so->rxfc.bs || ++so->rx.bs < so->rxfc.bs) { + /* start rx timeout watchdog */ +- hrtimer_start(&so->rxtimer, ktime_set(1, 0), ++ hrtimer_start(&so->rxtimer, ktime_set(ISOTP_FC_TIMEOUT, 0), + HRTIMER_MODE_REL_SOFT); + return 0; + } +@@ -713,6 +733,63 @@ static void isotp_fill_dataframe(struct + cf->data[0] = so->opt.ext_address; + } + ++static void isotp_send_cframe(struct isotp_sock *so) ++{ ++ struct sock *sk = &so->sk; ++ struct sk_buff *skb; ++ struct net_device *dev; ++ struct canfd_frame *cf; ++ int can_send_ret; ++ int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; ++ ++ dev = dev_get_by_index(sock_net(sk), so->ifindex); ++ if (!dev) ++ return; ++ ++ skb = alloc_skb(so->ll.mtu + sizeof(struct can_skb_priv), GFP_ATOMIC); ++ if (!skb) { ++ dev_put(dev); ++ return; ++ } ++ ++ can_skb_reserve(skb); ++ can_skb_prv(skb)->ifindex = dev->ifindex; ++ can_skb_prv(skb)->skbcnt = 0; ++ ++ cf = (struct canfd_frame *)skb->data; ++ skb_put_zero(skb, so->ll.mtu); ++ ++ /* create consecutive frame */ ++ isotp_fill_dataframe(cf, so, ae, 0); ++ ++ /* place consecutive frame N_PCI in appropriate index */ ++ cf->data[ae] = N_PCI_CF | so->tx.sn++; ++ so->tx.sn %= 16; ++ so->tx.bs++; ++ ++ cf->flags = so->ll.tx_flags; ++ ++ skb->dev = dev; ++ can_skb_set_owner(skb, sk); ++ ++ /* cfecho should have been zero'ed by init/isotp_rcv_echo() */ ++ if (so->cfecho) ++ pr_notice_once("can-isotp: cfecho is %08X != 0\n", so->cfecho); ++ ++ /* set consecutive frame echo tag */ ++ so->cfecho = *(u32 *)cf->data; ++ ++ /* send frame with local echo enabled */ ++ can_send_ret = can_send(skb, 1); ++ if (can_send_ret) { ++ pr_notice_once("can-isotp: %s: can_send_ret %pe\n", ++ __func__, ERR_PTR(can_send_ret)); ++ if (can_send_ret == -ENOBUFS) ++ pr_notice_once("can-isotp: tx queue is full\n"); ++ } ++ dev_put(dev); ++} ++ + static void isotp_create_fframe(struct canfd_frame *cf, struct isotp_sock *so, + int ae) + { +@@ -746,145 +823,123 @@ static void isotp_create_fframe(struct c + cf->data[i] = so->tx.buf[so->tx.idx++]; + + so->tx.sn = 1; +- so->tx.state = ISOTP_WAIT_FIRST_FC; + } + +-static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer) ++static void isotp_rcv_echo(struct sk_buff *skb, void *data) + { +- struct isotp_sock *so = container_of(hrtimer, struct isotp_sock, +- txtimer); +- struct sock *sk = &so->sk; +- struct sk_buff *skb; +- struct net_device *dev; +- struct canfd_frame *cf; +- enum hrtimer_restart restart = HRTIMER_NORESTART; +- int can_send_ret; +- int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; ++ struct sock *sk = (struct sock *)data; ++ struct isotp_sock *so = isotp_sk(sk); ++ struct canfd_frame *cf = (struct canfd_frame *)skb->data; + +- switch (so->tx.state) { +- case ISOTP_WAIT_FC: +- case ISOTP_WAIT_FIRST_FC: ++ /* only handle my own local echo CF/SF skb's (no FF!) */ ++ if (skb->sk != sk || so->cfecho != *(u32 *)cf->data) ++ return; + +- /* we did not get any flow control frame in time */ ++ /* cancel local echo timeout */ ++ hrtimer_cancel(&so->txtimer); + +- /* report 'communication error on send' */ +- sk->sk_err = ECOMM; +- if (!sock_flag(sk, SOCK_DEAD)) +- sk_error_report(sk); ++ /* local echo skb with consecutive frame has been consumed */ ++ so->cfecho = 0; + +- /* reset tx state */ ++ if (so->tx.idx >= so->tx.len) { ++ /* we are done */ + so->tx.state = ISOTP_IDLE; + wake_up_interruptible(&so->wait); +- break; ++ return; ++ } + +- case ISOTP_SENDING: ++ if (so->txfc.bs && so->tx.bs >= so->txfc.bs) { ++ /* stop and wait for FC with timeout */ ++ so->tx.state = ISOTP_WAIT_FC; ++ hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0), ++ HRTIMER_MODE_REL_SOFT); ++ return; ++ } + +- /* push out the next segmented pdu */ +- dev = dev_get_by_index(sock_net(sk), so->ifindex); +- if (!dev) +- break; ++ /* no gap between data frames needed => use burst mode */ ++ if (!so->tx_gap) { ++ /* enable echo timeout handling */ ++ hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0), ++ HRTIMER_MODE_REL_SOFT); ++ isotp_send_cframe(so); ++ return; ++ } + +-isotp_tx_burst: +- skb = alloc_skb(so->ll.mtu + sizeof(struct can_skb_priv), +- GFP_ATOMIC); +- if (!skb) { +- dev_put(dev); +- break; +- } ++ /* start timer to send next consecutive frame with correct delay */ ++ hrtimer_start(&so->txfrtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT); ++} + +- can_skb_reserve(skb); +- can_skb_prv(skb)->ifindex = dev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; +- +- cf = (struct canfd_frame *)skb->data; +- skb_put_zero(skb, so->ll.mtu); +- +- /* create consecutive frame */ +- isotp_fill_dataframe(cf, so, ae, 0); +- +- /* place consecutive frame N_PCI in appropriate index */ +- cf->data[ae] = N_PCI_CF | so->tx.sn++; +- so->tx.sn %= 16; +- so->tx.bs++; +- +- cf->flags = so->ll.tx_flags; +- +- skb->dev = dev; +- can_skb_set_owner(skb, sk); +- +- can_send_ret = can_send(skb, 1); +- if (can_send_ret) { +- pr_notice_once("can-isotp: %s: can_send_ret %pe\n", +- __func__, ERR_PTR(can_send_ret)); +- if (can_send_ret == -ENOBUFS) +- pr_notice_once("can-isotp: tx queue is full, increasing txqueuelen may prevent this error\n"); +- } +- if (so->tx.idx >= so->tx.len) { +- /* we are done */ +- so->tx.state = ISOTP_IDLE; +- dev_put(dev); +- wake_up_interruptible(&so->wait); +- break; +- } ++static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer) ++{ ++ struct isotp_sock *so = container_of(hrtimer, struct isotp_sock, ++ txtimer); ++ struct sock *sk = &so->sk; + +- if (so->txfc.bs && so->tx.bs >= so->txfc.bs) { +- /* stop and wait for FC */ +- so->tx.state = ISOTP_WAIT_FC; +- dev_put(dev); +- hrtimer_set_expires(&so->txtimer, +- ktime_add(ktime_get(), +- ktime_set(1, 0))); +- restart = HRTIMER_RESTART; +- break; +- } ++ /* don't handle timeouts in IDLE or SHUTDOWN state */ ++ if (so->tx.state == ISOTP_IDLE || so->tx.state == ISOTP_SHUTDOWN) ++ return HRTIMER_NORESTART; ++ ++ /* we did not get any flow control or echo frame in time */ ++ ++ /* report 'communication error on send' */ ++ sk->sk_err = ECOMM; ++ if (!sock_flag(sk, SOCK_DEAD)) ++ sk_error_report(sk); + +- /* no gap between data frames needed => use burst mode */ +- if (!so->tx_gap) +- goto isotp_tx_burst; ++ /* reset tx state */ ++ so->tx.state = ISOTP_IDLE; ++ wake_up_interruptible(&so->wait); + +- /* start timer to send next data frame with correct delay */ +- dev_put(dev); +- hrtimer_set_expires(&so->txtimer, +- ktime_add(ktime_get(), so->tx_gap)); +- restart = HRTIMER_RESTART; +- break; ++ return HRTIMER_NORESTART; ++} + +- default: +- WARN_ON_ONCE(1); +- } ++static enum hrtimer_restart isotp_txfr_timer_handler(struct hrtimer *hrtimer) ++{ ++ struct isotp_sock *so = container_of(hrtimer, struct isotp_sock, ++ txfrtimer); + +- return restart; ++ /* start echo timeout handling and cover below protocol error */ ++ hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0), ++ HRTIMER_MODE_REL_SOFT); ++ ++ /* cfecho should be consumed by isotp_rcv_echo() here */ ++ if (so->tx.state == ISOTP_SENDING && !so->cfecho) ++ isotp_send_cframe(so); ++ ++ return HRTIMER_NORESTART; + } + + static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) + { + struct sock *sk = sock->sk; + struct isotp_sock *so = isotp_sk(sk); +- u32 old_state = so->tx.state; + struct sk_buff *skb; + struct net_device *dev; + struct canfd_frame *cf; + int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; + int wait_tx_done = (so->opt.flags & CAN_ISOTP_WAIT_TX_DONE) ? 1 : 0; +- s64 hrtimer_sec = 0; ++ s64 hrtimer_sec = ISOTP_ECHO_TIMEOUT; + int off; + int err; + +- if (!so->bound) ++ if (!so->bound || so->tx.state == ISOTP_SHUTDOWN) + return -EADDRNOTAVAIL; + ++wait_free_buffer: + /* we do not support multiple buffers - for now */ +- if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE || +- wq_has_sleeper(&so->wait)) { +- if (msg->msg_flags & MSG_DONTWAIT) { +- err = -EAGAIN; +- goto err_out; +- } ++ if (wq_has_sleeper(&so->wait) && (msg->msg_flags & MSG_DONTWAIT)) ++ return -EAGAIN; + +- /* wait for complete transmission of current pdu */ +- err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); +- if (err) +- goto err_out; ++ /* wait for complete transmission of current pdu */ ++ err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); ++ if (err) ++ goto err_event_drop; ++ ++ if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) { ++ if (so->tx.state == ISOTP_SHUTDOWN) ++ return -EADDRNOTAVAIL; ++ ++ goto wait_free_buffer; + } + + if (!size || size > MAX_MSG_LENGTH) { +@@ -896,7 +951,7 @@ static int isotp_sendmsg(struct socket * + off = (so->tx.ll_dl > CAN_MAX_DLEN) ? 1 : 0; + + /* does the given data fit into a single frame for SF_BROADCAST? */ +- if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) && ++ if ((isotp_bc_flags(so) == CAN_ISOTP_SF_BROADCAST) && + (size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) { + err = -EINVAL; + goto err_out_drop; +@@ -929,6 +984,10 @@ static int isotp_sendmsg(struct socket * + cf = (struct canfd_frame *)skb->data; + skb_put_zero(skb, so->ll.mtu); + ++ /* cfecho should have been zero'ed by init / former isotp_rcv_echo() */ ++ if (so->cfecho) ++ pr_notice_once("can-isotp: uninit cfecho %08X\n", so->cfecho); ++ + /* check for single frame transmission depending on TX_DL */ + if (size <= so->tx.ll_dl - SF_PCI_SZ4 - ae - off) { + /* The message size generally fits into a SingleFrame - good. +@@ -954,22 +1013,40 @@ static int isotp_sendmsg(struct socket * + else + cf->data[ae] |= size; + +- so->tx.state = ISOTP_IDLE; +- wake_up_interruptible(&so->wait); +- +- /* don't enable wait queue for a single frame transmission */ +- wait_tx_done = 0; ++ /* set CF echo tag for isotp_rcv_echo() (SF-mode) */ ++ so->cfecho = *(u32 *)cf->data; + } else { +- /* send first frame and wait for FC */ ++ /* send first frame */ + + isotp_create_fframe(cf, so, ae); + +- /* start timeout for FC */ +- hrtimer_sec = 1; +- hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0), +- HRTIMER_MODE_REL_SOFT); ++ if (isotp_bc_flags(so) == CAN_ISOTP_CF_BROADCAST) { ++ /* set timer for FC-less operation (STmin = 0) */ ++ if (so->opt.flags & CAN_ISOTP_FORCE_TXSTMIN) ++ so->tx_gap = ktime_set(0, so->force_tx_stmin); ++ else ++ so->tx_gap = ktime_set(0, so->frame_txtime); ++ ++ /* disable wait for FCs due to activated block size */ ++ so->txfc.bs = 0; ++ ++ /* set CF echo tag for isotp_rcv_echo() (CF-mode) */ ++ so->cfecho = *(u32 *)cf->data; ++ } else { ++ /* standard flow control check */ ++ so->tx.state = ISOTP_WAIT_FIRST_FC; ++ ++ /* start timeout for FC */ ++ hrtimer_sec = ISOTP_FC_TIMEOUT; ++ ++ /* no CF echo tag for isotp_rcv_echo() (FF-mode) */ ++ so->cfecho = 0; ++ } + } + ++ hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0), ++ HRTIMER_MODE_REL_SOFT); ++ + /* send the first or only CAN frame */ + cf->flags = so->ll.tx_flags; + +@@ -982,15 +1059,19 @@ static int isotp_sendmsg(struct socket * + __func__, ERR_PTR(err)); + + /* no transmission -> no timeout monitoring */ +- if (hrtimer_sec) +- hrtimer_cancel(&so->txtimer); ++ hrtimer_cancel(&so->txtimer); ++ ++ /* reset consecutive frame echo tag */ ++ so->cfecho = 0; + + goto err_out_drop; + } + + if (wait_tx_done) { + /* wait for complete transmission of current pdu */ +- wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); ++ err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); ++ if (err) ++ goto err_event_drop; + + err = sock_error(sk); + if (err) +@@ -999,13 +1080,15 @@ static int isotp_sendmsg(struct socket * + + return size; + ++err_event_drop: ++ /* got signal: force tx state machine to be idle */ ++ so->tx.state = ISOTP_IDLE; ++ hrtimer_cancel(&so->txfrtimer); ++ hrtimer_cancel(&so->txtimer); + err_out_drop: + /* drop this PDU and unlock a potential wait queue */ +- old_state = ISOTP_IDLE; +-err_out: +- so->tx.state = old_state; +- if (so->tx.state == ISOTP_IDLE) +- wake_up_interruptible(&so->wait); ++ so->tx.state = ISOTP_IDLE; ++ wake_up_interruptible(&so->wait); + + return err; + } +@@ -1069,10 +1152,12 @@ static int isotp_release(struct socket * + net = sock_net(sk); + + /* wait for complete transmission of current pdu */ +- wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); ++ while (wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0 && ++ cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SHUTDOWN) != ISOTP_IDLE) ++ ; + + /* force state machines to be idle also when a signal occurred */ +- so->tx.state = ISOTP_IDLE; ++ so->tx.state = ISOTP_SHUTDOWN; + so->rx.state = ISOTP_IDLE; + + spin_lock(&isotp_notifier_lock); +@@ -1087,21 +1172,27 @@ static int isotp_release(struct socket * + lock_sock(sk); + + /* remove current filters & unregister */ +- if (so->bound && (!(so->opt.flags & CAN_ISOTP_SF_BROADCAST))) { ++ if (so->bound) { + if (so->ifindex) { + struct net_device *dev; + + dev = dev_get_by_index(net, so->ifindex); + if (dev) { +- can_rx_unregister(net, dev, so->rxid, +- SINGLE_MASK(so->rxid), +- isotp_rcv, sk); ++ if (isotp_register_rxid(so)) ++ can_rx_unregister(net, dev, so->rxid, ++ SINGLE_MASK(so->rxid), ++ isotp_rcv, sk); ++ ++ can_rx_unregister(net, dev, so->txid, ++ SINGLE_MASK(so->txid), ++ isotp_rcv_echo, sk); + dev_put(dev); + synchronize_rcu(); + } + } + } + ++ hrtimer_cancel(&so->txfrtimer); + hrtimer_cancel(&so->txtimer); + hrtimer_cancel(&so->rxtimer); + +@@ -1128,7 +1219,6 @@ static int isotp_bind(struct socket *soc + canid_t tx_id, rx_id; + int err = 0; + int notify_enetdown = 0; +- int do_rx_reg = 1; + + if (len < ISOTP_MIN_NAMELEN) + return -EINVAL; +@@ -1164,12 +1254,8 @@ static int isotp_bind(struct socket *soc + goto out; + } + +- /* do not register frame reception for functional addressing */ +- if (so->opt.flags & CAN_ISOTP_SF_BROADCAST) +- do_rx_reg = 0; +- +- /* do not validate rx address for functional addressing */ +- if (do_rx_reg && rx_id == tx_id) { ++ /* ensure different CAN IDs when the rx_id is to be registered */ ++ if (isotp_register_rxid(so) && rx_id == tx_id) { + err = -EADDRNOTAVAIL; + goto out; + } +@@ -1194,10 +1280,17 @@ static int isotp_bind(struct socket *soc + + ifindex = dev->ifindex; + +- if (do_rx_reg) ++ if (isotp_register_rxid(so)) + can_rx_register(net, dev, rx_id, SINGLE_MASK(rx_id), + isotp_rcv, sk, "isotp", sk); + ++ /* no consecutive frame echo skb in flight */ ++ so->cfecho = 0; ++ ++ /* register for echo skb's */ ++ can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id), ++ isotp_rcv_echo, sk, "isotpe", sk); ++ + dev_put(dev); + + /* switch to new settings */ +@@ -1258,6 +1351,15 @@ static int isotp_setsockopt_locked(struc + if (!(so->opt.flags & CAN_ISOTP_RX_EXT_ADDR)) + so->opt.rx_ext_address = so->opt.ext_address; + ++ /* these broadcast flags are not allowed together */ ++ if (isotp_bc_flags(so) == ISOTP_ALL_BC_FLAGS) { ++ /* CAN_ISOTP_SF_BROADCAST is prioritized */ ++ so->opt.flags &= ~CAN_ISOTP_CF_BROADCAST; ++ ++ /* give user feedback on wrong config attempt */ ++ ret = -EINVAL; ++ } ++ + /* check for frame_txtime changes (0 => no changes) */ + if (so->opt.frame_txtime) { + if (so->opt.frame_txtime == CAN_ISOTP_FRAME_TXTIME_ZERO) +@@ -1408,10 +1510,16 @@ static void isotp_notify(struct isotp_so + case NETDEV_UNREGISTER: + lock_sock(sk); + /* remove current filters & unregister */ +- if (so->bound && (!(so->opt.flags & CAN_ISOTP_SF_BROADCAST))) +- can_rx_unregister(dev_net(dev), dev, so->rxid, +- SINGLE_MASK(so->rxid), +- isotp_rcv, sk); ++ if (so->bound) { ++ if (isotp_register_rxid(so)) ++ can_rx_unregister(dev_net(dev), dev, so->rxid, ++ SINGLE_MASK(so->rxid), ++ isotp_rcv, sk); ++ ++ can_rx_unregister(dev_net(dev), dev, so->txid, ++ SINGLE_MASK(so->txid), ++ isotp_rcv_echo, sk); ++ } + + so->ifindex = 0; + so->bound = 0; +@@ -1484,6 +1592,8 @@ static int isotp_init(struct sock *sk) + so->rxtimer.function = isotp_rx_timer_handler; + hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); + so->txtimer.function = isotp_tx_timer_handler; ++ hrtimer_init(&so->txfrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); ++ so->txfrtimer.function = isotp_txfr_timer_handler; + + init_waitqueue_head(&so->wait); + spin_lock_init(&so->rx_lock); diff --git a/queue-5.15/can-isotp-check-can-address-family-in-isotp_bind.patch b/queue-5.15/can-isotp-check-can-address-family-in-isotp_bind.patch new file mode 100644 index 00000000000..7fedb26ee62 --- /dev/null +++ b/queue-5.15/can-isotp-check-can-address-family-in-isotp_bind.patch @@ -0,0 +1,45 @@ +From stable-owner@vger.kernel.org Tue Oct 31 10:31:04 2023 +From: Oliver Hartkopp +Date: Tue, 31 Oct 2023 10:30:21 +0100 +Subject: can: isotp: check CAN address family in isotp_bind() +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, sashal@kernel.org +Cc: linux-can@vger.kernel.org, lukas.magel@posteo.net, patches@lists.linux.dev, maxime.jayat@mobile-devices.fr, mkl@pengutronix.de, michal.sojka@cvut.cz, Oliver Hartkopp , syzbot+5aed6c3aaba661f5b917@syzkaller.appspotmail.com +Message-ID: <20231031093025.2699-4-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +commit c6adf659a8ba85913e16a571d5a9bcd17d3d1234 upstream + +Add missing check to block non-AF_CAN binds. + +Syzbot created some code which matched the right sockaddr struct size +but used AF_XDP (0x2C) instead of AF_CAN (0x1D) in the address family +field: + +bind$xdp(r2, &(0x7f0000000540)={0x2c, 0x0, r4, 0x0, r2}, 0x10) + ^^^^ +This has no funtional impact but the userspace should be notified about +the wrong address family field content. + +Link: https://syzkaller.appspot.com/text?tag=CrashLog&x=11ff9d8c480000 +Reported-by: syzbot+5aed6c3aaba661f5b917@syzkaller.appspotmail.com +Signed-off-by: Oliver Hartkopp +Link: https://lore.kernel.org/all/20230104201844.13168-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/isotp.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -1129,6 +1129,9 @@ static int isotp_bind(struct socket *soc + if (len < ISOTP_MIN_NAMELEN) + return -EINVAL; + ++ if (addr->can_family != AF_CAN) ++ return -EINVAL; ++ + /* sanitize tx/rx CAN identifiers */ + tx_id = addr->can_addr.tp.tx_id; + if (tx_id & CAN_EFF_FLAG) diff --git a/queue-5.15/can-isotp-handle-wait_event_interruptible-return-values.patch b/queue-5.15/can-isotp-handle-wait_event_interruptible-return-values.patch new file mode 100644 index 00000000000..dbfff7aba58 --- /dev/null +++ b/queue-5.15/can-isotp-handle-wait_event_interruptible-return-values.patch @@ -0,0 +1,39 @@ +From stable-owner@vger.kernel.org Tue Oct 31 10:30:57 2023 +From: Oliver Hartkopp +Date: Tue, 31 Oct 2023 10:30:22 +0100 +Subject: can: isotp: handle wait_event_interruptible() return values +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, sashal@kernel.org +Cc: linux-can@vger.kernel.org, lukas.magel@posteo.net, patches@lists.linux.dev, maxime.jayat@mobile-devices.fr, mkl@pengutronix.de, michal.sojka@cvut.cz, Oliver Hartkopp +Message-ID: <20231031093025.2699-5-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +commit 823b2e42720f96f277940c37ea438b7c5ead51a4 upstream + +When wait_event_interruptible() has been interrupted by a signal the +tx.state value might not be ISOTP_IDLE. Force the state machines +into idle state to inhibit the timer handlers to continue working. + +Fixes: 866337865f37 ("can: isotp: fix tx state handling for echo tx processing") +Cc: stable@vger.kernel.org +Signed-off-by: Oliver Hartkopp +Link: https://lore.kernel.org/all/20230112192347.1944-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/isotp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -1071,6 +1071,10 @@ static int isotp_release(struct socket * + /* wait for complete transmission of current pdu */ + wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); + ++ /* force state machines to be idle also when a signal occurred */ ++ so->tx.state = ISOTP_IDLE; ++ so->rx.state = ISOTP_IDLE; ++ + spin_lock(&isotp_notifier_lock); + while (isotp_busy_notifier == so) { + spin_unlock(&isotp_notifier_lock); diff --git a/queue-5.15/can-isotp-isotp_bind-do-not-validate-unused-address-information.patch b/queue-5.15/can-isotp-isotp_bind-do-not-validate-unused-address-information.patch new file mode 100644 index 00000000000..98d8af81134 --- /dev/null +++ b/queue-5.15/can-isotp-isotp_bind-do-not-validate-unused-address-information.patch @@ -0,0 +1,81 @@ +From stable-owner@vger.kernel.org Tue Oct 31 10:31:04 2023 +From: Oliver Hartkopp +Date: Tue, 31 Oct 2023 10:30:24 +0100 +Subject: can: isotp: isotp_bind(): do not validate unused address information +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, sashal@kernel.org +Cc: linux-can@vger.kernel.org, lukas.magel@posteo.net, patches@lists.linux.dev, maxime.jayat@mobile-devices.fr, mkl@pengutronix.de, michal.sojka@cvut.cz, Oliver Hartkopp +Message-ID: <20231031093025.2699-7-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +commit b76b163f46b661499921a0049982764a6659bfe7 upstream + +With commit 2aa39889c463 ("can: isotp: isotp_bind(): return -EINVAL on +incorrect CAN ID formatting") the bind() syscall returns -EINVAL when +the given CAN ID needed to be sanitized. But in the case of an unconfirmed +broadcast mode the rx CAN ID is not needed and may be uninitialized from +the caller - which is ok. + +This patch makes sure the result of an inproper CAN ID format is only +provided when the address information is needed. + +Link: https://lore.kernel.org/all/20220517145653.2556-1-socketcan@hartkopp.net +Signed-off-by: Oliver Hartkopp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/isotp.c | 29 +++++++++++++++++------------ + 1 file changed, 17 insertions(+), 12 deletions(-) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -1216,7 +1216,8 @@ static int isotp_bind(struct socket *soc + struct net *net = sock_net(sk); + int ifindex; + struct net_device *dev; +- canid_t tx_id, rx_id; ++ canid_t tx_id = addr->can_addr.tp.tx_id; ++ canid_t rx_id = addr->can_addr.tp.rx_id; + int err = 0; + int notify_enetdown = 0; + +@@ -1226,24 +1227,28 @@ static int isotp_bind(struct socket *soc + if (addr->can_family != AF_CAN) + return -EINVAL; + +- /* sanitize tx/rx CAN identifiers */ +- tx_id = addr->can_addr.tp.tx_id; ++ /* sanitize tx CAN identifier */ + if (tx_id & CAN_EFF_FLAG) + tx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK); + else + tx_id &= CAN_SFF_MASK; + +- rx_id = addr->can_addr.tp.rx_id; +- if (rx_id & CAN_EFF_FLAG) +- rx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK); +- else +- rx_id &= CAN_SFF_MASK; +- +- /* give feedback on wrong CAN-ID values */ +- if (tx_id != addr->can_addr.tp.tx_id || +- rx_id != addr->can_addr.tp.rx_id) ++ /* give feedback on wrong CAN-ID value */ ++ if (tx_id != addr->can_addr.tp.tx_id) + return -EINVAL; + ++ /* sanitize rx CAN identifier (if needed) */ ++ if (isotp_register_rxid(so)) { ++ if (rx_id & CAN_EFF_FLAG) ++ rx_id &= (CAN_EFF_FLAG | CAN_EFF_MASK); ++ else ++ rx_id &= CAN_SFF_MASK; ++ ++ /* give feedback on wrong CAN-ID value */ ++ if (rx_id != addr->can_addr.tp.rx_id) ++ return -EINVAL; ++ } ++ + if (!addr->can_ifindex) + return -ENODEV; + diff --git a/queue-5.15/can-isotp-isotp_bind-return-einval-on-incorrect-can-id-formatting.patch b/queue-5.15/can-isotp-isotp_bind-return-einval-on-incorrect-can-id-formatting.patch new file mode 100644 index 00000000000..6361d636712 --- /dev/null +++ b/queue-5.15/can-isotp-isotp_bind-return-einval-on-incorrect-can-id-formatting.patch @@ -0,0 +1,47 @@ +From stable-owner@vger.kernel.org Tue Oct 31 10:30:57 2023 +From: Oliver Hartkopp +Date: Tue, 31 Oct 2023 10:30:20 +0100 +Subject: can: isotp: isotp_bind(): return -EINVAL on incorrect CAN ID formatting +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, sashal@kernel.org +Cc: linux-can@vger.kernel.org, lukas.magel@posteo.net, patches@lists.linux.dev, maxime.jayat@mobile-devices.fr, mkl@pengutronix.de, michal.sojka@cvut.cz, Oliver Hartkopp , Derek Will +Message-ID: <20231031093025.2699-3-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +commit 2aa39889c463195a0dfe2aff9fad413139c32a4f upstream + +Commit 3ea566422cbd ("can: isotp: sanitize CAN ID checks in +isotp_bind()") checks the given CAN ID address information by +sanitizing the input values. + +This check (silently) removes obsolete bits by masking the given CAN +IDs. + +Derek Will suggested to give a feedback to the application programmer +when the 'sanitizing' was actually needed which means the programmer +provided CAN ID content in a wrong format (e.g. SFF CAN IDs with a CAN +ID > 0x7FF). + +Link: https://lore.kernel.org/all/20220515181633.76671-1-socketcan@hartkopp.net +Suggested-by: Derek Will +Signed-off-by: Oliver Hartkopp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/isotp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -1142,6 +1142,11 @@ static int isotp_bind(struct socket *soc + else + rx_id &= CAN_SFF_MASK; + ++ /* give feedback on wrong CAN-ID values */ ++ if (tx_id != addr->can_addr.tp.tx_id || ++ rx_id != addr->can_addr.tp.rx_id) ++ return -EINVAL; ++ + if (!addr->can_ifindex) + return -ENODEV; + diff --git a/queue-5.15/can-isotp-isotp_sendmsg-fix-tx-state-detection-and-wait-behavior.patch b/queue-5.15/can-isotp-isotp_sendmsg-fix-tx-state-detection-and-wait-behavior.patch new file mode 100644 index 00000000000..3a5cfb8b483 --- /dev/null +++ b/queue-5.15/can-isotp-isotp_sendmsg-fix-tx-state-detection-and-wait-behavior.patch @@ -0,0 +1,78 @@ +From stable-owner@vger.kernel.org Tue Oct 31 10:31:21 2023 +From: Oliver Hartkopp +Date: Tue, 31 Oct 2023 10:30:25 +0100 +Subject: can: isotp: isotp_sendmsg(): fix TX state detection and wait behavior +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, sashal@kernel.org +Cc: linux-can@vger.kernel.org, lukas.magel@posteo.net, patches@lists.linux.dev, maxime.jayat@mobile-devices.fr, mkl@pengutronix.de, michal.sojka@cvut.cz, Oliver Hartkopp +Message-ID: <20231031093025.2699-8-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +From: Lukas Magel + +[ Upstream commit d9c2ba65e651467de739324d978b04ed8729f483 ] + +With patch [1], isotp_poll was updated to also queue the poller in the +so->wait queue, which is used for send state changes. Since the queue +now also contains polling tasks that are not interested in sending, the +queue fill state can no longer be used as an indication of send +readiness. As a consequence, nonblocking writes can lead to a race and +lock-up of the socket if there is a second task polling the socket in +parallel. + +With this patch, isotp_sendmsg does not consult wq_has_sleepers but +instead tries to atomically set so->tx.state and waits on so->wait if it +is unable to do so. This behavior is in alignment with isotp_poll, which +also checks so->tx.state to determine send readiness. + +V2: +- Revert direct exit to goto err_event_drop + +[1] https://lore.kernel.org/all/20230331125511.372783-1-michal.sojka@cvut.cz + +Reported-by: Maxime Jayat +Closes: https://lore.kernel.org/linux-can/11328958-453f-447f-9af8-3b5824dfb041@munic.io/ +Signed-off-by: Lukas Magel +Reviewed-by: Oliver Hartkopp +Fixes: 79e19fa79cb5 ("can: isotp: isotp_ops: fix poll() to not report false EPOLLOUT events") +Link: https://github.com/pylessard/python-udsoncan/issues/178#issuecomment-1743786590 +Link: https://lore.kernel.org/all/20230827092205.7908-1-lukas.magel@posteo.net +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/can/isotp.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -925,21 +925,18 @@ static int isotp_sendmsg(struct socket * + if (!so->bound || so->tx.state == ISOTP_SHUTDOWN) + return -EADDRNOTAVAIL; + +-wait_free_buffer: +- /* we do not support multiple buffers - for now */ +- if (wq_has_sleeper(&so->wait) && (msg->msg_flags & MSG_DONTWAIT)) +- return -EAGAIN; ++ while (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) { ++ /* we do not support multiple buffers - for now */ ++ if (msg->msg_flags & MSG_DONTWAIT) ++ return -EAGAIN; + +- /* wait for complete transmission of current pdu */ +- err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); +- if (err) +- goto err_event_drop; +- +- if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) { + if (so->tx.state == ISOTP_SHUTDOWN) + return -EADDRNOTAVAIL; + +- goto wait_free_buffer; ++ /* wait for complete transmission of current pdu */ ++ err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); ++ if (err) ++ goto err_event_drop; + } + + if (!size || size > MAX_MSG_LENGTH) { diff --git a/queue-5.15/can-isotp-set-max-pdu-size-to-64-kbyte.patch b/queue-5.15/can-isotp-set-max-pdu-size-to-64-kbyte.patch new file mode 100644 index 00000000000..d0c51d3fa7c --- /dev/null +++ b/queue-5.15/can-isotp-set-max-pdu-size-to-64-kbyte.patch @@ -0,0 +1,45 @@ +From stable-owner@vger.kernel.org Tue Oct 31 10:30:57 2023 +From: Oliver Hartkopp +Date: Tue, 31 Oct 2023 10:30:19 +0100 +Subject: can: isotp: set max PDU size to 64 kByte +To: gregkh@linuxfoundation.org, stable@vger.kernel.org, sashal@kernel.org +Cc: linux-can@vger.kernel.org, lukas.magel@posteo.net, patches@lists.linux.dev, maxime.jayat@mobile-devices.fr, mkl@pengutronix.de, michal.sojka@cvut.cz, Oliver Hartkopp +Message-ID: <20231031093025.2699-2-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +commit 9c0c191d82a1de964ac953a1df8b5744ec670b07 upstream + +The reason to extend the max PDU size from 4095 Byte (12 bit length value) +to a 32 bit value (up to 4 GByte) was to be able to flash 64 kByte +bootloaders with a single ISO-TP PDU. The max PDU size in the Linux kernel +implementation was set to 8200 Bytes to be able to test the length +information escape sequence. + +It turns out that the demand for 64 kByte PDUs is real so the value for +MAX_MSG_LENGTH is set to 66000 to be able to potentially add some checksums +to the 65.536 Byte block. + +Link: https://github.com/linux-can/can-utils/issues/347#issuecomment-1056142301 +Link: https://lore.kernel.org/all/20220309120416.83514-3-socketcan@hartkopp.net +Signed-off-by: Oliver Hartkopp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/isotp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -87,9 +87,9 @@ MODULE_ALIAS("can-proto-6"); + /* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can + * take full 32 bit values (4 Gbyte). We would need some good concept to handle + * this between user space and kernel space. For now increase the static buffer +- * to something about 8 kbyte to be able to test this new functionality. ++ * to something about 64 kbyte to be able to test this new functionality. + */ +-#define MAX_MSG_LENGTH 8200 ++#define MAX_MSG_LENGTH 66000 + + /* N_PCI type values in bits 7-4 of N_PCI bytes */ + #define N_PCI_SF 0x00 /* single frame */ diff --git a/queue-5.15/series b/queue-5.15/series index 3aaa6311501..e1add43375f 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -102,3 +102,10 @@ powerpc-mm-fix-boot-crash-with-flatmem.patch perf-evlist-add-evlist__add_dummy_on_all_cpus.patch perf-tools-get-rid-of-evlist__add_on_all_cpus.patch perf-evlist-avoid-frequency-mode-for-the-dummy-event.patch +can-isotp-set-max-pdu-size-to-64-kbyte.patch +can-isotp-isotp_bind-return-einval-on-incorrect-can-id-formatting.patch +can-isotp-check-can-address-family-in-isotp_bind.patch +can-isotp-handle-wait_event_interruptible-return-values.patch +can-isotp-add-local-echo-tx-processing-and-tx-without-fc.patch +can-isotp-isotp_bind-do-not-validate-unused-address-information.patch +can-isotp-isotp_sendmsg-fix-tx-state-detection-and-wait-behavior.patch