diff options
author | Willy Tarreau <w@1wt.eu> | 2014-09-27 06:31:36 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-28 05:08:01 -0400 |
commit | af958a38a60c7ca3d8a39c918c1baa2ff7b6b233 (patch) | |
tree | 933dcf1f3e11ad913d5408c7cbcaa2925d78a587 | |
parent | d98a0526434d27e261f622cf9d2e0028b5ff1a00 (diff) |
Revert "lzo: properly check for overruns"
This reverts commit 206a81c ("lzo: properly check for overruns").
As analysed by Willem Pinckaers, this fix is still incomplete on
certain rare corner cases, and it is easier to restart from the
original code.
Reported-by: Willem Pinckaers <willem@lekkertech.net>
Cc: "Don A. Bailey" <donb@securitymouse.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | lib/lzo/lzo1x_decompress_safe.c | 62 |
1 files changed, 21 insertions, 41 deletions
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c index 8563081e8da3..569985d522d5 100644 --- a/lib/lzo/lzo1x_decompress_safe.c +++ b/lib/lzo/lzo1x_decompress_safe.c | |||
@@ -19,31 +19,11 @@ | |||
19 | #include <linux/lzo.h> | 19 | #include <linux/lzo.h> |
20 | #include "lzodefs.h" | 20 | #include "lzodefs.h" |
21 | 21 | ||
22 | #define HAVE_IP(t, x) \ | 22 | #define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x)) |
23 | (((size_t)(ip_end - ip) >= (size_t)(t + x)) && \ | 23 | #define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x)) |
24 | (((t + x) >= t) && ((t + x) >= x))) | 24 | #define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun |
25 | 25 | #define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun | |
26 | #define HAVE_OP(t, x) \ | 26 | #define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun |
27 | (((size_t)(op_end - op) >= (size_t)(t + x)) && \ | ||
28 | (((t + x) >= t) && ((t + x) >= x))) | ||
29 | |||
30 | #define NEED_IP(t, x) \ | ||
31 | do { \ | ||
32 | if (!HAVE_IP(t, x)) \ | ||
33 | goto input_overrun; \ | ||
34 | } while (0) | ||
35 | |||
36 | #define NEED_OP(t, x) \ | ||
37 | do { \ | ||
38 | if (!HAVE_OP(t, x)) \ | ||
39 | goto output_overrun; \ | ||
40 | } while (0) | ||
41 | |||
42 | #define TEST_LB(m_pos) \ | ||
43 | do { \ | ||
44 | if ((m_pos) < out) \ | ||
45 | goto lookbehind_overrun; \ | ||
46 | } while (0) | ||
47 | 27 | ||
48 | int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, | 28 | int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, |
49 | unsigned char *out, size_t *out_len) | 29 | unsigned char *out, size_t *out_len) |
@@ -78,14 +58,14 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, | |||
78 | while (unlikely(*ip == 0)) { | 58 | while (unlikely(*ip == 0)) { |
79 | t += 255; | 59 | t += 255; |
80 | ip++; | 60 | ip++; |
81 | NEED_IP(1, 0); | 61 | NEED_IP(1); |
82 | } | 62 | } |
83 | t += 15 + *ip++; | 63 | t += 15 + *ip++; |
84 | } | 64 | } |
85 | t += 3; | 65 | t += 3; |
86 | copy_literal_run: | 66 | copy_literal_run: |
87 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 67 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
88 | if (likely(HAVE_IP(t, 15) && HAVE_OP(t, 15))) { | 68 | if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) { |
89 | const unsigned char *ie = ip + t; | 69 | const unsigned char *ie = ip + t; |
90 | unsigned char *oe = op + t; | 70 | unsigned char *oe = op + t; |
91 | do { | 71 | do { |
@@ -101,8 +81,8 @@ copy_literal_run: | |||
101 | } else | 81 | } else |
102 | #endif | 82 | #endif |
103 | { | 83 | { |
104 | NEED_OP(t, 0); | 84 | NEED_OP(t); |
105 | NEED_IP(t, 3); | 85 | NEED_IP(t + 3); |
106 | do { | 86 | do { |
107 | *op++ = *ip++; | 87 | *op++ = *ip++; |
108 | } while (--t > 0); | 88 | } while (--t > 0); |
@@ -115,7 +95,7 @@ copy_literal_run: | |||
115 | m_pos -= t >> 2; | 95 | m_pos -= t >> 2; |
116 | m_pos -= *ip++ << 2; | 96 | m_pos -= *ip++ << 2; |
117 | TEST_LB(m_pos); | 97 | TEST_LB(m_pos); |
118 | NEED_OP(2, 0); | 98 | NEED_OP(2); |
119 | op[0] = m_pos[0]; | 99 | op[0] = m_pos[0]; |
120 | op[1] = m_pos[1]; | 100 | op[1] = m_pos[1]; |
121 | op += 2; | 101 | op += 2; |
@@ -139,10 +119,10 @@ copy_literal_run: | |||
139 | while (unlikely(*ip == 0)) { | 119 | while (unlikely(*ip == 0)) { |
140 | t += 255; | 120 | t += 255; |
141 | ip++; | 121 | ip++; |
142 | NEED_IP(1, 0); | 122 | NEED_IP(1); |
143 | } | 123 | } |
144 | t += 31 + *ip++; | 124 | t += 31 + *ip++; |
145 | NEED_IP(2, 0); | 125 | NEED_IP(2); |
146 | } | 126 | } |
147 | m_pos = op - 1; | 127 | m_pos = op - 1; |
148 | next = get_unaligned_le16(ip); | 128 | next = get_unaligned_le16(ip); |
@@ -157,10 +137,10 @@ copy_literal_run: | |||
157 | while (unlikely(*ip == 0)) { | 137 | while (unlikely(*ip == 0)) { |
158 | t += 255; | 138 | t += 255; |
159 | ip++; | 139 | ip++; |
160 | NEED_IP(1, 0); | 140 | NEED_IP(1); |
161 | } | 141 | } |
162 | t += 7 + *ip++; | 142 | t += 7 + *ip++; |
163 | NEED_IP(2, 0); | 143 | NEED_IP(2); |
164 | } | 144 | } |
165 | next = get_unaligned_le16(ip); | 145 | next = get_unaligned_le16(ip); |
166 | ip += 2; | 146 | ip += 2; |
@@ -174,7 +154,7 @@ copy_literal_run: | |||
174 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 154 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
175 | if (op - m_pos >= 8) { | 155 | if (op - m_pos >= 8) { |
176 | unsigned char *oe = op + t; | 156 | unsigned char *oe = op + t; |
177 | if (likely(HAVE_OP(t, 15))) { | 157 | if (likely(HAVE_OP(t + 15))) { |
178 | do { | 158 | do { |
179 | COPY8(op, m_pos); | 159 | COPY8(op, m_pos); |
180 | op += 8; | 160 | op += 8; |
@@ -184,7 +164,7 @@ copy_literal_run: | |||
184 | m_pos += 8; | 164 | m_pos += 8; |
185 | } while (op < oe); | 165 | } while (op < oe); |
186 | op = oe; | 166 | op = oe; |
187 | if (HAVE_IP(6, 0)) { | 167 | if (HAVE_IP(6)) { |
188 | state = next; | 168 | state = next; |
189 | COPY4(op, ip); | 169 | COPY4(op, ip); |
190 | op += next; | 170 | op += next; |
@@ -192,7 +172,7 @@ copy_literal_run: | |||
192 | continue; | 172 | continue; |
193 | } | 173 | } |
194 | } else { | 174 | } else { |
195 | NEED_OP(t, 0); | 175 | NEED_OP(t); |
196 | do { | 176 | do { |
197 | *op++ = *m_pos++; | 177 | *op++ = *m_pos++; |
198 | } while (op < oe); | 178 | } while (op < oe); |
@@ -201,7 +181,7 @@ copy_literal_run: | |||
201 | #endif | 181 | #endif |
202 | { | 182 | { |
203 | unsigned char *oe = op + t; | 183 | unsigned char *oe = op + t; |
204 | NEED_OP(t, 0); | 184 | NEED_OP(t); |
205 | op[0] = m_pos[0]; | 185 | op[0] = m_pos[0]; |
206 | op[1] = m_pos[1]; | 186 | op[1] = m_pos[1]; |
207 | op += 2; | 187 | op += 2; |
@@ -214,15 +194,15 @@ match_next: | |||
214 | state = next; | 194 | state = next; |
215 | t = next; | 195 | t = next; |
216 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 196 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) |
217 | if (likely(HAVE_IP(6, 0) && HAVE_OP(4, 0))) { | 197 | if (likely(HAVE_IP(6) && HAVE_OP(4))) { |
218 | COPY4(op, ip); | 198 | COPY4(op, ip); |
219 | op += t; | 199 | op += t; |
220 | ip += t; | 200 | ip += t; |
221 | } else | 201 | } else |
222 | #endif | 202 | #endif |
223 | { | 203 | { |
224 | NEED_IP(t, 3); | 204 | NEED_IP(t + 3); |
225 | NEED_OP(t, 0); | 205 | NEED_OP(t); |
226 | while (t > 0) { | 206 | while (t > 0) { |
227 | *op++ = *ip++; | 207 | *op++ = *ip++; |
228 | t--; | 208 | t--; |