diff mbox series

[4/5] selftests/umd_mgmt: Add selftests for UMD management library

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

Checks

Context Check Description
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: 18 this patch: 18
netdev/cc_maintainers success CCed 4 of 4 maintainers
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 fail Script umd_mgmt.sh not found in tools/testing/selftests/umd_mgmt/Makefile
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 18 this patch: 18
netdev/checkpatch warning WARNING: externs should be avoided in .c files WARNING: line length of 84 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>

Introduce a simple UMD driver using the management library, for testing
purposes.

UMD Manager: sample_mgr.c
UMD Loader: sample_loader.c
UMD Handler: sample_handler.c

The UMD Manager exposes /sys/kernel/security/sample_umd and accepts an
offset between 0-128K. It invokes the UMD Loader to start the UMD Handler
and passes to the latter the offset at which it sets the byte of the
response buffer to 1. The UMD Manager verifies that and returns the number
of bytes written on success, a negative value on failure.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 MAINTAINERS                                   |   1 +
 tools/testing/selftests/Makefile              |   1 +
 tools/testing/selftests/umd_mgmt/.gitignore   |   1 +
 tools/testing/selftests/umd_mgmt/Makefile     |  14 ++
 tools/testing/selftests/umd_mgmt/config       |   1 +
 .../selftests/umd_mgmt/sample_umd/Makefile    |  22 ++++
 .../selftests/umd_mgmt/sample_umd/msgfmt.h    |  13 ++
 .../umd_mgmt/sample_umd/sample_binary_blob.S  |   7 +
 .../umd_mgmt/sample_umd/sample_handler.c      |  81 ++++++++++++
 .../umd_mgmt/sample_umd/sample_loader.c       |  28 ++++
 .../umd_mgmt/sample_umd/sample_mgr.c          | 124 ++++++++++++++++++
 tools/testing/selftests/umd_mgmt/umd_mgmt.sh  |  40 ++++++
 12 files changed, 333 insertions(+)
 create mode 100644 tools/testing/selftests/umd_mgmt/.gitignore
 create mode 100644 tools/testing/selftests/umd_mgmt/Makefile
 create mode 100644 tools/testing/selftests/umd_mgmt/config
 create mode 100644 tools/testing/selftests/umd_mgmt/sample_umd/Makefile
 create mode 100644 tools/testing/selftests/umd_mgmt/sample_umd/msgfmt.h
 create mode 100644 tools/testing/selftests/umd_mgmt/sample_umd/sample_binary_blob.S
 create mode 100644 tools/testing/selftests/umd_mgmt/sample_umd/sample_handler.c
 create mode 100644 tools/testing/selftests/umd_mgmt/sample_umd/sample_loader.c
 create mode 100644 tools/testing/selftests/umd_mgmt/sample_umd/sample_mgr.c
 create mode 100755 tools/testing/selftests/umd_mgmt/umd_mgmt.sh
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 7b27435fd20..a0cd161843e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11251,6 +11251,7 @@  L:	linux-kernel@vger.kernel.org
 S:	Maintained
 F:	include/linux/usermode_driver_mgmt.h
 F:	kernel/usermode_driver_mgmt.c
