Commit ddb2c43594f22843e9f3153da151deaba1a834c5

Authored by Chris Wright
Committed by Linus Torvalds
1 parent efedf51c86

asn1: additional sanity checking during BER decoding

- Don't trust a length which is greater than the working buffer.
  An invalid length could cause overflow when calculating buffer size
  for decoding oid.

- An oid length of zero is invalid and allows for an off-by-one error when
  decoding oid because the first subid actually encodes first 2 subids.

- A primitive encoding may not have an indefinite length.

Thanks to Wei Wang from McAfee for report.

Cc: Steven French <sfrench@us.ibm.com>
Cc: stable@kernel.org
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 28 additions and 0 deletions Side-by-side Diff

... ... @@ -186,6 +186,11 @@
186 186 }
187 187 }
188 188 }
  189 +
  190 + /* don't trust len bigger than ctx buffer */
  191 + if (*len > ctx->end - ctx->pointer)
  192 + return 0;
  193 +
189 194 return 1;
190 195 }
191 196  
... ... @@ -203,6 +208,10 @@
203 208 if (!asn1_length_decode(ctx, &def, &len))
204 209 return 0;
205 210  
  211 + /* primitive shall be definite, indefinite shall be constructed */
  212 + if (*con == ASN1_PRI && !def)
  213 + return 0;
  214 +
206 215 if (def)
207 216 *eoc = ctx->pointer + len;
208 217 else
... ... @@ -389,6 +398,11 @@
389 398 unsigned long *optr;
390 399  
391 400 size = eoc - ctx->pointer + 1;
  401 +
  402 + /* first subid actually encodes first two subids */
  403 + if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
  404 + return 0;
  405 +
392 406 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
393 407 if (*oid == NULL)
394 408 return 0;
net/ipv4/netfilter/nf_nat_snmp_basic.c
... ... @@ -232,6 +232,11 @@
232 232 }
233 233 }
234 234 }
  235 +
  236 + /* don't trust len bigger than ctx buffer */
  237 + if (*len > ctx->end - ctx->pointer)
  238 + return 0;
  239 +
235 240 return 1;
236 241 }
237 242  
... ... @@ -250,6 +255,10 @@
250 255 if (!asn1_length_decode(ctx, &def, &len))
251 256 return 0;
252 257  
  258 + /* primitive shall be definite, indefinite shall be constructed */
  259 + if (*con == ASN1_PRI && !def)
  260 + return 0;
  261 +
253 262 if (def)
254 263 *eoc = ctx->pointer + len;
255 264 else
... ... @@ -434,6 +443,11 @@
434 443 unsigned long *optr;
435 444  
436 445 size = eoc - ctx->pointer + 1;
  446 +
  447 + /* first subid actually encodes first two subids */
  448 + if (size < 2 || size > ULONG_MAX/sizeof(unsigned long))
  449 + return 0;
  450 +
437 451 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
438 452 if (*oid == NULL) {
439 453 if (net_ratelimit())