mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
binfmt_flag_supported() returns 0 when the flag is supported and -1
when it is not, so every caller reads backwards:
if (binfmt_flag_supported('T'))
SKIP(return, "kernel without the 'T' flag");
Make it return a bool and flip the callers. errno from a failed probe
is still set for callers that check it.
Link: https://patch.msgid.link/20260730-work-binfmt_misc-preopen-v1-2-4a0b0da71f16@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com>
96 lines
2.4 KiB
C
96 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Test the static transparent flag 'T' of binfmt_misc. A magic-matched
|
|
* binary is dispatched to an interpreter with the argument vector left
|
|
* untouched, the binary passed through AT_EXECFD and mm->exe_file labeled
|
|
* with the binary. The asserting interpreter (binfmt_transparent_interp)
|
|
* verifies the constructed identity from inside the process and exits 0.
|
|
*
|
|
* Needs root for the registration; no bpf toolchain involved.
|
|
*/
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "binfmt_misc_common.h"
|
|
#include "kselftest_harness.h"
|
|
|
|
#define MAGIC "#TRANSPARENT-SELFTEST#"
|
|
#define TARGET_PATH "/tmp/binfmt_transparent_target"
|
|
#define INTERP_PATH "/tmp/binfmt_transparent_interp"
|
|
#define ENTRY "test_transparent"
|
|
#define RULE(flags) ":" ENTRY ":M:0:" MAGIC "::" INTERP_PATH ":" flags
|
|
|
|
/* The target only has to carry the magic; it is never actually loaded. */
|
|
static int create_target(void)
|
|
{
|
|
char buf[128] = MAGIC "\n";
|
|
int fd;
|
|
|
|
unlink(TARGET_PATH);
|
|
fd = open(TARGET_PATH, O_WRONLY | O_CREAT | O_EXCL, 0755);
|
|
if (fd < 0)
|
|
return -1;
|
|
if (write(fd, buf, sizeof(buf)) != (ssize_t)sizeof(buf)) {
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
close(fd);
|
|
return 0;
|
|
}
|
|
|
|
FIXTURE(transparent) {
|
|
};
|
|
|
|
FIXTURE_SETUP(transparent)
|
|
{
|
|
char src[PATH_MAX];
|
|
|
|
if (getuid() != 0)
|
|
SKIP(return, "test must be run as root");
|
|
if (!binfmt_misc_available())
|
|
SKIP(return, "no binfmt_misc");
|
|
|
|
ASSERT_EQ(artifact_path(src, sizeof(src), "binfmt_transparent_interp"), 0);
|
|
ASSERT_EQ(copy_file(src, INTERP_PATH), 0);
|
|
ASSERT_EQ(create_target(), 0);
|
|
|
|
/* Skip the whole suite on a kernel that does not know 'T'. */
|
|
if (!binfmt_flag_supported('T')) {
|
|
ASSERT_EQ(errno, EINVAL);
|
|
SKIP(return, "kernel without the 'T' flag");
|
|
}
|
|
}
|
|
|
|
FIXTURE_TEARDOWN(transparent)
|
|
{
|
|
unregister(ENTRY);
|
|
unlink(TARGET_PATH);
|
|
unlink(INTERP_PATH);
|
|
}
|
|
|
|
/* Grammar sanity check: the same entry without 'T' has to register. */
|
|
TEST_F(transparent, plain_entry_registers)
|
|
{
|
|
ASSERT_EQ(write_reg(RULE("")), 0);
|
|
}
|
|
|
|
/* 'T' preserves the whole argv, so combining it with 'P' is rejected. */
|
|
TEST_F(transparent, rejects_preserve_argv0)
|
|
{
|
|
ASSERT_NE(write_reg(RULE("TP")), 0);
|
|
EXPECT_EQ(errno, EINVAL);
|
|
}
|
|
|
|
/* The interpreter asserts the identity the kernel built for it. */
|
|
TEST_F(transparent, dispatch)
|
|
{
|
|
ASSERT_EQ(write_reg(RULE("T")), 0);
|
|
|
|
setenv("BINFMT_TEST_BINARY", TARGET_PATH, 1);
|
|
setenv("BINFMT_TEST_ARGV0", PAYLOAD_ARGV0, 1);
|
|
EXPECT_EQ(run_payload(TARGET_PATH), 0);
|
|
}
|
|
|
|
TEST_HARNESS_MAIN
|