diff options
author | Guy Harris <guy@alum.mit.edu> | 2018-10-16 23:23:10 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2018-10-16 23:23:10 -0700 |
commit | db833b997d9d825a4bb0e78804d85552b38a562a (patch) | |
tree | 8f059a7c3e95f7772d4b6c39175dff73a48b1db3 | |
parent | c0d8b3eadaccb07b46da5a5494ef589596bf858d (diff) |
Fix the semantics of BPF_LSH and BPF_RSH for shifts >= 32 bits.
Some processors treat shifts greater than the width of the shifted
operand as setting the destination to 0, some others treat it as a shift
modulo the width.
C says it's undefined, and most if not all implementations make it work
the way the target processor works.
We treat it as setting the destination to 0, regardless of how the
processor on which we're running works.
Credit to OSS-Fuzz for finding this issue.
-rw-r--r-- | bpf_filter.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/bpf_filter.c b/bpf_filter.c index e5c286b5..b19b25d1 100644 --- a/bpf_filter.c +++ b/bpf_filter.c @@ -302,11 +302,17 @@ pcap_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p, continue; case BPF_ALU|BPF_LSH|BPF_X: - A <<= X; + if (X < 32) + A <<= X; + else + A = 0; continue; case BPF_ALU|BPF_RSH|BPF_X: - A >>= X; + if (X < 32) + A >>= X; + else + A = 0; continue; case BPF_ALU|BPF_ADD|BPF_K: |