diff --git a/Documentation/admin-guide/binfmt-misc.rst b/Documentation/admin-guide/binfmt-misc.rst index 9f0d9132723f..62088468350b 100644 --- a/Documentation/admin-guide/binfmt-misc.rst +++ b/Documentation/admin-guide/binfmt-misc.rst @@ -90,6 +90,16 @@ Here is what the fields mean: emulation is installed and uses the opened image to spawn the emulator, meaning it is always available once installed, regardless of how the environment changes. + ``T`` - transparent + Run the interpreter transparently. The binary is handed to + the interpreter through ``AT_EXECFD`` (``T`` implies ``O``), + the argument vector is left exactly as the caller built it + and the kernel labels ``/proc/pid/exe`` with the binary + instead of the interpreter. The interpreter has to load the + binary from ``AT_EXECFD`` and follow the + ``AT_FLAGS_TRANSPARENT_INTERP`` contract. Combining ``T`` + with ``P`` is rejected: transparency preserves the whole + argument vector, argv[0] included. There are some restrictions: diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index c49e88283f12..d32ef07c810f 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -72,6 +72,7 @@ static const struct binfmt_misc_flag misc_flags[] = { { 'O', MISC_FMT_OPEN_BINARY, 0, "open binary" }, { 'C', MISC_FMT_CREDENTIALS, MISC_FMT_OPEN_BINARY, "credentials from the binary" }, { 'F', MISC_FMT_OPEN_FILE, 0, "open interpreter file now" }, + { 'T', MISC_FMT_TRANSPARENT, MISC_FMT_OPEN_BINARY, "transparent" }, }; /* Look up a flag character, NULL if @c is not one. */ @@ -764,6 +765,11 @@ static struct binfmt_misc_entry *create_entry(const char __user *buffer, if (test_bit(MISC_FMT_BPF_BIT, &e->flags) && p != flags) return ERR_PTR(-EINVAL); + /* Transparency preserves the whole argv, argv[0] included. */ + if ((e->flags & MISC_FMT_TRANSPARENT) && + (e->flags & MISC_FMT_PRESERVE_ARGV0)) + return ERR_PTR(-EINVAL); + if (*p == '\n') p++; if (p != buf + count)