From: Greg Kroah-Hartman Date: Mon, 28 Feb 2022 07:59:38 +0000 (+0100) Subject: 5.16-stable patches X-Git-Tag: v4.9.304~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ab70da9d8ac46af795c3cf5c9a3b6ac700683514;p=thirdparty%2Fkernel%2Fstable-queue.git 5.16-stable patches added patches: tty-n_gsm-fix-deadlock-in-gsmtty_open.patch tty-n_gsm-fix-encoding-of-command-response-bit.patch tty-n_gsm-fix-null-pointer-access-due-to-dlci-release.patch tty-n_gsm-fix-proper-link-termination-after-failed-open.patch tty-n_gsm-fix-wrong-modem-processing-in-convergence-layer-type-2.patch tty-n_gsm-fix-wrong-tty-control-line-for-flow-control.patch --- diff --git a/queue-5.16/series b/queue-5.16/series index 43772b5b0c4..a9a339f644c 100644 --- a/queue-5.16/series +++ b/queue-5.16/series @@ -152,3 +152,9 @@ riscv-fix-oops-caused-by-irqsoff-latency-tracer.patch mm-hugetlb-fix-kernel-crash-with-hugetlb-mremap.patch hugetlbfs-fix-a-truncation-issue-in-hugepages-parameter.patch tty-n_gsm-fix-encoding-of-control-signal-octet-bit-dv.patch +tty-n_gsm-fix-encoding-of-command-response-bit.patch +tty-n_gsm-fix-proper-link-termination-after-failed-open.patch +tty-n_gsm-fix-null-pointer-access-due-to-dlci-release.patch +tty-n_gsm-fix-wrong-tty-control-line-for-flow-control.patch +tty-n_gsm-fix-wrong-modem-processing-in-convergence-layer-type-2.patch +tty-n_gsm-fix-deadlock-in-gsmtty_open.patch diff --git a/queue-5.16/tty-n_gsm-fix-deadlock-in-gsmtty_open.patch b/queue-5.16/tty-n_gsm-fix-deadlock-in-gsmtty_open.patch new file mode 100644 index 00000000000..fbe39738e05 --- /dev/null +++ b/queue-5.16/tty-n_gsm-fix-deadlock-in-gsmtty_open.patch @@ -0,0 +1,42 @@ +From a2ab75b8e76e455af7867e3835fd9cdf386b508f Mon Sep 17 00:00:00 2001 +From: "daniel.starke@siemens.com" +Date: Thu, 17 Feb 2022 23:31:23 -0800 +Subject: tty: n_gsm: fix deadlock in gsmtty_open() + +From: daniel.starke@siemens.com + +commit a2ab75b8e76e455af7867e3835fd9cdf386b508f upstream. + +In the current implementation the user may open a virtual tty which then +could fail to establish the underlying DLCI. The function gsmtty_open() +gets stuck in tty_port_block_til_ready() while waiting for a carrier rise. +This happens if the remote side fails to acknowledge the link establishment +request in time or completely. At some point gsm_dlci_close() is called +to abort the link establishment attempt. The function tries to inform the +associated virtual tty by performing a hangup. But the blocking loop within +tty_port_block_til_ready() is not informed about this event. +The patch proposed here fixes this by resetting the initialization state of +the virtual tty to ensure the loop exits and triggering it to make +tty_port_block_til_ready() return. + +Fixes: e1eaea46bb40 ("tty: n_gsm line discipline") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Starke +Link: https://lore.kernel.org/r/20220218073123.2121-7-daniel.starke@siemens.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_gsm.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -1457,6 +1457,9 @@ static void gsm_dlci_close(struct gsm_dl + if (dlci->addr != 0) { + tty_port_tty_hangup(&dlci->port, false); + kfifo_reset(&dlci->fifo); ++ /* Ensure that gsmtty_open() can return. */ ++ tty_port_set_initialized(&dlci->port, 0); ++ wake_up_interruptible(&dlci->port.open_wait); + } else + dlci->gsm->dead = true; + /* Unregister gsmtty driver,report gsmtty dev remove uevent for user */ diff --git a/queue-5.16/tty-n_gsm-fix-encoding-of-command-response-bit.patch b/queue-5.16/tty-n_gsm-fix-encoding-of-command-response-bit.patch new file mode 100644 index 00000000000..3d615e156f4 --- /dev/null +++ b/queue-5.16/tty-n_gsm-fix-encoding-of-command-response-bit.patch @@ -0,0 +1,103 @@ +From 57435c42400ec147a527b2313188b649e81e449e Mon Sep 17 00:00:00 2001 +From: "daniel.starke@siemens.com" +Date: Thu, 17 Feb 2022 23:31:18 -0800 +Subject: tty: n_gsm: fix encoding of command/response bit + +From: daniel.starke@siemens.com + +commit 57435c42400ec147a527b2313188b649e81e449e upstream. + +n_gsm is based on the 3GPP 07.010 and its newer version is the 3GPP 27.010. +See https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1516 +The changes from 07.010 to 27.010 are non-functional. Therefore, I refer to +the newer 27.010 here. Chapter 5.2.1.2 describes the encoding of the +C/R (command/response) bit. Table 1 shows that the actual encoding of the +C/R bit is inverted if the associated frame is sent by the responder. + +The referenced commit fixed here further broke the internal meaning of this +bit in the outgoing path by always setting the C/R bit regardless of the +frame type. + +This patch fixes both by setting the C/R bit always consistently for +command (1) and response (0) frames and inverting it later for the +responder where necessary. The meaning of this bit in the debug output +is being preserved and shows the bit as if it was encoded by the initiator. +This reflects only the frame type rather than the encoded combination of +communication side and frame type. + +Fixes: cc0f42122a7e ("tty: n_gsm: Modify CR,PF bit when config requester") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Starke +Link: https://lore.kernel.org/r/20220218073123.2121-2-daniel.starke@siemens.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_gsm.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -448,7 +448,7 @@ static u8 gsm_encode_modem(const struct + * gsm_print_packet - display a frame for debug + * @hdr: header to print before decode + * @addr: address EA from the frame +- * @cr: C/R bit from the frame ++ * @cr: C/R bit seen as initiator + * @control: control including PF bit + * @data: following data bytes + * @dlen: length of data +@@ -548,7 +548,7 @@ static int gsm_stuff_frame(const u8 *inp + * gsm_send - send a control frame + * @gsm: our GSM mux + * @addr: address for control frame +- * @cr: command/response bit ++ * @cr: command/response bit seen as initiator + * @control: control byte including PF bit + * + * Format up and transmit a control frame. These do not go via the +@@ -563,11 +563,15 @@ static void gsm_send(struct gsm_mux *gsm + int len; + u8 cbuf[10]; + u8 ibuf[3]; ++ int ocr; ++ ++ /* toggle C/R coding if not initiator */ ++ ocr = cr ^ (gsm->initiator ? 0 : 1); + + switch (gsm->encoding) { + case 0: + cbuf[0] = GSM0_SOF; +- cbuf[1] = (addr << 2) | (cr << 1) | EA; ++ cbuf[1] = (addr << 2) | (ocr << 1) | EA; + cbuf[2] = control; + cbuf[3] = EA; /* Length of data = 0 */ + cbuf[4] = 0xFF - gsm_fcs_add_block(INIT_FCS, cbuf + 1, 3); +@@ -577,7 +581,7 @@ static void gsm_send(struct gsm_mux *gsm + case 1: + case 2: + /* Control frame + packing (but not frame stuffing) in mode 1 */ +- ibuf[0] = (addr << 2) | (cr << 1) | EA; ++ ibuf[0] = (addr << 2) | (ocr << 1) | EA; + ibuf[1] = control; + ibuf[2] = 0xFF - gsm_fcs_add_block(INIT_FCS, ibuf, 2); + /* Stuffing may double the size worst case */ +@@ -611,7 +615,7 @@ static void gsm_send(struct gsm_mux *gsm + + static inline void gsm_response(struct gsm_mux *gsm, int addr, int control) + { +- gsm_send(gsm, addr, 1, control); ++ gsm_send(gsm, addr, 0, control); + } + + /** +@@ -1800,10 +1804,10 @@ static void gsm_queue(struct gsm_mux *gs + goto invalid; + + cr = gsm->address & 1; /* C/R bit */ ++ cr ^= gsm->initiator ? 0 : 1; /* Flip so 1 always means command */ + + gsm_print_packet("<--", address, cr, gsm->control, gsm->buf, gsm->len); + +- cr ^= 1 - gsm->initiator; /* Flip so 1 always means command */ + dlci = gsm->dlci[address]; + + switch (gsm->control) { diff --git a/queue-5.16/tty-n_gsm-fix-null-pointer-access-due-to-dlci-release.patch b/queue-5.16/tty-n_gsm-fix-null-pointer-access-due-to-dlci-release.patch new file mode 100644 index 00000000000..020bb5e75b5 --- /dev/null +++ b/queue-5.16/tty-n_gsm-fix-null-pointer-access-due-to-dlci-release.patch @@ -0,0 +1,50 @@ +From 96b169f05cdcc844b400695184d77e42071d14f2 Mon Sep 17 00:00:00 2001 +From: "daniel.starke@siemens.com" +Date: Thu, 17 Feb 2022 23:31:20 -0800 +Subject: tty: n_gsm: fix NULL pointer access due to DLCI release + +From: daniel.starke@siemens.com + +commit 96b169f05cdcc844b400695184d77e42071d14f2 upstream. + +The here fixed commit made the tty hangup asynchronous to avoid a circular +locking warning. I could not reproduce this warning. Furthermore, due to +the asynchronous hangup the function call now gets queued up while the +underlying tty is being freed. Depending on the timing this results in a +NULL pointer access in the global work queue scheduler. To be precise in +process_one_work(). Therefore, the previous commit made the issue worse +which it tried to fix. + +This patch fixes this by falling back to the old behavior which uses a +blocking tty hangup call before freeing up the associated tty. + +Fixes: 7030082a7415 ("tty: n_gsm: avoid recursive locking with async port hangup") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Starke +Link: https://lore.kernel.org/r/20220218073123.2121-4-daniel.starke@siemens.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_gsm.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c +index 53fa1cec49bd..79397a40a8f8 100644 +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -1752,7 +1752,12 @@ static void gsm_dlci_release(struct gsm_dlci *dlci) + gsm_destroy_network(dlci); + mutex_unlock(&dlci->mutex); + +- tty_hangup(tty); ++ /* We cannot use tty_hangup() because in tty_kref_put() the tty ++ * driver assumes that the hangup queue is free and reuses it to ++ * queue release_one_tty() -> NULL pointer panic in ++ * process_one_work(). ++ */ ++ tty_vhangup(tty); + + tty_port_tty_set(&dlci->port, NULL); + tty_kref_put(tty); +-- +2.35.1 + diff --git a/queue-5.16/tty-n_gsm-fix-proper-link-termination-after-failed-open.patch b/queue-5.16/tty-n_gsm-fix-proper-link-termination-after-failed-open.patch new file mode 100644 index 00000000000..7cda743b86f --- /dev/null +++ b/queue-5.16/tty-n_gsm-fix-proper-link-termination-after-failed-open.patch @@ -0,0 +1,38 @@ +From e3b7468f082d106459e86e8dc6fb9bdd65553433 Mon Sep 17 00:00:00 2001 +From: "daniel.starke@siemens.com" +Date: Thu, 17 Feb 2022 23:31:19 -0800 +Subject: tty: n_gsm: fix proper link termination after failed open + +From: daniel.starke@siemens.com + +commit e3b7468f082d106459e86e8dc6fb9bdd65553433 upstream. + +Trying to open a DLCI by sending a SABM frame may fail with a timeout. +The link is closed on the initiator side without informing the responder +about this event. The responder assumes the link is open after sending a +UA frame to answer the SABM frame. The link gets stuck in a half open +state. + +This patch fixes this by initiating the proper link termination procedure +after link setup timeout instead of silently closing it down. + +Fixes: e1eaea46bb40 ("tty: n_gsm line discipline") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Starke +Link: https://lore.kernel.org/r/20220218073123.2121-3-daniel.starke@siemens.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_gsm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -1518,7 +1518,7 @@ static void gsm_dlci_t1(struct timer_lis + dlci->mode = DLCI_MODE_ADM; + gsm_dlci_open(dlci); + } else { +- gsm_dlci_close(dlci); ++ gsm_dlci_begin_close(dlci); /* prevent half open link */ + } + + break; diff --git a/queue-5.16/tty-n_gsm-fix-wrong-modem-processing-in-convergence-layer-type-2.patch b/queue-5.16/tty-n_gsm-fix-wrong-modem-processing-in-convergence-layer-type-2.patch new file mode 100644 index 00000000000..a0c4f8f3514 --- /dev/null +++ b/queue-5.16/tty-n_gsm-fix-wrong-modem-processing-in-convergence-layer-type-2.patch @@ -0,0 +1,115 @@ +From 687f9ad43c52501f46164758e908a5dd181a87fc Mon Sep 17 00:00:00 2001 +From: "daniel.starke@siemens.com" +Date: Thu, 17 Feb 2022 23:31:22 -0800 +Subject: tty: n_gsm: fix wrong modem processing in convergence layer type 2 + +From: daniel.starke@siemens.com + +commit 687f9ad43c52501f46164758e908a5dd181a87fc upstream. + +The function gsm_process_modem() exists to handle modem status bits of +incoming frames. This includes incoming MSC (modem status command) frames +and convergence layer type 2 data frames. The function, however, was only +designed to handle MSC frames as it expects the command length. Within +gsm_dlci_data() it is wrongly assumed that this is the same as the data +frame length. This is only true if the data frame contains only 1 byte of +payload. + +This patch names the length parameter of gsm_process_modem() in a generic +manner to reflect its association. It also corrects all calls to the +function to handle the variable number of modem status octets correctly in +both cases. + +Fixes: 7263287af93d ("tty: n_gsm: Fixed logic to decode break signal from modem status") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Starke +Link: https://lore.kernel.org/r/20220218073123.2121-6-daniel.starke@siemens.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_gsm.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -1021,25 +1021,25 @@ static void gsm_control_reply(struct gsm + * @tty: virtual tty bound to the DLCI + * @dlci: DLCI to affect + * @modem: modem bits (full EA) +- * @clen: command length ++ * @slen: number of signal octets + * + * Used when a modem control message or line state inline in adaption + * layer 2 is processed. Sort out the local modem state and throttles + */ + + static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, +- u32 modem, int clen) ++ u32 modem, int slen) + { + int mlines = 0; + u8 brk = 0; + int fc; + +- /* The modem status command can either contain one octet (v.24 signals) +- or two octets (v.24 signals + break signals). The length field will +- either be 2 or 3 respectively. This is specified in section +- 5.4.6.3.7 of the 27.010 mux spec. */ ++ /* The modem status command can either contain one octet (V.24 signals) ++ * or two octets (V.24 signals + break signals). This is specified in ++ * section 5.4.6.3.7 of the 07.10 mux spec. ++ */ + +- if (clen == 2) ++ if (slen == 1) + modem = modem & 0x7f; + else { + brk = modem & 0x7f; +@@ -1096,6 +1096,7 @@ static void gsm_control_modem(struct gsm + unsigned int brk = 0; + struct gsm_dlci *dlci; + int len = clen; ++ int slen; + const u8 *dp = data; + struct tty_struct *tty; + +@@ -1115,6 +1116,7 @@ static void gsm_control_modem(struct gsm + return; + dlci = gsm->dlci[addr]; + ++ slen = len; + while (gsm_read_ea(&modem, *dp++) == 0) { + len--; + if (len == 0) +@@ -1131,7 +1133,7 @@ static void gsm_control_modem(struct gsm + modem |= (brk & 0x7f); + } + tty = tty_port_tty_get(&dlci->port); +- gsm_process_modem(tty, dlci, modem, clen); ++ gsm_process_modem(tty, dlci, modem, slen); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); +@@ -1597,6 +1599,7 @@ static void gsm_dlci_data(struct gsm_dlc + struct tty_struct *tty; + unsigned int modem = 0; + int len = clen; ++ int slen = 0; + + if (debug & 16) + pr_debug("%d bytes for tty\n", len); +@@ -1609,12 +1612,14 @@ static void gsm_dlci_data(struct gsm_dlc + case 2: /* Asynchronous serial with line state in each frame */ + while (gsm_read_ea(&modem, *data++) == 0) { + len--; ++ slen++; + if (len == 0) + return; + } ++ slen++; + tty = tty_port_tty_get(port); + if (tty) { +- gsm_process_modem(tty, dlci, modem, clen); ++ gsm_process_modem(tty, dlci, modem, slen); + tty_kref_put(tty); + } + fallthrough; diff --git a/queue-5.16/tty-n_gsm-fix-wrong-tty-control-line-for-flow-control.patch b/queue-5.16/tty-n_gsm-fix-wrong-tty-control-line-for-flow-control.patch new file mode 100644 index 00000000000..cce49e8f073 --- /dev/null +++ b/queue-5.16/tty-n_gsm-fix-wrong-tty-control-line-for-flow-control.patch @@ -0,0 +1,51 @@ +From c19d93542a6081577e6da9bf5e887979c72e80c1 Mon Sep 17 00:00:00 2001 +From: "daniel.starke@siemens.com" +Date: Thu, 17 Feb 2022 23:31:21 -0800 +Subject: tty: n_gsm: fix wrong tty control line for flow control + +From: daniel.starke@siemens.com + +commit c19d93542a6081577e6da9bf5e887979c72e80c1 upstream. + +tty flow control is handled via gsmtty_throttle() and gsmtty_unthrottle(). +Both functions propagate the outgoing hardware flow control state to the +remote side via MSC (modem status command) frames. The local state is taken +from the RTS (ready to send) flag of the tty. However, RTS gets mapped to +DTR (data terminal ready), which is wrong. +This patch corrects this by mapping RTS to RTS. + +Fixes: e1eaea46bb40 ("tty: n_gsm line discipline") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Starke +Link: https://lore.kernel.org/r/20220218073123.2121-5-daniel.starke@siemens.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_gsm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -3246,9 +3246,9 @@ static void gsmtty_throttle(struct tty_s + if (dlci->state == DLCI_CLOSED) + return; + if (C_CRTSCTS(tty)) +- dlci->modem_tx &= ~TIOCM_DTR; ++ dlci->modem_tx &= ~TIOCM_RTS; + dlci->throttled = true; +- /* Send an MSC with DTR cleared */ ++ /* Send an MSC with RTS cleared */ + gsmtty_modem_update(dlci, 0); + } + +@@ -3258,9 +3258,9 @@ static void gsmtty_unthrottle(struct tty + if (dlci->state == DLCI_CLOSED) + return; + if (C_CRTSCTS(tty)) +- dlci->modem_tx |= TIOCM_DTR; ++ dlci->modem_tx |= TIOCM_RTS; + dlci->throttled = false; +- /* Send an MSC with DTR set */ ++ /* Send an MSC with RTS set */ + gsmtty_modem_update(dlci, 0); + } +