1*4882a593SmuzhiyunFrom a7ab0cc98fa89a3d5098c29cbe44bcd24b0a6454 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Peter Jones <pjones@redhat.com> 3*4882a593SmuzhiyunDate: Wed, 15 Apr 2020 15:45:02 -0400 4*4882a593SmuzhiyunSubject: [PATCH] yylex: Make lexer fatal errors actually be fatal 5*4882a593SmuzhiyunMIME-Version: 1.0 6*4882a593SmuzhiyunContent-Type: text/plain; charset=UTF-8 7*4882a593SmuzhiyunContent-Transfer-Encoding: 8bit 8*4882a593Smuzhiyun 9*4882a593SmuzhiyunWhen presented with a command that can't be tokenized to anything 10*4882a593Smuzhiyunsmaller than YYLMAX characters, the parser calls YY_FATAL_ERROR(errmsg), 11*4882a593Smuzhiyunexpecting that will stop further processing, as such: 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun #define YY_DO_BEFORE_ACTION \ 14*4882a593Smuzhiyun yyg->yytext_ptr = yy_bp; \ 15*4882a593Smuzhiyun yyleng = (int) (yy_cp - yy_bp); \ 16*4882a593Smuzhiyun yyg->yy_hold_char = *yy_cp; \ 17*4882a593Smuzhiyun *yy_cp = '\0'; \ 18*4882a593Smuzhiyun if ( yyleng >= YYLMAX ) \ 19*4882a593Smuzhiyun YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \ 20*4882a593Smuzhiyun yy_flex_strncpy( yytext, yyg->yytext_ptr, yyleng + 1 , yyscanner); \ 21*4882a593Smuzhiyun yyg->yy_c_buf_p = yy_cp; 22*4882a593Smuzhiyun 23*4882a593SmuzhiyunThe code flex generates expects that YY_FATAL_ERROR() will either return 24*4882a593Smuzhiyunfor it or do some form of longjmp(), or handle the error in some way at 25*4882a593Smuzhiyunleast, and so the strncpy() call isn't in an "else" clause, and thus if 26*4882a593SmuzhiyunYY_FATAL_ERROR() is *not* actually fatal, it does the call with the 27*4882a593Smuzhiyunquestionable limit, and predictable results ensue. 28*4882a593Smuzhiyun 29*4882a593SmuzhiyunUnfortunately, our implementation of YY_FATAL_ERROR() is: 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun #define YY_FATAL_ERROR(msg) \ 32*4882a593Smuzhiyun do { \ 33*4882a593Smuzhiyun grub_printf (_("fatal error: %s\n"), _(msg)); \ 34*4882a593Smuzhiyun } while (0) 35*4882a593Smuzhiyun 36*4882a593SmuzhiyunThe same pattern exists in yyless(), and similar problems exist in users 37*4882a593Smuzhiyunof YY_INPUT(), several places in the main parsing loop, 38*4882a593Smuzhiyunyy_get_next_buffer(), yy_load_buffer_state(), yyensure_buffer_stack, 39*4882a593Smuzhiyunyy_scan_buffer(), etc. 40*4882a593Smuzhiyun 41*4882a593SmuzhiyunAll of these callers expect YY_FATAL_ERROR() to actually be fatal, and 42*4882a593Smuzhiyunthe things they do if it returns after calling it are wildly unsafe. 43*4882a593Smuzhiyun 44*4882a593SmuzhiyunFixes: CVE-2020-10713 45*4882a593Smuzhiyun 46*4882a593SmuzhiyunSigned-off-by: Peter Jones <pjones@redhat.com> 47*4882a593SmuzhiyunReviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 48*4882a593SmuzhiyunSigned-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> 49*4882a593Smuzhiyun--- 50*4882a593Smuzhiyun grub-core/script/yylex.l | 4 ++-- 51*4882a593Smuzhiyun 1 file changed, 2 insertions(+), 2 deletions(-) 52*4882a593Smuzhiyun 53*4882a593Smuzhiyundiff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l 54*4882a593Smuzhiyunindex 7b44c37b7..b7203c823 100644 55*4882a593Smuzhiyun--- a/grub-core/script/yylex.l 56*4882a593Smuzhiyun+++ b/grub-core/script/yylex.l 57*4882a593Smuzhiyun@@ -37,11 +37,11 @@ 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun /* 60*4882a593Smuzhiyun * As we don't have access to yyscanner, we cannot do much except to 61*4882a593Smuzhiyun- * print the fatal error. 62*4882a593Smuzhiyun+ * print the fatal error and exit. 63*4882a593Smuzhiyun */ 64*4882a593Smuzhiyun #define YY_FATAL_ERROR(msg) \ 65*4882a593Smuzhiyun do { \ 66*4882a593Smuzhiyun- grub_printf (_("fatal error: %s\n"), _(msg)); \ 67*4882a593Smuzhiyun+ grub_fatal (_("fatal error: %s\n"), _(msg));\ 68*4882a593Smuzhiyun } while (0) 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun #define COPY(str, hint) \ 71*4882a593Smuzhiyun-- 72*4882a593Smuzhiyun2.26.2 73*4882a593Smuzhiyun 74