aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJann Horn <jannh@google.com>2018-10-05 12:17:59 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-10-05 12:41:45 -0400
commitb799207e1e1816b09e7a5920fbb2d5fcf6edd681 (patch)
treec3e93b0287fc25e137120342f98953362a27a555
parentb0584ea66d73919cbf5878a3420a837f06ab8396 (diff)
bpf: 32-bit RSH verification must truncate input before the ALU op
When I wrote commit 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification"), I assumed that, in order to emulate 64-bit arithmetic with 32-bit logic, it is sufficient to just truncate the output to 32 bits; and so I just moved the register size coercion that used to be at the start of the function to the end of the function. That assumption is true for almost every op, but not for 32-bit right shifts, because those can propagate information towards the least significant bit. Fix it by always truncating inputs for 32-bit ops to 32 bits. Also get rid of the coerce_reg_to_size() after the ALU op, since that has no effect. Fixes: 468f6eafa6c4 ("bpf: fix 32-bit ALU op verification") Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Jann Horn <jannh@google.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--kernel/bpf/verifier.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index bb07e74b34a2..465952a8e465 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2896,6 +2896,15 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
2896 u64 umin_val, umax_val; 2896 u64 umin_val, umax_val;
2897 u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32; 2897 u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
2898 2898
2899 if (insn_bitness == 32) {
2900 /* Relevant for 32-bit RSH: Information can propagate towards
2901 * LSB, so it isn't sufficient to only truncate the output to
2902 * 32 bits.
2903 */
2904 coerce_reg_to_size(dst_reg, 4);
2905 coerce_reg_to_size(&src_reg, 4);
2906 }
2907
2899 smin_val = src_reg.smin_value; 2908 smin_val = src_reg.smin_value;
2900 smax_val = src_reg.smax_value; 2909 smax_val = src_reg.smax_value;
2901 umin_val = src_reg.umin_value; 2910 umin_val = src_reg.umin_value;
@@ -3131,7 +3140,6 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
3131 if (BPF_CLASS(insn->code) != BPF_ALU64) { 3140 if (BPF_CLASS(insn->code) != BPF_ALU64) {
3132 /* 32-bit ALU ops are (32,32)->32 */ 3141 /* 32-bit ALU ops are (32,32)->32 */
3133 coerce_reg_to_size(dst_reg, 4); 3142 coerce_reg_to_size(dst_reg, 4);
3134 coerce_reg_to_size(&src_reg, 4);
3135 } 3143 }
3136 3144
3137 __reg_deduce_bounds(dst_reg); 3145 __reg_deduce_bounds(dst_reg);