Skip to content

Commit 3b7a8ec

Browse files
Maciej Fijalkowskiborkmann
authored andcommitted
samples/bpf: Check the prog id before exiting
Check the program id within the signal handler on polling xdp samples that were previously converted to libbpf usage. Avoid the situation of unloading the program that was not attached by sample that is exiting. Handle also the case where bpf_get_link_xdp_id didn't exit with an error but the xdp program was not found on an interface. Reported-by: Michal Papaj <michal.papaj@intel.com> Reported-by: Jakub Spizewski <jakub.spizewski@intel.com> Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
1 parent 50db9f0 commit 3b7a8ec

10 files changed

+308
-48
lines changed

samples/bpf/xdp1_user.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,22 @@
2323

2424
static int ifindex;
2525
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
26+
static __u32 prog_id;
2627

2728
static void int_exit(int sig)
2829
{
29-
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
30+
__u32 curr_prog_id = 0;
31+
32+
if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
33+
printf("bpf_get_link_xdp_id failed\n");
34+
exit(1);
35+
}
36+
if (prog_id == curr_prog_id)
37+
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
38+
else if (!curr_prog_id)
39+
printf("couldn't find a prog id on a given interface\n");
40+
else
41+
printf("program on interface changed, not removing\n");
3042
exit(0);
3143
}
3244

@@ -74,11 +86,14 @@ int main(int argc, char **argv)
7486
struct bpf_prog_load_attr prog_load_attr = {
7587
.prog_type = BPF_PROG_TYPE_XDP,
7688
};
89+
struct bpf_prog_info info = {};
90+
__u32 info_len = sizeof(info);
7791
const char *optstr = "FSN";
7892
int prog_fd, map_fd, opt;
7993
struct bpf_object *obj;
8094
struct bpf_map *map;
8195
char filename[256];
96+
int err;
8297

8398
while ((opt = getopt(argc, argv, optstr)) != -1) {
8499
switch (opt) {
@@ -139,6 +154,13 @@ int main(int argc, char **argv)
139154
return 1;
140155
}
141156

157+
err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
158+
if (err) {
159+
printf("can't get prog info - %s\n", strerror(errno));
160+
return err;
161+
}
162+
prog_id = info.id;
163+
142164
poll_stats(map_fd, 2);
143165

144166
return 0;

samples/bpf/xdp_adjust_tail_user.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,24 @@
2525

2626
static int ifindex = -1;
2727
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
28+
static __u32 prog_id;
2829

2930
static void int_exit(int sig)
3031
{
31-
if (ifindex > -1)
32-
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
32+
__u32 curr_prog_id = 0;
33+
34+
if (ifindex > -1) {
35+
if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
36+
printf("bpf_get_link_xdp_id failed\n");
37+
exit(1);
38+
}
39+
if (prog_id == curr_prog_id)
40+
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
41+
else if (!curr_prog_id)
42+
printf("couldn't find a prog id on a given iface\n");
43+
else
44+
printf("program on interface changed, not removing\n");
45+
}
3346
exit(0);
3447
}
3548

@@ -72,11 +85,14 @@ int main(int argc, char **argv)
7285
};
7386
unsigned char opt_flags[256] = {};
7487
const char *optstr = "i:T:SNFh";
88+
struct bpf_prog_info info = {};
89+
__u32 info_len = sizeof(info);
7590
unsigned int kill_after_s = 0;
7691
int i, prog_fd, map_fd, opt;
7792
struct bpf_object *obj;
7893
struct bpf_map *map;
7994
char filename[256];
95+
int err;
8096

8197
for (i = 0; i < strlen(optstr); i++)
8298
if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z')
@@ -146,9 +162,15 @@ int main(int argc, char **argv)
146162
return 1;
147163
}
148164

149-
poll_stats(map_fd, kill_after_s);
165+
err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
166+
if (err) {
167+
printf("can't get prog info - %s\n", strerror(errno));
168+
return 1;
169+
}
170+
prog_id = info.id;
150171

151-
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
172+
poll_stats(map_fd, kill_after_s);
173+
int_exit(0);
152174

153175
return 0;
154176
}