+F:	tools/testing/selftests/umd_mgmt/*
 
 KERNEL VIRTUAL MACHINE (KVM)
 M:	Paolo Bonzini <pbonzini@redhat.com>
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 13a6837a0c6..84202d5b4fb 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -84,6 +84,7 @@  TARGETS += timers
 endif
 TARGETS += tmpfs
 TARGETS += tpm2
+TARGETS += umd_mgmt
 TARGETS += user
 TARGETS += vDSO
 TARGETS += mm
diff --git a/tools/testing/selftests/umd_mgmt/.gitignore b/tools/testing/selftests/umd_mgmt/.gitignore
new file mode 100644
index 00000000000..215c17d13e9
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/.gitignore
@@ -0,0 +1 @@ 
+/sample_umd/sample_umh
diff --git a/tools/testing/selftests/umd_mgmt/Makefile b/tools/testing/selftests/umd_mgmt/Makefile
new file mode 100644
index 00000000000..f1d47eec04e
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/Makefile
@@ -0,0 +1,14 @@ 
+# SPDX-License-Identifier: GPL-2.0
+TEST_GEN_PROGS_EXTENDED = sample_umd.ko
+
+$(OUTPUT)/%.ko: $(wildcard sample_umd/Makefile sample_umd/*.[ch])
+	$(call msg,MOD,,$@)
+	$(Q)$(MAKE) -C sample_umd install
+
+OVERRIDE_TARGETS := 1
+override define CLEAN
+	$(call msg,CLEAN)
+	$(Q)$(MAKE) -C sample_umd clean
+endef
+
+include ../lib.mk
diff --git a/tools/testing/selftests/umd_mgmt/config b/tools/testing/selftests/umd_mgmt/config
new file mode 100644
index 00000000000..71a078a3ac0
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/config
@@ -0,0 +1 @@ 
+CONFIG_BPFILTER=y
diff --git a/tools/testing/selftests/umd_mgmt/sample_umd/Makefile b/tools/testing/selftests/umd_mgmt/sample_umd/Makefile
new file mode 100644
index 00000000000..6d950e05f3d
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/sample_umd/Makefile
@@ -0,0 +1,22 @@ 
+KDIR ?= ../../../../..
+
+userprogs := sample_umh
+sample_umh-objs := sample_handler.o
+userccflags += -I $(srctree)
+
+$(obj)/sample_binary_blob.o: $(obj)/sample_umh
+
+MODULES = sample_loader_kmod.ko sample_mgr.ko
+
+obj-m += sample_loader_kmod.o sample_mgr.o
+
+sample_loader_kmod-objs = sample_loader.o sample_binary_blob.o
+
+all:
+	+$(Q)$(MAKE) -C $(KDIR) M=$$PWD modules
+
+clean:
+	+$(Q)$(MAKE) -C $(KDIR) M=$$PWD clean
+
+install: all
+	+$(Q)$(MAKE) -C $(KDIR) M=$$PWD modules_install
diff --git a/tools/testing/selftests/umd_mgmt/sample_umd/msgfmt.h b/tools/testing/selftests/umd_mgmt/sample_umd/msgfmt.h
new file mode 100644
index 00000000000..34a62d72cde
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/sample_umd/msgfmt.h
@@ -0,0 +1,13 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SAMPLE_UMH_MSGFMT_H
+#define _SAMPLE_UMH_MSGFMT_H
+
+struct sample_request {
+	uint32_t offset;
+};
+
+struct sample_reply {
+	uint8_t data[128 * 1024];
+};
+
+#endif
diff --git a/tools/testing/selftests/umd_mgmt/sample_umd/sample_binary_blob.S b/tools/testing/selftests/umd_mgmt/sample_umd/sample_binary_blob.S
new file mode 100644
index 00000000000..3687dd13973
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/sample_umd/sample_binary_blob.S
@@ -0,0 +1,7 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+	.section .init.rodata, "a"
+	.global sample_umh_start
+sample_umh_start:
+	.incbin "tools/testing/selftests/umd_mgmt/sample_umd/sample_umh"
+	.global sample_umh_end
+sample_umh_end:
diff --git a/tools/testing/selftests/umd_mgmt/sample_umd/sample_handler.c b/tools/testing/selftests/umd_mgmt/sample_umd/sample_handler.c
new file mode 100644
index 00000000000..94ea6d99bbc
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/sample_umd/sample_handler.c
@@ -0,0 +1,81 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ *
+ * Implement the UMD Handler.
+ */
+#include <unistd.h>
+#include <malloc.h>
+#include <stdint.h>
+
+#include "msgfmt.h"
+
+FILE *debug_f;
+
+static void loop(void)
+{
+	struct sample_request *req = NULL;
+	struct sample_reply *reply = NULL;
+
+	req = calloc(1, sizeof(*req));
+	if (!req)
+		return;
+
+	reply = calloc(1, sizeof(*reply));
+	if (!reply)
+		goto out;
+
+	while (1) {
+		int n, len, offset;
+
+		offset = 0;
+		len = sizeof(*req);
+
+		while (len) {
+			n = read(0, ((void *)req) + offset, len);
+			if (n <= 0) {
+				fprintf(debug_f, "invalid request %d\n", n);
+				goto out;
+			}
+
+			len -= n;
+			offset += n;
+		}
+
+		if (req->offset < sizeof(reply->data))
+			reply->data[req->offset] = 1;
+
+		offset = 0;
+		len = sizeof(*reply);
+
+		while (len) {
+			n = write(1, ((void *)reply) + offset, len);
+			if (n <= 0) {
+				fprintf(debug_f, "reply failed %d\n", n);
+				goto out;
+			}
+
+			len -= n;
+			offset += n;
+		}
+
+		if (req->offset < sizeof(reply->data))
+			reply->data[req->offset] = 0;
+	}
+out:
+	free(req);
+	free(reply);
+}
+
+int main(void)
+{
+	debug_f = fopen("/dev/kmsg", "w");
+	setvbuf(debug_f, 0, _IOLBF, 0);
+	fprintf(debug_f, "<5>Started sample_umh\n");
+	loop();
+	fclose(debug_f);
+
+	return 0;
+}
diff --git a/tools/testing/selftests/umd_mgmt/sample_umd/sample_loader.c b/tools/testing/selftests/umd_mgmt/sample_umd/sample_loader.c
new file mode 100644
index 00000000000..36c0e69e3f7
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/sample_umd/sample_loader.c
@@ -0,0 +1,28 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ *
+ * Implement the UMD Loader (credits: bpfilter).
+ */
+#include <linux/module.h>
+#include <linux/usermode_driver_mgmt.h>
+
+extern char sample_umh_start;
+extern char sample_umh_end;
+extern struct umd_mgmt sample_mgmt_ops;
+
+static int __init load_umh(void)
+{
+	return umd_mgmt_load(&sample_mgmt_ops, &sample_umh_start,
+			     &sample_umh_end);
+}
+
+static void __exit fini_umh(void)
+{
+	umd_mgmt_unload(&sample_mgmt_ops);
+}
+module_init(load_umh);
+module_exit(fini_umh);
+MODULE_LICENSE("GPL");
diff --git a/tools/testing/selftests/umd_mgmt/sample_umd/sample_mgr.c b/tools/testing/selftests/umd_mgmt/sample_umd/sample_mgr.c
new file mode 100644
index 00000000000..75c572f9849
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/sample_umd/sample_mgr.c
@@ -0,0 +1,124 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ *
+ * Implement the UMD Manager.
+ */
+#include <linux/module.h>
+#include <linux/security.h>
+#include <linux/seq_file.h>
+#include <linux/usermode_driver_mgmt.h>
+
+#include "msgfmt.h"
+
+struct umd_mgmt sample_mgmt_ops;
+EXPORT_SYMBOL_GPL(sample_mgmt_ops);
+
+struct dentry *sample_umd_dentry;
+
+static int sample_write_common(u32 offset, bool test)
+{
+	struct sample_request *req;
+	struct sample_reply *reply;
+	int ret;
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	reply = kzalloc(sizeof(*reply), GFP_KERNEL);
+	if (!reply) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->offset = offset;
+
+	if (test)
+		/* Lock is already taken. */
+		ret = umd_send_recv(&sample_mgmt_ops.info, req, sizeof(*req),
+				    reply, sizeof(*reply));
+	else
+		ret = umd_mgmt_send_recv(&sample_mgmt_ops, req, sizeof(*req),
+					 reply, sizeof(*reply));
+	if (ret < 0)
+		goto out;
+
+	if (reply->data[req->offset] != 1) {
+		ret = -EINVAL;
+		goto out;
+	}
+out:
+	kfree(req);
+	kfree(reply);
+
+	return ret;
+}
+
+static ssize_t sample_umd_write(struct file *file, const char __user *buf,
+				size_t datalen, loff_t *ppos)
+{
+	char offset_str[8];
+	u32 offset;
+	int ret;
+
+	if (datalen >= sizeof(offset_str))
+		return -EINVAL;
+
+	ret = copy_from_user(offset_str, buf, datalen);
+	if (ret < 0)
+		return ret;
+
+	offset_str[datalen] = '\0';
+
+	ret = kstrtou32(offset_str, 10, &offset);
+	if (ret < 0)
+		return ret;
+
+	if (offset >= sizeof(((struct sample_reply *)0)->data))
+		return -EINVAL;
+
+	ret = sample_write_common(offset, false);
+	if (ret < 0)
+		return ret;
+
+	return datalen;
+}
+
+static const struct file_operations sample_umd_file_ops = {
+	.write = sample_umd_write,
+};
+
+static int sample_post_start_umh(struct umd_mgmt *mgmt)
+{
+	return sample_write_common(0, true);
+}
+
+static int __init load_umh(void)
+{
+	mutex_init(&sample_mgmt_ops.lock);
+	sample_mgmt_ops.info.tgid = NULL;
+	sample_mgmt_ops.info.driver_name = "sample_umh";
+	sample_mgmt_ops.post_start = sample_post_start_umh;
+	sample_mgmt_ops.kmod = "sample_loader_kmod";
+	sample_mgmt_ops.kmod_loaded = false;
+
+	sample_umd_dentry = securityfs_create_file("sample_umd", 0200, NULL,
+						   NULL, &sample_umd_file_ops);
+	if (IS_ERR(sample_umd_dentry))
+		return PTR_ERR(sample_umd_dentry);
+
+	return 0;
+}
+
+static void __exit fini_umh(void)
+{
+	securityfs_remove(sample_umd_dentry);
+}
+module_init(load_umh);
+module_exit(fini_umh);
+MODULE_LICENSE("GPL");
diff --git a/tools/testing/selftests/umd_mgmt/umd_mgmt.sh b/tools/testing/selftests/umd_mgmt/umd_mgmt.sh
new file mode 100755
index 00000000000..9b90d737fec
--- /dev/null
+++ b/tools/testing/selftests/umd_mgmt/umd_mgmt.sh
@@ -0,0 +1,40 @@ 
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH
+#
+# Author: Roberto Sassu <roberto.sassu@huawei.com>
+#
+# Script to test the UMD management library.
+
+# Kselftest framework defines: ksft_pass=0, ksft_fail=1, ksft_skip=4
+ksft_pass=0
+ksft_fail=1
+ksft_skip=4
+
+if ! /sbin/modprobe -q sample_mgr; then
+	echo "umd_mgmt: module sample_mgr is not found [SKIP]"
+	exit $ksft_skip
+fi
+
+if [ ! -f /sys/kernel/security/sample_umd ]; then
+	echo "umd_mgmt: kernel interface is not found [SKIP]"
+	exit $ksft_skip
+fi
+
+i=0
+
+while [ $i -lt 500 ]; do
+	if ! echo $(( RANDOM % 128 * 1024 )) > /sys/kernel/security/sample_umd; then
+		echo "umd_mgmt: test failed"
+		exit $ksft_fail
+	fi
+
+	if [ $(( i % 50 )) -eq 0 ]; then
+		rmmod sample_loader_kmod
+	fi
+
+	(( i++ ))
+done
+
+exit $ksft_pass