Commit ec8a8f3c authored by Eric Sesterhenn's avatar Eric Sesterhenn Committed by Pablo Neira Ayuso

netfilter: nf_ct_h323: Extend nf_h323_error_boundary to work on bits as well

This patch fixes several out of bounds memory reads by extending
the nf_h323_error_boundary() function to work on bits as well
an check the affected parts.
Signed-off-by: default avatarEric Sesterhenn <eric.sesterhenn@x41-dsec.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent bc7d811a
...@@ -164,8 +164,13 @@ static unsigned int get_len(struct bitstr *bs) ...@@ -164,8 +164,13 @@ static unsigned int get_len(struct bitstr *bs)
return v; return v;
} }
static int nf_h323_error_boundary(struct bitstr *bs, size_t bytes) static int nf_h323_error_boundary(struct bitstr *bs, size_t bytes, size_t bits)
{ {
bits += bs->bit;
bytes += bits / BITS_PER_BYTE;
if (bits % BITS_PER_BYTE > 0)
bytes++;
if (*bs->cur + bytes > *bs->end) if (*bs->cur + bytes > *bs->end)
return 1; return 1;
...@@ -286,8 +291,7 @@ static int decode_bool(struct bitstr *bs, const struct field_t *f, ...@@ -286,8 +291,7 @@ static int decode_bool(struct bitstr *bs, const struct field_t *f,
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
INC_BIT(bs); INC_BIT(bs);
if (nf_h323_error_boundary(bs, 0, 0))
if (nf_h323_error_boundary(bs, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
return H323_ERROR_NONE; return H323_ERROR_NONE;
} }
...@@ -301,12 +305,12 @@ static int decode_oid(struct bitstr *bs, const struct field_t *f, ...@@ -301,12 +305,12 @@ static int decode_oid(struct bitstr *bs, const struct field_t *f,
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 1)) if (nf_h323_error_boundary(bs, 1, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = *bs->cur++; len = *bs->cur++;
bs->cur += len; bs->cur += len;
if (nf_h323_error_boundary(bs, 0)) if (nf_h323_error_boundary(bs, 0, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
return H323_ERROR_NONE; return H323_ERROR_NONE;
...@@ -330,6 +334,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f, ...@@ -330,6 +334,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
bs->cur += 2; bs->cur += 2;
break; break;
case CONS: /* 64K < Range < 4G */ case CONS: /* 64K < Range < 4G */
if (nf_h323_error_boundary(bs, 0, 2))
return H323_ERROR_BOUND;
len = get_bits(bs, 2) + 1; len = get_bits(bs, 2) + 1;
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (base && (f->attr & DECODE)) { /* timeToLive */ if (base && (f->attr & DECODE)) { /* timeToLive */
...@@ -341,7 +347,7 @@ static int decode_int(struct bitstr *bs, const struct field_t *f, ...@@ -341,7 +347,7 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
break; break;
case UNCO: case UNCO:
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = get_len(bs); len = get_len(bs);
bs->cur += len; bs->cur += len;
...@@ -353,7 +359,7 @@ static int decode_int(struct bitstr *bs, const struct field_t *f, ...@@ -353,7 +359,7 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
PRINT("\n"); PRINT("\n");
if (nf_h323_error_boundary(bs, 0)) if (nf_h323_error_boundary(bs, 0, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
return H323_ERROR_NONE; return H323_ERROR_NONE;
} }
...@@ -370,7 +376,7 @@ static int decode_enum(struct bitstr *bs, const struct field_t *f, ...@@ -370,7 +376,7 @@ static int decode_enum(struct bitstr *bs, const struct field_t *f,
INC_BITS(bs, f->sz); INC_BITS(bs, f->sz);
} }
if (nf_h323_error_boundary(bs, 0)) if (nf_h323_error_boundary(bs, 0, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
return H323_ERROR_NONE; return H323_ERROR_NONE;
} }
...@@ -389,13 +395,13 @@ static int decode_bitstr(struct bitstr *bs, const struct field_t *f, ...@@ -389,13 +395,13 @@ static int decode_bitstr(struct bitstr *bs, const struct field_t *f,
len = f->lb; len = f->lb;
break; break;
case WORD: /* 2-byte length */ case WORD: /* 2-byte length */
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = (*bs->cur++) << 8; len = (*bs->cur++) << 8;
len += (*bs->cur++) + f->lb; len += (*bs->cur++) + f->lb;
break; break;
case SEMI: case SEMI:
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = get_len(bs); len = get_len(bs);
break; break;
...@@ -407,7 +413,7 @@ static int decode_bitstr(struct bitstr *bs, const struct field_t *f, ...@@ -407,7 +413,7 @@ static int decode_bitstr(struct bitstr *bs, const struct field_t *f,
bs->cur += len >> 3; bs->cur += len >> 3;
bs->bit = len & 7; bs->bit = len & 7;
if (nf_h323_error_boundary(bs, 0)) if (nf_h323_error_boundary(bs, 0, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
return H323_ERROR_NONE; return H323_ERROR_NONE;
} }
...@@ -421,12 +427,14 @@ static int decode_numstr(struct bitstr *bs, const struct field_t *f, ...@@ -421,12 +427,14 @@ static int decode_numstr(struct bitstr *bs, const struct field_t *f,
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name); PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
/* 2 <= Range <= 255 */ /* 2 <= Range <= 255 */
if (nf_h323_error_boundary(bs, 0, f->sz))
return H323_ERROR_BOUND;
len = get_bits(bs, f->sz) + f->lb; len = get_bits(bs, f->sz) + f->lb;
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
INC_BITS(bs, (len << 2)); INC_BITS(bs, (len << 2));
if (nf_h323_error_boundary(bs, 0)) if (nf_h323_error_boundary(bs, 0, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
return H323_ERROR_NONE; return H323_ERROR_NONE;
} }
...@@ -458,17 +466,19 @@ static int decode_octstr(struct bitstr *bs, const struct field_t *f, ...@@ -458,17 +466,19 @@ static int decode_octstr(struct bitstr *bs, const struct field_t *f,
break; break;
case BYTE: /* Range == 256 */ case BYTE: /* Range == 256 */
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 1)) if (nf_h323_error_boundary(bs, 1, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = (*bs->cur++) + f->lb; len = (*bs->cur++) + f->lb;
break; break;
case SEMI: case SEMI:
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = get_len(bs) + f->lb; len = get_len(bs) + f->lb;
break; break;
default: /* 2 <= Range <= 255 */ default: /* 2 <= Range <= 255 */
if (nf_h323_error_boundary(bs, 0, f->sz))
return H323_ERROR_BOUND;
len = get_bits(bs, f->sz) + f->lb; len = get_bits(bs, f->sz) + f->lb;
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
break; break;
...@@ -478,7 +488,7 @@ static int decode_octstr(struct bitstr *bs, const struct field_t *f, ...@@ -478,7 +488,7 @@ static int decode_octstr(struct bitstr *bs, const struct field_t *f,
PRINT("\n"); PRINT("\n");
if (nf_h323_error_boundary(bs, 0)) if (nf_h323_error_boundary(bs, 0, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
return H323_ERROR_NONE; return H323_ERROR_NONE;
} }
...@@ -494,11 +504,13 @@ static int decode_bmpstr(struct bitstr *bs, const struct field_t *f, ...@@ -494,11 +504,13 @@ static int decode_bmpstr(struct bitstr *bs, const struct field_t *f,
switch (f->sz) { switch (f->sz) {
case BYTE: /* Range == 256 */ case BYTE: /* Range == 256 */
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 1)) if (nf_h323_error_boundary(bs, 1, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = (*bs->cur++) + f->lb; len = (*bs->cur++) + f->lb;
break; break;
default: /* 2 <= Range <= 255 */ default: /* 2 <= Range <= 255 */
if (nf_h323_error_boundary(bs, 0, f->sz))
return H323_ERROR_BOUND;
len = get_bits(bs, f->sz) + f->lb; len = get_bits(bs, f->sz) + f->lb;
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
break; break;
...@@ -506,7 +518,7 @@ static int decode_bmpstr(struct bitstr *bs, const struct field_t *f, ...@@ -506,7 +518,7 @@ static int decode_bmpstr(struct bitstr *bs, const struct field_t *f,
bs->cur += len << 1; bs->cur += len << 1;
if (nf_h323_error_boundary(bs, 0)) if (nf_h323_error_boundary(bs, 0, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
return H323_ERROR_NONE; return H323_ERROR_NONE;
} }
...@@ -526,9 +538,13 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f, ...@@ -526,9 +538,13 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
/* Extensible? */ /* Extensible? */
if (nf_h323_error_boundary(bs, 0, 1))
return H323_ERROR_BOUND;
ext = (f->attr & EXT) ? get_bit(bs) : 0; ext = (f->attr & EXT) ? get_bit(bs) : 0;
/* Get fields bitmap */ /* Get fields bitmap */
if (nf_h323_error_boundary(bs, 0, f->sz))
return H323_ERROR_BOUND;
bmp = get_bitmap(bs, f->sz); bmp = get_bitmap(bs, f->sz);
if (base) if (base)
*(unsigned int *)base = bmp; *(unsigned int *)base = bmp;
...@@ -548,10 +564,10 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f, ...@@ -548,10 +564,10 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
/* Decode */ /* Decode */
if (son->attr & OPEN) { /* Open field */ if (son->attr & OPEN) { /* Open field */
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = get_len(bs); len = get_len(bs);
if (nf_h323_error_boundary(bs, len)) if (nf_h323_error_boundary(bs, len, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
if (!base || !(son->attr & DECODE)) { if (!base || !(son->attr & DECODE)) {
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
...@@ -580,8 +596,10 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f, ...@@ -580,8 +596,10 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
return H323_ERROR_NONE; return H323_ERROR_NONE;
/* Get the extension bitmap */ /* Get the extension bitmap */
if (nf_h323_error_boundary(bs, 0, 7))
return H323_ERROR_BOUND;
bmp2_len = get_bits(bs, 7) + 1; bmp2_len = get_bits(bs, 7) + 1;
if (nf_h323_error_boundary(bs, (bmp2_len + 7) >> 3)) if (nf_h323_error_boundary(bs, 0, bmp2_len))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
bmp2 = get_bitmap(bs, bmp2_len); bmp2 = get_bitmap(bs, bmp2_len);
bmp |= bmp2 >> f->sz; bmp |= bmp2 >> f->sz;
...@@ -593,10 +611,10 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f, ...@@ -593,10 +611,10 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
for (opt = 0; opt < bmp2_len; opt++, i++, son++) { for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
/* Check Range */ /* Check Range */
if (i >= f->ub) { /* Newer Version? */ if (i >= f->ub) { /* Newer Version? */
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = get_len(bs); len = get_len(bs);
if (nf_h323_error_boundary(bs, len)) if (nf_h323_error_boundary(bs, len, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
bs->cur += len; bs->cur += len;
continue; continue;
...@@ -611,10 +629,10 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f, ...@@ -611,10 +629,10 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
if (!((0x80000000 >> opt) & bmp2)) /* Not present */ if (!((0x80000000 >> opt) & bmp2)) /* Not present */
continue; continue;
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
len = get_len(bs); len = get_len(bs);
if (nf_h323_error_boundary(bs, len)) if (nf_h323_error_boundary(bs, len, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
if (!base || !(son->attr & DECODE)) { if (!base || !(son->attr & DECODE)) {
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
...@@ -653,13 +671,13 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f, ...@@ -653,13 +671,13 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f,
switch (f->sz) { switch (f->sz) {
case BYTE: case BYTE:
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 1)) if (nf_h323_error_boundary(bs, 1, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
count = *bs->cur++; count = *bs->cur++;
break; break;
case WORD: case WORD:
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
count = *bs->cur++; count = *bs->cur++;
count <<= 8; count <<= 8;
...@@ -667,11 +685,13 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f, ...@@ -667,11 +685,13 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f,
break; break;
case SEMI: case SEMI:
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 2)) if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
count = get_len(bs); count = get_len(bs);
break; break;
default: default:
if (nf_h323_error_boundary(bs, 0, f->sz))
return H323_ERROR_BOUND;
count = get_bits(bs, f->sz); count = get_bits(bs, f->sz);
break; break;
} }
...@@ -691,8 +711,10 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f, ...@@ -691,8 +711,10 @@ static int decode_seqof(struct bitstr *bs, const struct field_t *f,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (son->attr & OPEN) { if (son->attr & OPEN) {
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND;
len = get_len(bs); len = get_len(bs);
if (nf_h323_error_boundary(bs, len)) if (nf_h323_error_boundary(bs, len, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
if (!base || !(son->attr & DECODE)) { if (!base || !(son->attr & DECODE)) {
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
...@@ -744,11 +766,17 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f, ...@@ -744,11 +766,17 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f,
base = (base && (f->attr & DECODE)) ? base + f->offset : NULL; base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
/* Decode the choice index number */ /* Decode the choice index number */
if (nf_h323_error_boundary(bs, 0, 1))
return H323_ERROR_BOUND;
if ((f->attr & EXT) && get_bit(bs)) { if ((f->attr & EXT) && get_bit(bs)) {
ext = 1; ext = 1;
if (nf_h323_error_boundary(bs, 0, 7))
return H323_ERROR_BOUND;
type = get_bits(bs, 7) + f->lb; type = get_bits(bs, 7) + f->lb;
} else { } else {
ext = 0; ext = 0;
if (nf_h323_error_boundary(bs, 0, f->sz))
return H323_ERROR_BOUND;
type = get_bits(bs, f->sz); type = get_bits(bs, f->sz);
if (type >= f->lb) if (type >= f->lb)
return H323_ERROR_RANGE; return H323_ERROR_RANGE;
...@@ -761,8 +789,10 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f, ...@@ -761,8 +789,10 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f,
/* Check Range */ /* Check Range */
if (type >= f->ub) { /* Newer version? */ if (type >= f->ub) { /* Newer version? */
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND;
len = get_len(bs); len = get_len(bs);
if (nf_h323_error_boundary(bs, len)) if (nf_h323_error_boundary(bs, len, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
bs->cur += len; bs->cur += len;
return H323_ERROR_NONE; return H323_ERROR_NONE;
...@@ -777,8 +807,10 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f, ...@@ -777,8 +807,10 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f,
if (ext || (son->attr & OPEN)) { if (ext || (son->attr & OPEN)) {
BYTE_ALIGN(bs); BYTE_ALIGN(bs);
if (nf_h323_error_boundary(bs, len, 0))
return H323_ERROR_BOUND;
len = get_len(bs); len = get_len(bs);
if (nf_h323_error_boundary(bs, len)) if (nf_h323_error_boundary(bs, len, 0))
return H323_ERROR_BOUND; return H323_ERROR_BOUND;
if (!base || !(son->attr & DECODE)) { if (!base || !(son->attr & DECODE)) {
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment