From: Christian Brauner <brauner@kernel.org>
To: linux-fsdevel@vger.kernel.org
Cc: Alexander Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>,
Kees Cook <kees@kernel.org>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
bpf@vger.kernel.org, linux-doc@vger.kernel.org,
Farid Zakaria <farid.m.zakaria@gmail.com>,
"Christian Brauner (Amutable)" <brauner@kernel.org>
Subject: [PATCH 2/3] selftests/exec: test delimiter restrictions
Date: Wed, 26 Aug 2026 17:55:47 +0200 [thread overview]
Message-ID: <20260826-work-binfmt_misc-delim-v1-2-43618adf8599@kernel.org> (raw)
In-Reply-To: <20260826-work-binfmt_misc-delim-v1-0-43618adf8599@kernel.org>
Test that the new delimiter restrictions work.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
tools/testing/selftests/exec/Makefile | 4 +
tools/testing/selftests/exec/binfmt_misc_delim.c | 127 +++++++++++++++++++++++
2 files changed, 131 insertions(+)
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile
index b640af8f02b5..2220ed345e92 100644
--- a/tools/testing/selftests/exec/Makefile
+++ b/tools/testing/selftests/exec/Makefile
@@ -45,6 +45,10 @@ TEST_GEN_FILES += binfmt_transparent_interp
TEST_GEN_PROGS += binfmt_misc_loader
TEST_GEN_FILES += binfmt_loader_payload binfmt_loader_payload_static
+# Only ASCII punctuation delimits the fields of a register string, so a new
+# flag character cannot change which strings register. No bpf toolchain.
+TEST_GEN_PROGS += binfmt_misc_delim
+
# binfmt_misc bpf-backed ('B') handler test: a libbpf harness plus its
# struct_ops objects and the test interpreter/app it routes between. Only
# built when clang, bpftool, the vmlinux BTF and libbpf are all present
diff --git a/tools/testing/selftests/exec/binfmt_misc_delim.c b/tools/testing/selftests/exec/binfmt_misc_delim.c
new file mode 100644
index 000000000000..ffc17cb78545
--- /dev/null
+++ b/tools/testing/selftests/exec/binfmt_misc_delim.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test which characters may delimit the fields of a register string.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "binfmt_misc_common.h"
+#include "kselftest_harness.h"
+
+#define ENTRY "bmdelim"
+/* Shares no character with the sets below, or a refusal proves nothing. */
+#define MAGIC "bmmagic"
+#define INTERP "/bin/true"
+
+/*
+ * ASCII punctuation without '\' and '/'. The backslash is refused because
+ * it would cut a magic that uses \x to escape short. '/' is accepted
+ * but cannot delimit a rule that names an absolute interpreter.
+ */
+#define PUNCTUATION "!\"#$%&'()*+,-.:;<=>?@[]^_`{|}~"
+
+/* 'M', 'E' and 'B' name types, 'P' through 'D' are the flags. */
+#define LETTERS "MEBPOCFTLDqz"
+#define DIGITS "0157"
+#define WHITESPACE " \t\n"
+#define CONTROL "\001\033\177"
+#define NON_ASCII "\200\244\377"
+
+/* ':bmdelim:E::bmmagic::/bin/true:' with @del in place of every ':'. */
+static int register_with(char del)
+{
+ char rule[128];
+
+ snprintf(rule, sizeof(rule), "%c%s%cE%c%c%s%c%c%s%c", del, ENTRY, del,
+ del, del, MAGIC, del, del, INTERP, del);
+ return write_reg(rule);
+}
+
+/* No character of @set may delimit a register string. */
+static void expect_refused(struct __test_metadata *_metadata, const char *set)
+{
+ const char *d;
+
+ for (d = set; *d; d++) {
+ int rc = register_with(*d);
+
+ EXPECT_EQ(rc, -1)
+ TH_LOG("%#x delimited a register string",
+ (unsigned char)*d);
+ if (rc == 0) {
+ unregister(ENTRY);
+ continue;
+ }
+ EXPECT_EQ(errno, EINVAL);
+ }
+}
+
+FIXTURE(delim) {
+};
+
+FIXTURE_SETUP(delim)
+{
+ if (getuid() != 0)
+ SKIP(return, "test must be run as root");
+ if (!binfmt_misc_available())
+ SKIP(return, "no binfmt_misc");
+
+ /* A kernel without the allow-list takes any character but a flag. */
+ if (register_with('q') == 0) {
+ unregister(ENTRY);
+ SKIP(return, "kernel without the delimiter allow-list");
+ }
+}
+
+FIXTURE_TEARDOWN(delim)
+{
+ unregister(ENTRY);
+}
+
+/* Punctuation delimits, which is all anything deployed ever uses. */
+TEST_F(delim, punctuation_accepted)
+{
+ const char *d;
+
+ for (d = PUNCTUATION; *d; d++) {
+ EXPECT_EQ(register_with(*d), 0)
+ TH_LOG("'%c' refused with errno %d", *d, errno);
+ unregister(ENTRY);
+ }
+}
+
+/* Letters name the types and the flags, so none of them can delimit. */
+TEST_F(delim, letters_refused)
+{
+ expect_refused(_metadata, LETTERS);
+}
+
+/* The offset field is written in digits. */
+TEST_F(delim, digits_refused)
+{
+ expect_refused(_metadata, DIGITS);
+}
+
+TEST_F(delim, whitespace_refused)
+{
+ expect_refused(_metadata, WHITESPACE);
+}
+
+TEST_F(delim, control_refused)
+{
+ expect_refused(_metadata, CONTROL);
+}
+
+TEST_F(delim, non_ascii_refused)
+{
+ expect_refused(_metadata, NON_ASCII);
+}
+
+/* The escape character would cut every magic that uses one short. */
+TEST_F(delim, backslash_refused)
+{
+ expect_refused(_metadata, "\\");
+}
+
+TEST_HARNESS_MAIN
--
2.53.0
next prev parent reply other threads:[~2026-08-26 15:56 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-26 15:55 [PATCH 0/3] binfmt_misc: only let punctuation delimit a register string Christian Brauner
2026-08-26 15:55 ` [PATCH 1/3] " Christian Brauner
2026-08-28 3:50 ` Farid Zakaria
2026-08-26 15:55 ` Christian Brauner [this message]
2026-08-26 15:55 ` [PATCH 3/3] binfmt_misc: document the field delimiter Christian Brauner
2026-08-28 3:50 ` Farid Zakaria
2026-08-28 3:50 ` [PATCH 0/3] binfmt_misc: only let punctuation delimit a register string Farid Zakaria
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260826-work-binfmt_misc-delim-v1-2-43618adf8599@kernel.org \
--to=brauner@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=farid.m.zakaria@gmail.com \
--cc=jack@suse.cz \
--cc=kees@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox