diff options
| -rw-r--r-- | kernel/bpf/verifier.c | 8 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 14 |
2 files changed, 20 insertions, 2 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 8b8d6ba39e23..20f3889c006e 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
| @@ -1116,7 +1116,12 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn | |||
| 1116 | /* ctx accesses must be at a fixed offset, so that we can | 1116 | /* ctx accesses must be at a fixed offset, so that we can |
| 1117 | * determine what type of data were returned. | 1117 | * determine what type of data were returned. |
| 1118 | */ | 1118 | */ |
| 1119 | if (!tnum_is_const(reg->var_off)) { | 1119 | if (reg->off) { |
| 1120 | verbose("dereference of modified ctx ptr R%d off=%d+%d, ctx+const is allowed, ctx+const+const is not\n", | ||
| 1121 | regno, reg->off, off - reg->off); | ||
| 1122 | return -EACCES; | ||
| 1123 | } | ||
| 1124 | if (!tnum_is_const(reg->var_off) || reg->var_off.value) { | ||
| 1120 | char tn_buf[48]; | 1125 | char tn_buf[48]; |
| 1121 | 1126 | ||
| 1122 | tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); | 1127 | tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); |
| @@ -1124,7 +1129,6 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn | |||
| 1124 | tn_buf, off, size); | 1129 | tn_buf, off, size); |
| 1125 | return -EACCES; | 1130 | return -EACCES; |
| 1126 | } | 1131 | } |
| 1127 | off += reg->var_off.value; | ||
| 1128 | err = check_ctx_access(env, insn_idx, off, size, t, ®_type); | 1132 | err = check_ctx_access(env, insn_idx, off, size, t, ®_type); |
| 1129 | if (!err && t == BPF_READ && value_regno >= 0) { | 1133 | if (!err && t == BPF_READ && value_regno >= 0) { |
| 1130 | /* ctx access returns either a scalar, or a | 1134 | /* ctx access returns either a scalar, or a |
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 26f3250bdcd2..3c7d3a45a3c5 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c | |||
| @@ -6645,6 +6645,20 @@ static struct bpf_test tests[] = { | |||
| 6645 | .errstr = "BPF_END uses reserved fields", | 6645 | .errstr = "BPF_END uses reserved fields", |
| 6646 | .result = REJECT, | 6646 | .result = REJECT, |
| 6647 | }, | 6647 | }, |
| 6648 | { | ||
| 6649 | "arithmetic ops make PTR_TO_CTX unusable", | ||
| 6650 | .insns = { | ||
| 6651 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, | ||
| 6652 | offsetof(struct __sk_buff, data) - | ||
| 6653 | offsetof(struct __sk_buff, mark)), | ||
| 6654 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, | ||
| 6655 | offsetof(struct __sk_buff, mark)), | ||
| 6656 | BPF_EXIT_INSN(), | ||
| 6657 | }, | ||
| 6658 | .errstr = "dereference of modified ctx ptr R1 off=68+8, ctx+const is allowed, ctx+const+const is not", | ||
| 6659 | .result = REJECT, | ||
| 6660 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 6661 | }, | ||
| 6648 | }; | 6662 | }; |
| 6649 | 6663 | ||
| 6650 | static int probe_filter_length(const struct bpf_insn *fp) | 6664 | static int probe_filter_length(const struct bpf_insn *fp) |
