From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C560DC4332F for ; Thu, 7 Apr 2022 22:31:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232059AbiDGWdp (ORCPT ); Thu, 7 Apr 2022 18:33:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48168 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229921AbiDGWdn (ORCPT ); Thu, 7 Apr 2022 18:33:43 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1175D75E76 for ; Thu, 7 Apr 2022 15:31:30 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-2d7eaa730d9so60485257b3.13 for ; Thu, 07 Apr 2022 15:31:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=iMY106jMlEhxmvPO6SMZTv9EIM2l5eJ//6ptxJ0yJys=; b=PrAPhCiYLH8ZlcDHi4ATLb4BIcWvslHVx+Uwoli3C8c/llT1GUnPW6CAc/vLOZgQ07 9IYTlE2knJHOaImyh5d4tYGq0AFCnKFCl9HkRKiapdJCdOoFQW3x1eJeNmtdt5/dDu6D DRUq1L+CZfuifppGvRXGLl7YEQoI7MxD7LtdX7Bw1/DhlCsuZthv8MLKyf5OwL8ARz5y YtsBOodRAdHm796uH+nNr7+R/e1Z0DPUtI7QX1SH5fvf15je2l8Z6hcSL2BCXUqHeFhu ghBKvF8REkd3EGWLrnHQHSduHXy+eI34XJtMwiOaJwfaUPz6JMc3VG8hXPxCa5foF5se 5a9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=iMY106jMlEhxmvPO6SMZTv9EIM2l5eJ//6ptxJ0yJys=; b=PKZ9JKQTd6Dh4wF4H9BiTZ5zPKwzI/0UQmm96WuVqqFh6hDfv7X7J54VJluDiX3bIc N5ukKlx/jr8wlGrv7Sq2JqGCTsac51vWWCsxlF+NnjY8o53MFW1PcvO/Qw6LtGljXUXf BnIlpJLj5i6hO2FIm+Jj02Y5CLezREyXqoJSTDwjVecI5QLq3HjYr0DHiRU13LffRfYq Ad9mrpWLSyYGfwQ7KPB2Sci2MzvLBGWC3soaSX7wsUSxHroYW1d+VodikF/0p3HQWE+I IxqtJzUIHtk1pwHR891CFOrEQDF8pkrJMMr7Qynnolhby5XHsPkT0op+9Fda1dtgDAtw ByLw== X-Gm-Message-State: AOAM531u2BLKkfcbdfbZj6CwkyB0GxlA23ZrxtvtYIQRakE939BAJl4u TbL5LWNDjmsETEsDRszvij9rq+2rhp/45TKuBu7jQ/S9ky89F0NKgkJx7T2jzrkeBPEHUKhgIW3 5jdxH1UbXGMY5snjYQPKb5qlNr5Tg78XkMTftjWl/L1qGtyvVDEmZRw== X-Google-Smtp-Source: ABdhPJx8yuZfhYIvqBldr7jbRFe2e7MASqRF09Qx66xiw2tpn80KIuP+sRqzVMSsCZb2XbR+hkFsq2o= X-Received: from sdf2.svl.corp.google.com ([2620:15c:2c4:201:9e25:5910:c207:e29a]) (user=sdf job=sendgmr) by 2002:a05:6902:721:b0:635:6818:d861 with SMTP id l1-20020a056902072100b006356818d861mr11917115ybt.395.1649370689735; Thu, 07 Apr 2022 15:31:29 -0700 (PDT) Date: Thu, 7 Apr 2022 15:31:11 -0700 In-Reply-To: <20220407223112.1204582-1-sdf@google.com> Message-Id: <20220407223112.1204582-7-sdf@google.com> Mime-Version: 1.0 References: <20220407223112.1204582-1-sdf@google.com> X-Mailer: git-send-email 2.35.1.1178.g4f1659d476-goog Subject: [PATCH bpf-next v3 6/7] selftests/bpf: lsm_cgroup functional test From: Stanislav Fomichev To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, Stanislav Fomichev Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Functional test that exercises the following: 1. apply default sk_priority policy 2. permit TX-only AF_PACKET socket 3. cgroup attach/detach/replace 4. reusing trampoline shim Signed-off-by: Stanislav Fomichev --- .../selftests/bpf/prog_tests/lsm_cgroup.c | 158 ++++++++++++++++++ .../testing/selftests/bpf/progs/lsm_cgroup.c | 94 +++++++++++ 2 files changed, 252 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c create mode 100644 tools/testing/selftests/bpf/progs/lsm_cgroup.c diff --git a/tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c b/tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c new file mode 100644 index 000000000000..e786b63d81e2 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/lsm_cgroup.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +#include "lsm_cgroup.skel.h" +#include "cgroup_helpers.h" + +void test_lsm_cgroup(void) +{ + DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, attach_opts); + DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts); + int cgroup_fd, cgroup_fd2, err, fd, prio; + struct lsm_cgroup *skel = NULL; + int post_create_prog_fd2 = -1; + int post_create_prog_fd = -1; + int bind_link_fd2 = -1; + int bind_prog_fd2 = -1; + int alloc_prog_fd = -1; + int bind_prog_fd = -1; + int bind_link_fd = -1; + socklen_t socklen; + + cgroup_fd = test__join_cgroup("/sock_policy"); + if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup")) + goto close_skel; + + cgroup_fd2 = create_and_get_cgroup("/sock_policy2"); + if (!ASSERT_GE(cgroup_fd2, 0, "create second cgroup")) + goto close_skel; + + skel = lsm_cgroup__open_and_load(); + if (!ASSERT_OK_PTR(skel, "open_and_load")) + goto close_cgroup; + + post_create_prog_fd = bpf_program__fd(skel->progs.socket_post_create); + post_create_prog_fd2 = bpf_program__fd(skel->progs.socket_post_create2); + bind_prog_fd = bpf_program__fd(skel->progs.socket_bind); + bind_prog_fd2 = bpf_program__fd(skel->progs.socket_bind2); + alloc_prog_fd = bpf_program__fd(skel->progs.socket_alloc); + + err = bpf_prog_attach(alloc_prog_fd, cgroup_fd, BPF_LSM_CGROUP, 0); + if (!ASSERT_OK(err, "attach alloc_prog_fd")) + goto detach_cgroup; + + /* Make sure replacing works. + */ + + err = bpf_prog_attach(post_create_prog_fd, cgroup_fd, + BPF_LSM_CGROUP, 0); + if (!ASSERT_OK(err, "attach post_create_prog_fd")) + goto close_cgroup; + + attach_opts.replace_prog_fd = post_create_prog_fd; + err = bpf_prog_attach_opts(post_create_prog_fd2, cgroup_fd, + BPF_LSM_CGROUP, &attach_opts); + if (!ASSERT_OK(err, "prog replace post_create_prog_fd")) + goto detach_cgroup; + + /* Try the same attach/replace via link API. + */ + + bind_link_fd = bpf_link_create(bind_prog_fd, cgroup_fd, + BPF_LSM_CGROUP, NULL); + if (!ASSERT_GE(bind_link_fd, 0, "link create bind_prog_fd")) + goto detach_cgroup; + + update_opts.old_prog_fd = bind_prog_fd; + update_opts.flags = BPF_F_REPLACE; + + err = bpf_link_update(bind_link_fd, bind_prog_fd2, &update_opts); + if (!ASSERT_OK(err, "link update bind_prog_fd")) + goto detach_cgroup; + + /* Attach another instance of bind program to another cgroup. + * This should trigger the reuse of the trampoline shim (two + * programs attaching to the same btf_id). + */ + + bind_link_fd2 = bpf_link_create(bind_prog_fd2, cgroup_fd2, + BPF_LSM_CGROUP, NULL); + if (!ASSERT_GE(bind_link_fd2, 0, "link create bind_prog_fd2")) + goto detach_cgroup; + + /* AF_UNIX is prohibited. + */ + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + ASSERT_LT(fd, 0, "socket(AF_UNIX)"); + + /* 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); + + /* Make sure other cgroup doesn't trigger the programs. + */ + + if (!ASSERT_OK(join_cgroup(""), "join root cgroup")) + goto detach_cgroup; + + 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, 0, "sk_priority"); + + close(fd); + +detach_cgroup: + ASSERT_GE(bpf_prog_detach2(post_create_prog_fd2, cgroup_fd, + BPF_LSM_CGROUP), 0, "detach_create"); + close(bind_link_fd); + /* Don't close bind_link_fd2, exercise cgroup release cleanup. */ + ASSERT_GE(bpf_prog_detach2(alloc_prog_fd, cgroup_fd, + BPF_LSM_CGROUP), 0, "detach_alloc"); + +close_cgroup: + close(cgroup_fd); +close_skel: + lsm_cgroup__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/lsm_cgroup.c b/tools/testing/selftests/bpf/progs/lsm_cgroup.c new file mode 100644 index 000000000000..fd3b2daa26aa --- /dev/null +++ b/tools/testing/selftests/bpf/progs/lsm_cgroup.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" +#include +#include + +char _license[] SEC("license") = "GPL"; + +#ifndef AF_PACKET +#define AF_PACKET 17 +#endif + +#ifndef AF_UNIX +#define AF_UNIX 1 +#endif + +#ifndef EPERM +#define EPERM 1 +#endif + +static __always_inline int real_create(struct socket *sock, int family, + int protocol) +{ + 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/socket_post_create") +int BPF_PROG(socket_post_create, struct socket *sock, int family, + int type, int protocol, int kern) +{ + return real_create(sock, family, protocol); +} + +SEC("lsm_cgroup/socket_post_create") +int BPF_PROG(socket_post_create2, struct socket *sock, int family, + int type, int protocol, int kern) +{ + return real_create(sock, family, protocol); +} + +static __always_inline int real_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; +} + +SEC("lsm_cgroup/socket_bind") +int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, + int addrlen) +{ + return real_bind(sock, address, addrlen); +} + +SEC("lsm_cgroup/socket_bind") +int BPF_PROG(socket_bind2, struct socket *sock, struct sockaddr *address, + int addrlen) +{ + return real_bind(sock, address, addrlen); +} + +SEC("lsm_cgroup/sk_alloc_security") +int BPF_PROG(socket_alloc, struct sock *sk, int family, gfp_t priority) +{ + if (family == AF_UNIX) + return 0; /* EPERM */ + return 1; +} -- 2.35.1.1178.g4f1659d476-goog