libxml2-2-hash-randomization.patch 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. From 8973d58b7498fa5100a876815476b81fd1a2412a Mon Sep 17 00:00:00 2001
  2. From: Daniel Veillard <veillard@redhat.com>
  3. Date: Sat, 4 Feb 2012 19:07:44 +0800
  4. Subject: [PATCH] Add hash randomization to hash and dict structures
  5. Following http://www.ocert.org/advisories/ocert-2011-003.html
  6. it seems that having hash randomization might be a good idea
  7. when using XML with untrusted data
  8. * configure.in: lookup for rand, srand and time
  9. * dict.c: add randomization to dictionaries hash tables
  10. * hash.c: add randomization to normal hash tables
  11. ---
  12. configure.in | 1 +
  13. dict.c | 81 ++++++++++++++++++++++++++++++++++++++++-----------------
  14. hash.c | 38 ++++++++++++++++++++++++++-
  15. 3 files changed, 95 insertions(+), 25 deletions(-)
  16. diff --git a/configure.in b/configure.in
  17. index fa80375..828b66a 100644
  18. --- a/configure.in
  19. +++ b/configure.in
  20. @@ -512,6 +512,7 @@ AC_CHECK_FUNCS(strdup strndup strerror)
  21. AC_CHECK_FUNCS(finite isnand fp_class class fpclass)
  22. AC_CHECK_FUNCS(strftime localtime gettimeofday ftime)
  23. AC_CHECK_FUNCS(stat _stat signal)
  24. +AC_CHECK_FUNCS(rand srand time)
  25. dnl Checking the standard string functions availability
  26. AC_CHECK_FUNCS(printf sprintf fprintf snprintf vfprintf vsprintf vsnprintf sscanf,,
  27. diff --git a/dict.c b/dict.c
  28. index 3eff231..ae4966b 100644
  29. --- a/dict.c
  30. +++ b/dict.c
  31. @@ -2,7 +2,7 @@
  32. * dict.c: dictionary of reusable strings, just used to avoid allocation
  33. * and freeing operations.
  34. *
  35. - * Copyright (C) 2003 Daniel Veillard.
  36. + * Copyright (C) 2003-2012 Daniel Veillard.
  37. *
  38. * Permission to use, copy, modify, and distribute this software for any
  39. * purpose with or without fee is hereby granted, provided that the above
  40. @@ -19,6 +19,28 @@
  41. #define IN_LIBXML
  42. #include "libxml.h"
  43. +#ifdef HAVE_STDLIB_H
  44. +#include <stdlib.h>
  45. +#endif
  46. +#ifdef HAVE_TIME_H
  47. +#include <time.h>
  48. +#endif
  49. +
  50. +/*
  51. + * Following http://www.ocert.org/advisories/ocert-2011-003.html
  52. + * it seems that having hash randomization might be a good idea
  53. + * when using XML with untrusted data
  54. + * Note1: that it works correctly only if compiled with WITH_BIG_KEY
  55. + * which is the default.
  56. + * Note2: the fast function used for a small dict won't protect very
  57. + * well but since the attack is based on growing a very big hash
  58. + * list we will use the BigKey algo as soon as the hash size grows
  59. + * over MIN_DICT_SIZE so this actually works
  60. + */
  61. +#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
  62. +#define DICT_RANDOMIZATION
  63. +#endif
  64. +
  65. #include <string.h>
  66. #ifdef HAVE_STDINT_H
  67. #include <stdint.h>
  68. @@ -44,23 +66,23 @@ typedef unsigned __int32 uint32_t;
  69. #define WITH_BIG_KEY
  70. #ifdef WITH_BIG_KEY
  71. -#define xmlDictComputeKey(dict, name, len) \
  72. - (((dict)->size == MIN_DICT_SIZE) ? \
  73. - xmlDictComputeFastKey(name, len) : \
  74. - xmlDictComputeBigKey(name, len))
  75. -
  76. -#define xmlDictComputeQKey(dict, prefix, plen, name, len) \
  77. - (((prefix) == NULL) ? \
  78. - (xmlDictComputeKey(dict, name, len)) : \
  79. - (((dict)->size == MIN_DICT_SIZE) ? \
  80. - xmlDictComputeFastQKey(prefix, plen, name, len) : \
  81. - xmlDictComputeBigQKey(prefix, plen, name, len)))
  82. +#define xmlDictComputeKey(dict, name, len) \
  83. + (((dict)->size == MIN_DICT_SIZE) ? \
  84. + xmlDictComputeFastKey(name, len, (dict)->seed) : \
  85. + xmlDictComputeBigKey(name, len, (dict)->seed))
  86. +
  87. +#define xmlDictComputeQKey(dict, prefix, plen, name, len) \
  88. + (((prefix) == NULL) ? \
  89. + (xmlDictComputeKey(dict, name, len)) : \
  90. + (((dict)->size == MIN_DICT_SIZE) ? \
  91. + xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) : \
  92. + xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed)))
  93. #else /* !WITH_BIG_KEY */
  94. -#define xmlDictComputeKey(dict, name, len) \
  95. - xmlDictComputeFastKey(name, len)
  96. -#define xmlDictComputeQKey(dict, prefix, plen, name, len) \
  97. - xmlDictComputeFastQKey(prefix, plen, name, len)
  98. +#define xmlDictComputeKey(dict, name, len) \
  99. + xmlDictComputeFastKey(name, len, (dict)->seed)
  100. +#define xmlDictComputeQKey(dict, prefix, plen, name, len) \
  101. + xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed)
  102. #endif /* WITH_BIG_KEY */
  103. /*
  104. @@ -98,6 +120,8 @@ struct _xmlDict {
  105. xmlDictStringsPtr strings;
  106. struct _xmlDict *subdict;
  107. + /* used for randomization */
  108. + int seed;
  109. };
  110. /*
  111. @@ -125,6 +149,9 @@ static int xmlInitializeDict(void) {
  112. if ((xmlDictMutex = xmlNewRMutex()) == NULL)
  113. return(0);
  114. +#ifdef DICT_RANDOMIZATION
  115. + srand(time(NULL));
  116. +#endif
  117. xmlDictInitialized = 1;
  118. return(1);
  119. }
  120. @@ -277,13 +304,13 @@ found_pool:
  121. */
  122. static uint32_t
  123. -xmlDictComputeBigKey(const xmlChar* data, int namelen) {
  124. +xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
  125. uint32_t hash;
  126. int i;
  127. if (namelen <= 0 || data == NULL) return(0);
  128. - hash = 0;
  129. + hash = seed;
  130. for (i = 0;i < namelen; i++) {
  131. hash += data[i];
  132. @@ -310,12 +337,12 @@ xmlDictComputeBigKey(const xmlChar* data, int namelen) {
  133. */
  134. static unsigned long
  135. xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
  136. - const xmlChar *name, int len)
  137. + const xmlChar *name, int len, int seed)
  138. {
  139. uint32_t hash;
  140. int i;
  141. - hash = 0;
  142. + hash = seed;
  143. for (i = 0;i < plen; i++) {
  144. hash += prefix[i];
  145. @@ -346,8 +373,8 @@ xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
  146. * for low hash table fill.
  147. */
  148. static unsigned long
  149. -xmlDictComputeFastKey(const xmlChar *name, int namelen) {
  150. - unsigned long value = 0L;
  151. +xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
  152. + unsigned long value = seed;
  153. if (name == NULL) return(0);
  154. value = *name;
  155. @@ -381,9 +408,9 @@ xmlDictComputeFastKey(const xmlChar *name, int namelen) {
  156. */
  157. static unsigned long
  158. xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
  159. - const xmlChar *name, int len)
  160. + const xmlChar *name, int len, int seed)
  161. {
  162. - unsigned long value = 0L;
  163. + unsigned long value = (unsigned long) seed;
  164. if (plen == 0)
  165. value += 30 * (unsigned long) ':';
  166. @@ -460,6 +487,11 @@ xmlDictCreate(void) {
  167. dict->subdict = NULL;
  168. if (dict->dict) {
  169. memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
  170. +#ifdef DICT_RANDOMIZATION
  171. + dict->seed = rand();
  172. +#else
  173. + dict->seed = 0;
  174. +#endif
  175. return(dict);
  176. }
  177. xmlFree(dict);
  178. @@ -486,6 +518,7 @@ xmlDictCreateSub(xmlDictPtr sub) {
  179. #ifdef DICT_DEBUG_PATTERNS
  180. fprintf(stderr, "R");
  181. #endif
  182. + dict->seed = sub->seed;
  183. dict->subdict = sub;
  184. xmlDictReference(dict->subdict);
  185. }
  186. diff --git a/hash.c b/hash.c
  187. index b78bc2d..fe1424f 100644
  188. --- a/hash.c
  189. +++ b/hash.c
  190. @@ -3,7 +3,7 @@
  191. *
  192. * Reference: Your favorite introductory book on algorithms
  193. *
  194. - * Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
  195. + * Copyright (C) 2000,2012 Bjorn Reese and Daniel Veillard.
  196. *
  197. * Permission to use, copy, modify, and distribute this software for any
  198. * purpose with or without fee is hereby granted, provided that the above
  199. @@ -21,6 +21,22 @@
  200. #include "libxml.h"
  201. #include <string.h>
  202. +#ifdef HAVE_STDLIB_H
  203. +#include <stdlib.h>
  204. +#endif
  205. +#ifdef HAVE_TIME_H
  206. +#include <time.h>
  207. +#endif
  208. +
  209. +/*
  210. + * Following http://www.ocert.org/advisories/ocert-2011-003.html
  211. + * it seems that having hash randomization might be a good idea
  212. + * when using XML with untrusted data
  213. + */
  214. +#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
  215. +#define HASH_RANDOMIZATION
  216. +#endif
  217. +
  218. #include <libxml/parser.h>
  219. #include <libxml/hash.h>
  220. #include <libxml/xmlmemory.h>
  221. @@ -31,6 +47,10 @@
  222. /* #define DEBUG_GROW */
  223. +#ifdef HASH_RANDOMIZATION
  224. +static int hash_initialized = 0;
  225. +#endif
  226. +
  227. /*
  228. * A single entry in the hash table
  229. */
  230. @@ -53,6 +73,9 @@ struct _xmlHashTable {
  231. int size;
  232. int nbElems;
  233. xmlDictPtr dict;
  234. +#ifdef HASH_RANDOMIZATION
  235. + int random_seed;
  236. +#endif
  237. };
  238. /*
  239. @@ -65,6 +88,9 @@ xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
  240. unsigned long value = 0L;
  241. char ch;
  242. +#ifdef HASH_RANDOMIZATION
  243. + value = table->random_seed;
  244. +#endif
  245. if (name != NULL) {
  246. value += 30 * (*name);
  247. while ((ch = *name++) != 0) {
  248. @@ -92,6 +118,9 @@ xmlHashComputeQKey(xmlHashTablePtr table,
  249. unsigned long value = 0L;
  250. char ch;
  251. +#ifdef HASH_RANDOMIZATION
  252. + value = table->random_seed;
  253. +#endif
  254. if (prefix != NULL)
  255. value += 30 * (*prefix);
  256. else
  257. @@ -156,6 +185,13 @@ xmlHashCreate(int size) {
  258. table->table = xmlMalloc(size * sizeof(xmlHashEntry));
  259. if (table->table) {
  260. memset(table->table, 0, size * sizeof(xmlHashEntry));
  261. +#ifdef HASH_RANDOMIZATION
  262. + if (!hash_initialized) {
  263. + srand(time(NULL));
  264. + hash_initialized = 1;
  265. + }
  266. + table->random_seed = rand();
  267. +#endif
  268. return(table);
  269. }
  270. xmlFree(table);
  271. --
  272. 1.7.8.4