]> The Tcpdump Group git mirrors - libpcap/commitdiff
Add checks for invalid qualifiers for "port" and "portrange".
authorGuy Harris <[email protected]>
Tue, 16 Oct 2018 23:11:06 +0000 (16:11 -0700)
committerGuy Harris <[email protected]>
Tue, 16 Oct 2018 23:11:06 +0000 (16:11 -0700)
Just as for most addresses, various 802.11 address qualifiers work only
for 802.11 MAC addresses; give errors when they're used elsewhere.

Shuffle the cases around in gen_ahostop() to be in the same order as
elsewhere.

Credit to OSS-Fuzz for finding this issue.

gencode.c

index 51adc328f799f7bc26a099c662adb6efca0614e7..1b20124b40309fe2453b9ac051d4676082e315d6 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -3878,8 +3878,8 @@ gen_hostop(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
                gen_and(b0, b1);
                return b1;
 
-       case Q_OR:
        case Q_DEFAULT:
+       case Q_OR:
                b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
                b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
                gen_or(b0, b1);
@@ -3943,8 +3943,8 @@ gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr,
                gen_and(b0, b1);
                return b1;
 
-       case Q_OR:
        case Q_DEFAULT:
+       case Q_OR:
                b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
                b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
                gen_or(b0, b1);
@@ -4444,6 +4444,68 @@ gen_wlanhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
                gen_and(b1, b0);
                return b0;
 
+       case Q_AND:
+               b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+               b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_DEFAULT:
+       case Q_OR:
+               b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+               b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+               gen_or(b0, b1);
+               return b1;
+
+       /*
+        * XXX - add BSSID keyword?
+        */
+       case Q_ADDR1:
+               return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
+
+       case Q_ADDR2:
+               /*
+                * Not present in CTS or ACK control frames.
+                */
+               b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b1);
+               b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+                       IEEE80211_FC0_SUBTYPE_MASK);
+               gen_not(b2);
+               gen_and(b1, b2);
+               gen_or(b0, b2);
+               b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
+               gen_and(b2, b1);
+               return b1;
+
+       case Q_ADDR3:
+               /*
+                * Not present in control frames.
+                */
+               b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+                       IEEE80211_FC0_TYPE_MASK);
+               gen_not(b0);
+               b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
+               gen_and(b0, b1);
+               return b1;
+
+       case Q_ADDR4:
+               /*
+                * Present only if the direction mask has both "From DS"
+                * and "To DS" set.  Neither control frames nor management
+                * frames should have both of those set, so we don't
+                * check the frame type.
+                */
+               b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
+                       IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
+               b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
+               gen_and(b0, b1);
+               return b1;
+
        case Q_RA:
                /*
                 * Not present in management frames; addr1 in other
@@ -4514,68 +4576,6 @@ gen_wlanhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
                b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
                gen_and(b2, b1);
                return b1;
-
-       /*
-        * XXX - add BSSID keyword?
-        */
-       case Q_ADDR1:
-               return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
-
-       case Q_ADDR2:
-               /*
-                * Not present in CTS or ACK control frames.
-                */
-               b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
-                       IEEE80211_FC0_TYPE_MASK);
-               gen_not(b0);
-               b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
-                       IEEE80211_FC0_SUBTYPE_MASK);
-               gen_not(b1);
-               b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
-                       IEEE80211_FC0_SUBTYPE_MASK);
-               gen_not(b2);
-               gen_and(b1, b2);
-               gen_or(b0, b2);
-               b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
-               gen_and(b2, b1);
-               return b1;
-
-       case Q_ADDR3:
-               /*
-                * Not present in control frames.
-                */
-               b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
-                       IEEE80211_FC0_TYPE_MASK);
-               gen_not(b0);
-               b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
-               gen_and(b0, b1);
-               return b1;
-
-       case Q_ADDR4:
-               /*
-                * Present only if the direction mask has both "From DS"
-                * and "To DS" set.  Neither control frames nor management
-                * frames should have both of those set, so we don't
-                * check the frame type.
-                */
-               b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
-                       IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
-               b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
-               gen_and(b0, b1);
-               return b1;
-
-       case Q_AND:
-               b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
-               b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
-               gen_and(b0, b1);
-               return b1;
-
-       case Q_DEFAULT:
-       case Q_OR:
-               b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
-               b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
-               gen_or(b0, b1);
-               return b1;
        }
        abort();
        /* NOTREACHED */
