diff mbox series

[1/5] usermode_driver: Introduce umd_send_recv() from bpfilter

Message ID 20230317145240.363908-2-roberto.sassu@huaweicloud.com (mailing list archive)
State Not Applicable
Delegated to: Netdev Maintainers
Headers show
Series usermode_driver: Add management library and API | expand

Checks

Context Check Description
bpf/vmtest-bpf-PR fail merge-conflict
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Guessed tree name to be net-next, async
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: 20 this patch: 20
netdev/cc_maintainers warning 1 maintainers not CCed: viro@zeniv.linux.org.uk
netdev/build_clang success Errors and warnings before: 18 this patch: 18
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
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: 20 this patch: 20
netdev/checkpatch warning WARNING: line length of 82 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-6 success Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-7 success Logs for llvm-toolchain
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-2 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-3 success Logs for build for aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-5 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-4 success Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for test_maps on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-24 success Logs for test_progs_no_alu32_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for test_progs_no_alu32_parallel on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-26 success Logs for test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for test_progs_no_alu32_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-28 success Logs for test_progs_parallel on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-29 success Logs for test_progs_parallel on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-30 success Logs for test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-31 success Logs for test_progs_parallel on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-32 success Logs for test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-33 success Logs for test_verifier on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-35 success Logs for test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-36 success Logs for test_verifier on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-9 success Logs for test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for test_maps on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-14 success Logs for test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-15 success Logs for test_progs on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-17 success Logs for test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for test_progs on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-19 success Logs for test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for test_progs_no_alu32 on aarch64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-22 fail Logs for test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 fail Logs for test_progs_no_alu32 on x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-34 success Logs for test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-11 success Logs for test_maps on s390x with gcc

Commit Message

Roberto Sassu March 17, 2023, 2:52 p.m. UTC
From: Roberto Sassu <roberto.sassu@huawei.com>

Move bpfilter_send_req() to usermode_driver.c and rename it to
umd_send_recv(). Make the latter independent from the message format by
passing to it the pointers to the request and reply message buffers and the
respective lengths, and by merely doing read/write operations.

>From umd_send_recv(), remove the call to __stop_umh() and returning
reply.status, which is message format-specific. Let the callers of
umd_send_recv(), such as bpfilter_process_sockopt(), call shutdown_umh()
and evaluate the reply. Consequently, remove __stop_umh(), since in
bpfilter_process_sockopt() the CONFIG_INET condition is always true.

In addition to the original bpfilter_send_req() implementation, support
partial reads and writes, so that callers are not limited by the length of
the message to send or receive. Currently, the pipe supports receiving
64 KB at once.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 include/linux/usermode_driver.h |  2 ++
 kernel/usermode_driver.c        | 47 ++++++++++++++++++++++++++++++-
 net/bpfilter/bpfilter_kern.c    | 50 +++++++++------------------------
 3 files changed, 62 insertions(+), 37 deletions(-)
diff mbox series

Patch

diff --git a/include/linux/usermode_driver.h b/include/linux/usermode_driver.h
index ad970416260..37b8d08cc3d 100644
--- a/include/linux/usermode_driver.h
+++ b/include/linux/usermode_driver.h
@@ -15,5 +15,7 @@  int umd_load_blob(struct umd_info *info, const void *data, size_t len);
 int umd_unload_blob(struct umd_info *info);
 int fork_usermode_driver(struct umd_info *info);
 void umd_cleanup_helper(struct umd_info *info);
+int umd_send_recv(struct umd_info *info, void *in, size_t in_len, void *out,
+		  size_t out_len);
 
 #endif /* __LINUX_USERMODE_DRIVER_H__ */
diff --git a/kernel/usermode_driver.c b/kernel/usermode_driver.c
index 8303f4c7ca7..cdbfaad99d7 100644
--- a/kernel/usermode_driver.c
+++ b/kernel/usermode_driver.c
@@ -188,4 +188,49 @@  int fork_usermode_driver(struct umd_info *info)
 }
 EXPORT_SYMBOL_GPL(fork_usermode_driver);
 
