Skip to content

Commit f6d199c

Browse files
committed
Merge tag 'tty-6.10-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial fixes from Greg KH: "Here are some small TTY and Serial driver fixes that missed the 6.9-final merge window, but have been in my tree for weeks (my fault, travel caused me to miss this) These fixes include: - more n_gsm fixes for reported problems - 8520_mtk driver fix - 8250_bcm7271 driver fix - sc16is7xx driver fix All of these have been in linux-next for weeks without any reported problems" * tag 'tty-6.10-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler serial: 8250_bcm7271: use default_mux_rate if possible serial: 8520_mtk: Set RTS on shutdown for Rx in-band wakeup tty: n_gsm: fix missing receive state reset after mode switch tty: n_gsm: fix possible out-of-bounds in gsm0_receive()
2 parents b0a9ba1 + 8492bd9 commit f6d199c

File tree

4 files changed

+181
-91
lines changed

4 files changed

+181
-91
lines changed

drivers/tty/n_gsm.c

Lines changed: 97 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -245,16 +245,18 @@ enum gsm_encoding {
245245

246246
enum gsm_mux_state {
247247
GSM_SEARCH,
248-
GSM_START,
249-
GSM_ADDRESS,
250-
GSM_CONTROL,
251-
GSM_LEN,
252-
GSM_DATA,
253-
GSM_FCS,
254-
GSM_OVERRUN,
255-
GSM_LEN0,
256-
GSM_LEN1,
257-
GSM_SSOF,
248+
GSM0_ADDRESS,
249+
GSM0_CONTROL,
250+
GSM0_LEN0,
251+
GSM0_LEN1,
252+
GSM0_DATA,
253+
GSM0_FCS,
254+
GSM0_SSOF,
255+
GSM1_START,
256+
GSM1_ADDRESS,
257+
GSM1_CONTROL,
258+
GSM1_DATA,
259+
GSM1_OVERRUN,
258260
};
259261

260262
/*
@@ -2847,6 +2849,30 @@ static void gsm_queue(struct gsm_mux *gsm)
28472849
return;
28482850
}
28492851

2852+
/**
2853+
* gsm0_receive_state_check_and_fix - check and correct receive state
2854+
* @gsm: gsm data for this ldisc instance
2855+
*
2856+
* Ensures that the current receive state is valid for basic option mode.
2857+
*/
2858+
2859+
static void gsm0_receive_state_check_and_fix(struct gsm_mux *gsm)
2860+
{
2861+
switch (gsm->state) {
2862+
case GSM_SEARCH:
2863+
case GSM0_ADDRESS:
2864+
case GSM0_CONTROL:
2865+
case GSM0_LEN0:
2866+
case GSM0_LEN1:
2867+
case GSM0_DATA:
2868+
case GSM0_FCS:
2869+
case GSM0_SSOF:
2870+
break;
2871+
default:
2872+
gsm->state = GSM_SEARCH;
2873+
break;
2874+
}
2875+
}
28502876

28512877
/**
28522878
* gsm0_receive - perform processing for non-transparency
@@ -2860,26 +2886,27 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
28602886
{
28612887
unsigned int len;
28622888

2889+
gsm0_receive_state_check_and_fix(gsm);
28632890
switch (gsm->state) {
28642891
case GSM_SEARCH: /* SOF marker */
28652892
if (c == GSM0_SOF) {
2866-
gsm->state = GSM_ADDRESS;
2893+
gsm->state = GSM0_ADDRESS;
28672894
gsm->address = 0;
28682895
gsm->len = 0;
28692896
gsm->fcs = INIT_FCS;
28702897
}
28712898
break;
2872-
case GSM_ADDRESS: /* Address EA */
2899+
case GSM0_ADDRESS: /* Address EA */
28732900
gsm->fcs = gsm_fcs_add(gsm->fcs, c);
28742901
if (gsm_read_ea(&gsm->address, c))
2875-
gsm->state = GSM_CONTROL;
2902+
gsm->state = GSM0_CONTROL;
28762903
break;
2877-
case GSM_CONTROL: /* Control Byte */
2904+
case GSM0_CONTROL: /* Control Byte */
28782905
gsm->fcs = gsm_fcs_add(gsm->fcs, c);
28792906
gsm->control = c;
2880-
gsm->state = GSM_LEN0;
2907+
gsm->state = GSM0_LEN0;
28812908
break;
2882-
case GSM_LEN0: /* Length EA */
2909+
case GSM0_LEN0: /* Length EA */
28832910
gsm->fcs = gsm_fcs_add(gsm->fcs, c);
28842911
if (gsm_read_ea(&gsm->len, c)) {
28852912
if (gsm->len > gsm->mru) {
@@ -2889,14 +2916,14 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
28892916
}
28902917
gsm->count = 0;
28912918
if (!gsm->len)
2892-
gsm->state = GSM_FCS;
2919+
gsm->state = GSM0_FCS;
28932920
else
2894-
gsm->state = GSM_DATA;
2921+
gsm->state = GSM0_DATA;
28952922
break;
28962923
}
2897-
gsm->state = GSM_LEN1;
2924+
gsm->state = GSM0_LEN1;
28982925
break;
2899-
case GSM_LEN1:
2926+
case GSM0_LEN1:
29002927
gsm->fcs = gsm_fcs_add(gsm->fcs, c);
29012928
len = c;
29022929
gsm->len |= len << 7;
@@ -2907,26 +2934,29 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
29072934
}
29082935
gsm->count = 0;
29092936
if (!gsm->len)
2910-
gsm->state = GSM_FCS;
2937+
gsm->state = GSM0_FCS;
29112938
else
2912-
gsm->state = GSM_DATA;
2939+
gsm->state = GSM0_DATA;
29132940
break;
2914-
case GSM_DATA: /* Data */
2941+
case GSM0_DATA: /* Data */
29152942
gsm->buf[gsm->count++] = c;
2916-
if (gsm->count == gsm->len) {
2943+
if (gsm->count >= MAX_MRU) {
2944+
gsm->bad_size++;
2945+
gsm->state = GSM_SEARCH;
2946+
} else if (gsm->count >= gsm->len) {
29172947
/* Calculate final FCS for UI frames over all data */
29182948
if ((gsm->control & ~PF) != UIH) {
29192949
gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf,
29202950
gsm->count);
29212951
}
2922-
gsm->state = GSM_FCS;
2952+
gsm->state = GSM0_FCS;
29232953
}
29242954
break;
2925-
case GSM_FCS: /* FCS follows the packet */
2955+
case GSM0_FCS: /* FCS follows the packet */
29262956
gsm->fcs = gsm_fcs_add(gsm->fcs, c);
2927-
gsm->state = GSM_SSOF;
2957+
gsm->state = GSM0_SSOF;
29282958
break;
2929-
case GSM_SSOF:
2959+
case GSM0_SSOF:
29302960
gsm->state = GSM_SEARCH;
29312961
if (c == GSM0_SOF)
29322962
gsm_queue(gsm);
@@ -2939,6 +2969,29 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
29392969
}
29402970
}
29412971

