mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-08 23:04:35 +08:00
selftests/bpf: Check that flow dissector can be re-attached
Make sure a new flow dissector program can be attached to replace the old one with a single syscall. Also check that attaching the same program twice is prohibited. Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Stanislav Fomichev <sdf@google.com> Acked-by: Martin KaFai Lau <kafai@fb.com> Link: https://lore.kernel.org/bpf/20191011082946.22695-3-jakub@cloudflare.com
This commit is contained in:
parent
719b78a567
commit
f97eea1756
127
tools/testing/selftests/bpf/prog_tests/flow_dissector_reattach.c
Normal file
127
tools/testing/selftests/bpf/prog_tests/flow_dissector_reattach.c
Normal file
@ -0,0 +1,127 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Test that the flow_dissector program can be updated with a single
|
||||
* syscall by attaching a new program that replaces the existing one.
|
||||
*
|
||||
* Corner case - the same program cannot be attached twice.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sched.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf.h>
|
||||
|
||||
#include "test_progs.h"
|
||||
|
||||
static bool is_attached(int netns)
|
||||
{
|
||||
__u32 cnt;
|
||||
int err;
|
||||
|
||||
err = bpf_prog_query(netns, BPF_FLOW_DISSECTOR, 0, NULL, NULL, &cnt);
|
||||
if (CHECK_FAIL(err)) {
|
||||
perror("bpf_prog_query");
|
||||
return true; /* fail-safe */
|
||||
}
|
||||
|
||||
return cnt > 0;
|
||||
}
|
||||
|
||||
static int load_prog(void)
|
||||
{
|
||||
struct bpf_insn prog[] = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, BPF_OK),
|
||||
BPF_EXIT_INSN(),
|
||||
};
|
||||
int fd;
|
||||
|
||||
fd = bpf_load_program(BPF_PROG_TYPE_FLOW_DISSECTOR, prog,
|
||||
ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
|
||||
if (CHECK_FAIL(fd < 0))
|
||||
perror("bpf_load_program");
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void do_flow_dissector_reattach(void)
|
||||
{
|
||||
int prog_fd[2] = { -1, -1 };
|
||||
int err;
|
||||
|
||||
prog_fd[0] = load_prog();
|
||||
if (prog_fd[0] < 0)
|
||||
return;
|
||||
|
||||
prog_fd[1] = load_prog();
|
||||
if (prog_fd[1] < 0)
|
||||
goto out_close;
|
||||
|
||||
err = bpf_prog_attach(prog_fd[0], 0, BPF_FLOW_DISSECTOR, 0);
|
||||
if (CHECK_FAIL(err)) {
|
||||
perror("bpf_prog_attach-0");
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
/* Expect success when attaching a different program */
|
||||
err = bpf_prog_attach(prog_fd[1], 0, BPF_FLOW_DISSECTOR, 0);
|
||||
if (CHECK_FAIL(err)) {
|
||||
perror("bpf_prog_attach-1");
|
||||
goto out_detach;
|
||||
}
|
||||
|
||||
/* Expect failure when attaching the same program twice */
|
||||
err = bpf_prog_attach(prog_fd[1], 0, BPF_FLOW_DISSECTOR, 0);
|
||||
if (CHECK_FAIL(!err || errno != EINVAL))
|
||||
perror("bpf_prog_attach-2");
|
||||
|
||||
out_detach:
|
||||
err = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
|
||||
if (CHECK_FAIL(err))
|
||||
perror("bpf_prog_detach");
|
||||
|
||||
out_close:
|
||||
close(prog_fd[1]);
|
||||
close(prog_fd[0]);
|
||||
}
|
||||
|
||||
void test_flow_dissector_reattach(void)
|
||||
{
|
||||
int init_net, err;
|
||||
|
||||
init_net = open("/proc/1/ns/net", O_RDONLY);
|
||||
if (CHECK_FAIL(init_net < 0)) {
|
||||
perror("open(/proc/1/ns/net)");
|
||||
return;
|
||||
}
|
||||
|
||||
err = setns(init_net, CLONE_NEWNET);
|
||||
if (CHECK_FAIL(err)) {
|
||||
perror("setns(/proc/1/ns/net)");
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
if (is_attached(init_net)) {
|
||||
test__skip();
|
||||
printf("Can't test with flow dissector attached to init_net\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* First run tests in root network namespace */
|
||||
do_flow_dissector_reattach();
|
||||
|
||||
/* Then repeat tests in a non-root namespace */
|
||||
err = unshare(CLONE_NEWNET);
|
||||
if (CHECK_FAIL(err)) {
|
||||
perror("unshare(CLONE_NEWNET)");
|
||||
goto out_close;
|
||||
}
|
||||
do_flow_dissector_reattach();
|
||||
|
||||
out_close:
|
||||
close(init_net);
|
||||
}
|
Loading…
Reference in New Issue
Block a user