-
+/**
+ * umd_send_recv - send/receive a message through the pipe
+ * @info: user mode driver info
+ * @in: request message
+ * @in_len: size of @in
+ * @out: reply message
+ * @out_len: size of @out
+ *
+ * Send a message to the user space process through the created pipe and read
+ * the reply. Partial reads and writes are supported.
+ *
+ * Return: Zero on success, -EFAULT otherwise.
+ */
+int umd_send_recv(struct umd_info *info, void *in, size_t in_len, void *out,
+		  size_t out_len)
+{
+	loff_t pos, offset;
+	ssize_t n;
+
+	if (!info->tgid)
+		return -EFAULT;
+	pos = 0;
+	offset = 0;
+	while (in_len) {
+		n = kernel_write(info->pipe_to_umh, in + offset, in_len, &pos);
+		if (n <= 0) {
+			pr_err("write fail %zd\n", n);
+			return -EFAULT;
+		}
+		in_len -= n;
+		offset += n;
+	}
+	pos = 0;
+	offset = 0;
+	while (out_len) {
+		n = kernel_read(info->pipe_from_umh, out + offset, out_len, &pos);
+		if (n <= 0) {
+			pr_err("read fail %zd\n", n);
+			return -EFAULT;
+		}
+		out_len -= n;
+		offset += n;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(umd_send_recv);
diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c
index 422ec6e7ccf..17d4df5f8fe 100644
--- a/net/bpfilter/bpfilter_kern.c
+++ b/net/bpfilter/bpfilter_kern.c
@@ -25,40 +25,6 @@  static void shutdown_umh(void)
 	}
 }
 
-static void __stop_umh(void)
-{
-	if (IS_ENABLED(CONFIG_INET))
-		shutdown_umh();
-}
-
-static int bpfilter_send_req(struct mbox_request *req)
-{
-	struct mbox_reply reply;
-	loff_t pos = 0;
-	ssize_t n;
-
-	if (!bpfilter_ops.info.tgid)
-		return -EFAULT;
-	pos = 0;
-	n = kernel_write(bpfilter_ops.info.pipe_to_umh, req, sizeof(*req),
-			   &pos);
-	if (n != sizeof(*req)) {
-		pr_err("write fail %zd\n", n);
-		goto stop;
-	}
-	pos = 0;
-	n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply),
-			&pos);
-	if (n != sizeof(reply)) {
-		pr_err("read fail %zd\n", n);
-		goto stop;
-	}
-	return reply.status;
-stop:
-	__stop_umh();
-	return -EFAULT;
-}
-
 static int bpfilter_process_sockopt(struct sock *sk, int optname,
 				    sockptr_t optval, unsigned int optlen,
 				    bool is_set)
@@ -70,16 +36,27 @@  static int bpfilter_process_sockopt(struct sock *sk, int optname,
 		.addr		= (uintptr_t)optval.user,
 		.len		= optlen,
 	};
+	struct mbox_reply reply;
+	int err;
+
 	if (sockptr_is_kernel(optval)) {
 		pr_err("kernel access not supported\n");
 		return -EFAULT;
 	}
-	return bpfilter_send_req(&req);
+	err = umd_send_recv(&bpfilter_ops.info, &req, sizeof(req), &reply,
+			    sizeof(reply));
+	if (err) {
+		shutdown_umh();
+		return err;
+	}
+
+	return reply.status;
 }
 
 static int start_umh(void)
 {
 	struct mbox_request req = { .pid = current->pid };
+	struct mbox_reply reply;
 	int err;
 
 	/* fork usermode process */
@@ -89,7 +66,8 @@  static int start_umh(void)
 	pr_info("Loaded bpfilter_umh pid %d\n", pid_nr(bpfilter_ops.info.tgid));
 
 	/* health check that usermode process started correctly */
-	if (bpfilter_send_req(&req) != 0) {
+	if (umd_send_recv(&bpfilter_ops.info, &req, sizeof(req), &reply,
+			  sizeof(reply)) != 0 || reply.status != 0) {
 		shutdown_umh();
 		return -EFAULT;
 	}