Skip to content

Commit 2cb494a

Browse files
liu-song-6Alexei Starovoitov
authored andcommitted
bpf: add tests for direct packet access from CGROUP_SKB
Tests are added to make sure CGROUP_SKB cannot access: tc_classid, data_meta, flow_keys and can read and write: mark, prority, and cb[0-4] and can read other fields. To make selftest with skb->sk work, a dummy sk is added in bpf_prog_test_run_skb(). Signed-off-by: Song Liu <songliubraving@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent b39b5f4 commit 2cb494a

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

net/bpf/test_run.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <linux/etherdevice.h>
1111
#include <linux/filter.h>
1212
#include <linux/sched/signal.h>
13+
#include <net/sock.h>
14+
#include <net/tcp.h>
1315

1416
static __always_inline u32 bpf_test_run_one(struct bpf_prog *prog, void *ctx,
1517
struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE])
@@ -115,6 +117,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
115117
u32 retval, duration;
116118
int hh_len = ETH_HLEN;
117119
struct sk_buff *skb;
120+
struct sock *sk;
118121
void *data;
119122
int ret;
120123

@@ -137,11 +140,21 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
137140
break;
138141
}
139142

143+
sk = kzalloc(sizeof(struct sock), GFP_USER);
144+
if (!sk) {
145+
kfree(data);
146+
return -ENOMEM;
147+
}
148+
sock_net_set(sk, current->nsproxy->net_ns);
149+
sock_init_data(NULL, sk);
150+
140151
skb = build_skb(data, 0);
141152
if (!skb) {
142153
kfree(data);
154+
kfree(sk);
143155
return -ENOMEM;
144156
}
157+
skb->sk = sk;
145158

146159
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
147160
__skb_put(skb, size);
@@ -159,6 +172,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
159172

160173
if (pskb_expand_head(skb, nhead, 0, GFP_USER)) {
161174
kfree_skb(skb);
175+
kfree(sk);
162176
return -ENOMEM;
163177
}
164178
}
@@ -171,6 +185,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
171185
size = skb_headlen(skb);
172186
ret = bpf_test_finish(kattr, uattr, skb->data, size, retval, duration);
173187
kfree_skb(skb);
188+
kfree(sk);
174189
return ret;
175190
}
176191

