Skip to content

Commit f37a8cb

Browse files
borkmannAlexei Starovoitov
authored andcommitted
bpf: reject stores into ctx via st and xadd
Alexei found that verifier does not reject stores into context via BPF_ST instead of BPF_STX. And while looking at it, we also should not allow XADD variant of BPF_STX. The context rewriter is only assuming either BPF_LDX_MEM- or BPF_STX_MEM-type operations, thus reject anything other than that so that assumptions in the rewriter properly hold. Add test cases as well for BPF selftests. Fixes: d691f9e ("bpf: allow programs to write to certain skb fields") Reported-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent a2284d9 commit f37a8cb

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

kernel/bpf/verifier.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,13 @@ static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
978978
return __is_pointer_value(env->allow_ptr_leaks, cur_regs(env) + regno);
979979
}
980980

981+
static bool is_ctx_reg(struct bpf_verifier_env *env, int regno)
982+
{
983+
const struct bpf_reg_state *reg = cur_regs(env) + regno;
984+
985+
return reg->type == PTR_TO_CTX;
986+
}
987+
981988
static int check_pkt_ptr_alignment(struct bpf_verifier_env *env,
982989
const struct bpf_reg_state *reg,
983990
int off, int size, bool strict)
@@ -1258,6 +1265,12 @@ static int check_xadd(struct bpf_verifier_env *env, int insn_idx, struct bpf_ins
12581265
return -EACCES;
12591266
}
12601267

1268+
if (is_ctx_reg(env, insn->dst_reg)) {
1269+
verbose(env, "BPF_XADD stores into R%d context is not allowed\n",
1270+
insn->dst_reg);
1271+
return -EACCES;
1272+
}
1273+
12611274
/* check whether atomic_add can read the memory */
12621275
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
12631276
BPF_SIZE(insn->code), BPF_READ, -1);
@@ -3993,6 +4006,12 @@ static int do_check(struct bpf_verifier_env *env)
39934006
if (err)
39944007
return err;
39954008

4009+
if (is_ctx_reg(env, insn->dst_reg)) {
4010+
verbose(env, "BPF_ST stores into R%d context is not allowed\n",
4011+
insn->dst_reg);
4012+
return -EACCES;
4013+
}
4014+
39964015
/* check that memory (dst_reg + off) is writeable */
39974016
err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
39984017
BPF_SIZE(insn->code), BPF_WRITE,

tools/testing/selftests/bpf/test_verifier.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2592,6 +2592,29 @@ static struct bpf_test tests[] = {
25922592
.result = ACCEPT,
25932593
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
25942594
},
2595+
{
2596+
"context stores via ST",
2597+
.insns = {
2598+
BPF_MOV64_IMM(BPF_REG_0, 0),
2599+
BPF_ST_MEM(BPF_DW, BPF_REG_1, offsetof(struct __sk_buff, mark), 0),
2600+
BPF_EXIT_INSN(),
2601+
},
2602+
.errstr = "BPF_ST stores into R1 context is not allowed",
2603+
.result = REJECT,
2604+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
2605+
},
2606+
{
2607+
"context stores via XADD",
2608+
.insns = {
2609+
BPF_MOV64_IMM(BPF_REG_0, 0),
2610+
BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_W, BPF_REG_1,
2611+
BPF_REG_0, offsetof(struct __sk_buff, mark), 0),
2612+
BPF_EXIT_INSN(),
2613+
},
2614+
.errstr = "BPF_XADD stores into R1 context is not allowed",
2615+
.result = REJECT,
2616+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
2617+
},
25952618
{
25962619
"direct packet access: test1",
25972620
.insns = {
@@ -4312,7 +4335,8 @@ static struct bpf_test tests[] = {
43124335
.fixup_map1 = { 2 },
43134336
.errstr_unpriv = "R2 leaks addr into mem",
43144337
.result_unpriv = REJECT,
4315-
.result = ACCEPT,
4338+
.result = REJECT,
4339+
.errstr = "BPF_XADD stores into R1 context is not allowed",
43164340
},
43174341
{
43184342
"leak pointer into ctx 2",
@@ -4326,7 +4350,8 @@ static struct bpf_test tests[] = {
43264350
},
43274351
.errstr_unpriv = "R10 leaks addr into mem",
43284352
.result_unpriv = REJECT,
4329-
.result = ACCEPT,
4353+
.result = REJECT,
4354+
.errstr = "BPF_XADD stores into R1 context is not allowed",
43304355
},
43314356
{
43324357
"leak pointer into ctx 3",

0 commit comments

Comments
 (0)