From 805a1f0c6014a080d812adb6b45f8657291fcfc3 Mon Sep 17 00:00:00 2001 From: miod Date: Sun, 26 Feb 2023 15:09:53 +0000 Subject: [PATCH] Add a few missing bounds checks when processing terminal escape sequences. Without them, the kernel could be made to crash or reboot after receiving some specially crafted terminal escape sequences. Reported by David Leadbeater (dgl, dgl dot cx) --- sys/dev/wscons/wsemul_vt100.c | 17 ++++++---- sys/dev/wscons/wsemul_vt100_subr.c | 54 ++++++++++++++++++------------ 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/sys/dev/wscons/wsemul_vt100.c b/sys/dev/wscons/wsemul_vt100.c index e38cb5435c1..7796bab1700 100644 --- a/sys/dev/wscons/wsemul_vt100.c +++ b/sys/dev/wscons/wsemul_vt100.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wsemul_vt100.c,v 1.42 2023/01/12 20:39:37 nicm Exp $ */ +/* $OpenBSD: wsemul_vt100.c,v 1.43 2023/02/26 15:09:53 miod Exp $ */ /* $NetBSD: wsemul_vt100.c,v 1.13 2000/04/28 21:56:16 mycroft Exp $ */ /* @@ -191,7 +191,7 @@ wsemul_vt100_cnattach(const struct wsscreen_descr *type, void *cookie, int ccol, edp->dblwid = NULL; edp->dw = 0; #endif - edp->dcsarg = 0; + edp->dcsarg = NULL; edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = NULL; edp->nrctab = NULL; wsemul_vt100_reset(edp); @@ -584,12 +584,15 @@ wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp, edp->sschartab = 3; break; case 'M': /* RI */ - if (ROWS_ABOVE > 0) { - edp->crow--; + i = ROWS_ABOVE; + if (i > 0) { + if (edp->crow > 0) + edp->crow--; CHECK_DW; - break; + } else if (i == 0) { + /* Top of scroll region. */ + rc = wsemul_vt100_scrolldown(edp, 1); } - rc = wsemul_vt100_scrolldown(edp, 1); break; case 'P': /* DCS */ edp->nargs = 0; @@ -817,7 +820,7 @@ int wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp, struct wsemul_inputstate *instate) { - if (edp->dcstype && edp->dcspos < DCS_MAXLEN) { + if (edp->dcsarg && edp->dcstype && edp->dcspos < DCS_MAXLEN) { if (instate->inchar & ~0xff) { #ifdef VT100_PRINTUNKNOWN printf("unknown char %x in DCS\n", instate->inchar); diff --git a/sys/dev/wscons/wsemul_vt100_subr.c b/sys/dev/wscons/wsemul_vt100_subr.c index e63d90d73a6..9c04ce36912 100644 --- a/sys/dev/wscons/wsemul_vt100_subr.c +++ b/sys/dev/wscons/wsemul_vt100_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wsemul_vt100_subr.c,v 1.29 2023/01/12 20:39:37 nicm Exp $ */ +/* $OpenBSD: wsemul_vt100_subr.c,v 1.30 2023/02/26 15:09:53 miod Exp $ */ /* $NetBSD: wsemul_vt100_subr.c,v 1.7 2000/04/28 21:56:16 mycroft Exp $ */ /* @@ -457,11 +457,15 @@ wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp, ERASECOLS(edp->ccol, n, edp->bkgdattr)); break; case 'A': /* CUU */ - edp->crow -= min(DEF1_ARG(0), ROWS_ABOVE); + n = ROWS_ABOVE; + if (n > 0) + edp->crow -= min(DEF1_ARG(0), n); CHECK_DW; break; case 'B': /* CUD */ - edp->crow += min(DEF1_ARG(0), ROWS_BELOW); + n = ROWS_BELOW; + if (n > 0) + edp->crow += min(DEF1_ARG(0), n); CHECK_DW; break; case 'C': /* CUF */ @@ -488,21 +492,22 @@ wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp, break; case 'L': /* IL insert line */ case 'M': /* DL delete line */ - { - int savscrstartrow, savscrnrows; - - n = min(DEF1_ARG(0), ROWS_BELOW + 1); - savscrstartrow = edp->scrreg_startrow; - savscrnrows = edp->scrreg_nrows; - edp->scrreg_nrows -= ROWS_ABOVE; - edp->scrreg_startrow = edp->crow; - if (c == 'L') - rc = wsemul_vt100_scrolldown(edp, n); - else - rc = wsemul_vt100_scrollup(edp, n); - edp->scrreg_startrow = savscrstartrow; - edp->scrreg_nrows = savscrnrows; - } + if (edp->crow >= edp->scrreg_startrow && + edp->crow < edp->scrreg_startrow + edp->scrreg_nrows) { + int savscrstartrow, savscrnrows; + + n = min(DEF1_ARG(0), ROWS_BELOW + 1); + savscrstartrow = edp->scrreg_startrow; + savscrnrows = edp->scrreg_nrows; + edp->scrreg_nrows -= ROWS_ABOVE; + edp->scrreg_startrow = edp->crow; + if (c == 'L') + rc = wsemul_vt100_scrolldown(edp, n); + else + rc = wsemul_vt100_scrollup(edp, n); + edp->scrreg_startrow = savscrstartrow; + edp->scrreg_nrows = savscrnrows; + } /* else not within scrolling region, ignore the sequence */ break; case 'P': /* DCH delete character */ n = min(DEF1_ARG(0), COLS_LEFT + 1); @@ -676,9 +681,11 @@ wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp, { char buf[20]; int row; - if (edp->flags & VTFL_DECOM) + if (edp->flags & VTFL_DECOM) { row = ROWS_ABOVE; - else + if (row < 0) + row = 0; + } else row = edp->crow; n = snprintf(buf, sizeof buf, "\033[%d;%dR", row + 1, edp->ccol + 1); @@ -839,13 +846,17 @@ wsemul_vt100_handle_dcs(struct wsemul_vt100_emuldata *edp) if (edp->tabs != NULL) { memset(edp->tabs, 0, edp->ncols); pos = 0; + if (edp->dcsarg == NULL) + goto out; for (i = 0; i < edp->dcspos; i++) { char c = edp->dcsarg[i]; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - pos = pos * 10 + (edp->dcsarg[i] - '0'); + pos = pos * 10 + (c - '0'); + if (pos > edp->ncols) + goto out; break; case '/': if (pos > 0) @@ -869,6 +880,7 @@ wsemul_vt100_handle_dcs(struct wsemul_vt100_emuldata *edp) #endif break; } +out: edp->dcstype = 0; } -- 2.20.1