@@ -4683,8 +4683,8 @@ gen_dnhostop(compiler_state_t *cstate, bpf_u_int32 addr, int dir)
                gen_and(b0, b1);
                return b1;
 
-       case Q_OR:
        case Q_DEFAULT:
+       case Q_OR:
                /* Inefficient because we do our Calvinball dance twice */
                b0 = gen_dnhostop(cstate, addr, Q_SRC);
                b1 = gen_dnhostop(cstate, addr, Q_DST);
@@ -5430,17 +5430,41 @@ gen_portop(compiler_state_t *cstate, int port, int proto, int dir)
                b1 = gen_portatom(cstate, 2, (bpf_int32)port);
                break;
 
-       case Q_OR:
-       case Q_DEFAULT:
+       case Q_AND:
                tmp = gen_portatom(cstate, 0, (bpf_int32)port);
                b1 = gen_portatom(cstate, 2, (bpf_int32)port);
-               gen_or(tmp, b1);
+               gen_and(tmp, b1);
                break;
 
-       case Q_AND:
+       case Q_DEFAULT:
+       case Q_OR:
                tmp = gen_portatom(cstate, 0, (bpf_int32)port);
                b1 = gen_portatom(cstate, 2, (bpf_int32)port);
-               gen_and(tmp, b1);
+               gen_or(tmp, b1);
+               break;
+
+       case Q_ADDR1:
+               bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for ports");
+               break;
+
+       case Q_ADDR2:
+               bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for ports");
+               break;
+
+       case Q_ADDR3:
+               bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for ports");
+               break;
+
+       case Q_ADDR4:
+               bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for ports");
+               break;
+
+       case Q_RA:
+               bpf_error(cstate, "'ra' is not a valid qualifier for ports");
+               break;
+
+       case Q_TA:
+               bpf_error(cstate, "'ta' is not a valid qualifier for ports");
                break;
 
        default:
@@ -5515,17 +5539,17 @@ gen_portop6(compiler_state_t *cstate, int port, int proto, int dir)
                b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
                break;
 
-       case Q_OR:
-       case Q_DEFAULT:
+       case Q_AND:
                tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
                b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
-               gen_or(tmp, b1);
+               gen_and(tmp, b1);
                break;
 
-       case Q_AND:
+       case Q_DEFAULT:
+       case Q_OR:
                tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
                b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
-               gen_and(tmp, b1);
+               gen_or(tmp, b1);
                break;
 
        default:
@@ -5612,17 +5636,41 @@ gen_portrangeop(compiler_state_t *cstate, int port1, int port2, int proto,
                b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
                break;
 
-       case Q_OR:
-       case Q_DEFAULT:
+       case Q_AND:
                tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
                b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
-               gen_or(tmp, b1);
+               gen_and(tmp, b1);
                break;
 
-       case Q_AND:
+       case Q_DEFAULT:
+       case Q_OR:
                tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
                b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
-               gen_and(tmp, b1);
+               gen_or(tmp, b1);
+               break;
+
+       case Q_ADDR1:
+               bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for port ranges");
+               break;
+
+       case Q_ADDR2:
+               bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for port ranges");
+               break;
+
+       case Q_ADDR3:
+               bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for port ranges");
+               break;
+
+       case Q_ADDR4:
+               bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for port ranges");
+               break;
+
+       case Q_RA:
+               bpf_error(cstate, "'ra' is not a valid qualifier for port ranges");
+               break;
+
+       case Q_TA:
+               bpf_error(cstate, "'ta' is not a valid qualifier for port ranges");
                break;
 
        default:
@@ -5708,17 +5756,17 @@ gen_portrangeop6(compiler_state_t *cstate, int port1, int port2, int proto,
                b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
                break;
 
-       case Q_OR:
-       case Q_DEFAULT:
+       case Q_AND:
                tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
                b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
-               gen_or(tmp, b1);
+               gen_and(tmp, b1);
                break;
 
-       case Q_AND:
+       case Q_DEFAULT:
+       case Q_OR:
                tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
                b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
-               gen_and(tmp, b1);
+               gen_or(tmp, b1);
                break;
 
        default: