Skip to content

Commit c6f420a

Browse files
kkdwivediAlexei Starovoitov
authored andcommitted
selftests/bpf: Add negative tests for new nf_conntrack kfuncs
Test cases we care about and ensure improper usage is caught and rejected by the verifier. Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 6eb7fba commit c6f420a

File tree

2 files changed

+189
-1
lines changed

2 files changed

+189
-1
lines changed

tools/testing/selftests/bpf/prog_tests/bpf_nf.c

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,29 @@
22
#include <test_progs.h>
33
#include <network_helpers.h>
44
#include "test_bpf_nf.skel.h"
5+
#include "test_bpf_nf_fail.skel.h"
6+
7+
static char log_buf[1024 * 1024];
8+
9+
struct {
10+
const char *prog_name;
11+
const char *err_msg;
12+
} test_bpf_nf_fail_tests[] = {
13+
{ "alloc_release", "kernel function bpf_ct_release args#0 expected pointer to STRUCT nf_conn but" },
14+
{ "insert_insert", "kernel function bpf_ct_insert_entry args#0 expected pointer to STRUCT nf_conn___init but" },
15+
{ "lookup_insert", "kernel function bpf_ct_insert_entry args#0 expected pointer to STRUCT nf_conn___init but" },
16+
{ "set_timeout_after_insert", "kernel function bpf_ct_set_timeout args#0 expected pointer to STRUCT nf_conn___init but" },
17+
{ "set_status_after_insert", "kernel function bpf_ct_set_status args#0 expected pointer to STRUCT nf_conn___init but" },
18+
{ "change_timeout_after_alloc", "kernel function bpf_ct_change_timeout args#0 expected pointer to STRUCT nf_conn but" },
19+
{ "change_status_after_alloc", "kernel function bpf_ct_change_status args#0 expected pointer to STRUCT nf_conn but" },
20+
};
521

622
enum {
723
TEST_XDP,
824
TEST_TC_BPF,
925
};
1026

11-
void test_bpf_nf_ct(int mode)
27+
static void test_bpf_nf_ct(int mode)
1228
{
1329
struct test_bpf_nf *skel;
1430
int prog_fd, err;
@@ -51,10 +67,48 @@ void test_bpf_nf_ct(int mode)
5167
test_bpf_nf__destroy(skel);
5268
}
5369

