cherry-pick.FILE5_25-2-gde23336.pr-479-protect-against-0-divide-and-offset-out-of-bounds-reads.patch 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. Subject: PR/479: Protect against 0-divide and offset out of bounds reads
  2. Origin: FILE5_25-2-gde23336
  3. Upstream-Author: Christos Zoulas <christos@zoulas.com>
  4. Date: Wed Sep 16 18:25:23 2015 +0000
  5. --- a/src/softmagic.c
  6. +++ b/src/softmagic.c
  7. @@ -57,10 +57,10 @@
  8. private int mconvert(struct magic_set *, struct magic *, int);
  9. private int print_sep(struct magic_set *, int);
  10. private int handle_annotation(struct magic_set *, struct magic *);
  11. -private void cvt_8(union VALUETYPE *, const struct magic *);
  12. -private void cvt_16(union VALUETYPE *, const struct magic *);
  13. -private void cvt_32(union VALUETYPE *, const struct magic *);
  14. -private void cvt_64(union VALUETYPE *, const struct magic *);
  15. +private int cvt_8(union VALUETYPE *, const struct magic *);
  16. +private int cvt_16(union VALUETYPE *, const struct magic *);
  17. +private int cvt_32(union VALUETYPE *, const struct magic *);
  18. +private int cvt_64(union VALUETYPE *, const struct magic *);
  19. #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o)))
  20. #define BE64(p) (((uint64_t)(p)->hq[0]<<56)|((uint64_t)(p)->hq[1]<<48)| \
  21. @@ -858,37 +858,45 @@
  22. p->fld *= cast m->num_mask; \
  23. break; \
  24. case FILE_OPDIVIDE: \
  25. + if (cast m->num_mask == 0) \
  26. + return -1; \
  27. p->fld /= cast m->num_mask; \
  28. break; \
  29. case FILE_OPMODULO: \
  30. + if (cast m->num_mask == 0) \
  31. + return -1; \
  32. p->fld %= cast m->num_mask; \
  33. break; \
  34. } \
  35. if (m->mask_op & FILE_OPINVERSE) \
  36. p->fld = ~p->fld \
  37. -private void
  38. +private int
  39. cvt_8(union VALUETYPE *p, const struct magic *m)
  40. {
  41. DO_CVT(b, (uint8_t));
  42. + return 0;
  43. }
  44. -private void
  45. +private int
  46. cvt_16(union VALUETYPE *p, const struct magic *m)
  47. {
  48. DO_CVT(h, (uint16_t));
  49. + return 0;
  50. }
  51. -private void
  52. +private int
  53. cvt_32(union VALUETYPE *p, const struct magic *m)
  54. {
  55. DO_CVT(l, (uint32_t));
  56. + return 0;
  57. }
  58. -private void
  59. +private int
  60. cvt_64(union VALUETYPE *p, const struct magic *m)
  61. {
  62. DO_CVT(q, (uint64_t));
  63. + return 0;
  64. }
  65. #define DO_CVT2(fld, cast) \
  66. @@ -904,20 +912,24 @@
  67. p->fld *= cast m->num_mask; \
  68. break; \
  69. case FILE_OPDIVIDE: \
  70. + if (cast m->num_mask == 0) \
  71. + return -1; \
  72. p->fld /= cast m->num_mask; \
  73. break; \
  74. } \
  75. -private void
  76. +private int
  77. cvt_float(union VALUETYPE *p, const struct magic *m)
  78. {
  79. DO_CVT2(f, (float));
  80. + return 0;
  81. }
  82. -private void
  83. +private int
  84. cvt_double(union VALUETYPE *p, const struct magic *m)
  85. {
  86. DO_CVT2(d, (double));
  87. + return 0;
  88. }
  89. /*
  90. @@ -933,21 +945,25 @@
  91. switch (type = cvt_flip(m->type, flip)) {
  92. case FILE_BYTE:
  93. - cvt_8(p, m);
  94. + if (cvt_8(p, m) == -1)
  95. + goto out;
  96. return 1;
  97. case FILE_SHORT:
  98. - cvt_16(p, m);
  99. + if (cvt_16(p, m) == -1)
  100. + goto out;
  101. return 1;
  102. case FILE_LONG:
  103. case FILE_DATE:
  104. case FILE_LDATE:
  105. - cvt_32(p, m);
  106. + if (cvt_32(p, m) == -1)
  107. + goto out;
  108. return 1;
  109. case FILE_QUAD:
  110. case FILE_QDATE:
  111. case FILE_QLDATE:
  112. case FILE_QWDATE:
  113. - cvt_64(p, m);
  114. + if (cvt_64(p, m) == -1)
  115. + goto out;
  116. return 1;
  117. case FILE_STRING:
  118. case FILE_BESTRING16:
  119. @@ -979,65 +995,78 @@
  120. }
  121. case FILE_BESHORT:
  122. p->h = (short)BE16(p);
  123. - cvt_16(p, m);
  124. + if (cvt_16(p, m) == -1)
  125. + goto out;
  126. return 1;
  127. case FILE_BELONG:
  128. case FILE_BEDATE:
  129. case FILE_BELDATE:
  130. p->l = (int32_t)BE32(p);
  131. - cvt_32(p, m);
  132. + if (cvt_32(p, m) == -1)
  133. + goto out;
  134. return 1;
  135. case FILE_BEQUAD:
  136. case FILE_BEQDATE:
  137. case FILE_BEQLDATE:
  138. case FILE_BEQWDATE:
  139. p->q = (uint64_t)BE64(p);
  140. - cvt_64(p, m);
  141. + if (cvt_64(p, m) == -1)
  142. + goto out;
  143. return 1;
  144. case FILE_LESHORT:
  145. p->h = (short)LE16(p);
  146. - cvt_16(p, m);
  147. + if (cvt_16(p, m) == -1)
  148. + goto out;
  149. return 1;
  150. case FILE_LELONG:
  151. case FILE_LEDATE:
  152. case FILE_LELDATE:
  153. p->l = (int32_t)LE32(p);
  154. - cvt_32(p, m);
  155. + if (cvt_32(p, m) == -1)
  156. + goto out;
  157. return 1;
  158. case FILE_LEQUAD:
  159. case FILE_LEQDATE:
  160. case FILE_LEQLDATE:
  161. case FILE_LEQWDATE:
  162. p->q = (uint64_t)LE64(p);
  163. - cvt_64(p, m);
  164. + if (cvt_64(p, m) == -1)
  165. + goto out;
  166. return 1;
  167. case FILE_MELONG:
  168. case FILE_MEDATE:
  169. case FILE_MELDATE:
  170. p->l = (int32_t)ME32(p);
  171. - cvt_32(p, m);
  172. + if (cvt_32(p, m) == -1)
  173. + goto out;
  174. return 1;
  175. case FILE_FLOAT:
  176. - cvt_float(p, m);
  177. + if (cvt_float(p, m) == -1)
  178. + goto out;
  179. return 1;
  180. case FILE_BEFLOAT:
  181. p->l = BE32(p);
  182. - cvt_float(p, m);
  183. + if (cvt_float(p, m) == -1)
  184. + goto out;
  185. return 1;
  186. case FILE_LEFLOAT:
  187. p->l = LE32(p);
  188. - cvt_float(p, m);
  189. + if (cvt_float(p, m) == -1)
  190. + goto out;
  191. return 1;
  192. case FILE_DOUBLE:
  193. - cvt_double(p, m);
  194. + if (cvt_double(p, m) == -1)
  195. + goto out;
  196. return 1;
  197. case FILE_BEDOUBLE:
  198. p->q = BE64(p);
  199. - cvt_double(p, m);
  200. + if (cvt_double(p, m) == -1)
  201. + goto out;
  202. return 1;
  203. case FILE_LEDOUBLE:
  204. p->q = LE64(p);
  205. - cvt_double(p, m);
  206. + if (cvt_double(p, m) == -1)
  207. + goto out;
  208. return 1;
  209. case FILE_REGEX:
  210. case FILE_SEARCH:
  211. @@ -1050,6 +1079,9 @@
  212. file_magerror(ms, "invalid type %d in mconvert()", m->type);
  213. return 0;
  214. }
  215. +out:
  216. + file_magerror(ms, "zerodivide in mconvert()");
  217. + return 0;
  218. }
  219. @@ -1066,6 +1098,12 @@
  220. mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
  221. const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
  222. {
  223. + if (offset >= nbytes) {
  224. + file_magerror(ms,
  225. + "offset in magic %u greater than buffer size %zu",
  226. + offset, nbytes);
  227. + return -1;
  228. + }
  229. /*
  230. * Note: FILE_SEARCH and FILE_REGEX do not actually copy
  231. * anything, but setup pointers into the source
  232. @@ -1230,6 +1268,8 @@
  233. if (m->in_op & FILE_OPINDIRECT) {
  234. const union VALUETYPE *q = CAST(const union VALUETYPE *,
  235. ((const void *)(s + offset + off)));
  236. + if (OFFSET_OOB(offset + off, nbytes, sizeof(*q)))
  237. + return 0;
  238. switch (cvt_flip(m->in_type, flip)) {
  239. case FILE_BYTE:
  240. off = q->b;