diff options
-rw-r--r-- | kernel/bpf/verifier.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 4da8c73e168f..9ac205d1b8b7 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -1387,6 +1387,31 @@ static int check_stack_read(struct bpf_verifier_env *env, | |||
1387 | } | 1387 | } |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | static int check_stack_access(struct bpf_verifier_env *env, | ||
1391 | const struct bpf_reg_state *reg, | ||
1392 | int off, int size) | ||
1393 | { | ||
1394 | /* Stack accesses must be at a fixed offset, so that we | ||
1395 | * can determine what type of data were returned. See | ||
1396 | * check_stack_read(). | ||
1397 | */ | ||
1398 | if (!tnum_is_const(reg->var_off)) { | ||
1399 | char tn_buf[48]; | ||
1400 | |||
1401 | tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); | ||
1402 | verbose(env, "variable stack access var_off=%s off=%d size=%d", | ||
1403 | tn_buf, off, size); | ||
1404 | return -EACCES; | ||
1405 | } | ||
1406 | |||
1407 | if (off >= 0 || off < -MAX_BPF_STACK) { | ||
1408 | verbose(env, "invalid stack off=%d size=%d\n", off, size); | ||
1409 | return -EACCES; | ||
1410 | } | ||
1411 | |||
1412 | return 0; | ||
1413 | } | ||
1414 | |||
1390 | /* check read/write into map element returned by bpf_map_lookup_elem() */ | 1415 | /* check read/write into map element returned by bpf_map_lookup_elem() */ |
1391 | static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off, | 1416 | static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off, |
1392 | int size, bool zero_size_allowed) | 1417 | int size, bool zero_size_allowed) |
@@ -1954,24 +1979,10 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn | |||
1954 | } | 1979 | } |
1955 | 1980 | ||
1956 | } else if (reg->type == PTR_TO_STACK) { | 1981 | } else if (reg->type == PTR_TO_STACK) { |
1957 | /* stack accesses must be at a fixed offset, so that we can | ||
1958 | * determine what type of data were returned. | ||
1959 | * See check_stack_read(). | ||
1960 | */ | ||
1961 | if (!tnum_is_const(reg->var_off)) { | ||
1962 | char tn_buf[48]; | ||
1963 | |||
1964 | tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); | ||
1965 | verbose(env, "variable stack access var_off=%s off=%d size=%d", | ||
1966 | tn_buf, off, size); | ||
1967 | return -EACCES; | ||
1968 | } | ||
1969 | off += reg->var_off.value; | 1982 | off += reg->var_off.value; |
1970 | if (off >= 0 || off < -MAX_BPF_STACK) { | 1983 | err = check_stack_access(env, reg, off, size); |
1971 | verbose(env, "invalid stack off=%d size=%d\n", off, | 1984 | if (err) |
1972 | size); | 1985 | return err; |
1973 | return -EACCES; | ||
1974 | } | ||
1975 | 1986 | ||
1976 | state = func(env, reg); | 1987 | state = func(env, reg); |
1977 | err = update_stack_depth(env, state, off); | 1988 | err = update_stack_depth(env, state, off); |
@@ -3253,11 +3264,19 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, | |||
3253 | /* For unprivileged we require that resulting offset must be in bounds | 3264 | /* For unprivileged we require that resulting offset must be in bounds |
3254 | * in order to be able to sanitize access later on. | 3265 | * in order to be able to sanitize access later on. |
3255 | */ | 3266 | */ |
3256 | if (!env->allow_ptr_leaks && dst_reg->type == PTR_TO_MAP_VALUE && | 3267 | if (!env->allow_ptr_leaks) { |
3257 | check_map_access(env, dst, dst_reg->off, 1, false)) { | 3268 | if (dst_reg->type == PTR_TO_MAP_VALUE && |
3258 | verbose(env, "R%d pointer arithmetic of map value goes out of range, prohibited for !root\n", | 3269 | check_map_access(env, dst, dst_reg->off, 1, false)) { |
3259 | dst); | 3270 | verbose(env, "R%d pointer arithmetic of map value goes out of range, " |
3260 | return -EACCES; | 3271 | "prohibited for !root\n", dst); |
3272 | return -EACCES; | ||
3273 | } else if (dst_reg->type == PTR_TO_STACK && | ||
3274 | check_stack_access(env, dst_reg, dst_reg->off + | ||
3275 | dst_reg->var_off.value, 1)) { | ||
3276 | verbose(env, "R%d stack pointer arithmetic goes out of range, " | ||
3277 | "prohibited for !root\n", dst); | ||
3278 | return -EACCES; | ||
3279 | } | ||
3261 | } | 3280 | } |
3262 | 3281 | ||
3263 | return 0; | 3282 | return 0; |