diff mbox series

[v1,bpf-next,1/8] selftests/bpf: Introduce sock_addr_testmod

Message ID 20240329191907.1808635-2-jrife@google.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series selftests/bpf: Add sockaddr tests for kernel networking | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 949 this patch: 949
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 4 maintainers not CCed: linux-stm32@st-md-mailman.stormreply.com alexandre.torgue@foss.st.com mcoquelin.stm32@gmail.com linux-arm-kernel@lists.infradead.org
netdev/build_clang success Errors and warnings before: 955 this patch: 955
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api fail Found: 'module_param' was: 0 now: 5
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 961 this patch: 961
netdev/checkpatch warning WARNING: Block comments should align the * on each line WARNING: Prefer strscpy over strcpy - see: https://github.com/KSPP/linux/issues/88 WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? WARNING: line length of 104 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-15 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-7 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-18 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / veristat

Commit Message

Jordan Rife March 29, 2024, 7:18 p.m. UTC
sock_addr_testmod provides a mechanism for the sock_addr_kern prog_test
to drive socket operations in kernel space. On init, one of the
following socket operations is performed based on the module parameters:
kernel_bind(), kernel_connect(), or sock_sendmsg()/kernel_sendmsg() and
results are exposed through debugfs.

Signed-off-by: Jordan Rife <jrife@google.com>
---
 tools/testing/selftests/bpf/Makefile          |  11 +-
 .../bpf/sock_addr_testmod/.gitignore          |   6 +
 .../selftests/bpf/sock_addr_testmod/Makefile  |  20 ++
 .../bpf/sock_addr_testmod/sock_addr_testmod.c | 256 ++++++++++++++++++
 4 files changed, 292 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/bpf/sock_addr_testmod/.gitignore
 create mode 100644 tools/testing/selftests/bpf/sock_addr_testmod/Makefile
 create mode 100644 tools/testing/selftests/bpf/sock_addr_testmod/sock_addr_testmod.c

Comments

Andrii Nakryiko March 29, 2024, 10:09 p.m. UTC | #1
On Fri, Mar 29, 2024 at 12:20 PM Jordan Rife <jrife@google.com> wrote:
>
> sock_addr_testmod provides a mechanism for the sock_addr_kern prog_test
> to drive socket operations in kernel space. On init, one of the
> following socket operations is performed based on the module parameters:
> kernel_bind(), kernel_connect(), or sock_sendmsg()/kernel_sendmsg() and
> results are exposed through debugfs.
>
> Signed-off-by: Jordan Rife <jrife@google.com>
> ---
>  tools/testing/selftests/bpf/Makefile          |  11 +-
>  .../bpf/sock_addr_testmod/.gitignore          |   6 +
>  .../selftests/bpf/sock_addr_testmod/Makefile  |  20 ++
>  .../bpf/sock_addr_testmod/sock_addr_testmod.c | 256 ++++++++++++++++++
>  4 files changed, 292 insertions(+), 1 deletion(-)
>  create mode 100644 tools/testing/selftests/bpf/sock_addr_testmod/.gitignore
>  create mode 100644 tools/testing/selftests/bpf/sock_addr_testmod/Makefile
>  create mode 100644 tools/testing/selftests/bpf/sock_addr_testmod/sock_addr_testmod.c
>
> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> index 3b9eb40d63436..b5d02ff724957 100644
> --- a/tools/testing/selftests/bpf/Makefile
> +++ b/tools/testing/selftests/bpf/Makefile
> @@ -132,7 +132,7 @@ TEST_GEN_PROGS_EXTENDED = test_sock_addr test_skb_cgroup_id_user \
>         flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \
>         test_lirc_mode2_user xdping test_cpp runqslower bench bpf_testmod.ko \
>         xskxceiver xdp_redirect_multi xdp_synproxy veristat xdp_hw_metadata \
> -       xdp_features bpf_test_no_cfi.ko
> +       xdp_features bpf_test_no_cfi.ko sock_addr_testmod.ko
>

Do we need yet another kernel module? Can this be done as part of
existing bpf_testmod module?

