summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2018-10-23 20:29:05 -0700
committerGuy Harris <guy@alum.mit.edu>2018-10-23 20:29:05 -0700
commit71abe040fa49dfcb8ba3e08e5f21896b0c7cc6e8 (patch)
tree520fccb102947f787cb839515a3a6099add0f85e
parent2954b59a01a2e5f5a3305e900659e9f2807cc875 (diff)
downloadlibpcap-71abe040fa49dfcb8ba3e08e5f21896b0c7cc6e8.tar.gz
Report an error for MPLS labels that don't fit in 20 bits.
Also, make the label an unsigned value, with a separate argument to gen_mpls() to indicate whether we *have* a label value to test; this prevents "mpls 0xFFFFFFFF" from being treated as equivalent to "mpls" just because (on 2's complement machines; we make no effort to support other types) 32-bit -1 and 32-bit 0xFFFFFFFF have the same bit pattern. Credit to OSS-Fuzz for finding this issue (which showed up as an invalid shift of a signed value, shifting into the sign bit; making the shift value unsigned avoids that headache).
-rw-r--r--gencode.c8
-rw-r--r--gencode.h2
-rw-r--r--grammar.y4
3 files changed, 9 insertions, 5 deletions
diff --git a/gencode.c b/gencode.c
index 95a3ef95..09f72d43 100644
--- a/gencode.c
+++ b/gencode.c
@@ -8574,7 +8574,7 @@ gen_vlan(compiler_state_t *cstate, int vlan_num)
* support for MPLS
*/
struct block *
-gen_mpls(compiler_state_t *cstate, int label_num)
+gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num, int has_label_num)
{
struct block *b0, *b1;
@@ -8612,7 +8612,11 @@ gen_mpls(compiler_state_t *cstate, int label_num)
}
/* If a specific MPLS label is requested, check it */
- if (label_num >= 0) {
+ if (has_label_num) {
+ if (label_num > 0xFFFFF) {
+ bpf_error(cstate, "MPLS label %u greater than maximum %u",
+ label_num, 0xFFFFF);
+ }
label_num = label_num << 12; /* label is shifted 12 bits on the wire */
b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
0xfffff000); /* only compare the first 20 bits */
diff --git a/gencode.h b/gencode.h
index a8199002..287e9b9a 100644
--- a/gencode.h
+++ b/gencode.h
@@ -325,7 +325,7 @@ struct block *gen_llc_s_subtype(compiler_state_t *, bpf_u_int32);
struct block *gen_llc_u_subtype(compiler_state_t *, bpf_u_int32);
struct block *gen_vlan(compiler_state_t *, int);
-struct block *gen_mpls(compiler_state_t *, int);
+struct block *gen_mpls(compiler_state_t *, bpf_u_int32, int);
struct block *gen_pppoed(compiler_state_t *);
struct block *gen_pppoes(compiler_state_t *, int);
diff --git a/grammar.y b/grammar.y
index e3883b53..dfaa6d86 100644
--- a/grammar.y
+++ b/grammar.y
@@ -550,8 +550,8 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast(cstate, $1); }
| OUTBOUND { $$ = gen_inbound(cstate, 1); }
| VLAN pnum { $$ = gen_vlan(cstate, $2); }
| VLAN { $$ = gen_vlan(cstate, -1); }
- | MPLS pnum { $$ = gen_mpls(cstate, $2); }
- | MPLS { $$ = gen_mpls(cstate, -1); }
+ | MPLS pnum { $$ = gen_mpls(cstate, (bpf_u_int32)$2, 1); }
+ | MPLS { $$ = gen_mpls(cstate, 0, 0); }
| PPPOED { $$ = gen_pppoed(cstate); }
| PPPOES pnum { $$ = gen_pppoes(cstate, $2); }
| PPPOES { $$ = gen_pppoes(cstate, -1); }