samples/bpf/xdp_redirect_cpu_user.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ static const char *__doc__ =
3232
static int ifindex = -1;
3333
static char ifname_buf[IF_NAMESIZE];
3434
static char *ifname;
35+
static __u32 prog_id;
3536

3637
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
3738
static int cpu_map_fd;
@@ -68,11 +69,24 @@ static const struct option long_options[] = {
6869

6970
static void int_exit(int sig)
7071
{
71-
fprintf(stderr,
72-
"Interrupted: Removing XDP program on ifindex:%d device:%s\n",
73-
ifindex, ifname);
74-
if (ifindex > -1)
75-
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
72+
__u32 curr_prog_id = 0;
73+
74+
if (ifindex > -1) {
75+
if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
76+
printf("bpf_get_link_xdp_id failed\n");
77+
exit(EXIT_FAIL);
78+
}
79+
if (prog_id == curr_prog_id) {
80+
fprintf(stderr,
81+
"Interrupted: Removing XDP program on ifindex:%d device:%s\n",
82+
ifindex, ifname);
83+
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
84+
} else if (!curr_prog_id) {
85+
printf("couldn't find a prog id on a given iface\n");
86+
} else {
87+
printf("program on interface changed, not removing\n");
88+
}
89+
}
7690
exit(EXIT_OK);
7791
}
7892

@@ -608,6 +622,8 @@ int main(int argc, char **argv)
608622
struct bpf_prog_load_attr prog_load_attr = {
609623
.prog_type = BPF_PROG_TYPE_UNSPEC,
610624
};
625+
struct bpf_prog_info info = {};
626+
__u32 info_len = sizeof(info);
611627
bool use_separators = true;
612628
bool stress_mode = false;
613629
struct bpf_program *prog;
@@ -617,9 +633,9 @@ int main(int argc, char **argv)
617633
int longindex = 0;
618634
int interval = 2;
619635
int add_cpu = -1;
636+
int opt, err;
620637
int prog_fd;
621638
__u32 qsize;
622-
int opt;
623639

624640
/* Notice: choosing he queue size is very important with the
625641
* ixgbe driver, because it's driver page recycling trick is
@@ -746,6 +762,13 @@ int main(int argc, char **argv)
746762
return EXIT_FAIL_XDP;
747763
}
748764

765+
err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
766+
if (err) {
767+
printf("can't get prog info - %s\n", strerror(errno));
768+
return err;
769+
}
770+
prog_id = info.id;
771+
749772
stats_poll(interval, use_separators, prog_name, stress_mode);
750773
return EXIT_OK;
751774
}

samples/bpf/xdp_redirect_map_user.c

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,41 @@
2929
static int ifindex_in;
3030
static int ifindex_out;
3131
static bool ifindex_out_xdp_dummy_attached = true;
32+
static __u32 prog_id;
33+
static __u32 dummy_prog_id;
3234

3335
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
3436
static int rxcnt_map_fd;
3537

3638
static void int_exit(int sig)
3739
{
38-
bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
39-
if (ifindex_out_xdp_dummy_attached)
40-
bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
40+
__u32 curr_prog_id = 0;
41+
42+
if (bpf_get_link_xdp_id(ifindex_in, &curr_prog_id, xdp_flags)) {
43+
printf("bpf_get_link_xdp_id failed\n");
44+
exit(1);
45+
}
46+
if (prog_id == curr_prog_id)
47+
bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
48+
else if (!curr_prog_id)
49+
printf("couldn't find a prog id on iface IN\n");
50+
else
51+
printf("program on iface IN changed, not removing\n");
52+
53+
if (ifindex_out_xdp_dummy_attached) {
54+
curr_prog_id = 0;
55+
if (bpf_get_link_xdp_id(ifindex_out, &curr_prog_id,
56+
xdp_flags)) {
57+
printf("bpf_get_link_xdp_id failed\n");
58+
exit(1);
59+
}
60+
if (prog_id == curr_prog_id)
61+
bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
62+
else if (!curr_prog_id)
63+
printf("couldn't find a prog id on iface OUT\n");
64+
else
65+
printf("program on iface OUT changed, not removing\n");
66+
}
4167
exit(0);
4268
}
4369

@@ -82,6 +108,8 @@ int main(int argc, char **argv)
82108
.prog_type = BPF_PROG_TYPE_XDP,
83109
};
84110
struct bpf_program *prog, *dummy_prog;
111+
struct bpf_prog_info info = {};
112+
__u32 info_len = sizeof(info);
85113
int prog_fd, dummy_prog_fd;
86114
const char *optstr = "FSN";
87115
struct bpf_object *obj;
@@ -153,13 +181,28 @@ int main(int argc, char **argv)
153181
return 1;
154182
}
155183

184+
ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
185+
if (ret) {
186+
printf("can't get prog info - %s\n", strerror(errno));
187+
return ret;
188+
}
189+
prog_id = info.id;
190+
156191
/* Loading dummy XDP prog on out-device */
157192
if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
158193
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
159194
printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
160195
ifindex_out_xdp_dummy_attached = false;
161196
}
162197

