History

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.

Alexei Starovoitov committed 8 years ago

Commit bb7f0f91 parent 179d1c52 files · +50 −2Browse files

Unified · Split

2 files
  1. include/linux/bpf_verifier.h +2 −2
  2. kernel/bpf/verifier.c +48 −0
include/linux/bpf_verifier.h+2−2
@@ -15,11 +15,11 @@ · 14 unmodified lines
15 * In practice this is far bigger than any realistic pointer offset; this limit15 * In practice this is far bigger than any realistic pointer offset; this limit
16 * ensures that umax_value + (int)off + (int)size cannot overflow a u64.16 * ensures that umax_value + (int)off + (int)size cannot overflow a u64.
17 */17 */
18#define BPF_MAX_VAR_OFF (1ULL << 31)18#define BPF_MAX_VAR_OFF (1 << 29)
19/* Maximum variable size permitted for ARG_CONST_SIZE[_OR_ZERO]. This ensures19/* Maximum variable size permitted for ARG_CONST_SIZE[_OR_ZERO]. This ensures
20 * that converting umax_value to int cannot overflow.20 * that converting umax_value to int cannot overflow.
21 */21 */
22#define BPF_MAX_VAR_SIZ INT_MAX22#define BPF_MAX_VAR_SIZ (1 << 29)
23 23
24/* Liveness marks, used for registers and spilled-regs (in stack slots).24/* Liveness marks, used for registers and spilled-regs (in stack slots).
25 * Read marks propagate upwards until they find a write mark; they record that25 * Read marks propagate upwards until they find a write mark; they record that
kernel/bpf/verifier.c+48−0
@@ -1819,6 +1819,41 @@ static bool signed_sub_overflows(s64 a, s64 b) · 1818 unmodified lines
1819 return res > a;1819 return res > a;
1820}1820}
1821 1821
1822static 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
1822/* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.1857/* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.
1823 * Caller should also handle BPF_MOV case separately.1858 * Caller should also handle BPF_MOV case separately.
1824 * If we return -EACCES, caller may want to try again treating pointer as a1859 * 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, · 62 unmodified lines
1887 dst_reg->type = ptr_reg->type;1922 dst_reg->type = ptr_reg->type;
1888 dst_reg->id = ptr_reg->id;1923 dst_reg->id = ptr_reg->id;
1889 1924
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
1890 switch (opcode) {1929 switch (opcode) {
1891 case BPF_ADD:1930 case BPF_ADD:
1892 /* We can take a fixed offset as long as it doesn't overflow1931 /* 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, · 124 unmodified lines
2017 return -EACCES;2056 return -EACCES;
2018 }2057 }
2019 2058
2059 if (!check_reg_sane_offset(env, dst_reg, ptr_reg->type))
2060 return -EINVAL;
2061
2020 __update_reg_bounds(dst_reg);2062 __update_reg_bounds(dst_reg);
2021 __reg_deduce_bounds(dst_reg);2063 __reg_deduce_bounds(dst_reg);
2022 __reg_bound_offset(dst_reg);2064 __reg_bound_offset(dst_reg);
@@ -2046,6 +2088,12 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, · 23 unmodified lines
2046 src_known = tnum_is_const(src_reg.var_off);2088 src_known = tnum_is_const(src_reg.var_off);
2047 dst_known = tnum_is_const(dst_reg->var_off);2089 dst_known = tnum_is_const(dst_reg->var_off);
2048 2090
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
2049 switch (opcode) {2097 switch (opcode) {
2050 case BPF_ADD:2098 case BPF_ADD:
2051 if (signed_add_overflows(dst_reg->smin_value, smin_val) ||2099 if (signed_add_overflows(dst_reg->smin_value, smin_val) ||

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t