From dc98bdbbf0f494df010cc0dd55359e593395b302 Mon Sep 17 00:00:00 2001
From: Salvatore Bonaccorso <carnil@debian.org>
Date: Fri, 22 Dec 2017 14:37:21 +0100
Subject: [PATCH 8/8] bpf: fix integer overflows

---
 debian/changelog                                   |   1 +
 .../bugfix/all/bpf-fix-integer-overflows.patch     | 127 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 3 files changed, 129 insertions(+)
 create mode 100644 debian/patches/bugfix/all/bpf-fix-integer-overflows.patch

diff --git a/debian/changelog b/debian/changelog
index 40916d33b..f7c14ab01 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -516,6 +516,7 @@ linux (4.14.7-1) UNRELEASED; urgency=medium
   * bpf: fix missing error return in check_stack_boundary()
   * bpf: force strict alignment checks for stack pointers
   * bpf: don't prune branches when a scalar is replaced with a pointer
+  * bpf: fix integer overflows
 
   [ Vagrant Cascadian ]
   * [armhf, arm64] Backport patches from 4.15.x to support dwmac-sun8i.
diff --git a/debian/patches/bugfix/all/bpf-fix-integer-overflows.patch b/debian/patches/bugfix/all/bpf-fix-integer-overflows.patch
new file mode 100644
index 000000000..b98ca125c
--- /dev/null
+++ b/debian/patches/bugfix/all/bpf-fix-integer-overflows.patch
@@ -0,0 +1,127 @@
+From: Alexei Starovoitov <ast@kernel.org>
+Date: Mon, 18 Dec 2017 20:12:00 -0800
+Subject: bpf: fix integer overflows
+Origin: https://git.kernel.org/linus/bb7f0f989ca7de1153bd128a40a71709e339fa03
+
+There were various issues related to the limited size of integers used in
+the verifier:
+ - `off + size` overflow in __check_map_access()
+ - `off + reg->off` overflow in check_mem_access()
+ - `off + reg->var_off.value` overflow or 32-bit truncation of
+   `reg->var_off.value` in check_mem_access()
+ - 32-bit truncation in check_stack_boundary()
+
+Make sure that any integer math cannot overflow by not allowing
+pointer math with large values.
+
+Also reduce the scope of "scalar op scalar" tracking.
+
+Fixes: f1174f77b50c ("bpf/verifier: rework value tracking")
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+[carnil: backport for 4.14:
+ - 61bd5218eef349fcacc4976a251bc83a4748b4af in v4.15-rc1, "bpf: move global
+   verifier log into verifier environment" introduced that bpf_verifier_env
+   has to be passed all invocations of verbose(). Change invokation to pre-
+   v4.15-rc1 change.
+]
+---
+ include/linux/bpf_verifier.h |  4 ++--
+ kernel/bpf/verifier.c        | 48 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 50 insertions(+), 2 deletions(-)
+
+--- a/include/linux/bpf_verifier.h
++++ b/include/linux/bpf_verifier.h
+@@ -15,11 +15,11 @@
+  * In practice this is far bigger than any realistic pointer offset; this limit
+  * ensures that umax_value + (int)off + (int)size cannot overflow a u64.
+  */
+-#define BPF_MAX_VAR_OFF	(1ULL << 31)
++#define BPF_MAX_VAR_OFF	(1 << 29)
+ /* Maximum variable size permitted for ARG_CONST_SIZE[_OR_ZERO].  This ensures
+  * that converting umax_value to int cannot overflow.
+  */
+-#define BPF_MAX_VAR_SIZ	INT_MAX
++#define BPF_MAX_VAR_SIZ	(1 << 29)
+ 
+ /* Liveness marks, used for registers and spilled-regs (in stack slots).
+  * Read marks propagate upwards until they find a write mark; they record that
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -1789,6 +1789,41 @@ static bool signed_sub_overflows(s64 a,
+ 	return res > a;
+ }
+ 
++static bool check_reg_sane_offset(struct bpf_verifier_env *env,
++				  const struct bpf_reg_state *reg,
++				  enum bpf_reg_type type)
++{
++	bool known = tnum_is_const(reg->var_off);
++	s64 val = reg->var_off.value;
++	s64 smin = reg->smin_value;
++
++	if (known && (val >= BPF_MAX_VAR_OFF || val <= -BPF_MAX_VAR_OFF)) {
++		verbose("math between %s pointer and %lld is not allowed\n",
++			reg_type_str[type], val);
++		return false;
++	}
++
++	if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) {
++		verbose("%s pointer offset %d is not allowed\n",
++			reg_type_str[type], reg->off);
++		return false;
++	}
++
++	if (smin == S64_MIN) {
++		verbose("math between %s pointer and register with unbounded min value is not allowed\n",
++			reg_type_str[type]);
++		return false;
++	}
++
++	if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) {
++		verbose("value %lld makes %s pointer be out of bounds\n",
++			smin, reg_type_str[type]);
++		return false;
++	}
++
++	return true;
++}
++
+ /* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.
+  * Caller should also handle BPF_MOV case separately.
+  * If we return -EACCES, caller may want to try again treating pointer as a
+@@ -1854,6 +1889,10 @@ static int adjust_ptr_min_max_vals(struc
+ 	dst_reg->type = ptr_reg->type;
+ 	dst_reg->id = ptr_reg->id;
+ 
++	if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
++	    !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
++		return -EINVAL;
++
+ 	switch (opcode) {
+ 	case BPF_ADD:
+ 		/* We can take a fixed offset as long as it doesn't overflow
+@@ -1984,6 +2023,9 @@ static int adjust_ptr_min_max_vals(struc
+ 		return -EACCES;
+ 	}
+ 
++	if (!check_reg_sane_offset(env, dst_reg, ptr_reg->type))
++		return -EINVAL;
++
+ 	__update_reg_bounds(dst_reg);
+ 	__reg_deduce_bounds(dst_reg);
+ 	__reg_bound_offset(dst_reg);
+@@ -2013,6 +2055,12 @@ static int adjust_scalar_min_max_vals(st
+ 	src_known = tnum_is_const(src_reg.var_off);
+ 	dst_known = tnum_is_const(dst_reg->var_off);
+ 
++	if (!src_known &&
++	    opcode != BPF_ADD && opcode != BPF_SUB && opcode != BPF_AND) {
++		__mark_reg_unknown(dst_reg);
++		return 0;
++	}
++
+ 	switch (opcode) {
+ 	case BPF_ADD:
+ 		if (signed_add_overflows(dst_reg->smin_value, smin_val) ||
diff --git a/debian/patches/series b/debian/patches/series
index a794a4b37..d41c162ef 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -136,6 +136,7 @@ bugfix/all/bpf-fix-32-bit-ALU-op-verification.patch
 bugfix/all/bpf-fix-missing-error-return-in-check_stack_boundary.patch
 bugfix/all/bpf-force-strict-alignment-checks-for-stack-pointers.patch
 bugfix/all/bpf-don-t-prune-branches-when-a-scalar-is-replaced-w.patch
+bugfix/all/bpf-fix-integer-overflows.patch
 
 # Fix exported symbol versions
 bugfix/all/module-disable-matching-missing-version-crc.patch
-- 
2.15.1

