mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 23:59:33 -04:00
binfmt_misc: normalize the per-exec invocation flags
A static entry fixes its invocation flags at registration. A 'B' entry's load program picks them per exec. Since load_misc_binary() branches on which kind of entry matched and then applies the two flag sets side by side every flag is handled twice and each new one has to be added to both arms. Translate the 'B' flags into the entry flags they mirror and let the dispatch act on a single set of flags. The boolean the two arms communicated 'P' can be removed. No functional change. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-4-e57866e4ae0f@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
@@ -319,6 +319,40 @@ static const char *entry_select_interpreter(const struct binfmt_misc_entry *e,
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
|
||||
/**
|
||||
* entry_invocation_flags - the invocation flags in effect for this exec
|
||||
* @e: matched binary type handler
|
||||
* @bprm: binary that is being executed
|
||||
*
|
||||
* A static entry fixes its flags at registration, a 'B' entry's load program
|
||||
* picks them per exec with bpf_binprm_set_flags(). Translate the latter into
|
||||
* the former, implications included, so the dispatch has one set to act on.
|
||||
*
|
||||
* Return: the invocation flags for this exec
|
||||
*/
|
||||
static unsigned long entry_invocation_flags(const struct binfmt_misc_entry *e,
|
||||
struct linux_binprm *bprm)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
u64 bpf_flags;
|
||||
|
||||
if (!test_bit(MISC_FMT_BPF_BIT, &e->flags))
|
||||
return e->flags;
|
||||
|
||||
bpf_flags = bprm->bpf_flags;
|
||||
/* Clear so they can't accumulate into a nested interpreter level. */
|
||||
bprm->bpf_flags = 0;
|
||||
|
||||
if (bpf_flags & BPF_BINPRM_PRESERVE_ARGV0)
|
||||
flags |= MISC_FMT_PRESERVE_ARGV0;
|
||||
if (bpf_flags & BPF_BINPRM_EXECFD)
|
||||
flags |= MISC_FMT_OPEN_BINARY;
|
||||
if (bpf_flags & BPF_BINPRM_CREDENTIALS)
|
||||
flags |= MISC_FMT_CREDENTIALS | MISC_FMT_OPEN_BINARY;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* the loader itself
|
||||
*/
|
||||
@@ -328,7 +362,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
|
||||
const char *interpreter;
|
||||
struct file *interp_file;
|
||||
struct binfmt_misc *misc;
|
||||
bool preserve_argv0, want_execfd, want_creds;
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
misc = current_binfmt_misc();
|
||||
@@ -347,28 +381,10 @@ static int load_misc_binary(struct linux_binprm *bprm)
|
||||
if (IS_ERR(interpreter))
|
||||
return PTR_ERR(interpreter);
|
||||
|
||||
/*
|
||||
* The invocation flags are fixed at registration for a static handler
|
||||
* and chosen per exec by the load program, via bpf_binprm_set_flags(),
|
||||
* for a bpf one.
|
||||
*/
|
||||
if (test_bit(MISC_FMT_BPF_BIT, &fmt->flags)) {
|
||||
u64 f = bprm->bpf_flags;
|
||||
|
||||
/* Clear so it can't accumulate into a nested interpreter level. */
|
||||
bprm->bpf_flags = 0;
|
||||
|
||||
preserve_argv0 = f & BPF_BINPRM_PRESERVE_ARGV0;
|
||||
want_creds = f & BPF_BINPRM_CREDENTIALS;
|
||||
want_execfd = f & (BPF_BINPRM_CREDENTIALS | BPF_BINPRM_EXECFD);
|
||||
} else {
|
||||
preserve_argv0 = fmt->flags & MISC_FMT_PRESERVE_ARGV0;
|
||||
want_creds = fmt->flags & MISC_FMT_CREDENTIALS;
|
||||
want_execfd = fmt->flags & MISC_FMT_OPEN_BINARY;
|
||||
}
|
||||
flags = entry_invocation_flags(fmt, bprm);
|
||||
|
||||
/* The entry's own choice - not one accumulated from an earlier level. */
|
||||
if (preserve_argv0) {
|
||||
if (flags & MISC_FMT_PRESERVE_ARGV0) {
|
||||
bprm->interp_flags |= BINPRM_FLAGS_PRESERVE_ARGV0;
|
||||
} else {
|
||||
retval = remove_arg_zero(bprm);
|
||||
@@ -424,9 +440,9 @@ static int load_misc_binary(struct linux_binprm *bprm)
|
||||
return PTR_ERR(interp_file);
|
||||
|
||||
bprm->interpreter = interp_file;
|
||||
if (want_execfd)
|
||||
if (flags & MISC_FMT_OPEN_BINARY)
|
||||
bprm->have_execfd = 1;
|
||||
if (want_creds)
|
||||
if (flags & MISC_FMT_CREDENTIALS)
|
||||
bprm->execfd_creds = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user