tools/testing/selftests/bpf/test_verifier.c

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4862,6 +4862,177 @@ static struct bpf_test tests[] = {
48624862
.result = REJECT,
48634863
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
48644864
},
4865+
{
4866+
"direct packet read test#1 for CGROUP_SKB",
4867+
.insns = {
4868+
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
4869+
offsetof(struct __sk_buff, data)),
4870+
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
4871+
offsetof(struct __sk_buff, data_end)),
4872+
BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
4873+
offsetof(struct __sk_buff, len)),
4874+
BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4875+
offsetof(struct __sk_buff, pkt_type)),
4876+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4877+
offsetof(struct __sk_buff, mark)),
4878+
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_6,
4879+
offsetof(struct __sk_buff, mark)),
4880+
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
4881+
offsetof(struct __sk_buff, queue_mapping)),
4882+
BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
4883+
offsetof(struct __sk_buff, protocol)),
4884+
BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
4885+
offsetof(struct __sk_buff, vlan_present)),
4886+
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
4887+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
4888+
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
4889+
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
4890+
BPF_MOV64_IMM(BPF_REG_0, 0),
4891+
BPF_EXIT_INSN(),
4892+
},
4893+
.result = ACCEPT,
4894+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4895+
},
4896+
{
4897+
"direct packet read test#2 for CGROUP_SKB",
4898+
.insns = {
4899+
BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
4900+
offsetof(struct __sk_buff, vlan_tci)),
4901+
BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4902+
offsetof(struct __sk_buff, vlan_proto)),
4903+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4904+
offsetof(struct __sk_buff, priority)),
4905+
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_6,
4906+
offsetof(struct __sk_buff, priority)),
4907+
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
4908+
offsetof(struct __sk_buff,
4909+
ingress_ifindex)),
4910+
BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
4911+
offsetof(struct __sk_buff, tc_index)),
4912+
BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
4913+
offsetof(struct __sk_buff, hash)),
4914+
BPF_MOV64_IMM(BPF_REG_0, 0),
4915+
BPF_EXIT_INSN(),
4916+
},
4917+
.result = ACCEPT,
4918+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4919+
},
4920+
{
4921+
"direct packet read test#3 for CGROUP_SKB",
4922+
.insns = {
4923+
BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
4924+
offsetof(struct __sk_buff, cb[0])),
4925+
BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4926+
offsetof(struct __sk_buff, cb[1])),
4927+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4928+
offsetof(struct __sk_buff, cb[2])),
4929+
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
4930+
offsetof(struct __sk_buff, cb[3])),
4931+
BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
4932+
offsetof(struct __sk_buff, cb[4])),
4933+
BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
4934+
offsetof(struct __sk_buff, napi_id)),
4935+
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_4,
4936+
offsetof(struct __sk_buff, cb[0])),
4937+
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_5,
4938+
offsetof(struct __sk_buff, cb[1])),
4939+
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_6,
4940+
offsetof(struct __sk_buff, cb[2])),
4941+
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_7,
4942+
offsetof(struct __sk_buff, cb[3])),
4943+
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_8,
4944+
offsetof(struct __sk_buff, cb[4])),
4945+
BPF_MOV64_IMM(BPF_REG_0, 0),
4946+
BPF_EXIT_INSN(),
4947+
},
4948+
.result = ACCEPT,
4949+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4950+
},
4951+
{
4952+
"direct packet read test#4 for CGROUP_SKB",
4953+
.insns = {
4954+
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
4955+
offsetof(struct __sk_buff, family)),
4956+
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
4957+
offsetof(struct __sk_buff, remote_ip4)),
4958+
BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
4959+
offsetof(struct __sk_buff, local_ip4)),
4960+
BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4961+
offsetof(struct __sk_buff, remote_ip6[0])),
4962+
BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4963+
offsetof(struct __sk_buff, remote_ip6[1])),
4964+
BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4965+
offsetof(struct __sk_buff, remote_ip6[2])),
4966+
BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1,
4967+
offsetof(struct __sk_buff, remote_ip6[3])),
4968+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4969+
offsetof(struct __sk_buff, local_ip6[0])),
4970+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4971+
offsetof(struct __sk_buff, local_ip6[1])),
4972+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4973+
offsetof(struct __sk_buff, local_ip6[2])),
4974+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
4975+
offsetof(struct __sk_buff, local_ip6[3])),
4976+
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
4977+
offsetof(struct __sk_buff, remote_port)),
4978+
BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
4979+
offsetof(struct __sk_buff, local_port)),
4980+
BPF_MOV64_IMM(BPF_REG_0, 0),
4981+
BPF_EXIT_INSN(),
4982+
},
4983+
.result = ACCEPT,
4984+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4985+
},
4986+
{
4987+
"invalid access of tc_classid for CGROUP_SKB",
4988+
.insns = {
4989+
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
4990+
offsetof(struct __sk_buff, tc_classid)),
4991+
BPF_MOV64_IMM(BPF_REG_0, 0),
4992+
BPF_EXIT_INSN(),
4993+
},
4994+
.result = REJECT,
4995+
.errstr = "invalid bpf_context access",
4996+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
4997+
},
4998+
{
4999+
"invalid access of data_meta for CGROUP_SKB",
5000+
.insns = {
5001+
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
5002+
offsetof(struct __sk_buff, data_meta)),
5003+
BPF_MOV64_IMM(BPF_REG_0, 0),
5004+
BPF_EXIT_INSN(),
5005+
},
5006+
.result = REJECT,
5007+
.errstr = "invalid bpf_context access",
5008+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5009+
},
5010+
{
5011+
"invalid access of flow_keys for CGROUP_SKB",
5012+
.insns = {
5013+
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
5014+
offsetof(struct __sk_buff, flow_keys)),
5015+
BPF_MOV64_IMM(BPF_REG_0, 0),
5016+
BPF_EXIT_INSN(),
5017+
},
5018+
.result = REJECT,
5019+
.errstr = "invalid bpf_context access",
5020+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5021+
},
5022+
{
5023+
"invalid write access to napi_id for CGROUP_SKB",
5024+
.insns = {
5025+
BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_1,
5026+
offsetof(struct __sk_buff, napi_id)),
5027+
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_9,
5028+
offsetof(struct __sk_buff, napi_id)),
5029+
BPF_MOV64_IMM(BPF_REG_0, 0),
5030+
BPF_EXIT_INSN(),
5031+
},
5032+
.result = REJECT,
5033+
.errstr = "invalid bpf_context access",
5034+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5035+
},
48655036
{
48665037
"valid cgroup storage access",
48675038
.insns = {

0 commit comments

Comments
 (0)