2972+
/**
2973+
* gsm1_receive_state_check_and_fix - check and correct receive state
2974+
* @gsm: gsm data for this ldisc instance
2975+
*
2976+
* Ensures that the current receive state is valid for advanced option mode.
2977+
*/
2978+
2979+
static void gsm1_receive_state_check_and_fix(struct gsm_mux *gsm)
2980+
{
2981+
switch (gsm->state) {
2982+
case GSM_SEARCH:
2983+
case GSM1_START:
2984+
case GSM1_ADDRESS:
2985+
case GSM1_CONTROL:
2986+
case GSM1_DATA:
2987+
case GSM1_OVERRUN:
2988+
break;
2989+
default:
2990+
gsm->state = GSM_SEARCH;
2991+
break;
2992+
}
2993+
}
2994+
29422995
/**
29432996
* gsm1_receive - perform processing for non-transparency
29442997
* @gsm: gsm data for this ldisc instance
@@ -2949,6 +3002,7 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
29493002

29503003
static void gsm1_receive(struct gsm_mux *gsm, u8 c)
29513004
{
3005+
gsm1_receive_state_check_and_fix(gsm);
29523006
/* handle XON/XOFF */
29533007
if ((c & ISO_IEC_646_MASK) == XON) {
29543008
gsm->constipated = true;
@@ -2961,11 +3015,11 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c)
29613015
}
29623016
if (c == GSM1_SOF) {
29633017
/* EOF is only valid in frame if we have got to the data state */
2964-
if (gsm->state == GSM_DATA) {
3018+
if (gsm->state == GSM1_DATA) {
29653019
if (gsm->count < 1) {
29663020
/* Missing FSC */
29673021
gsm->malformed++;
2968-
gsm->state = GSM_START;
3022+
gsm->state = GSM1_START;
29693023
return;
29703024
}
29713025
/* Remove the FCS from data */
@@ -2981,14 +3035,14 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c)
29813035
gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->buf[gsm->count]);
29823036
gsm->len = gsm->count;
29833037
gsm_queue(gsm);
2984-
gsm->state = GSM_START;
3038+
gsm->state = GSM1_START;
29853039
return;
29863040
}
29873041
/* Any partial frame was a runt so go back to start */
2988-
if (gsm->state != GSM_START) {
3042+
if (gsm->state != GSM1_START) {
29893043
if (gsm->state != GSM_SEARCH)
29903044
gsm->malformed++;
2991-
gsm->state = GSM_START;
3045+
gsm->state = GSM1_START;
29923046
}
29933047
/* A SOF in GSM_START means we are still reading idling or
29943048
framing bytes */
@@ -3009,30 +3063,30 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c)
30093063
gsm->escape = false;
30103064
}
30113065
switch (gsm->state) {
3012-
case GSM_START: /* First byte after SOF */
3066+
case GSM1_START: /* First byte after SOF */
30133067
gsm->address = 0;
3014-
gsm->state = GSM_ADDRESS;
3068+
gsm->state = GSM1_ADDRESS;
30153069
gsm->fcs = INIT_FCS;
30163070
fallthrough;
3017-
case GSM_ADDRESS: /* Address continuation */
3071+
case GSM1_ADDRESS: /* Address continuation */
30183072
gsm->fcs = gsm_fcs_add(gsm->fcs, c);
30193073
if (gsm_read_ea(&gsm->address, c))
3020-
gsm->state = GSM_CONTROL;
3074+
gsm->state = GSM1_CONTROL;
30213075
break;
3022-
case GSM_CONTROL: /* Control Byte */
3076+
case GSM1_CONTROL: /* Control Byte */
30233077
gsm->fcs = gsm_fcs_add(gsm->fcs, c);
30243078
gsm->control = c;
30253079
gsm->count = 0;
3026-
gsm->state = GSM_DATA;
3080+
gsm->state = GSM1_DATA;
30273081
break;
3028-
case GSM_DATA: /* Data */
3029-
if (gsm->count > gsm->mru) { /* Allow one for the FCS */
3030-
gsm->state = GSM_OVERRUN;
3082+
case GSM1_DATA: /* Data */
3083+
if (gsm->count > gsm->mru || gsm->count > MAX_MRU) { /* Allow one for the FCS */
3084+
gsm->state = GSM1_OVERRUN;
30313085
gsm->bad_size++;
30323086
} else
30333087
gsm->buf[gsm->count++] = c;
30343088
break;
3035-
case GSM_OVERRUN: /* Over-long - eg a dropped SOF */
3089+
case GSM1_OVERRUN: /* Over-long - eg a dropped SOF */
30363090
break;
30373091
default:
30383092
pr_debug("%s: unhandled state: %d\n", __func__, gsm->state);

0 commit comments

Comments
 (0)