summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2019-01-02 18:58:31 -0500
committerAlexei Starovoitov <ast@kernel.org>2019-01-02 19:01:24 -0500
commite4298d25830a866cc0f427d4bccb858e76715859 (patch)
treea3915815e64315b9c2b16cb78783a7a821597270
parent0d6303db7970e6f56ae700fa07e11eb510cda125 (diff)
bpf: restrict stack pointer arithmetic for unprivileged
Restrict stack pointer arithmetic for unprivileged users in that arithmetic itself must not go out of bounds as opposed to the actual access later on. Therefore after each adjust_ptr_min_max_vals() with a stack pointer as a destination we simulate a check_stack_access() of 1 byte on the destination and once that fails the program is rejected for unprivileged program loads. This is analog to map value pointer arithmetic and needed for masking later on. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r--kernel/bpf/verifier.c63
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
1390static 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() */
1391static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off, 1416static 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;