tty: n_gsm: fix wrong command retry handling
authorDaniel Starke <daniel.starke@siemens.com>
Thu, 14 Apr 2022 09:42:16 +0000 (02:42 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 May 2022 07:14:43 +0000 (09:14 +0200)
commit d0bcdffcad5a22f202e3bf37190c0dd8c080ea92 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.3 states that the valid range for the
maximum number of retransmissions (N2) is from 0 to 255 (both including).
gsm_config() fails to limit this range correctly. Furthermore,
gsm_control_retransmit() handles this number incorrectly by performing
N2 - 1 retransmission attempts. Setting N2 to zero results in more than 255
retransmission attempts.
Fix the range check in gsm_config() and the value handling in
gsm_control_send() and gsm_control_retransmit() to comply with 3GPP 27.010.

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-11-daniel.starke@siemens.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/n_gsm.c

index bc7f8810ee9e23a6fa30b37a510390e4aae6d68d..c8f043ad057d86e850d4c03d30c2882b5ce47d2b 100644 (file)
@@ -1329,7 +1329,6 @@ static void gsm_control_retransmit(struct timer_list *t)
        spin_lock_irqsave(&gsm->control_lock, flags);
        ctrl = gsm->pending_cmd;
        if (ctrl) {
-               gsm->cretries--;
                if (gsm->cretries == 0) {
                        gsm->pending_cmd = NULL;
                        ctrl->error = -ETIMEDOUT;
@@ -1338,6 +1337,7 @@ static void gsm_control_retransmit(struct timer_list *t)
                        wake_up(&gsm->event);
                        return;
                }
+               gsm->cretries--;
                gsm_control_transmit(gsm, ctrl);
                mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100);
        }
@@ -1378,7 +1378,7 @@ retry:
 
        /* If DLCI0 is in ADM mode skip retries, it won't respond */
        if (gsm->dlci[0]->mode == DLCI_MODE_ADM)
-               gsm->cretries = 1;
+               gsm->cretries = 0;
        else
                gsm->cretries = gsm->n2;
 
@@ -2278,7 +2278,7 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
        /* Check the MRU/MTU range looks sane */
        if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8)
                return -EINVAL;
-       if (c->n2 < 3)
+       if (c->n2 > 255)
                return -EINVAL;
        if (c->encapsulation > 1)       /* Basic, advanced, no I */
                return -EINVAL;