70+
static void test_bpf_nf_ct_fail(const char *prog_name, const char *err_msg)
71+
{
72+
LIBBPF_OPTS(bpf_object_open_opts, opts, .kernel_log_buf = log_buf,
73+
.kernel_log_size = sizeof(log_buf),
74+
.kernel_log_level = 1);
75+
struct test_bpf_nf_fail *skel;
76+
struct bpf_program *prog;
77+
int ret;
78+
79+
skel = test_bpf_nf_fail__open_opts(&opts);
80+
if (!ASSERT_OK_PTR(skel, "test_bpf_nf_fail__open"))
81+
return;
82+
83+
prog = bpf_object__find_program_by_name(skel->obj, prog_name);
84+
if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
85+
goto end;
86+
87+
bpf_program__set_autoload(prog, true);
88+
89+
ret = test_bpf_nf_fail__load(skel);
90+
if (!ASSERT_ERR(ret, "test_bpf_nf_fail__load must fail"))
91+
goto end;
92+
93+
if (!ASSERT_OK_PTR(strstr(log_buf, err_msg), "expected error message")) {
94+
fprintf(stderr, "Expected: %s\n", err_msg);
95+
fprintf(stderr, "Verifier: %s\n", log_buf);
96+
}
97+
98+
end:
99+
test_bpf_nf_fail__destroy(skel);
100+
}
101+
54102
void test_bpf_nf(void)
55103
{
104+
int i;
56105
if (test__start_subtest("xdp-ct"))
57106
test_bpf_nf_ct(TEST_XDP);
58107
if (test__start_subtest("tc-bpf-ct"))
59108
test_bpf_nf_ct(TEST_TC_BPF);
109+
for (i = 0; i < ARRAY_SIZE(test_bpf_nf_fail_tests); i++) {
110+
if (test__start_subtest(test_bpf_nf_fail_tests[i].prog_name))
111+
test_bpf_nf_ct_fail(test_bpf_nf_fail_tests[i].prog_name,
112+
test_bpf_nf_fail_tests[i].err_msg);
113+
}
60114
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <vmlinux.h>
3+
#include <bpf/bpf_tracing.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/bpf_core_read.h>
6+
7+
struct nf_conn;
8+
9+
struct bpf_ct_opts___local {
10+
s32 netns_id;
11+
s32 error;
12+
u8 l4proto;
13+
u8 reserved[3];
14+
} __attribute__((preserve_access_index));
15+
16+
struct nf_conn *bpf_skb_ct_alloc(struct __sk_buff *, struct bpf_sock_tuple *, u32,
17+
struct bpf_ct_opts___local *, u32) __ksym;
18+
struct nf_conn *bpf_skb_ct_lookup(struct __sk_buff *, struct bpf_sock_tuple *, u32,
19+
struct bpf_ct_opts___local *, u32) __ksym;
20+
struct nf_conn *bpf_ct_insert_entry(struct nf_conn *) __ksym;
21+
void bpf_ct_release(struct nf_conn *) __ksym;
22+
void bpf_ct_set_timeout(struct nf_conn *, u32) __ksym;
23+
int bpf_ct_change_timeout(struct nf_conn *, u32) __ksym;
24+
int bpf_ct_set_status(struct nf_conn *, u32) __ksym;
25+
int bpf_ct_change_status(struct nf_conn *, u32) __ksym;
26+
27+
SEC("?tc")
28+
int alloc_release(struct __sk_buff *ctx)
29+
{
30+
struct bpf_ct_opts___local opts = {};
31+
struct bpf_sock_tuple tup = {};
32+
struct nf_conn *ct;
33+
34+
ct = bpf_skb_ct_alloc(ctx, &tup, sizeof(tup.ipv4), &opts, sizeof(opts));
35+
if (!ct)
36+
return 0;
37+
bpf_ct_release(ct);
38+
return 0;
39+
}
40+
41+
SEC("?tc")
42+
int insert_insert(struct __sk_buff *ctx)
43+
{
44+
struct bpf_ct_opts___local opts = {};
45+
struct bpf_sock_tuple tup = {};
46+
struct nf_conn *ct;
47+
48+
ct = bpf_skb_ct_alloc(ctx, &tup, sizeof(tup.ipv4), &opts, sizeof(opts));
49+
if (!ct)
50+
return 0;
51+
ct = bpf_ct_insert_entry(ct);
52+
if (!ct)
53+
return 0;
54+
ct = bpf_ct_insert_entry(ct);
55+
return 0;
56+
}
57+
58+
SEC("?tc")
59+
int lookup_insert(struct __sk_buff *ctx)
60+
{
61+
struct bpf_ct_opts___local opts = {};
62+
struct bpf_sock_tuple tup = {};
63+
struct nf_conn *ct;
64+
65+
ct = bpf_skb_ct_lookup(ctx, &tup, sizeof(tup.ipv4), &opts, sizeof(opts));
66+
if (!ct)
67+
return 0;
68+
bpf_ct_insert_entry(ct);
69+
return 0;
70+
}
71+
72+
SEC("?tc")
73+
int set_timeout_after_insert(struct __sk_buff *ctx)
74+
{
75+
struct bpf_ct_opts___local opts = {};
76+
struct bpf_sock_tuple tup = {};
77+
struct nf_conn *ct;
78+
79+
ct = bpf_skb_ct_alloc(ctx, &tup, sizeof(tup.ipv4), &opts, sizeof(opts));
80+
if (!ct)
81+
return 0;
82+
ct = bpf_ct_insert_entry(ct);
83+
if (!ct)
84+
return 0;
85+
bpf_ct_set_timeout(ct, 0);
86+
return 0;
87+
}
88+
89+
SEC("?tc")
90+
int set_status_after_insert(struct __sk_buff *ctx)
91+
{
92+
struct bpf_ct_opts___local opts = {};
93+
struct bpf_sock_tuple tup = {};
94+
struct nf_conn *ct;
95+
96+
ct = bpf_skb_ct_alloc(ctx, &tup, sizeof(tup.ipv4), &opts, sizeof(opts));
97+
if (!ct)
98+
return 0;
99+
ct = bpf_ct_insert_entry(ct);
100+
if (!ct)
101+
return 0;
102+
bpf_ct_set_status(ct, 0);
103+
return 0;
104+
}
105+
106+
SEC("?tc")
107+
int change_timeout_after_alloc(struct __sk_buff *ctx)
108+
{
109+
struct bpf_ct_opts___local opts = {};
110+
struct bpf_sock_tuple tup = {};
111+
struct nf_conn *ct;
112+
113+
ct = bpf_skb_ct_alloc(ctx, &tup, sizeof(tup.ipv4), &opts, sizeof(opts));
114+
if (!ct)
115+
return 0;
116+
bpf_ct_change_timeout(ct, 0);
117+
return 0;
118+
}
119+
120+
SEC("?tc")
121+
int change_status_after_alloc(struct __sk_buff *ctx)
122+
{
123+
struct bpf_ct_opts___local opts = {};
124+
struct bpf_sock_tuple tup = {};
125+
struct nf_conn *ct;
126+
127+
ct = bpf_skb_ct_alloc(ctx, &tup, sizeof(tup.ipv4), &opts, sizeof(opts));
128+
if (!ct)
129+
return 0;
130+
bpf_ct_change_status(ct, 0);
131+
return 0;
132+
}
133+
134+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)