tty: n_gsm: fix insufficient txframe size
authorDaniel Starke <daniel.starke@siemens.com>
Thu, 14 Apr 2022 09:42:13 +0000 (02:42 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 May 2022 07:14:43 +0000 (09:14 +0200)
commit 535bf600de75a859698892ee873521a48d289ec1 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.7.2 states that the maximum frame size
(N1) refers to the length of the information field (i.e. user payload).
However, 'txframe' stores the whole frame including frame header, checksum
and start/end flags. We also need to consider the byte stuffing overhead.
Define constant for the protocol overhead and adjust the 'txframe' size
calculation accordingly to reserve enough space for a complete mux frame
including byte stuffing for advanced option mode. Note that no byte
stuffing is applied to the start and end flag.
Also use MAX_MTU instead of MAX_MRU as this buffer is used for data
transmission.

Fixes: e1eaea46bb40 ("tty: n_gsm line discipline")
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Starke <daniel.starke@siemens.com>
Link: https://lore.kernel.org/r/20220414094225.4527-8-daniel.starke@siemens.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/n_gsm.c

index 43b403342729f45becb0a45ea488b1890c3823e5..a26eba50d58e379f6e8e1887a2f9a70cbd55c4dc 100644 (file)
@@ -73,6 +73,8 @@ module_param(debug, int, 0600);
  */
 #define MAX_MRU 1500
 #define MAX_MTU 1500
+/* SOF, ADDR, CTRL, LEN1, LEN2, ..., FCS, EOF */
+#define PROT_OVERHEAD 7
 #define        GSM_NET_TX_TIMEOUT (HZ*10)
 
 /*
@@ -2199,7 +2201,7 @@ static struct gsm_mux *gsm_alloc_mux(void)
                kfree(gsm);
                return NULL;
        }
-       gsm->txframe = kmalloc(2 * MAX_MRU + 2, GFP_KERNEL);
+       gsm->txframe = kmalloc(2 * (MAX_MTU + PROT_OVERHEAD - 1), GFP_KERNEL);
        if (gsm->txframe == NULL) {
                kfree(gsm->buf);
                kfree(gsm);