Implement two things I'd like to get from this: 1. apply default sk_priority policy 2. permit TX-only AF_PACKET socket Signed-off-by: Stanislav Fomichev <sdf@xxxxxxxxxx> --- .../bpf/prog_tests/lsm_cgroup_sock.c | 81 +++++++++++++++++++ .../selftests/bpf/progs/lsm_cgroup_sock.c | 55 +++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_cgroup_sock.c create mode 100644 tools/testing/selftests/bpf/progs/lsm_cgroup_sock.c diff --git a/tools/testing/selftests/bpf/prog_tests/lsm_cgroup_sock.c b/tools/testing/selftests/bpf/prog_tests/lsm_cgroup_sock.c new file mode 100644 index 000000000000..4afc40282b15 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/lsm_cgroup_sock.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <sys/types.h> +#include <sys/socket.h> +#include <test_progs.h> + +#include "lsm_cgroup_sock.skel.h" + +void test_lsm_cgroup_sock(void) +{ + int post_create_prog_fd = -1, bind_prog_fd = -1; + struct lsm_cgroup_sock *skel = NULL; + int cgroup_fd, err, fd, prio; + socklen_t socklen; + + + cgroup_fd = test__join_cgroup("/sock_policy"); + if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup")) + goto close_skel; + + skel = lsm_cgroup_sock__open_and_load(); + if (!ASSERT_OK_PTR(skel, "open_and_load")) + goto close_cgroup; + + err = lsm_cgroup_sock__attach(skel); + if (!ASSERT_OK(err, "attach")) + goto close_cgroup; + + post_create_prog_fd = bpf_program__fd(skel->progs.socket_post_create); + bind_prog_fd = bpf_program__fd(skel->progs.socket_bind); + + err = bpf_prog_attach(post_create_prog_fd, cgroup_fd, BPF_LSM_CGROUP_SOCK, 0); + if (!ASSERT_OK(err, "attach post_create_prog_fd")) + goto close_cgroup; + + err = bpf_prog_attach(bind_prog_fd, cgroup_fd, BPF_LSM_CGROUP_SOCK, 0); + if (!ASSERT_OK(err, "attach bind_prog_fd")) + goto detach_cgroup; + + /* AF_INET6 gets default policy (sk_priority). + */ + + fd = socket(AF_INET6, SOCK_STREAM, 0); + if (!ASSERT_GE(fd, 0, "socket(SOCK_STREAM)")) + goto detach_cgroup; + + prio = 0; + socklen = sizeof(prio); + ASSERT_GE(getsockopt(fd, SOL_SOCKET, SO_PRIORITY, &prio, &socklen), 0, "getsockopt"); + ASSERT_EQ(prio, 123, "sk_priority"); + + close(fd); + + /* TX-only AF_PACKET is allowed. + */ + + ASSERT_LT(socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)), 0, "socket(AF_PACKET, ..., ETH_P_ALL)"); + + fd = socket(AF_PACKET, SOCK_RAW, 0); + ASSERT_GE(fd, 0, "socket(AF_PACKET, ..., 0)"); + + /* TX-only AF_PACKET can not be rebound. + */ + + struct sockaddr_ll sa = { + .sll_family = AF_PACKET, + .sll_protocol = htons(ETH_P_ALL), + }; + ASSERT_LT(bind(fd, (struct sockaddr *)&sa, sizeof(sa)), 0, "bind(ETH_P_ALL)"); + + close(fd); + +detach_cgroup: + bpf_prog_detach2(post_create_prog_fd, cgroup_fd, BPF_LSM_CGROUP_SOCK); + bpf_prog_detach2(bind_prog_fd, cgroup_fd, BPF_LSM_CGROUP_SOCK); + +close_cgroup: + close(cgroup_fd); +close_skel: + lsm_cgroup_sock__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/lsm_cgroup_sock.c b/tools/testing/selftests/bpf/progs/lsm_cgroup_sock.c new file mode 100644 index 000000000000..7fe3da5a8dc7 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/lsm_cgroup_sock.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +char _license[] SEC("license") = "GPL"; + +#ifndef AF_PACKET +#define AF_PACKET 17 +#endif + +#ifndef EPERM +#define EPERM 1 +#endif + +SEC("lsm_cgroup_sock/socket_post_create") +int BPF_PROG(socket_post_create, struct socket *sock, int family, + int type, int protocol, int kern) +{ + struct sock *sk; + + /* Reject non-tx-only AF_PACKET. + */ + if (family == AF_PACKET && protocol != 0) + return 0; /* EPERM */ + + sk = sock->sk; + if (!sk) + return 1; + + /* The rest of the sockets get default policy. + */ + sk->sk_priority = 123; + return 1; +} + +SEC("lsm_cgroup_sock/socket_bind") +int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, + int addrlen) +{ + struct sockaddr_ll sa = {}; + + if (sock->sk->__sk_common.skc_family != AF_PACKET) + return 1; + + if (sock->sk->sk_kern_sock) + return 1; + + bpf_probe_read_kernel(&sa, sizeof(sa), address); + if (sa.sll_protocol) + return 0; /* EPERM */ + + return 1; +} -- 2.35.1.265.g69c8d7142f-goog