198+
memset(&info, 0, sizeof(info));
199+
ret = bpf_obj_get_info_by_fd(dummy_prog_fd, &info, &info_len);
200+
if (ret) {
201+
printf("can't get prog info - %s\n", strerror(errno));
202+
return ret;
203+
}
204+
dummy_prog_id = info.id;
205+
163206
signal(SIGINT, int_exit);
164207
signal(SIGTERM, int_exit);
165208

samples/bpf/xdp_redirect_user.c

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,41 @@
2929
static int ifindex_in;
3030
static int ifindex_out;
3131
static bool ifindex_out_xdp_dummy_attached = true;
32+
static __u32 prog_id;
33+
static __u32 dummy_prog_id;
3234

3335
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
3436
static int rxcnt_map_fd;
3537

3638
static void int_exit(int sig)
3739
{
38-
bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
39-
if (ifindex_out_xdp_dummy_attached)
40-
bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
40+
__u32 curr_prog_id = 0;
41+
42+
if (bpf_get_link_xdp_id(ifindex_in, &curr_prog_id, xdp_flags)) {
43+
printf("bpf_get_link_xdp_id failed\n");
44+
exit(1);
45+
}
46+
if (prog_id == curr_prog_id)
47+
bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags);
48+
else if (!curr_prog_id)
49+
printf("couldn't find a prog id on iface IN\n");
50+
else
51+
printf("program on iface IN changed, not removing\n");
52+
53+
if (ifindex_out_xdp_dummy_attached) {
54+
curr_prog_id = 0;
55+
if (bpf_get_link_xdp_id(ifindex_out, &curr_prog_id,
56+
xdp_flags)) {
57+
printf("bpf_get_link_xdp_id failed\n");
58+
exit(1);
59+
}
60+
if (prog_id == curr_prog_id)
61+
bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags);
62+
else if (!curr_prog_id)
63+
printf("couldn't find a prog id on iface OUT\n");
64+
else
65+
printf("program on iface OUT changed, not removing\n");
66+
}
4167
exit(0);
4268
}
4369

@@ -84,6 +110,8 @@ int main(int argc, char **argv)
84110
};
85111
struct bpf_program *prog, *dummy_prog;
86112
int prog_fd, tx_port_map_fd, opt;
113+
struct bpf_prog_info info = {};
114+
__u32 info_len = sizeof(info);
87115
const char *optstr = "FSN";
88116
struct bpf_object *obj;
89117
char filename[256];
@@ -154,13 +182,28 @@ int main(int argc, char **argv)
154182
return 1;
155183
}
156184

185+
ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
186+
if (ret) {
187+
printf("can't get prog info - %s\n", strerror(errno));
188+
return ret;
189+
}
190+
prog_id = info.id;
191+
157192
/* Loading dummy XDP prog on out-device */
158193
if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
159194
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
160195
printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
161196
ifindex_out_xdp_dummy_attached = false;
162197
}
163198

199+
memset(&info, 0, sizeof(info));
200+
ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
201+
if (ret) {
202+
printf("can't get prog info - %s\n", strerror(errno));
203+
return ret;
204+
}
205+
dummy_prog_id = info.id;
206+
164207
signal(SIGINT, int_exit);
165208
signal(SIGTERM, int_exit);
166209

0 commit comments

Comments
 (0)