]> The Tcpdump Group git mirrors - libpcap/commitdiff
Report an error for MPLS labels that don't fit in 20 bits.
authorGuy Harris <[email protected]>
Wed, 24 Oct 2018 03:29:05 +0000 (20:29 -0700)
committerGuy Harris <[email protected]>
Wed, 24 Oct 2018 03:29:05 +0000 (20:29 -0700)
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).

gencode.c
gencode.h
grammar.y

index 95a3ef9579a27e409202a320c1420aa1a6b7fe2f..09f72d437cb17b9aaa85d8b61f3a0474c57d9009 100644 (file)
--- 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 */
index a81990026e908b300648349f6942144890b0efad..287e9b9aaf08ef4367653337587e624555a6f061 100644 (file)
--- 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);
index e3883b536e1b3e89472aaeec88edc839ba384a95..dfaa6d86c3279c72c2bc7b0cdc05033528755f9c 100644 (file)
--- 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); }