>  TEST_GEN_FILES += liburandom_read.so urandom_read sign-file uprobe_multi
>
> @@ -160,6 +160,7 @@ override define CLEAN
>         $(Q)$(RM) -r $(TEST_GEN_FILES)
>         $(Q)$(RM) -r $(EXTRA_CLEAN)
>         $(Q)$(MAKE) -C bpf_testmod clean
> +       $(Q)$(MAKE) -C sock_addr_testmod clean
>         $(Q)$(MAKE) docs-clean
>  endef
>

[...]
Martin KaFai Lau April 2, 2024, 5:57 p.m. UTC | #2
On 3/29/24 12:18 PM, Jordan Rife wrote:
> +static int do_sock_op(int op, struct sockaddr *addr, int addrlen)

This function can be made as a new kfunc in bpf_testmod.c. The 
sock_create_kern() could be moved to here also. Take a look at the 
register_btf_kfunc_id_set() usage in bpf_testmod.c and how those registered 
kfunc(s) can be called by the bpf prog in progs/*.

If the do_kernel_{bind,connect,sendmsg} and the sock_create_kern need a 
sleepable context, it will need to mark the kfunc KF_SLEEPABLE. The kfunc can be 
registered to the BPF_PROG_TYPE_SYSCALL sleepable prog type. There are some 
examples in progs/kfunc_call_test.c and how the "syscall" bpf prog can be run by 
bpf_prog_test_run_opts().

The result (e.g. ensuring the addr and addrlen have not been changed) can be 
checked in the bpf prog itself. Then the new sock_addr_testmod is not needed.

> +{
> +	switch (op) {
> +	case BIND:
> +		return do_kernel_bind(addr, addrlen);
> +	case CONNECT:
> +		return do_kernel_connect(addr, addrlen);
> +	case SENDMSG:
> +		return do_kernel_sendmsg(addr, addrlen);
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
Jordan Rife April 2, 2024, 6:14 p.m. UTC | #3
Martin and Andrii,

> This function can be made as a new kfunc in bpf_testmod.c. The
> sock_create_kern() could be moved to here also. Take a look at the
> register_btf_kfunc_id_set() usage in bpf_testmod.c and how those registered
> kfunc(s) can be called by the bpf prog in progs/*.

Thanks for the feedback. I will explore this approach and see if I can
get rid of the additional test module.

-Jordan
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 3b9eb40d63436..b5d02ff724957 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -132,7 +132,7 @@  TEST_GEN_PROGS_EXTENDED = test_sock_addr test_skb_cgroup_id_user \
 	flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \
 	test_lirc_mode2_user xdping test_cpp runqslower bench bpf_testmod.ko \
 	xskxceiver xdp_redirect_multi xdp_synproxy veristat xdp_hw_metadata \
-	xdp_features bpf_test_no_cfi.ko
+	xdp_features bpf_test_no_cfi.ko sock_addr_testmod.ko
 
 TEST_GEN_FILES += liburandom_read.so urandom_read sign-file uprobe_multi
 
@@ -160,6 +160,7 @@  override define CLEAN
 	$(Q)$(RM) -r $(TEST_GEN_FILES)
 	$(Q)$(RM) -r $(EXTRA_CLEAN)
 	$(Q)$(MAKE) -C bpf_testmod clean
+	$(Q)$(MAKE) -C sock_addr_testmod clean
 	$(Q)$(MAKE) docs-clean
 endef
 
@@ -260,6 +261,12 @@  $(OUTPUT)/bpf_test_no_cfi.ko: $(VMLINUX_BTF) $(RESOLVE_BTFIDS) $(wildcard bpf_te
 	$(Q)$(MAKE) $(submake_extras) RESOLVE_BTFIDS=$(RESOLVE_BTFIDS) -C bpf_test_no_cfi
 	$(Q)cp bpf_test_no_cfi/bpf_test_no_cfi.ko $@
 
+$(OUTPUT)/sock_addr_testmod.ko: $(VMLINUX_BTF) $(RESOLVE_BTFIDS) $(wildcard sock_addr_testmod/Makefile sock_addr_testmod/*.[ch])
+	$(call msg,MOD,,$@)
+	$(Q)$(RM) sock_addr_testmod/sock_addr_testmod.ko # force re-compilation
+	$(Q)$(MAKE) $(submake_extras) RESOLVE_BTFIDS=$(RESOLVE_BTFIDS) -C sock_addr_testmod
+	$(Q)cp sock_addr_testmod/sock_addr_testmod.ko $@
+
 DEFAULT_BPFTOOL := $(HOST_SCRATCH_DIR)/sbin/bpftool
 ifneq ($(CROSS_COMPILE),)
 CROSS_BPFTOOL := $(SCRATCH_DIR)/sbin/bpftool
@@ -638,6 +645,7 @@  TRUNNER_EXTRA_SOURCES := test_progs.c		\
 			 ip_check_defrag_frags.h
 TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko	\
 		       $(OUTPUT)/bpf_test_no_cfi.ko			\
+		       $(OUTPUT)/sock_addr_testmod.ko	\
 		       $(OUTPUT)/liburandom_read.so			\
 		       $(OUTPUT)/xdp_synproxy				\
 		       $(OUTPUT)/sign-file				\
@@ -767,6 +775,7 @@  EXTRA_CLEAN := $(SCRATCH_DIR) $(HOST_SCRATCH_DIR)			\
 	$(addprefix $(OUTPUT)/,*.o *.skel.h *.lskel.h *.subskel.h	\
 			       no_alu32 cpuv4 bpf_gcc bpf_testmod.ko	\
 			       bpf_test_no_cfi.ko			\
+				   sock_addr_testmod.ko	\
 			       liburandom_read.so)
 
 .PHONY: docs docs-clean
diff --git a/tools/testing/selftests/bpf/sock_addr_testmod/.gitignore b/tools/testing/selftests/bpf/sock_addr_testmod/.gitignore
new file mode 100644
index 0000000000000..ded5137772813
--- /dev/null
+++ b/tools/testing/selftests/bpf/sock_addr_testmod/.gitignore
@@ -0,0 +1,6 @@ 
+*.mod
+*.mod.c
+*.o
+.ko
+/Module.symvers
+/modules.order
diff --git a/tools/testing/selftests/bpf/sock_addr_testmod/Makefile b/tools/testing/selftests/bpf/sock_addr_testmod/Makefile
new file mode 100644
index 0000000000000..47c92fb3a7748
--- /dev/null
+++ b/tools/testing/selftests/bpf/sock_addr_testmod/Makefile
@@ -0,0 +1,20 @@ 
+SOCK_ADDR_TEST_MOD_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+KDIR ?= $(abspath $(SOCK_ADDR_TEST_MOD_DIR)/../../../../..)
+
+ifeq ($(V),1)
+Q =
+else
+Q = @
+endif
+
+MODULES = sock_addr_testmod.ko
+
+obj-m += sock_addr_testmod.o
+CFLAGS_sock_addr_testmod.o = -I$(src)
+
+all:
+	+$(Q)make -C $(KDIR) M=$(SOCK_ADDR_TEST_MOD_DIR) modules
+
+clean:
+	+$(Q)make -C $(KDIR) M=$(SOCK_ADDR_TEST_MOD_DIR) clean
+
diff --git a/tools/testing/selftests/bpf/sock_addr_testmod/sock_addr_testmod.c b/tools/testing/selftests/bpf/sock_addr_testmod/sock_addr_testmod.c
new file mode 100644
index 0000000000000..de0b2007f0829
--- /dev/null
+++ b/tools/testing/selftests/bpf/sock_addr_testmod/sock_addr_testmod.c
@@ -0,0 +1,256 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Google LLC. */
+#include <linux/net.h>
+#include <linux/socket.h>
+#include <linux/nsproxy.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/un.h>
+#include <linux/debugfs.h>
+#include <net/sock.h>
+
+#define BIND    0
+#define CONNECT 1
+#define SENDMSG 2
+
+#define CONNECT_TIMEOUT_SEC 1
+
+static char ip[256];
+module_param_string(ip, ip, sizeof(ip), 0644);
+MODULE_PARM_DESC(ip, "IPv4/IPv6/Unix address to use for socket operation");
+static char port[7];
+module_param_string(port, port, sizeof(port), 0644);
+MODULE_PARM_DESC(port, "Port number to use for socket operation");
+static uint af;
+module_param(af, uint, 0644);
+MODULE_PARM_DESC(af, "Address family (AF_INET, AF_INET6, or AF_UNIX)");
+static int type;
+module_param(type, int, 0644);
+MODULE_PARM_DESC(type, "Socket type (SOCK_STREAM or SOCK_DGRAM)");
+static uint op;
+module_param(op, uint, 0644);
+MODULE_PARM_DESC(op, "Socket operation (BIND=0, CONNECT=1, SENDMSG=2)");
+
+static struct debugfs_blob_wrapper sock_name_blob;
+static struct debugfs_blob_wrapper peer_name_blob;
+static struct debugfs_blob_wrapper addr_blob;
+static struct dentry *debugfs_dentry;
+static struct sockaddr_storage sock_name;
+static struct sockaddr_storage peer_name;
+static struct sockaddr_storage addr;
+static bool success;
+
+static struct socket *sock;
+
+static int do_kernel_bind(struct sockaddr *addr, int addrlen)
+{
+	int err;
+
+	err = kernel_bind(sock, (struct sockaddr *)addr, addrlen);
+	if (err) {
+		pr_err("kernel_bind() returned %d\n", err);
+		goto err;
+	}
+
+	err = kernel_getsockname(sock, (struct sockaddr *)&sock_name);
+	if (err < 0) {
+		pr_err("kernel_getsockname() returned %d\n", err);
+		goto err;
+	}
+
+	if (type == SOCK_STREAM) {
+		err = kernel_listen(sock, 128);
+		if (err == -1) {
+			pr_err("kernel_listen() returned %d\n", err);
+			goto err;
+		}
+	}
+
+	err = 0;
+	goto out;
+err:
+	err = -1;
+out:
+	return err;
+}
+
+static int do_kernel_connect(struct sockaddr *addr, int addrlen)
+{
+	int err;
+
+	/* Set timeout for call to kernel_connect() to prevent it from hanging,
+	 * and consider the connection attempt failed if it returns
+	 * -EINPROGRESS.
+	 */
+	sock->sk->sk_sndtimeo = CONNECT_TIMEOUT_SEC * HZ;
+
+	err = kernel_connect(sock, addr, addrlen, 0);
+	if (err) {
+		pr_err("kernel_connect() returned %d\n", err);
+		goto err;
+	}
+
+	err = kernel_getsockname(sock, (struct sockaddr *)&sock_name);
+	if (err < 0) {
+		pr_err("kernel_getsockname() returned %d\n", err);
+		goto err;
+	}
+
+	err = kernel_getpeername(sock, (struct sockaddr *)&peer_name);
+	if (err < 0) {
+		pr_err("kernel_getpeername() returned %d\n", err);
+		goto err;
+	}
+
+	err = 0;
+	goto out;
+err:
+	err = -1;
+out:
+	return err;
+}
+
+static int do_kernel_sendmsg(struct sockaddr *addr, int addrlen)
+{
+	struct msghdr msg = {
+		.msg_name	= addr,
+		.msg_namelen	= addrlen,
+	};
+	struct kvec iov;
+	int err;
+
+	iov.iov_base = "abc";
+	iov.iov_len  = sizeof("abc");
+
+	err = kernel_sendmsg(sock, &msg, &iov, 1, sizeof("abc"));
+	if (err < 0) {
+		pr_err("kernel_sendmsg() returned %d\n", err);
+		goto err;
+	}
+
+	/* Unix socket sockaddr hooks may transform msg_namelen. Make sure it is
+	 * unmodified after the call to kernel_sendmsg().
+	 */
+	if (msg.msg_namelen != addrlen) {
+		pr_err("msg_namelen was modified (original=%d,current=%d)\n", addrlen, msg.msg_namelen);
+		goto err;
+	}
+
+	/* kernel_sendmsg() and sock_sendmsg() are both used throughout the
+	 * kernel. Neither of these functions should modify msg_name, so call
+	 * both just to make sure.
+	 */
+	iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, sizeof("abc"));
+	err = sock_sendmsg(sock, &msg);
+	if (err < 0) {
+		pr_err("sock_sendmsg() returned %d\n", err);
+		goto err;
+	}
+
+	/* Unix socket sockaddr hooks may transform msg_namelen. Make sure it is
+	* unmodified after the call to sock_sendmsg().
+	*/
+	if (msg.msg_namelen != addrlen) {
+		pr_err("msg_namelen was modified (original=%d,current=%d)\n", addrlen, msg.msg_namelen);
+		goto err;
+	}
+
+	err = 0;
+	goto out;
+err:
+	err = -1;
+out:
+	return err;
+}
+
+static int do_sock_op(int op, struct sockaddr *addr, int addrlen)
+{
+	switch (op) {
+	case BIND:
+		return do_kernel_bind(addr, addrlen);
+	case CONNECT:
+		return do_kernel_connect(addr, addrlen);
+	case SENDMSG:
+		return do_kernel_sendmsg(addr, addrlen);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int kernel_sock_addr_testmod_init(void)
+{
+	int addr_len = sizeof(struct sockaddr_storage);
+	int proto;
+	int err;
+
+	debugfs_dentry = debugfs_create_dir("sock_addr_testmod", NULL);
+
+	addr_blob.data = &addr;
+	addr_blob.size = sizeof(addr);
+	sock_name_blob.data = &sock_name;
+	sock_name_blob.size = sizeof(sock_name);
+	peer_name_blob.data = &peer_name;
+	peer_name_blob.size = sizeof(peer_name);
+
+	debugfs_create_blob("addr", 0444, debugfs_dentry, &addr_blob);
+	debugfs_create_blob("sock_name", 0444, debugfs_dentry, &sock_name_blob);
+	debugfs_create_blob("peer_name", 0444, debugfs_dentry, &peer_name_blob);
+	debugfs_create_bool("success", 0444, debugfs_dentry, &success);
+
+	switch (af) {
+	case AF_INET:
+	case AF_INET6:
+		err = inet_pton_with_scope(&init_net, af, ip, port, &addr);
+		if (err) {
+			pr_err("inet_pton_with_scope() returned %d\n", err);
+			goto err;
+		}
+
+		proto = type == SOCK_STREAM ? IPPROTO_TCP : IPPROTO_UDP;
+		break;
+	case AF_UNIX:
+		memset(&addr, 0, sizeof(addr));
+		((struct sockaddr_un *)&addr)->sun_family = AF_UNIX;
+		((struct sockaddr_un *)&addr)->sun_path[0] = 0; // abstract
+		strcpy(((struct sockaddr_un *)&addr)->sun_path + 1, ip);
+		addr_len = offsetof(struct sockaddr_un, sun_path) + 1 +
+			   strlen(ip);
+		proto = PF_UNIX;
+		break;
+	default:
+		pr_err("invalid address family %d\n", af);
+		goto err;
+	}
+
+	err = sock_create_kern(&init_net, af, type, proto, &sock);
+	if (err) {
+		pr_err("sock_create_kern() returned %d\n", err);
+		goto err;
+	}
+
+	if (do_sock_op(op, (struct sockaddr *)&addr, addr_len))
+		goto err;
+
+	success = true;
+	goto out;
+err:
+	success = false;
+out:
+	return 0;
+}
+
+static void kernel_sock_addr_testmod_exit(void)
+{
+	if (sock)
+		sock_release(sock);
+
+	debugfs_remove_recursive(debugfs_dentry);
+}
+
+module_init(kernel_sock_addr_testmod_init);
+module_exit(kernel_sock_addr_testmod_exit);
+
+MODULE_AUTHOR("Jordan Rife");
+MODULE_DESCRIPTION("BPF socket address selftests module");
+MODULE_LICENSE("Dual BSD/GPL");