CVE-2014-3478.patch 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. Subject: Buffer overflow in the mconvert function allows remote attackers to cause a denial of service
  2. ID: CVE-2014-3478
  3. Author: Christos Zoulas <christos@zoulas.com>
  4. Date:
  5. Wed Jun 4 17:36:34 2014 +0000 (A)
  6. Wed Dec 22 18:14:05 2010 +0000 (B)
  7. Wed Dec 22 19:09:10 2010 +0000 (C)
  8. Origin:
  9. commit 27a14bc7ba285a0a5ebfdb55e54001aa11932b08 (A)
  10. commit 2f0eeb07ba633f1d915f78a50b22808123b38ea0 (B)
  11. commit 57e4574e062e538b16b225e822ece6ca0ce539b8 (C)
  12. Debian-Author: Holger Levsen <holger@debian.org>
  13. Comment:
  14. made apply cleanly based on the [above] commits
  15. Reviewed-By: Christoph Biedl <debian.axhn@manchmal.in-ulm.de>
  16. Last-Update: 2014-09-07
  17. [ A: ]
  18. Correctly compute the truncated pascal string size (Francisco Alonso and
  19. Jan Kaluza at RedHat)
  20. [ B: ]
  21. support for various formats of pascal strings.
  22. [ C: ]
  23. don't undo our initialization
  24. --- a/src/softmagic.c
  25. +++ b/src/softmagic.c
  26. @@ -169,6 +169,8 @@
  27. continue;
  28. }
  29. + if ((e = handle_annotation(ms, m)) != 0)
  30. + return e;
  31. /*
  32. * If we are going to print something, we'll need to print
  33. * a blank before we print something else.
  34. @@ -176,8 +178,6 @@
  35. if (*m->desc) {
  36. need_separator = 1;
  37. printed_something = 1;
  38. - if ((e = handle_annotation(ms, m)) != 0)
  39. - return e;
  40. if (print_sep(ms, firstline) == -1)
  41. return -1;
  42. }
  43. @@ -252,13 +252,13 @@
  44. ms->c.li[cont_level].got_match = 0;
  45. break;
  46. }
  47. + if ((e = handle_annotation(ms, m)) != 0)
  48. + return e;
  49. /*
  50. * If we are going to print something,
  51. * make sure that we have a separator first.
  52. */
  53. if (*m->desc) {
  54. - if ((e = handle_annotation(ms, m)) != 0)
  55. - return e;
  56. if (!printed_something) {
  57. printed_something = 1;
  58. if (print_sep(ms, firstline)
  59. @@ -450,7 +450,7 @@
  60. return -1;
  61. t = ms->offset + strlen(p->s);
  62. if (m->type == FILE_PSTRING)
  63. - t++;
  64. + t += file_pstring_length_size(m);
  65. }
  66. break;
  67. @@ -615,7 +615,7 @@
  68. p->s[strcspn(p->s, "\n")] = '\0';
  69. t = CAST(uint32_t, (ms->offset + strlen(p->s)));
  70. if (m->type == FILE_PSTRING)
  71. - t++;
  72. + t += file_pstring_length_size(m);
  73. return t;
  74. }
  75. @@ -800,10 +800,18 @@
  76. return 1;
  77. }
  78. case FILE_PSTRING: {
  79. - char *ptr1 = p->s, *ptr2 = ptr1 + 1;
  80. - size_t len = *p->s;
  81. - if (len >= sizeof(p->s))
  82. - len = sizeof(p->s) - 1;
  83. + size_t sz = file_pstring_length_size(m);
  84. + char *ptr1 = p->s, *ptr2 = ptr1 + sz;
  85. + size_t len = file_pstring_get_length(m, ptr1);
  86. + if (len >= sizeof(p->s)) {
  87. + /*
  88. + * The size of the pascal string length (sz)
  89. + * is 1, 2, or 4. We need at least 1 byte for NUL
  90. + * termination, but we've already truncated the
  91. + * string by p->s, so we need to deduct sz.
  92. + */
  93. + len = sizeof(p->s) - sz;
  94. + }
  95. while (len--)
  96. *ptr1++ = *ptr2++;
  97. *ptr1 = '\0';
  98. --- a/doc/magic.man
  99. +++ b/doc/magic.man
  100. @@ -71,8 +71,22 @@
  101. target, whereas upper case characters in the magic only match uppercase
  102. characters in the target.
  103. .It Dv pstring
  104. -A Pascal-style string where the first byte is interpreted as the an
  105. +A Pascal-style string where the first byte/short/int is interpreted as the an
  106. unsigned length.
  107. +The length defaults to byte and can be specified as a modifier.
  108. +The following modifiers are supported:
  109. +.Bl -tag -compact -width B
  110. +.It B
  111. +A byte length (default).
  112. +.It H
  113. +A 2 byte big endian length.
  114. +.It h
  115. +A 2 byte big little length.
  116. +.It L
  117. +A 4 byte big endian length.
  118. +.It l
  119. +A 4 byte big little length.
  120. +.El
  121. The string is not NUL terminated.
  122. .It Dv date
  123. A four-byte value interpreted as a UNIX date.
  124. --- a/src/apprentice.c
  125. +++ b/src/apprentice.c
  126. @@ -932,6 +932,11 @@
  127. if ((ms->flags & MAGIC_CHECK) == 0)
  128. return 0;
  129. + if (m->type != FILE_PSTRING && (m->str_flags & PSTRING_LEN) != 0) {
  130. + file_magwarn(ms,
  131. + "'/BHhLl' modifiers are only allowed for pascal strings\n");
  132. + return -1;
  133. + }
  134. switch (m->type) {
  135. case FILE_BESTRING16:
  136. case FILE_LESTRING16:
  137. @@ -1308,8 +1313,7 @@
  138. ++l;
  139. }
  140. m->str_range = 0;
  141. - m->str_flags = 0;
  142. - m->num_mask = 0;
  143. + m->str_flags = m->type == FILE_PSTRING ? PSTRING_1_LE : 0;
  144. if ((op = get_op(*l)) != -1) {
  145. if (!IS_STRING(m->type)) {
  146. uint64_t val;
  147. @@ -1362,6 +1366,32 @@
  148. case CHAR_TEXTTEST:
  149. m->str_flags |= STRING_TEXTTEST;
  150. break;
  151. + case CHAR_PSTRING_1_LE:
  152. + if (m->type != FILE_PSTRING)
  153. + goto bad;
  154. + m->str_flags |= PSTRING_1_LE;
  155. + break;
  156. + case CHAR_PSTRING_2_BE:
  157. + if (m->type != FILE_PSTRING)
  158. + goto bad;
  159. + m->str_flags |= PSTRING_2_BE;
  160. + break;
  161. + case CHAR_PSTRING_2_LE:
  162. + if (m->type != FILE_PSTRING)
  163. + goto bad;
  164. + m->str_flags |= PSTRING_2_LE;
  165. + break;
  166. + case CHAR_PSTRING_4_BE:
  167. + if (m->type != FILE_PSTRING)
  168. + goto bad;
  169. + m->str_flags |= PSTRING_4_BE;
  170. + break;
  171. + case CHAR_PSTRING_4_LE:
  172. + if (m->type != FILE_PSTRING)
  173. + goto bad;
  174. + m->str_flags |= PSTRING_4_LE;
  175. + break;
  176. + bad:
  177. default:
  178. if (ms->flags & MAGIC_CHECK)
  179. file_magwarn(ms,
  180. @@ -1990,7 +2020,7 @@
  181. *p = '\0';
  182. m->vallen = CAST(unsigned char, (p - origp));
  183. if (m->type == FILE_PSTRING)
  184. - m->vallen++;
  185. + m->vallen += file_pstring_length_size(m);
  186. return s;
  187. }
  188. @@ -2371,6 +2401,8 @@
  189. m->in_offset = swap4((uint32_t)m->in_offset);
  190. m->lineno = swap4((uint32_t)m->lineno);
  191. if (IS_STRING(m->type)) {
  192. + if (m->type == FILE_PSTRING)
  193. + printf("flags! %d\n", m->str_flags);
  194. m->str_range = swap4(m->str_range);
  195. m->str_flags = swap4(m->str_flags);
  196. }
  197. @@ -2379,3 +2411,40 @@
  198. m->num_mask = swap8(m->num_mask);
  199. }
  200. }
  201. +
  202. +protected size_t
  203. +file_pstring_length_size(const struct magic *m)
  204. +{
  205. + switch (m->str_flags & PSTRING_LEN) {
  206. + case PSTRING_1_LE:
  207. + return 1;
  208. + case PSTRING_2_LE:
  209. + case PSTRING_2_BE:
  210. + return 2;
  211. + case PSTRING_4_LE:
  212. + case PSTRING_4_BE:
  213. + return 4;
  214. + default:
  215. + abort(); /* Impossible */
  216. + return 1;
  217. + }
  218. +}
  219. +protected size_t
  220. +file_pstring_get_length(const struct magic *m, const char *s)
  221. +{
  222. + switch (m->str_flags & PSTRING_LEN) {
  223. + case PSTRING_1_LE:
  224. + return *s;
  225. + case PSTRING_2_LE:
  226. + return (s[1] << 8) | s[0];
  227. + case PSTRING_2_BE:
  228. + return (s[0] << 8) | s[1];
  229. + case PSTRING_4_LE:
  230. + return (s[3] << 24) | (s[2] << 16) | (s[1] << 8) | s[0];
  231. + case PSTRING_4_BE:
  232. + return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
  233. + default:
  234. + abort(); /* Impossible */
  235. + return 1;
  236. + }
  237. +}
  238. --- a/src/file.h
  239. +++ b/src/file.h
  240. @@ -285,6 +285,14 @@
  241. #define REGEX_OFFSET_START BIT(4)
  242. #define STRING_TEXTTEST BIT(5)
  243. #define STRING_BINTEST BIT(6)
  244. +#define PSTRING_1_BE BIT(7)
  245. +#define PSTRING_1_LE BIT(7)
  246. +#define PSTRING_2_BE BIT(8)
  247. +#define PSTRING_2_LE BIT(9)
  248. +#define PSTRING_4_BE BIT(10)
  249. +#define PSTRING_4_LE BIT(11)
  250. +#define PSTRING_LEN \
  251. + (PSTRING_1_BE|PSTRING_2_LE|PSTRING_2_BE|PSTRING_4_LE|PSTRING_4_BE)
  252. #define CHAR_COMPACT_WHITESPACE 'W'
  253. #define CHAR_COMPACT_OPTIONAL_WHITESPACE 'w'
  254. #define CHAR_IGNORE_LOWERCASE 'c'
  255. @@ -292,6 +300,12 @@
  256. #define CHAR_REGEX_OFFSET_START 's'
  257. #define CHAR_TEXTTEST 't'
  258. #define CHAR_BINTEST 'b'
  259. +#define CHAR_PSTRING_1_BE 'B'
  260. +#define CHAR_PSTRING_1_LE 'B'
  261. +#define CHAR_PSTRING_2_BE 'H'
  262. +#define CHAR_PSTRING_2_LE 'h'
  263. +#define CHAR_PSTRING_4_BE 'L'
  264. +#define CHAR_PSTRING_4_LE 'l'
  265. #define STRING_IGNORE_CASE (STRING_IGNORE_LOWERCASE|STRING_IGNORE_UPPERCASE)
  266. #define STRING_DEFAULT_RANGE 100
  267. @@ -400,6 +414,8 @@
  268. protected int file_check_mem(struct magic_set *, unsigned int);
  269. protected int file_looks_utf8(const unsigned char *, size_t, unichar *,
  270. size_t *);
  271. +protected size_t file_pstring_length_size(const struct magic *);
  272. +protected size_t file_pstring_get_length(const struct magic *, const char *);
  273. #ifdef __EMX__
  274. protected int file_os2_apptype(struct magic_set *, const char *, const void *,
  275. size_t);