Commit f97eea17 authored by Jakub Sitnicki's avatar Jakub Sitnicki Committed by Daniel Borkmann

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: default avatarJakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Reviewed-by: default avatarStanislav Fomichev <sdf@google.com>
Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/20191011082946.22695-3-jakub@cloudflare.com
parent 719b78a5
// 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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment