Skip to content

Commit bb7f0f9

Browse files
Alexei Starovoitovborkmann
authored andcommitted
bpf: fix integer overflows
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: f1174f7 ("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>
1 parent 179d1c5 commit bb7f0f9

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

include/linux/bpf_verifier.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
* In practice this is far bigger than any realistic pointer offset; this limit
1616
* ensures that umax_value + (int)off + (int)size cannot overflow a u64.
1717
*/
18-
#define BPF_MAX_VAR_OFF (1ULL << 31)
18+
#define BPF_MAX_VAR_OFF (1 << 29)
1919
/* Maximum variable size permitted for ARG_CONST_SIZE[_OR_ZERO]. This ensures
2020
* that converting umax_value to int cannot overflow.
2121
*/
22-
#define BPF_MAX_VAR_SIZ INT_MAX
22+
#define BPF_MAX_VAR_SIZ (1 << 29)
2323

2424
/* Liveness marks, used for registers and spilled-regs (in stack slots).
2525
* Read marks propagate upwards until they find a write mark; they record that

kernel/bpf/verifier.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,41 @@ static bool signed_sub_overflows(s64 a, s64 b)
18191819
return res > a;
18201820
}
18211821

1822+
static bool check_reg_sane_offset(struct bpf_verifier_env *env,
1823+
const struct bpf_reg_state *reg,
1824+
enum bpf_reg_type type)
1825+
{
1826+
bool known = tnum_is_const(reg->var_off);
1827+
s64 val = reg->var_off.value;
1828+
s64 smin = reg->smin_value;
1829+
1830+
if (known && (val >= BPF_MAX_VAR_OFF || val <= -BPF_MAX_VAR_OFF)) {
1831+
verbose(env, "math between %s pointer and %lld is not allowed\n",
1832+
reg_type_str[type], val);
1833+
return false;
1834+
}
1835+
1836+
if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) {
1837+
verbose(env, "%s pointer offset %d is not allowed\n",
1838+
reg_type_str[type], reg->off);
1839+
return false;
1840+
}
1841+
1842+
if (smin == S64_MIN) {
1843+
verbose(env, "math between %s pointer and register with unbounded min value is not allowed\n",
1844+
reg_type_str[type]);
1845+
return false;
1846+
}
1847+
1848+
if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) {
1849+
verbose(env, "value %lld makes %s pointer be out of bounds\n",
1850+
smin, reg_type_str[type]);
1851+
return false;
1852+
}
1853+
1854+
return true;
1855+
}
1856+
18221857
/* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.
18231858
* Caller should also handle BPF_MOV case separately.
18241859
* If we return -EACCES, caller may want to try again treating pointer as a
@@ -1887,6 +1922,10 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
18871922
dst_reg->type = ptr_reg->type;
18881923
dst_reg->id = ptr_reg->id;
18891924

1925+
if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
1926+
!check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
1927+
return -EINVAL;
1928+
18901929
switch (opcode) {
18911930
case BPF_ADD:
18921931
/* We can take a fixed offset as long as it doesn't overflow
@@ -2017,6 +2056,9 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
20172056
return -EACCES;
20182057
}
20192058

2059+
if (!check_reg_sane_offset(env, dst_reg, ptr_reg->type))
2060+
return -EINVAL;
2061+
20202062
__update_reg_bounds(dst_reg);
20212063
__reg_deduce_bounds(dst_reg);
20222064
__reg_bound_offset(dst_reg);
@@ -2046,6 +2088,12 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
20462088
src_known = tnum_is_const(src_reg.var_off);
20472089
dst_known = tnum_is_const(dst_reg->var_off);
20482090

2091+
if (!src_known &&
2092+
opcode != BPF_ADD && opcode != BPF_SUB && opcode != BPF_AND) {
2093+
__mark_reg_unknown(dst_reg);
2094+
return 0;
2095+
}
2096+
20492097
switch (opcode) {
20502098
case BPF_ADD:
20512099
if (signed_add_overflows(dst_reg->smin_value, smin_val) ||

0 commit comments

Comments
 (0)