bpf: Test ref release issue in bpf_tcp_sock and bpf_sk_fullsock
Adding verifier tests to ensure the ptr returned from bpf_tcp_sock() and bpf_sk_fullsock() cannot be accessed after bpf_sk_release() is called. A few of the tests are derived from a reproducer test by Lorenz Bauer. Signed-off-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:

committed by
Alexei Starovoitov

parent
ef776a272b
commit
b55aa7b04b
@@ -605,3 +605,171 @@
|
|||||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
.result = ACCEPT,
|
.result = ACCEPT,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"reference tracking: use ptr from bpf_tcp_sock() after release",
|
||||||
|
.insns = {
|
||||||
|
BPF_SK_LOOKUP,
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_tcp_sock, snd_cwnd)),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
|
.result = REJECT,
|
||||||
|
.errstr = "invalid mem access",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reference tracking: use ptr from bpf_sk_fullsock() after release",
|
||||||
|
.insns = {
|
||||||
|
BPF_SK_LOOKUP,
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
|
.result = REJECT,
|
||||||
|
.errstr = "invalid mem access",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reference tracking: use ptr from bpf_sk_fullsock(tp) after release",
|
||||||
|
.insns = {
|
||||||
|
BPF_SK_LOOKUP,
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
|
.result = REJECT,
|
||||||
|
.errstr = "invalid mem access",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reference tracking: use sk after bpf_sk_release(tp)",
|
||||||
|
.insns = {
|
||||||
|
BPF_SK_LOOKUP,
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
|
.result = REJECT,
|
||||||
|
.errstr = "invalid mem access",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reference tracking: use ptr from bpf_get_listener_sock() after bpf_sk_release(sk)",
|
||||||
|
.insns = {
|
||||||
|
BPF_SK_LOOKUP,
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_get_listener_sock),
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, src_port)),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
|
.result = ACCEPT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reference tracking: bpf_sk_release(listen_sk)",
|
||||||
|
.insns = {
|
||||||
|
BPF_SK_LOOKUP,
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_get_listener_sock),
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
|
.result = REJECT,
|
||||||
|
.errstr = "reference has not been acquired before",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* !bpf_sk_fullsock(sk) is checked but !bpf_tcp_sock(sk) is not checked */
|
||||||
|
"reference tracking: tp->snd_cwnd after bpf_sk_fullsock(sk) and bpf_tcp_sock(sk)",
|
||||||
|
.insns = {
|
||||||
|
BPF_SK_LOOKUP,
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
|
||||||
|
BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
|
||||||
|
BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
|
||||||
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 3),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_8, offsetof(struct bpf_tcp_sock, snd_cwnd)),
|
||||||
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
||||||
|
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||||
|
BPF_EXIT_INSN(),
|
||||||
|
},
|
||||||
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
|
.result = REJECT,
|
||||||
|
.errstr = "invalid mem access",
|
||||||
|
},
|
||||||
|
@@ -342,7 +342,7 @@
|
|||||||
},
|
},
|
||||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
.result = REJECT,
|
.result = REJECT,
|
||||||
.errstr = "type=sock_common expected=sock",
|
.errstr = "reference has not been acquired before",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bpf_sk_release(bpf_sk_fullsock(skb->sk))",
|
"bpf_sk_release(bpf_sk_fullsock(skb->sk))",
|
||||||
@@ -380,5 +380,5 @@
|
|||||||
},
|
},
|
||||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||||
.result = REJECT,
|
.result = REJECT,
|
||||||
.errstr = "type=tcp_sock expected=sock",
|
.errstr = "reference has not been acquired before",
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user