logo

oasis

Own branch of Oasis Linux (upstream: <https://git.sr.ht/~mcf/oasis/>) git clone https://anongit.hacktivis.me/git/oasis.git

0011-Fix-CVE-2014-8141-out-of-bounds-read-issues-in-getZi.patch (5485B)


  1. From 0bec3de89a03c7c998b755ff6091ab1e0f6c43b7 Mon Sep 17 00:00:00 2001
  2. From: "Steven M. Schweda" <sms@antinode.info>
  3. Date: Sat, 15 Jun 2019 18:13:11 -0700
  4. Subject: [PATCH] Fix CVE-2014-8141: out-of-bounds read issues in
  5. getZip64Data()
  6. ---
  7. fileio.c | 9 +++++++-
  8. process.c | 68 +++++++++++++++++++++++++++++++++++++++++--------------
  9. 2 files changed, 59 insertions(+), 18 deletions(-)
  10. diff --git a/fileio.c b/fileio.c
  11. index ba0a1d0..36bfea3 100644
  12. --- a/fileio.c
  13. +++ b/fileio.c
  14. @@ -176,6 +176,8 @@ static ZCONST char Far FilenameTooLongTrunc[] =
  15. #endif
  16. static ZCONST char Far ExtraFieldTooLong[] =
  17. "warning: extra field too long (%d). Ignoring...\n";
  18. +static ZCONST char Far ExtraFieldCorrupt[] =
  19. + "warning: extra field (type: 0x%04x) corrupt. Continuing...\n";
  20. #ifdef WINDLL
  21. static ZCONST char Far DiskFullQuery[] =
  22. @@ -2295,7 +2297,12 @@ int do_string(__G__ length, option) /* return PK-type error code */
  23. if (readbuf(__G__ (char *)G.extra_field, length) == 0)
  24. return PK_EOF;
  25. /* Looks like here is where extra fields are read */
  26. - getZip64Data(__G__ G.extra_field, length);
  27. + if (getZip64Data(__G__ G.extra_field, length) != PK_COOL)
  28. + {
  29. + Info(slide, 0x401, ((char *)slide,
  30. + LoadFarString( ExtraFieldCorrupt), EF_PKSZ64));
  31. + error = PK_WARN;
  32. + }
  33. #ifdef UNICODE_SUPPORT
  34. G.unipath_filename = NULL;
  35. if (G.UzO.U_flag < 2) {
  36. diff --git a/process.c b/process.c
  37. index 3228bde..df683ea 100644
  38. --- a/process.c
  39. +++ b/process.c
  40. @@ -1,5 +1,5 @@
  41. /*
  42. - Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
  43. + Copyright (c) 1990-2014 Info-ZIP. All rights reserved.
  44. See the accompanying file LICENSE, version 2009-Jan-02 or later
  45. (the contents of which are also included in unzip.h) for terms of use.
  46. @@ -1901,48 +1901,82 @@ int getZip64Data(__G__ ef_buf, ef_len)
  47. and a 4-byte version of disk start number.
  48. Sets both local header and central header fields. Not terribly clever,
  49. but it means that this procedure is only called in one place.
  50. +
  51. + 2014-12-05 SMS.
  52. + Added checks to ensure that enough data are available before calling
  53. + makeint64() or makelong(). Replaced various sizeof() values with
  54. + simple ("4" or "8") constants. (The Zip64 structures do not depend
  55. + on our variable sizes.) Error handling is crude, but we should now
  56. + stay within the buffer.
  57. ---------------------------------------------------------------------------*/
  58. +#define Z64FLGS 0xffff
  59. +#define Z64FLGL 0xffffffff
  60. +
  61. if (ef_len == 0 || ef_buf == NULL)
  62. return PK_COOL;
  63. Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n",
  64. ef_len));
  65. - while (ef_len >= EB_HEADSIZE) {
  66. + while (ef_len >= EB_HEADSIZE)
  67. + {
  68. eb_id = makeword(EB_ID + ef_buf);
  69. eb_len = makeword(EB_LEN + ef_buf);
  70. - if (eb_len > (ef_len - EB_HEADSIZE)) {
  71. - /* discovered some extra field inconsistency! */
  72. + if (eb_len > (ef_len - EB_HEADSIZE))
  73. + {
  74. + /* Extra block length exceeds remaining extra field length. */
  75. Trace((stderr,
  76. "getZip64Data: block length %u > rest ef_size %u\n", eb_len,
  77. ef_len - EB_HEADSIZE));
  78. break;
  79. }
  80. - if (eb_id == EF_PKSZ64) {
  81. -
  82. + if (eb_id == EF_PKSZ64)
  83. + {
  84. int offset = EB_HEADSIZE;
  85. - if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){
  86. - G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf);
  87. - offset += sizeof(G.crec.ucsize);
  88. + if ((G.crec.ucsize == Z64FLGL) || (G.lrec.ucsize == Z64FLGL))
  89. + {
  90. + if (offset+ 8 > ef_len)
  91. + return PK_ERR;
  92. +
  93. + G.crec.ucsize = G.lrec.ucsize = makeint64(offset + ef_buf);
  94. + offset += 8;
  95. }
  96. - if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){
  97. - G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf);
  98. - offset += sizeof(G.crec.csize);
  99. +
  100. + if ((G.crec.csize == Z64FLGL) || (G.lrec.csize == Z64FLGL))
  101. + {
  102. + if (offset+ 8 > ef_len)
  103. + return PK_ERR;
  104. +
  105. + G.csize = G.crec.csize = G.lrec.csize = makeint64(offset + ef_buf);
  106. + offset += 8;
  107. }
  108. - if (G.crec.relative_offset_local_header == 0xffffffff){
  109. +
  110. + if (G.crec.relative_offset_local_header == Z64FLGL)
  111. + {
  112. + if (offset+ 8 > ef_len)
  113. + return PK_ERR;
  114. +
  115. G.crec.relative_offset_local_header = makeint64(offset + ef_buf);
  116. - offset += sizeof(G.crec.relative_offset_local_header);
  117. + offset += 8;
  118. }
  119. - if (G.crec.disk_number_start == 0xffff){
  120. +
  121. + if (G.crec.disk_number_start == Z64FLGS)
  122. + {
  123. + if (offset+ 4 > ef_len)
  124. + return PK_ERR;
  125. +
  126. G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf);
  127. - offset += sizeof(G.crec.disk_number_start);
  128. + offset += 4;
  129. }
  130. +#if 0
  131. + break; /* Expect only one EF_PKSZ64 block. */
  132. +#endif /* 0 */
  133. }
  134. - /* Skip this extra field block */
  135. + /* Skip this extra field block. */
  136. ef_buf += (eb_len + EB_HEADSIZE);
  137. ef_len -= (eb_len + EB_HEADSIZE);
  138. }
  139. --
  140. 2.20.1