// SPDX-License-Identifier: GPL-2.0 #include #include "test_progs.h" #include "sock_addr_kern.skel.h" #include "bind4_prog.skel.h" #include "bind6_prog.skel.h" #include "connect_unix_prog.skel.h" #include "connect4_prog.skel.h" #include "connect6_prog.skel.h" #include "sendmsg4_prog.skel.h" #include "sendmsg6_prog.skel.h" #include "recvmsg4_prog.skel.h" #include "recvmsg6_prog.skel.h" #include "sendmsg_unix_prog.skel.h" #include "recvmsg_unix_prog.skel.h" #include "getsockname4_prog.skel.h" #include "getsockname6_prog.skel.h" #include "getsockname_unix_prog.skel.h" #include "getpeername4_prog.skel.h" #include "getpeername6_prog.skel.h" #include "getpeername_unix_prog.skel.h" #include "network_helpers.h" #ifndef ENOTSUPP # define ENOTSUPP 524 #endif #define TEST_NS "sock_addr" #define TEST_IF_PREFIX "test_sock_addr" #define TEST_IPV4 "127.0.0.4" #define TEST_IPV6 "::6" #define SERV4_IP "192.168.1.254" #define SERV4_REWRITE_IP "127.0.0.1" #define SRC4_IP "172.16.0.1" #define SRC4_REWRITE_IP TEST_IPV4 #define SERV4_PORT 4040 #define SERV4_REWRITE_PORT 4444 #define SERV6_IP "face:b00c:1234:5678::abcd" #define SERV6_REWRITE_IP "::1" #define SERV6_V4MAPPED_IP "::ffff:192.168.0.4" #define SRC6_IP "::1" #define SRC6_REWRITE_IP TEST_IPV6 #define WILDCARD6_IP "::" #define SERV6_PORT 6060 #define SERV6_REWRITE_PORT 6666 #define SERVUN_ADDRESS "bpf_cgroup_unix_test" #define SERVUN_REWRITE_ADDRESS "bpf_cgroup_unix_test_rewrite" #define SRCUN_ADDRESS "bpf_cgroup_unix_test_src" #define save_errno_do(op) ({ int __save = errno; op; errno = __save; }) enum sock_addr_test_type { SOCK_ADDR_TEST_BIND, SOCK_ADDR_TEST_CONNECT, SOCK_ADDR_TEST_SENDMSG, SOCK_ADDR_TEST_RECVMSG, SOCK_ADDR_TEST_GETSOCKNAME, SOCK_ADDR_TEST_GETPEERNAME, }; typedef void *(*load_fn)(int cgroup_fd, enum bpf_attach_type attach_type, bool expect_reject); typedef void (*destroy_fn)(void *skel); static int cmp_addr(const struct sockaddr_storage *addr1, socklen_t addr1_len, const struct sockaddr_storage *addr2, socklen_t addr2_len, bool cmp_port); struct init_sock_args { int af; int type; }; struct addr_args { char addr[sizeof(struct sockaddr_storage)]; int addrlen; }; struct sendmsg_args { struct addr_args addr; char msg[10]; int msglen; }; static struct sock_addr_kern *skel; static int run_bpf_prog(const char *prog_name, void *ctx, int ctx_size) { LIBBPF_OPTS(bpf_test_run_opts, topts); struct bpf_program *prog; int prog_fd, err; topts.ctx_in = ctx; topts.ctx_size_in = ctx_size; prog = bpf_object__find_program_by_name(skel->obj, prog_name); if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) goto err; prog_fd = bpf_program__fd(prog); err = bpf_prog_test_run_opts(prog_fd, &topts); if (!ASSERT_OK(err, prog_name)) goto err; err = topts.retval; errno = -topts.retval; goto out; err: err = -1; out: return err; } static int kernel_init_sock(int af, int type, int protocol) { struct init_sock_args args = { .af = af, .type = type, }; return run_bpf_prog("init_sock", &args, sizeof(args)); } static int kernel_close_sock(int fd) { return run_bpf_prog("close_sock", NULL, 0); } static int sock_addr_op(const char *name, struct sockaddr *addr, socklen_t *addrlen, bool expect_change) { struct addr_args args; int err; if (addrlen) args.addrlen = *addrlen; if (addr) memcpy(&args.addr, addr, *addrlen); err = run_bpf_prog(name, &args, sizeof(args)); if (!expect_change && addr) if (!ASSERT_EQ(cmp_addr((struct sockaddr_storage *)addr, *addrlen, (struct sockaddr_storage *)&args.addr, args.addrlen, 1), 0, "address_param_modified")) return -1; if (addrlen) *addrlen = args.addrlen; if (addr) memcpy(addr, &args.addr, *addrlen); return err; } static int send_msg_op(const char *name, struct sockaddr *addr, socklen_t addrlen, const char *msg, int msglen) { struct sendmsg_args args; int err; memset(&args, 0, sizeof(args)); memcpy(&args.addr.addr, addr, addrlen); args.addr.addrlen = addrlen; memcpy(args.msg, msg, msglen); args.msglen = msglen; err = run_bpf_prog(name, &args, sizeof(args)); if (!ASSERT_EQ(cmp_addr((struct sockaddr_storage *)addr, addrlen, (struct sockaddr_storage *)&args.addr.addr, args.addr.addrlen, 1), 0, "address_param_modified")) return -1; return err; } static int kernel_connect(struct sockaddr *addr, socklen_t addrlen) { return sock_addr_op("kernel_connect", addr, &addrlen, false); } static int kernel_bind(int fd, struct sockaddr *addr, socklen_t addrlen) { return sock_addr_op("kernel_bind", addr, &addrlen, false); } static int kernel_listen(void) { return sock_addr_op("kernel_listen", NULL, NULL, false); } static int kernel_sendmsg(int fd, struct sockaddr *addr, socklen_t addrlen, char *msg, int msglen) { return send_msg_op("kernel_sendmsg", addr, addrlen, msg, msglen); } static int sock_sendmsg(int fd, struct sockaddr *addr, socklen_t addrlen, char *msg, int msglen) { return send_msg_op("sock_sendmsg", addr, addrlen, msg, msglen); } static int kernel_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) { return sock_addr_op("kernel_getsockname", addr, addrlen, true); } static int kernel_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) { return sock_addr_op("kernel_getpeername", addr, addrlen, true); } int kernel_connect_to_addr(int type, const struct sockaddr_storage *addr, socklen_t addrlen, const struct network_helper_opts *opts) { int err; if (!ASSERT_OK(kernel_init_sock(addr->ss_family, type, 0), "kernel_init_sock")) goto err; if (kernel_connect((struct sockaddr *)addr, addrlen) < 0) goto err; /* Test code expects a "file descriptor" on success. */ err = 1; goto out; err: err = -1; save_errno_do(ASSERT_OK(kernel_close_sock(0), "kernel_close_sock")); out: return err; } int kernel_start_server(int family, int type, const char *addr_str, __u16 port, int timeout_ms) { struct sockaddr_storage addr; socklen_t addrlen; int err; if (!ASSERT_OK(kernel_init_sock(family, type, 0), "kernel_init_sock")) goto err; if (make_sockaddr(family, addr_str, port, &addr, &addrlen)) goto err; if (kernel_bind(0, (struct sockaddr *)&addr, addrlen) < 0) goto err; if (type == SOCK_STREAM) { if (!ASSERT_OK(kernel_listen(), "kernel_listen")) goto err; } /* Test code expects a "file descriptor" on success. */ err = 1; goto out; err: err = -1; save_errno_do(ASSERT_OK(kernel_close_sock(0), "kernel_close_sock")); out: return err; } struct sock_ops { int (*connect_to_addr)(int type, const struct sockaddr_storage *addr, socklen_t addrlen, const struct network_helper_opts *opts); int (*start_server)(int family, int type, const char *addr_str, __u16 port, int timeout_ms); int (*socket)(int famil, int type, int protocol); int (*bind)(int fd, struct sockaddr *addr, socklen_t addrlen); int (*getsockname)(int fd, struct sockaddr *addr, socklen_t *addrlen); int (*getpeername)(int fd, struct sockaddr *addr, socklen_t *addrlen); int (*sendmsg)(int fd, struct sockaddr *addr, socklen_t addrlen, char *msg, int msglen); int (*close)(int fd); }; static int user_sendmsg(int fd, struct sockaddr *addr, socklen_t addrlen, char *msg, int msglen) { struct msghdr hdr; struct iovec iov; memset(&iov, 0, sizeof(iov)); iov.iov_base = msg; iov.iov_len = msglen; memset(&hdr, 0, sizeof(hdr)); hdr.msg_name = (void *)addr; hdr.msg_namelen = addrlen; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; return sendmsg(fd, &hdr, 0); } static int user_bind(int fd, struct sockaddr *addr, socklen_t addrlen) { return bind(fd, (const struct sockaddr *)addr, addrlen); } struct sock_ops user_ops = { .connect_to_addr = connect_to_addr, .start_server = start_server, .socket = socket, .bind = user_bind, .getsockname = getsockname, .getpeername = getpeername, .sendmsg = user_sendmsg, .close = close, }; struct sock_ops kern_ops_sock_sendmsg = { .connect_to_addr = kernel_connect_to_addr, .start_server = kernel_start_server, .socket = kernel_init_sock, .bind = kernel_bind, .getsockname = kernel_getsockname, .getpeername = kernel_getpeername, .sendmsg = sock_sendmsg, .close = kernel_close_sock, }; struct sock_ops kern_ops_kernel_sendmsg = { .connect_to_addr = kernel_connect_to_addr, .start_server = kernel_start_server, .socket = kernel_init_sock, .bind = kernel_bind, .getsockname = kernel_getsockname, .getpeername = kernel_getpeername, .sendmsg = kernel_sendmsg, .close = kernel_close_sock, }; struct sock_addr_test { enum sock_addr_test_type type; const char *name; /* BPF prog properties */ load_fn loadfn; destroy_fn destroyfn; enum bpf_attach_type attach_type; /* Socket operations */ struct sock_ops *ops; /* Socket properties */ int socket_family; int socket_type; /* IP:port pairs for BPF prog to override */ const char *requested_addr; unsigned short requested_port; const char *expected_addr; unsigned short expected_port; const char *expected_src_addr; /* Expected test result */ enum { LOAD_REJECT, ATTACH_REJECT, SYSCALL_EPERM, SYSCALL_ENOTSUPP, SUCCESS, } expected_result; }; #define BPF_SKEL_FUNCS_RAW(skel_name, prog_name) \ static void *prog_name##_load_raw(int cgroup_fd, \ enum bpf_attach_type attach_type, \ bool expect_reject) \ { \ struct skel_name *skel = skel_name##__open(); \ int prog_fd = -1; \ if (!ASSERT_OK_PTR(skel, "skel_open")) \ goto cleanup; \ if (!ASSERT_OK(skel_name##__load(skel), "load")) \ goto cleanup; \ prog_fd = bpf_program__fd(skel->progs.prog_name); \ if (!ASSERT_GT(prog_fd, 0, "prog_fd")) \ goto cleanup; \ if (bpf_prog_attach(prog_fd, cgroup_fd, attach_type, \ BPF_F_ALLOW_OVERRIDE), "bpf_prog_attach") { \ ASSERT_TRUE(expect_reject, "unexpected rejection"); \ goto cleanup; \ } \ if (!ASSERT_FALSE(expect_reject, "expected rejection")) \ goto cleanup; \ cleanup: \ if (prog_fd > 0) \ bpf_prog_detach(cgroup_fd, attach_type); \ skel_name##__destroy(skel); \ return NULL; \ } \ static void prog_name##_destroy_raw(void *progfd) \ { \ /* No-op. *_load_raw does all cleanup. */ \ } \ #define BPF_SKEL_FUNCS(skel_name, prog_name) \ static void *prog_name##_load(int cgroup_fd, \ enum bpf_attach_type attach_type, \ bool expect_reject) \ { \ struct skel_name *skel = skel_name##__open(); \ if (!ASSERT_OK_PTR(skel, "skel_open")) \ goto cleanup; \ if (!ASSERT_OK(bpf_program__set_expected_attach_type(skel->progs.prog_name, \ attach_type), \ "set_expected_attach_type")) \ goto cleanup; \ if (skel_name##__load(skel)) { \ ASSERT_TRUE(expect_reject, "unexpected rejection"); \ goto cleanup; \ } \ if (!ASSERT_FALSE(expect_reject, "expected rejection")) \ goto cleanup; \ skel->links.prog_name = bpf_program__attach_cgroup( \ skel->progs.prog_name, cgroup_fd); \ if (!ASSERT_OK_PTR(skel->links.prog_name, "prog_attach")) \ goto cleanup; \ return skel; \ cleanup: \ skel_name##__destroy(skel); \ return NULL; \ } \ static void prog_name##_destroy(void *skel) \ { \ skel_name##__destroy(skel); \ } BPF_SKEL_FUNCS(bind4_prog, bind_v4_prog); BPF_SKEL_FUNCS_RAW(bind4_prog, bind_v4_prog); BPF_SKEL_FUNCS(bind4_prog, bind_v4_deny_prog); BPF_SKEL_FUNCS(bind6_prog, bind_v6_prog); BPF_SKEL_FUNCS_RAW(bind6_prog, bind_v6_prog); BPF_SKEL_FUNCS(bind6_prog, bind_v6_deny_prog); BPF_SKEL_FUNCS(connect4_prog, connect_v4_prog); BPF_SKEL_FUNCS_RAW(connect4_prog, connect_v4_prog); BPF_SKEL_FUNCS(connect4_prog, connect_v4_deny_prog); BPF_SKEL_FUNCS(connect6_prog, connect_v6_prog); BPF_SKEL_FUNCS_RAW(connect6_prog, connect_v6_prog); BPF_SKEL_FUNCS(connect6_prog, connect_v6_deny_prog); BPF_SKEL_FUNCS(connect_unix_prog, connect_unix_prog); BPF_SKEL_FUNCS_RAW(connect_unix_prog, connect_unix_prog); BPF_SKEL_FUNCS(connect_unix_prog, connect_unix_deny_prog); BPF_SKEL_FUNCS(sendmsg4_prog, sendmsg_v4_prog); BPF_SKEL_FUNCS_RAW(sendmsg4_prog, sendmsg_v4_prog); BPF_SKEL_FUNCS(sendmsg4_prog, sendmsg_v4_deny_prog); BPF_SKEL_FUNCS(sendmsg6_prog, sendmsg_v6_prog); BPF_SKEL_FUNCS_RAW(sendmsg6_prog, sendmsg_v6_prog); BPF_SKEL_FUNCS(sendmsg6_prog, sendmsg_v6_deny_prog); BPF_SKEL_FUNCS(sendmsg6_prog, sendmsg_v6_preserve_dst_prog); BPF_SKEL_FUNCS(sendmsg6_prog, sendmsg_v6_v4mapped_prog); BPF_SKEL_FUNCS(sendmsg6_prog, sendmsg_v6_wildcard_prog); BPF_SKEL_FUNCS(sendmsg_unix_prog, sendmsg_unix_prog); BPF_SKEL_FUNCS_RAW(sendmsg_unix_prog, sendmsg_unix_prog); BPF_SKEL_FUNCS(sendmsg_unix_prog, sendmsg_unix_deny_prog); BPF_SKEL_FUNCS(recvmsg4_prog, recvmsg4_prog); BPF_SKEL_FUNCS_RAW(recvmsg4_prog, recvmsg4_prog); BPF_SKEL_FUNCS(recvmsg6_prog, recvmsg6_prog); BPF_SKEL_FUNCS_RAW(recvmsg6_prog, recvmsg6_prog); BPF_SKEL_FUNCS(recvmsg_unix_prog, recvmsg_unix_prog); BPF_SKEL_FUNCS_RAW(recvmsg_unix_prog, recvmsg_unix_prog); BPF_SKEL_FUNCS(getsockname_unix_prog, getsockname_unix_prog); BPF_SKEL_FUNCS_RAW(getsockname_unix_prog, getsockname_unix_prog); BPF_SKEL_FUNCS(getsockname4_prog, getsockname_v4_prog); BPF_SKEL_FUNCS_RAW(getsockname4_prog, getsockname_v4_prog); BPF_SKEL_FUNCS(getsockname6_prog, getsockname_v6_prog); BPF_SKEL_FUNCS_RAW(getsockname6_prog, getsockname_v6_prog); BPF_SKEL_FUNCS(getpeername_unix_prog, getpeername_unix_prog); BPF_SKEL_FUNCS_RAW(getpeername_unix_prog, getpeername_unix_prog); BPF_SKEL_FUNCS(getpeername4_prog, getpeername_v4_prog); BPF_SKEL_FUNCS_RAW(getpeername4_prog, getpeername_v4_prog); BPF_SKEL_FUNCS(getpeername6_prog, getpeername_v6_prog); BPF_SKEL_FUNCS_RAW(getpeername6_prog, getpeername_v6_prog); static struct sock_addr_test tests[] = { /* bind - system calls */ { SOCK_ADDR_TEST_BIND, "bind4: bind (stream)", bind_v4_prog_load, bind_v4_prog_destroy, BPF_CGROUP_INET4_BIND, &user_ops, AF_INET, SOCK_STREAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_BIND, "bind4: bind deny (stream)", bind_v4_deny_prog_load, bind_v4_deny_prog_destroy, BPF_CGROUP_INET4_BIND, &user_ops, AF_INET, SOCK_STREAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_BIND, "bind4: bind (dgram)", bind_v4_prog_load, bind_v4_prog_destroy, BPF_CGROUP_INET4_BIND, &user_ops, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_BIND, "bind4: bind deny (dgram)", bind_v4_deny_prog_load, bind_v4_deny_prog_destroy, BPF_CGROUP_INET4_BIND, &user_ops, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_BIND, "bind4: load prog with wrong expected attach type", bind_v4_prog_load, bind_v4_prog_destroy, BPF_CGROUP_INET6_BIND, &user_ops, AF_INET, SOCK_STREAM, NULL, 0, NULL, 0, NULL, LOAD_REJECT, }, { SOCK_ADDR_TEST_BIND, "bind4: attach prog with wrong attach type", bind_v4_prog_load_raw, bind_v4_prog_destroy_raw, BPF_CGROUP_INET6_BIND, &user_ops, AF_INET, SOCK_STREAM, NULL, 0, NULL, 0, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_BIND, "bind6: bind (stream)", bind_v6_prog_load, bind_v6_prog_destroy, BPF_CGROUP_INET6_BIND, &user_ops, AF_INET6, SOCK_STREAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_BIND, "bind6: bind deny (stream)", bind_v6_deny_prog_load, bind_v6_deny_prog_destroy, BPF_CGROUP_INET6_BIND, &user_ops, AF_INET6, SOCK_STREAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_BIND, "bind6: bind (dgram)", bind_v6_prog_load, bind_v6_prog_destroy, BPF_CGROUP_INET6_BIND, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_BIND, "bind6: bind deny (dgram)", bind_v6_deny_prog_load, bind_v6_deny_prog_destroy, BPF_CGROUP_INET6_BIND, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_BIND, "bind6: load prog with wrong expected attach type", bind_v6_prog_load, bind_v6_prog_destroy, BPF_CGROUP_INET4_BIND, &user_ops, AF_INET6, SOCK_STREAM, NULL, 0, NULL, 0, NULL, LOAD_REJECT, }, { SOCK_ADDR_TEST_BIND, "bind6: attach prog with wrong attach type", bind_v6_prog_load_raw, bind_v6_prog_destroy_raw, BPF_CGROUP_INET4_BIND, &user_ops, AF_INET, SOCK_STREAM, NULL, 0, NULL, 0, NULL, ATTACH_REJECT, }, /* bind - kernel calls */ { SOCK_ADDR_TEST_BIND, "bind4: kernel_bind (stream)", bind_v4_prog_load, bind_v4_prog_destroy, BPF_CGROUP_INET4_BIND, &kern_ops_sock_sendmsg, AF_INET, SOCK_STREAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_BIND, "bind4: kernel_bind deny (stream)", bind_v4_deny_prog_load, bind_v4_deny_prog_destroy, BPF_CGROUP_INET4_BIND, &kern_ops_sock_sendmsg, AF_INET, SOCK_STREAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_BIND, "bind4: kernel_bind (dgram)", bind_v4_prog_load, bind_v4_prog_destroy, BPF_CGROUP_INET4_BIND, &kern_ops_sock_sendmsg, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_BIND, "bind4: kernel_bind deny (dgram)", bind_v4_deny_prog_load, bind_v4_deny_prog_destroy, BPF_CGROUP_INET4_BIND, &kern_ops_sock_sendmsg, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_BIND, "bind6: kernel_bind (stream)", bind_v6_prog_load, bind_v6_prog_destroy, BPF_CGROUP_INET6_BIND, &kern_ops_sock_sendmsg, AF_INET6, SOCK_STREAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_BIND, "bind6: kernel_bind deny (stream)", bind_v6_deny_prog_load, bind_v6_deny_prog_destroy, BPF_CGROUP_INET6_BIND, &kern_ops_sock_sendmsg, AF_INET6, SOCK_STREAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_BIND, "bind6: kernel_bind (dgram)", bind_v6_prog_load, bind_v6_prog_destroy, BPF_CGROUP_INET6_BIND, &kern_ops_sock_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_BIND, "bind6: kernel_bind deny (dgram)", bind_v6_deny_prog_load, bind_v6_deny_prog_destroy, BPF_CGROUP_INET6_BIND, &kern_ops_sock_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, NULL, SYSCALL_EPERM, }, /* connect - system calls */ { SOCK_ADDR_TEST_CONNECT, "connect4: connect (stream)", connect_v4_prog_load, connect_v4_prog_destroy, BPF_CGROUP_INET4_CONNECT, &user_ops, AF_INET, SOCK_STREAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect4: connect deny (stream)", connect_v4_deny_prog_load, connect_v4_deny_prog_destroy, BPF_CGROUP_INET4_CONNECT, &user_ops, AF_INET, SOCK_STREAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect4: connect (dgram)", connect_v4_prog_load, connect_v4_prog_destroy, BPF_CGROUP_INET4_CONNECT, &user_ops, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect4: connect deny (dgram)", connect_v4_deny_prog_load, connect_v4_deny_prog_destroy, BPF_CGROUP_INET4_CONNECT, &user_ops, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect4: load prog with wrong expected attach type", connect_v4_prog_load, connect_v4_prog_destroy, BPF_CGROUP_INET6_CONNECT, &user_ops, AF_INET, SOCK_STREAM, NULL, 0, NULL, 0, NULL, LOAD_REJECT, }, { SOCK_ADDR_TEST_CONNECT, "connect4: attach prog with wrong attach type", connect_v4_prog_load_raw, connect_v4_prog_destroy_raw, BPF_CGROUP_INET6_CONNECT, &user_ops, AF_INET, SOCK_STREAM, NULL, 0, NULL, 0, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_CONNECT, "connect6: connect (stream)", connect_v6_prog_load, connect_v6_prog_destroy, BPF_CGROUP_INET6_CONNECT, &user_ops, AF_INET6, SOCK_STREAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect6: connect deny (stream)", connect_v6_deny_prog_load, connect_v6_deny_prog_destroy, BPF_CGROUP_INET6_CONNECT, &user_ops, AF_INET6, SOCK_STREAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect6: connect (dgram)", connect_v6_prog_load, connect_v6_prog_destroy, BPF_CGROUP_INET6_CONNECT, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect6: connect deny (dgram)", connect_v6_deny_prog_load, connect_v6_deny_prog_destroy, BPF_CGROUP_INET6_CONNECT, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect6: load prog with wrong expected attach type", connect_v6_prog_load, connect_v6_prog_destroy, BPF_CGROUP_INET4_CONNECT, &user_ops, AF_INET6, SOCK_STREAM, NULL, 0, NULL, 0, NULL, LOAD_REJECT, }, { SOCK_ADDR_TEST_CONNECT, "connect6: attach prog with wrong attach type", connect_v6_prog_load_raw, connect_v6_prog_destroy_raw, BPF_CGROUP_INET4_CONNECT, &user_ops, AF_INET, SOCK_STREAM, NULL, 0, NULL, 0, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_CONNECT, "connect_unix: connect (stream)", connect_unix_prog_load, connect_unix_prog_destroy, BPF_CGROUP_UNIX_CONNECT, &user_ops, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect_unix: connect deny (stream)", connect_unix_deny_prog_load, connect_unix_deny_prog_destroy, BPF_CGROUP_UNIX_CONNECT, &user_ops, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect_unix: attach prog with wrong attach type", connect_unix_prog_load_raw, connect_unix_prog_destroy_raw, BPF_CGROUP_INET4_CONNECT, &user_ops, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, ATTACH_REJECT, }, /* connect - kernel calls */ { SOCK_ADDR_TEST_CONNECT, "connect4: kernel_connect (stream)", connect_v4_prog_load, connect_v4_prog_destroy, BPF_CGROUP_INET4_CONNECT, &kern_ops_sock_sendmsg, AF_INET, SOCK_STREAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect4: kernel_connect deny (stream)", connect_v4_deny_prog_load, connect_v4_deny_prog_destroy, BPF_CGROUP_INET4_CONNECT, &kern_ops_sock_sendmsg, AF_INET, SOCK_STREAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect4: kernel_connect (dgram)", connect_v4_prog_load, connect_v4_prog_destroy, BPF_CGROUP_INET4_CONNECT, &kern_ops_sock_sendmsg, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect4: kernel_connect deny (dgram)", connect_v4_deny_prog_load, connect_v4_deny_prog_destroy, BPF_CGROUP_INET4_CONNECT, &kern_ops_sock_sendmsg, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect6: kernel_connect (stream)", connect_v6_prog_load, connect_v6_prog_destroy, BPF_CGROUP_INET6_CONNECT, &kern_ops_sock_sendmsg, AF_INET6, SOCK_STREAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect6: kernel_connect deny (stream)", connect_v6_deny_prog_load, connect_v6_deny_prog_destroy, BPF_CGROUP_INET6_CONNECT, &kern_ops_sock_sendmsg, AF_INET6, SOCK_STREAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect6: kernel_connect (dgram)", connect_v6_prog_load, connect_v6_prog_destroy, BPF_CGROUP_INET6_CONNECT, &kern_ops_sock_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect6: kernel_connect deny (dgram)", connect_v6_deny_prog_load, connect_v6_deny_prog_destroy, BPF_CGROUP_INET6_CONNECT, &kern_ops_sock_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_CONNECT, "connect_unix: kernel_connect (dgram)", connect_unix_prog_load, connect_unix_prog_destroy, BPF_CGROUP_UNIX_CONNECT, &kern_ops_sock_sendmsg, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, { SOCK_ADDR_TEST_CONNECT, "connect_unix: kernel_connect deny (dgram)", connect_unix_deny_prog_load, connect_unix_deny_prog_destroy, BPF_CGROUP_UNIX_CONNECT, &kern_ops_sock_sendmsg, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SYSCALL_EPERM, }, /* sendmsg - system calls */ { SOCK_ADDR_TEST_SENDMSG, "sendmsg4: sendmsg (dgram)", sendmsg_v4_prog_load, sendmsg_v4_prog_destroy, BPF_CGROUP_UDP4_SENDMSG, &user_ops, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg4: sendmsg deny (dgram)", sendmsg_v4_deny_prog_load, sendmsg_v4_deny_prog_destroy, BPF_CGROUP_UDP4_SENDMSG, &user_ops, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg4: load prog with wrong expected attach type", sendmsg_v4_prog_load, sendmsg_v4_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &user_ops, AF_INET, SOCK_DGRAM, NULL, 0, NULL, 0, NULL, LOAD_REJECT, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg4: attach prog with wrong attach type", sendmsg_v4_prog_load_raw, sendmsg_v4_prog_destroy_raw, BPF_CGROUP_UDP6_SENDMSG, &user_ops, AF_INET, SOCK_DGRAM, NULL, 0, NULL, 0, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: sendmsg (dgram)", sendmsg_v6_prog_load, sendmsg_v6_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: sendmsg [::] (BSD'ism) (dgram)", sendmsg_v6_preserve_dst_prog_load, sendmsg_v6_preserve_dst_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &user_ops, AF_INET6, SOCK_DGRAM, WILDCARD6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_PORT, SRC6_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: sendmsg deny (dgram)", sendmsg_v6_deny_prog_load, sendmsg_v6_deny_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: sendmsg IPv4-mapped IPv6 (dgram)", sendmsg_v6_v4mapped_prog_load, sendmsg_v6_v4mapped_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SYSCALL_ENOTSUPP, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: sendmsg dst IP = [::] (BSD'ism) (dgram)", sendmsg_v6_wildcard_prog_load, sendmsg_v6_wildcard_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: load prog with wrong expected attach type", sendmsg_v6_prog_load, sendmsg_v6_prog_destroy, BPF_CGROUP_UDP4_SENDMSG, &user_ops, AF_INET6, SOCK_DGRAM, NULL, 0, NULL, 0, NULL, LOAD_REJECT, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: attach prog with wrong attach type", sendmsg_v6_prog_load_raw, sendmsg_v6_prog_destroy_raw, BPF_CGROUP_UDP4_SENDMSG, &user_ops, AF_INET6, SOCK_DGRAM, NULL, 0, NULL, 0, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg_unix: sendmsg (dgram)", sendmsg_unix_prog_load, sendmsg_unix_prog_destroy, BPF_CGROUP_UNIX_SENDMSG, &user_ops, AF_UNIX, SOCK_DGRAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg_unix: sendmsg deny (dgram)", sendmsg_unix_deny_prog_load, sendmsg_unix_deny_prog_destroy, BPF_CGROUP_UNIX_SENDMSG, &user_ops, AF_UNIX, SOCK_DGRAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg_unix: attach prog with wrong attach type", sendmsg_unix_prog_load_raw, sendmsg_unix_prog_destroy_raw, BPF_CGROUP_UDP4_SENDMSG, &user_ops, AF_UNIX, SOCK_DGRAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, ATTACH_REJECT, }, /* sendmsg - kernel calls (sock_sendmsg) */ { SOCK_ADDR_TEST_SENDMSG, "sendmsg4: sock_sendmsg (dgram)", sendmsg_v4_prog_load, sendmsg_v4_prog_destroy, BPF_CGROUP_UDP4_SENDMSG, &kern_ops_sock_sendmsg, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg4: sock_sendmsg deny (dgram)", sendmsg_v4_deny_prog_load, sendmsg_v4_deny_prog_destroy, BPF_CGROUP_UDP4_SENDMSG, &kern_ops_sock_sendmsg, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: sock_sendmsg (dgram)", sendmsg_v6_prog_load, sendmsg_v6_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &kern_ops_sock_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: sock_sendmsg [::] (BSD'ism) (dgram)", sendmsg_v6_preserve_dst_prog_load, sendmsg_v6_preserve_dst_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &kern_ops_sock_sendmsg, AF_INET6, SOCK_DGRAM, WILDCARD6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_PORT, SRC6_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: sock_sendmsg deny (dgram)", sendmsg_v6_deny_prog_load, sendmsg_v6_deny_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &kern_ops_sock_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg_unix: sock_sendmsg (dgram)", sendmsg_unix_prog_load, sendmsg_unix_prog_destroy, BPF_CGROUP_UNIX_SENDMSG, &kern_ops_sock_sendmsg, AF_UNIX, SOCK_DGRAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg_unix: sock_sendmsg deny (dgram)", sendmsg_unix_deny_prog_load, sendmsg_unix_deny_prog_destroy, BPF_CGROUP_UNIX_SENDMSG, &kern_ops_sock_sendmsg, AF_UNIX, SOCK_DGRAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SYSCALL_EPERM, }, /* sendmsg - kernel calls (kernel_sendmsg) */ { SOCK_ADDR_TEST_SENDMSG, "sendmsg4: kernel_sendmsg (dgram)", sendmsg_v4_prog_load, sendmsg_v4_prog_destroy, BPF_CGROUP_UDP4_SENDMSG, &kern_ops_kernel_sendmsg, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg4: kernel_sendmsg deny (dgram)", sendmsg_v4_deny_prog_load, sendmsg_v4_deny_prog_destroy, BPF_CGROUP_UDP4_SENDMSG, &kern_ops_kernel_sendmsg, AF_INET, SOCK_DGRAM, SERV4_IP, SERV4_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SRC4_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: kernel_sendmsg (dgram)", sendmsg_v6_prog_load, sendmsg_v6_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &kern_ops_kernel_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: kernel_sendmsg [::] (BSD'ism) (dgram)", sendmsg_v6_preserve_dst_prog_load, sendmsg_v6_preserve_dst_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &kern_ops_kernel_sendmsg, AF_INET6, SOCK_DGRAM, WILDCARD6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_PORT, SRC6_IP, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg6: kernel_sendmsg deny (dgram)", sendmsg_v6_deny_prog_load, sendmsg_v6_deny_prog_destroy, BPF_CGROUP_UDP6_SENDMSG, &kern_ops_kernel_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_IP, SERV6_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SRC6_REWRITE_IP, SYSCALL_EPERM, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg_unix: sock_sendmsg (dgram)", sendmsg_unix_prog_load, sendmsg_unix_prog_destroy, BPF_CGROUP_UNIX_SENDMSG, &kern_ops_kernel_sendmsg, AF_UNIX, SOCK_DGRAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, { SOCK_ADDR_TEST_SENDMSG, "sendmsg_unix: kernel_sendmsg deny (dgram)", sendmsg_unix_deny_prog_load, sendmsg_unix_deny_prog_destroy, BPF_CGROUP_UNIX_SENDMSG, &kern_ops_kernel_sendmsg, AF_UNIX, SOCK_DGRAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SYSCALL_EPERM, }, /* recvmsg - system calls */ { SOCK_ADDR_TEST_RECVMSG, "recvmsg4: recvfrom (dgram)", recvmsg4_prog_load, recvmsg4_prog_destroy, BPF_CGROUP_UDP4_RECVMSG, &user_ops, AF_INET, SOCK_DGRAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SUCCESS, }, { SOCK_ADDR_TEST_RECVMSG, "recvmsg4: attach prog with wrong attach type", recvmsg4_prog_load_raw, recvmsg4_prog_destroy_raw, BPF_CGROUP_UDP6_RECVMSG, &user_ops, AF_INET, SOCK_DGRAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, ATTACH_REJECT, }, { SOCK_ADDR_TEST_RECVMSG, "recvmsg6: recvfrom (dgram)", recvmsg6_prog_load, recvmsg6_prog_destroy, BPF_CGROUP_UDP6_RECVMSG, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SUCCESS, }, { SOCK_ADDR_TEST_RECVMSG, "recvmsg6: attach prog with wrong attach type", recvmsg6_prog_load_raw, recvmsg6_prog_destroy_raw, BPF_CGROUP_UDP4_RECVMSG, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, ATTACH_REJECT, }, { SOCK_ADDR_TEST_RECVMSG, "recvmsg_unix: recvfrom (dgram)", recvmsg_unix_prog_load, recvmsg_unix_prog_destroy, BPF_CGROUP_UNIX_RECVMSG, &user_ops, AF_UNIX, SOCK_DGRAM, SERVUN_REWRITE_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, SERVUN_ADDRESS, SUCCESS, }, { SOCK_ADDR_TEST_RECVMSG, "recvmsg_unix: recvfrom (stream)", recvmsg_unix_prog_load, recvmsg_unix_prog_destroy, BPF_CGROUP_UNIX_RECVMSG, &user_ops, AF_UNIX, SOCK_STREAM, SERVUN_REWRITE_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, SERVUN_ADDRESS, SUCCESS, }, { SOCK_ADDR_TEST_RECVMSG, "recvmsg_unix: attach prog with wrong attach type", recvmsg_unix_prog_load_raw, recvmsg_unix_prog_destroy_raw, BPF_CGROUP_UDP4_RECVMSG, &user_ops, AF_INET6, SOCK_STREAM, SERVUN_REWRITE_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, SERVUN_ADDRESS, ATTACH_REJECT, }, /* getsockname - system calls */ { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname4: getsockname (stream)", getsockname_v4_prog_load, getsockname_v4_prog_destroy, BPF_CGROUP_INET4_GETSOCKNAME, &user_ops, AF_INET, SOCK_STREAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname4: getsockname (dgram)", getsockname_v4_prog_load, getsockname_v4_prog_destroy, BPF_CGROUP_INET4_GETSOCKNAME, &user_ops, AF_INET, SOCK_DGRAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname4: attach prog with wrong attach type", getsockname_v4_prog_load_raw, getsockname_v4_prog_destroy_raw, BPF_CGROUP_INET6_GETSOCKNAME, &user_ops, AF_INET, SOCK_DGRAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname6: getsockname (stream)", getsockname_v6_prog_load, getsockname_v6_prog_destroy, BPF_CGROUP_INET6_GETSOCKNAME, &user_ops, AF_INET6, SOCK_STREAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname6: getsockname (dgram)", getsockname_v6_prog_load, getsockname_v6_prog_destroy, BPF_CGROUP_INET6_GETSOCKNAME, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname6: attach prog with wrong attach type", getsockname_v6_prog_load_raw, getsockname_v6_prog_destroy_raw, BPF_CGROUP_INET4_GETSOCKNAME, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname_unix: getsockname", getsockname_unix_prog_load, getsockname_unix_prog_destroy, BPF_CGROUP_UNIX_GETSOCKNAME, &user_ops, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname_unix: attach prog with wrong attach type", getsockname_unix_prog_load_raw, getsockname_unix_prog_destroy_raw, BPF_CGROUP_INET4_GETSOCKNAME, &user_ops, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, ATTACH_REJECT, }, /* getsockname - kernel calls */ { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname4: kernel_getsockname (stream)", getsockname_v4_prog_load, getsockname_v4_prog_destroy, BPF_CGROUP_INET4_GETSOCKNAME, &kern_ops_kernel_sendmsg, AF_INET, SOCK_STREAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname4: kernel_getsockname (dgram)", getsockname_v4_prog_load, getsockname_v4_prog_destroy, BPF_CGROUP_INET4_GETSOCKNAME, &kern_ops_kernel_sendmsg, AF_INET, SOCK_DGRAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname6: kernel_getsockname (stream)", getsockname_v6_prog_load, getsockname_v6_prog_destroy, BPF_CGROUP_INET6_GETSOCKNAME, &kern_ops_kernel_sendmsg, AF_INET6, SOCK_STREAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname6: kernel_getsockname (dgram)", getsockname_v6_prog_load, getsockname_v6_prog_destroy, BPF_CGROUP_INET6_GETSOCKNAME, &kern_ops_kernel_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETSOCKNAME, "getsockname_unix: kernel_getsockname", getsockname_unix_prog_load, getsockname_unix_prog_destroy, BPF_CGROUP_UNIX_GETSOCKNAME, &kern_ops_kernel_sendmsg, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, /* getpeername - system calls */ { SOCK_ADDR_TEST_GETPEERNAME, "getpeername4: getpeername (stream)", getpeername_v4_prog_load, getpeername_v4_prog_destroy, BPF_CGROUP_INET4_GETPEERNAME, &user_ops, AF_INET, SOCK_STREAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername4: getpeername (dgram)", getpeername_v4_prog_load, getpeername_v4_prog_destroy, BPF_CGROUP_INET4_GETPEERNAME, &user_ops, AF_INET, SOCK_DGRAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername4: attach prog with wrong attach type", getpeername_v4_prog_load_raw, getpeername_v4_prog_destroy_raw, BPF_CGROUP_INET6_GETSOCKNAME, &user_ops, AF_UNIX, SOCK_DGRAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername6: getpeername (stream)", getpeername_v6_prog_load, getpeername_v6_prog_destroy, BPF_CGROUP_INET6_GETPEERNAME, &user_ops, AF_INET6, SOCK_STREAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername6: getpeername (dgram)", getpeername_v6_prog_load, getpeername_v6_prog_destroy, BPF_CGROUP_INET6_GETPEERNAME, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername6: attach prog with wrong attach type", getpeername_v6_prog_load_raw, getpeername_v6_prog_destroy_raw, BPF_CGROUP_INET4_GETSOCKNAME, &user_ops, AF_INET6, SOCK_DGRAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, ATTACH_REJECT, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername_unix: getpeername", getpeername_unix_prog_load, getpeername_unix_prog_destroy, BPF_CGROUP_UNIX_GETPEERNAME, &user_ops, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername_unix: attach prog with wrong attach type", getpeername_unix_prog_load_raw, getpeername_unix_prog_destroy_raw, BPF_CGROUP_INET4_GETSOCKNAME, &user_ops, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, ATTACH_REJECT, }, /* getpeername - kernel calls */ { SOCK_ADDR_TEST_GETPEERNAME, "getpeername4: kernel_getpeername (stream)", getpeername_v4_prog_load, getpeername_v4_prog_destroy, BPF_CGROUP_INET4_GETPEERNAME, &kern_ops_kernel_sendmsg, AF_INET, SOCK_STREAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername4: kernel_getpeername (dgram)", getpeername_v4_prog_load, getpeername_v4_prog_destroy, BPF_CGROUP_INET4_GETPEERNAME, &kern_ops_kernel_sendmsg, AF_INET, SOCK_DGRAM, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, SERV4_IP, SERV4_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername6: kernel_getpeername (stream)", getpeername_v6_prog_load, getpeername_v6_prog_destroy, BPF_CGROUP_INET6_GETPEERNAME, &kern_ops_kernel_sendmsg, AF_INET6, SOCK_STREAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername6: kernel_getpeername (dgram)", getpeername_v6_prog_load, getpeername_v6_prog_destroy, BPF_CGROUP_INET6_GETPEERNAME, &kern_ops_kernel_sendmsg, AF_INET6, SOCK_DGRAM, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, SERV6_IP, SERV6_PORT, NULL, SUCCESS, }, { SOCK_ADDR_TEST_GETPEERNAME, "getpeername_unix: kernel_getpeername", getpeername_unix_prog_load, getpeername_unix_prog_destroy, BPF_CGROUP_UNIX_GETPEERNAME, &kern_ops_kernel_sendmsg, AF_UNIX, SOCK_STREAM, SERVUN_ADDRESS, 0, SERVUN_REWRITE_ADDRESS, 0, NULL, SUCCESS, }, }; typedef int (*info_fn)(int, struct sockaddr *, socklen_t *); static int cmp_addr(const struct sockaddr_storage *addr1, socklen_t addr1_len, const struct sockaddr_storage *addr2, socklen_t addr2_len, bool cmp_port) { const struct sockaddr_in *four1, *four2; const struct sockaddr_in6 *six1, *six2; const struct sockaddr_un *un1, *un2; if (addr1->ss_family != addr2->ss_family) return -1; if (addr1_len != addr2_len) return -1; if (addr1->ss_family == AF_INET) { four1 = (const struct sockaddr_in *)addr1; four2 = (const struct sockaddr_in *)addr2; return !((four1->sin_port == four2->sin_port || !cmp_port) && four1->sin_addr.s_addr == four2->sin_addr.s_addr); } else if (addr1->ss_family == AF_INET6) { six1 = (const struct sockaddr_in6 *)addr1; six2 = (const struct sockaddr_in6 *)addr2; return !((six1->sin6_port == six2->sin6_port || !cmp_port) && !memcmp(&six1->sin6_addr, &six2->sin6_addr, sizeof(struct in6_addr))); } else if (addr1->ss_family == AF_UNIX) { un1 = (const struct sockaddr_un *)addr1; un2 = (const struct sockaddr_un *)addr2; return memcmp(un1, un2, addr1_len); } return -1; } static int cmp_sock_addr(info_fn fn, int sock1, const struct sockaddr_storage *addr2, socklen_t addr2_len, bool cmp_port) { struct sockaddr_storage addr1; socklen_t len1 = sizeof(addr1); memset(&addr1, 0, len1); if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0) return -1; return cmp_addr(&addr1, len1, addr2, addr2_len, cmp_port); } static int load_sock_addr_kern(void) { int err; skel = sock_addr_kern__open_and_load(); if (!ASSERT_OK_PTR(skel, "skel")) goto err; err = 0; goto out; err: err = -1; out: return err; } static void unload_sock_addr_kern(void) { sock_addr_kern__destroy(skel); } static int test_bind(struct sock_addr_test *test) { struct sockaddr_storage expected_addr; socklen_t expected_addr_len = sizeof(struct sockaddr_storage); int serv = -1, client = -1, err; serv = test->ops->start_server(test->socket_family, test->socket_type, test->requested_addr, test->requested_port, 0); if (serv < 0) { err = errno; goto err; } err = make_sockaddr(test->socket_family, test->expected_addr, test->expected_port, &expected_addr, &expected_addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; err = cmp_sock_addr(test->ops->getsockname, serv, &expected_addr, expected_addr_len, true); if (!ASSERT_EQ(err, 0, "cmp_local_addr")) goto cleanup; /* Try to connect to server just in case */ client = connect_to_addr(test->socket_type, &expected_addr, expected_addr_len, NULL); if (!ASSERT_GE(client, 0, "connect_to_addr")) goto cleanup; cleanup: err = 0; err: if (client != -1) close(client); if (serv != -1) test->ops->close(serv); return err; } static int test_connect(struct sock_addr_test *test) { struct sockaddr_storage addr, expected_addr, expected_src_addr; socklen_t addr_len = sizeof(struct sockaddr_storage), expected_addr_len = sizeof(struct sockaddr_storage), expected_src_addr_len = sizeof(struct sockaddr_storage); int serv = -1, client = -1, err; serv = start_server(test->socket_family, test->socket_type, test->expected_addr, test->expected_port, 0); if (!ASSERT_GE(serv, 0, "start_server")) goto cleanup; err = make_sockaddr(test->socket_family, test->requested_addr, test->requested_port, &addr, &addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; client = test->ops->connect_to_addr(test->socket_type, &addr, addr_len, NULL); if (client < 0) { err = errno; goto err; } err = make_sockaddr(test->socket_family, test->expected_addr, test->expected_port, &expected_addr, &expected_addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; if (test->expected_src_addr) { err = make_sockaddr(test->socket_family, test->expected_src_addr, 0, &expected_src_addr, &expected_src_addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; } err = cmp_sock_addr(test->ops->getpeername, client, &expected_addr, expected_addr_len, true); if (!ASSERT_EQ(err, 0, "cmp_peer_addr")) goto cleanup; if (test->expected_src_addr) { err = cmp_sock_addr(test->ops->getsockname, client, &expected_src_addr, expected_src_addr_len, false); if (!ASSERT_EQ(err, 0, "cmp_local_addr")) goto cleanup; } cleanup: err = 0; err: if (client != -1) test->ops->close(client); if (serv != -1) close(serv); return err; } static int test_xmsg(struct sock_addr_test *test) { struct sockaddr_storage addr, src_addr; socklen_t addr_len = sizeof(struct sockaddr_storage), src_addr_len = sizeof(struct sockaddr_storage); char data = 'a'; int serv = -1, client = -1, err; /* Unlike the other tests, here we test that we can rewrite the src addr * with a recvmsg() hook. */ serv = start_server(test->socket_family, test->socket_type, test->expected_addr, test->expected_port, 0); if (!ASSERT_GE(serv, 0, "start_server")) goto cleanup; client = test->ops->socket(test->socket_family, test->socket_type, 0); if (!ASSERT_GE(client, 0, "socket")) goto cleanup; /* AF_UNIX sockets have to be bound to something to trigger the recvmsg bpf program. */ if (test->socket_family == AF_UNIX) { err = make_sockaddr(AF_UNIX, SRCUN_ADDRESS, 0, &src_addr, &src_addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; err = test->ops->bind(client, (struct sockaddr *)&src_addr, src_addr_len); if (!ASSERT_OK(err, "bind")) goto cleanup; } err = make_sockaddr(test->socket_family, test->requested_addr, test->requested_port, &addr, &addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; if (test->socket_type == SOCK_DGRAM) { err = test->ops->sendmsg(client, (struct sockaddr *)&addr, addr_len, &data, sizeof(data)); if (err < 0) { err = errno; goto err; } if (!ASSERT_EQ(err, sizeof(data), "sendmsg")) goto cleanup; } else { /* Testing with connection-oriented sockets is only valid for * recvmsg() tests. */ if (!ASSERT_EQ(test->type, SOCK_ADDR_TEST_RECVMSG, "recvmsg")) goto cleanup; err = connect(client, (const struct sockaddr *)&addr, addr_len); if (!ASSERT_OK(err, "connect")) goto cleanup; err = send(client, &data, sizeof(data), 0); if (!ASSERT_EQ(err, sizeof(data), "send")) goto cleanup; err = listen(serv, 0); if (!ASSERT_OK(err, "listen")) goto cleanup; err = accept(serv, NULL, NULL); if (!ASSERT_GE(err, 0, "accept")) goto cleanup; close(serv); serv = err; } addr_len = src_addr_len = sizeof(struct sockaddr_storage); err = recvfrom(serv, &data, sizeof(data), 0, (struct sockaddr *) &src_addr, &src_addr_len); if (!ASSERT_EQ(err, sizeof(data), "recvfrom")) goto cleanup; ASSERT_EQ(data, 'a', "data mismatch"); if (test->expected_src_addr) { err = make_sockaddr(test->socket_family, test->expected_src_addr, 0, &addr, &addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; err = cmp_addr(&src_addr, src_addr_len, &addr, addr_len, false); if (!ASSERT_EQ(err, 0, "cmp_addr")) goto cleanup; } cleanup: err = 0; err: if (client != -1) test->ops->close(client); if (serv != -1) close(serv); return err; } static int test_getsockname(struct sock_addr_test *test) { struct sockaddr_storage expected_addr; socklen_t expected_addr_len = sizeof(struct sockaddr_storage); int serv = -1, err; serv = test->ops->start_server(test->socket_family, test->socket_type, test->requested_addr, test->requested_port, 0); if (!ASSERT_GE(serv, 0, "start_server")) goto cleanup; err = make_sockaddr(test->socket_family, test->expected_addr, test->expected_port, &expected_addr, &expected_addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; err = cmp_sock_addr(test->ops->getsockname, serv, &expected_addr, expected_addr_len, true); if (!ASSERT_EQ(err, 0, "cmp_local_addr")) goto cleanup; cleanup: if (serv != -1) test->ops->close(serv); return 0; } static int test_getpeername(struct sock_addr_test *test) { struct sockaddr_storage addr, expected_addr; socklen_t addr_len = sizeof(struct sockaddr_storage), expected_addr_len = sizeof(struct sockaddr_storage); int serv = -1, client = -1, err; serv = start_server(test->socket_family, test->socket_type, test->requested_addr, test->requested_port, 0); if (!ASSERT_GE(serv, 0, "start_server")) goto cleanup; err = make_sockaddr(test->socket_family, test->requested_addr, test->requested_port, &addr, &addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; client = test->ops->connect_to_addr(test->socket_type, &addr, addr_len, NULL); if (!ASSERT_GE(client, 0, "connect_to_addr")) goto cleanup; err = make_sockaddr(test->socket_family, test->expected_addr, test->expected_port, &expected_addr, &expected_addr_len); if (!ASSERT_EQ(err, 0, "make_sockaddr")) goto cleanup; err = cmp_sock_addr(test->ops->getpeername, client, &expected_addr, expected_addr_len, true); if (!ASSERT_EQ(err, 0, "cmp_peer_addr")) goto cleanup; cleanup: if (client != -1) test->ops->close(client); if (serv != -1) close(serv); return 0; } static int setup_test_env(struct nstoken **tok) { int err; SYS_NOFAIL("ip netns delete %s", TEST_NS); SYS(fail, "ip netns add %s", TEST_NS); *tok = open_netns(TEST_NS); if (!ASSERT_OK_PTR(*tok, "netns token")) goto fail; SYS(fail, "ip link add dev %s1 type veth peer name %s2", TEST_IF_PREFIX, TEST_IF_PREFIX); SYS(fail, "ip link set lo up"); SYS(fail, "ip link set %s1 up", TEST_IF_PREFIX); SYS(fail, "ip link set %s2 up", TEST_IF_PREFIX); SYS(fail, "ip -4 addr add %s/8 dev %s1", TEST_IPV4, TEST_IF_PREFIX); SYS(fail, "ip -6 addr add %s/128 nodad dev %s1", TEST_IPV6, TEST_IF_PREFIX); err = 0; goto out; fail: err = -1; close_netns(*tok); *tok = NULL; SYS_NOFAIL("ip netns delete %s", TEST_NS); out: return err; } static void cleanup_test_env(struct nstoken *tok) { close_netns(tok); SYS_NOFAIL("ip netns delete %s", TEST_NS); } void test_sock_addr(void) { struct nstoken *tok = NULL; int cgroup_fd = -1; void *skel; cgroup_fd = test__join_cgroup("/sock_addr"); if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup")) goto cleanup; if (!ASSERT_OK(setup_test_env(&tok), "setup_test_env")) goto cleanup; if (!ASSERT_OK(load_sock_addr_kern(), "load_sock_addr_kern")) goto cleanup; for (size_t i = 0; i < ARRAY_SIZE(tests); ++i) { struct sock_addr_test *test = &tests[i]; int err; if (!test__start_subtest(test->name)) continue; skel = test->loadfn(cgroup_fd, test->attach_type, test->expected_result == LOAD_REJECT || test->expected_result == ATTACH_REJECT); if (!skel) continue; switch (test->type) { /* Not exercised yet but we leave this code here for when the * INET and INET6 sockaddr tests are migrated to this file in * the future. */ case SOCK_ADDR_TEST_BIND: err = test_bind(test); break; case SOCK_ADDR_TEST_CONNECT: err = test_connect(test); break; case SOCK_ADDR_TEST_SENDMSG: case SOCK_ADDR_TEST_RECVMSG: err = test_xmsg(test); break; case SOCK_ADDR_TEST_GETSOCKNAME: err = test_getsockname(test); break; case SOCK_ADDR_TEST_GETPEERNAME: err = test_getpeername(test); break; default: ASSERT_TRUE(false, "Unknown sock addr test type"); break; } if (test->expected_result == SYSCALL_EPERM) ASSERT_EQ(err, EPERM, "socket operation returns EPERM"); else if (test->expected_result == SYSCALL_ENOTSUPP) ASSERT_EQ(err, ENOTSUPP, "socket operation returns ENOTSUPP"); else if (test->expected_result == SUCCESS) ASSERT_OK(err, "socket operation succeeds"); test->destroyfn(skel); } cleanup: unload_sock_addr_kern(); cleanup_test_env(tok); if (cgroup_fd >= 0) close(cgroup_fd); }