Commit 82ab6b50 authored by Daan De Meyer's avatar Daan De Meyer Committed by Martin KaFai Lau

selftests/bpf: Add tests for cgroup unix socket address hooks

These selftests are written in prog_tests style instead of adding
them to the existing test_sock_addr tests. Migrating the existing
sock addr tests to prog_tests style is left for future work. This
commit adds support for testing bind() sockaddr hooks, even though
there's no unix socket sockaddr hook for bind(). We leave this code
intact for when the INET and INET6 tests are migrated in the future
which do support intercepting bind().
Signed-off-by: default avatarDaan De Meyer <daan.j.demeyer@gmail.com>
Link: https://lore.kernel.org/r/20231011185113.140426-10-daan.j.demeyer@gmail.comSigned-off-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
parent af2752ed
#ifndef __BPF_KFUNCS__
#define __BPF_KFUNCS__
struct bpf_sock_addr_kern;
/* Description
* Initializes an skb-type dynptr
* Returns
......@@ -41,4 +43,16 @@ extern bool bpf_dynptr_is_rdonly(const struct bpf_dynptr *ptr) __ksym;
extern __u32 bpf_dynptr_size(const struct bpf_dynptr *ptr) __ksym;
extern int bpf_dynptr_clone(const struct bpf_dynptr *ptr, struct bpf_dynptr *clone__init) __ksym;
/* Description
* Modify the address of a AF_UNIX sockaddr.
* Returns__bpf_kfunc
* -EINVAL if the address size is too big or, 0 if the sockaddr was successfully modified.
*/
extern int bpf_sock_addr_set_sun_path(struct bpf_sock_addr_kern *sa_kern,
const __u8 *sun_path, __u32 sun_path__sz) __ksym;
void *bpf_cast_to_kern_ctx(void *) __ksym;
void *bpf_rdonly_cast(void *obj, __u32 btf_id) __ksym;
#endif
......@@ -11,6 +11,7 @@
#include <arpa/inet.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <linux/err.h>
#include <linux/in.h>
......@@ -257,6 +258,26 @@ static int connect_fd_to_addr(int fd,
return 0;
}
int connect_to_addr(const struct sockaddr_storage *addr, socklen_t addrlen, int type)
{
int fd;
fd = socket(addr->ss_family, type, 0);
if (fd < 0) {
log_err("Failed to create client socket");
return -1;
}
if (connect_fd_to_addr(fd, addr, addrlen, false))
goto error_close;
return fd;
error_close:
save_errno_close(fd);
return -1;
}
static const struct network_helper_opts default_opts;
int connect_to_fd_opts(int server_fd, const struct network_helper_opts *opts)
......@@ -380,6 +401,19 @@ int make_sockaddr(int family, const char *addr_str, __u16 port,
if (len)
*len = sizeof(*sin6);
return 0;
} else if (family == AF_UNIX) {
/* Note that we always use abstract unix sockets to avoid having
* to clean up leftover files.
*/
struct sockaddr_un *sun = (void *)addr;
memset(addr, 0, sizeof(*sun));
sun->sun_family = family;
sun->sun_path[0] = 0;
strcpy(sun->sun_path + 1, addr_str);
if (len)
*len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(addr_str);
return 0;
}
return -1;
}
......
......@@ -51,6 +51,7 @@ int *start_reuseport_server(int family, int type, const char *addr_str,
__u16 port, int timeout_ms,
unsigned int nr_listens);
void free_fds(int *fds, unsigned int nr_close_fds);
int connect_to_addr(const struct sockaddr_storage *addr, socklen_t len, int type);
int connect_to_fd(int server_fd, int timeout_ms);
int connect_to_fd_opts(int server_fd, const struct network_helper_opts *opts);
int connect_fd_to_fd(int client_fd, int server_fd, int timeout_ms);
......
......@@ -123,6 +123,11 @@ static struct sec_name_test tests[] = {
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT},
{0, BPF_CGROUP_INET6_CONNECT},
},
{
"cgroup/connect_unix",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_CONNECT},
{0, BPF_CGROUP_UNIX_CONNECT},
},
{
"cgroup/sendmsg4",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_SENDMSG},
......@@ -133,6 +138,11 @@ static struct sec_name_test tests[] = {
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
{0, BPF_CGROUP_UDP6_SENDMSG},
},
{
"cgroup/sendmsg_unix",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_SENDMSG},
{0, BPF_CGROUP_UNIX_SENDMSG},
},
{
"cgroup/recvmsg4",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG},
......@@ -143,6 +153,11 @@ static struct sec_name_test tests[] = {
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
{0, BPF_CGROUP_UDP6_RECVMSG},
},
{
"cgroup/recvmsg_unix",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_RECVMSG},
{0, BPF_CGROUP_UNIX_RECVMSG},
},
{
"cgroup/sysctl",
{0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
......@@ -168,6 +183,11 @@ static struct sec_name_test tests[] = {
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_GETPEERNAME},
{0, BPF_CGROUP_INET6_GETPEERNAME},
},
{
"cgroup/getpeername_unix",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_GETPEERNAME},
{0, BPF_CGROUP_UNIX_GETPEERNAME},
},
{
"cgroup/getsockname4",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_GETSOCKNAME},
......@@ -178,6 +198,11 @@ static struct sec_name_test tests[] = {
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_GETSOCKNAME},
{0, BPF_CGROUP_INET6_GETSOCKNAME},
},
{
"cgroup/getsockname_unix",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_GETSOCKNAME},
{0, BPF_CGROUP_UNIX_GETSOCKNAME},
},
};
static void test_prog_type_by_name(const struct sec_name_test *test)
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
#include "vmlinux.h"
#include <string.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include "bpf_kfuncs.h"
__u8 SERVUN_REWRITE_ADDRESS[] = "\0bpf_cgroup_unix_test_rewrite";
SEC("cgroup/connect_unix")
int connect_unix_prog(struct bpf_sock_addr *ctx)
{
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
struct sockaddr_un *sa_kern_unaddr;
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
sizeof(SERVUN_REWRITE_ADDRESS) - 1;
int ret;
/* Rewrite destination. */
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_REWRITE_ADDRESS,
sizeof(SERVUN_REWRITE_ADDRESS) - 1);
if (ret)
return 0;
if (sa_kern->uaddrlen != unaddrlen)
return 0;
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
bpf_core_type_id_kernel(struct sockaddr_un));
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_REWRITE_ADDRESS,
sizeof(SERVUN_REWRITE_ADDRESS) - 1) != 0)
return 0;
return 1;
}
char _license[] SEC("license") = "GPL";
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
#include "vmlinux.h"
#include <string.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include "bpf_kfuncs.h"
__u8 SERVUN_REWRITE_ADDRESS[] = "\0bpf_cgroup_unix_test_rewrite";
SEC("cgroup/getpeername_unix")
int getpeername_unix_prog(struct bpf_sock_addr *ctx)
{
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
struct sockaddr_un *sa_kern_unaddr;
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
sizeof(SERVUN_REWRITE_ADDRESS) - 1;
int ret;
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_REWRITE_ADDRESS,
sizeof(SERVUN_REWRITE_ADDRESS) - 1);
if (ret)
return 1;
if (sa_kern->uaddrlen != unaddrlen)
return 1;
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
bpf_core_type_id_kernel(struct sockaddr_un));
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_REWRITE_ADDRESS,
sizeof(SERVUN_REWRITE_ADDRESS) - 1) != 0)
return 1;
return 1;
}
char _license[] SEC("license") = "GPL";
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
#include "vmlinux.h"
#include <string.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include "bpf_kfuncs.h"
__u8 SERVUN_REWRITE_ADDRESS[] = "\0bpf_cgroup_unix_test_rewrite";
SEC("cgroup/getsockname_unix")
int getsockname_unix_prog(struct bpf_sock_addr *ctx)
{
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
struct sockaddr_un *sa_kern_unaddr;
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
sizeof(SERVUN_REWRITE_ADDRESS) - 1;
int ret;
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_REWRITE_ADDRESS,
sizeof(SERVUN_REWRITE_ADDRESS) - 1);
if (ret)
return 1;
if (sa_kern->uaddrlen != unaddrlen)
return 1;
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
bpf_core_type_id_kernel(struct sockaddr_un));
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_REWRITE_ADDRESS,
sizeof(SERVUN_REWRITE_ADDRESS) - 1) != 0)
return 1;
return 1;
}
char _license[] SEC("license") = "GPL";
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
#include "vmlinux.h"
#include <string.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include "bpf_kfuncs.h"
__u8 SERVUN_ADDRESS[] = "\0bpf_cgroup_unix_test";
SEC("cgroup/recvmsg_unix")
int recvmsg_unix_prog(struct bpf_sock_addr *ctx)
{
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
struct sockaddr_un *sa_kern_unaddr;
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
sizeof(SERVUN_ADDRESS) - 1;
int ret;
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_ADDRESS,
sizeof(SERVUN_ADDRESS) - 1);
if (ret)
return 1;
if (sa_kern->uaddrlen != unaddrlen)
return 1;
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
bpf_core_type_id_kernel(struct sockaddr_un));
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_ADDRESS,
sizeof(SERVUN_ADDRESS) - 1) != 0)
return 1;
return 1;
}
char _license[] SEC("license") = "GPL";
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
#include "vmlinux.h"
#include <string.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include "bpf_kfuncs.h"
__u8 SERVUN_REWRITE_ADDRESS[] = "\0bpf_cgroup_unix_test_rewrite";
SEC("cgroup/sendmsg_unix")
int sendmsg_unix_prog(struct bpf_sock_addr *ctx)
{
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
struct sockaddr_un *sa_kern_unaddr;
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
sizeof(SERVUN_REWRITE_ADDRESS) - 1;
int ret;
/* Rewrite destination. */
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_REWRITE_ADDRESS,
sizeof(SERVUN_REWRITE_ADDRESS) - 1);
if (ret)
return 0;
if (sa_kern->uaddrlen != unaddrlen)
return 0;
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
bpf_core_type_id_kernel(struct sockaddr_un));
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_REWRITE_ADDRESS,
sizeof(SERVUN_REWRITE_ADDRESS) - 1) != 0)
return 0;
return 1;
}
char _license[] SEC("license") = "GPL";
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