1*4882a593SmuzhiyunFrom 4e76b08f7171a8603d74fcafb27409a91f578647 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Daniel Axtens <dja@axtens.net> 3*4882a593SmuzhiyunDate: Thu, 21 Jan 2021 12:20:49 +1100 4*4882a593SmuzhiyunSubject: [PATCH] io/gzio: Catch missing values in huft_build() and bail 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunIn huft_build(), "v" is a table of values in order of bit length. 7*4882a593SmuzhiyunThe code later (when setting up table entries in "r") assumes that all 8*4882a593Smuzhiyunelements of this array corresponding to a code are initialized and less 9*4882a593Smuzhiyunthan N_MAX. However, it doesn't enforce this. 10*4882a593Smuzhiyun 11*4882a593SmuzhiyunWith sufficiently manipulated inputs (e.g. from fuzzing), there can be 12*4882a593Smuzhiyunelements of "v" that are not filled. Therefore a lookup into "e" or "d" 13*4882a593Smuzhiyunwill use an uninitialized value. This can lead to an invalid/OOB read on 14*4882a593Smuzhiyunthose values, often leading to a crash. 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunSigned-off-by: Daniel Axtens <dja@axtens.net> 17*4882a593SmuzhiyunReviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 18*4882a593SmuzhiyunSigned-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> 19*4882a593Smuzhiyun--- 20*4882a593Smuzhiyun grub-core/io/gzio.c | 10 +++++++++- 21*4882a593Smuzhiyun 1 file changed, 9 insertions(+), 1 deletion(-) 22*4882a593Smuzhiyun 23*4882a593Smuzhiyundiff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c 24*4882a593Smuzhiyunindex 4236f0f..19adebe 100644 25*4882a593Smuzhiyun--- a/grub-core/io/gzio.c 26*4882a593Smuzhiyun+++ b/grub-core/io/gzio.c 27*4882a593Smuzhiyun@@ -507,6 +507,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ 28*4882a593Smuzhiyun } 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun /* Make a table of values in order of bit lengths */ 31*4882a593Smuzhiyun+ grub_memset (v, N_MAX, ARRAY_SIZE (v)); 32*4882a593Smuzhiyun p = b; 33*4882a593Smuzhiyun i = 0; 34*4882a593Smuzhiyun do 35*4882a593Smuzhiyun@@ -588,11 +589,18 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ 36*4882a593Smuzhiyun r.v.n = (ush) (*p); /* simple code is just the value */ 37*4882a593Smuzhiyun p++; /* one compiler does not like *p++ */ 38*4882a593Smuzhiyun } 39*4882a593Smuzhiyun- else 40*4882a593Smuzhiyun+ else if (*p < N_MAX) 41*4882a593Smuzhiyun { 42*4882a593Smuzhiyun r.e = (uch) e[*p - s]; /* non-simple--look up in lists */ 43*4882a593Smuzhiyun r.v.n = d[*p++ - s]; 44*4882a593Smuzhiyun } 45*4882a593Smuzhiyun+ else 46*4882a593Smuzhiyun+ { 47*4882a593Smuzhiyun+ /* Detected an uninitialised value, abort. */ 48*4882a593Smuzhiyun+ if (h) 49*4882a593Smuzhiyun+ huft_free (u[0]); 50*4882a593Smuzhiyun+ return 2; 51*4882a593Smuzhiyun+ } 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun /* fill code-like entries with r */ 54*4882a593Smuzhiyun f = 1 << (k - w); 55*4882a593Smuzhiyun-- 56*4882a593Smuzhiyun2.14.2 57*4882a593Smuzhiyun 58