// SPDX-License-Identifier: GPL-2.0-only/* * binfmt_misc.c * * Copyright (C) 1997 Richard Günther * * binfmt_misc detects binaries via a magic or filename extension and invokes * a specified wrapper. See Documentation/admin-guide/binfmt-misc.rst for more details. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/array_size.h>#include <linux/binfmt_misc.h>#include <linux/binfmts.h>#include <linux/bitops.h>#include <linux/bits.h>#include <linux/bug.h>#include <linux/cleanup.h>#include <linux/cred.h>#include <linux/ctype.h>#include <linux/file.h>#include <linux/fs.h>#include <linux/fs_context.h>#include <linux/init.h>#include <linux/kstrtox.h>#include <linux/limits.h>#include <linux/list.h>#include <linux/magic.h>#include <linux/module.h>#include <linux/printk.h>#include <linux/rculist.h>#include <linux/refcount.h>#include <linux/seq_file.h>#include <linux/slab.h>#include <linux/srcu.h>#include <linux/string.h>#include <linux/string_helpers.h>#include <linux/uaccess.h>#include <linux/user_namespace.h> #include "internal.h" /* Entry status and match type bit numbers. */enum binfmt_misc_entry_bits { MISC_FMT_ENABLED_BIT = 0, MISC_FMT_MAGIC_BIT = 1, MISC_FMT_BPF_BIT = 2,}; /* Entry behavior flags, fixed at registration time. */enum binfmt_misc_entry_flags { MISC_FMT_PRESERVE_ARGV0 = (1U << 31), MISC_FMT_OPEN_BINARY = (1U << 30), MISC_FMT_CREDENTIALS = (1U << 29), MISC_FMT_OPEN_FILE = (1U << 28), MISC_FMT_TRANSPARENT = (1U << 27), MISC_FMT_LOADER = (1U << 26), MISC_FMT_DISABLED = (1U << 25),}; /* The flags that shape the invocation; a 'B' handler picks those per exec. */#define MISC_FMT_INVOCATION_FLAGS (MISC_FMT_PRESERVE_ARGV0 | \ MISC_FMT_OPEN_BINARY | \ MISC_FMT_CREDENTIALS | \ MISC_FMT_OPEN_FILE | \ MISC_FMT_TRANSPARENT | \ MISC_FMT_LOADER) /** * struct binfmt_misc_flag - a flag character of the register string * @c: the character userspace writes and reads back * @flag: the entry flag it sets * @implies: entry flags it turns on in addition * @desc: what it does, for the registration debug output */struct binfmt_misc_flag { char c; unsigned long flag; unsigned long implies; const char *desc;}; static const struct binfmt_misc_flag misc_flags[] = { { 'P', MISC_FMT_PRESERVE_ARGV0, 0, "preserve argv0" }, { '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" }, { 'L', MISC_FMT_LOADER, 0, "loader substitution" }, { 'D', MISC_FMT_DISABLED, 0, "register disabled" },}; /* Look up a flag character, NULL if @c is not one. */static const struct binfmt_misc_flag *misc_flag_by_char(const char c){ for (int i = 0; i < ARRAY_SIZE(misc_flags); i++) if (misc_flags[i].c == c) return &misc_flags[i]; return NULL;} struct binfmt_misc_entry { struct hlist_node node; unsigned long flags; /* type, status, etc. */ int offset; /* offset of magic */ int size; /* size of magic/mask */ char *magic; /* magic or filename extension */ char *mask; /* mask, NULL for exact match */ const char *interpreter; /* filename of interpreter */ char *name; struct dentry *dentry; const struct binfmt_misc_ops *bpf_ops; /* bpf-backed handler ('B') */ const char *bpf_ops_name; struct list_head interps; /* the interpreters it bound */ refcount_t users; /* sync removal with load_misc_binary() */ struct rcu_head rcu; char buf[]; /* register string, fields point in here */}; /* * Max length of the register string. Determined by: * - 7 delimiters * - name: ~50 bytes * - type: 1 byte * - offset: 3 bytes (has to be smaller than BINPRM_BUF_SIZE) * - magic: 128 bytes (512 in escaped form) * - mask: 128 bytes (512 in escaped form) * - interp: ~50 bytes * - flags: 5 bytes * Round that up a bit, and then back off to hold the internal data * (like struct binfmt_misc_entry). */#define MAX_REGISTER_LENGTH 1920 /* Trailing delimiter pad so field parsing always terminates at a delimiter. */#define MISC_DELIM_PAD 8 /* Protects the entry walk in load_misc_binary(), which may sleep in it. */DEFINE_STATIC_SRCU_FAST(bm_entries_srcu); /* Check if @e's magic matches @bprm's buffer, applying the mask if set. */static bool entry_matches_magic(const struct binfmt_misc_entry *e, const struct linux_binprm *bprm){ const char *s = bprm->buf + e->offset; int i; if (!e->mask) return !memcmp(s, e->magic, e->size); for (i = 0; i < e->size; i++) if ((s[i] ^ e->magic[i]) & e->mask[i]) return false; return true;} /* Check if @e's registered extension matches @ext, NULL if there is none. */static bool entry_matches_extension(const struct binfmt_misc_entry *e, const char *ext){ return ext && !strcmp(e->magic, ext);} /** * search_binfmt_handler - search for a binary handler for @bprm * @misc: handle to binfmt_misc instance * @bprm: binary for which we are looking for a handler * * Search for a binary type handler for @bprm in the list of registered binary * type handlers. A 'B' entry's match program decides whether the handler * applies; it may sleep to read the binary. The matched entry is returned * with a reference taken while the walk still held it; a dying entry - * unlinked with its last reference gone - cannot be matched and the walk * moves on. * * The caller must hold the bm_entries_srcu read lock, which allows an * entry's evaluation to sleep. * * Return: referenced binary type list entry on success, NULL on failure */static struct binfmt_misc_entry *search_binfmt_handler(struct binfmt_misc *misc, struct linux_binprm *bprm){ char *dot = strrchr(bprm->interp, '.'); const char *ext = dot ? dot + 1 : NULL; struct binfmt_misc_entry *e; /* Walk all the registered handlers. */ hlist_for_each_entry_rcu(e, &misc->entries, node, srcu_read_lock_held(&bm_entries_srcu)) { /* * Make sure this one is currently enabled. An entry enters * the list at most once and only whole: its configuration is * ordered before the rcu insertion that makes it visible * here. */ if (!test_bit(MISC_FMT_ENABLED_BIT, &e->flags)) continue; if (test_bit(MISC_FMT_BPF_BIT, &e->flags)) { if (!e->bpf_ops->match(bprm)) continue; } else if (test_bit(MISC_FMT_MAGIC_BIT, &e->flags)) { if (!entry_matches_magic(e, bprm)) continue; } else { if (!entry_matches_extension(e, ext)) continue; } /* A dying entry cannot be matched, walk on. */ if (refcount_inc_not_zero(&e->users)) return e; } return NULL;} /** * get_binfmt_handler - try to find a binary type handler * @misc: handle to binfmt_misc instance * @bprm: binary for which we are looking for a handler * * Try to find a binfmt handler for the binary type. If one is found it is * returned with a reference protecting it against removal via * bm_{entry,status}_write(). * * Return: binary type list entry on success, NULL on failure */static struct binfmt_misc_entry *get_binfmt_handler(struct binfmt_misc *misc, struct linux_binprm *bprm){ guard(srcu_fast)(&bm_entries_srcu); return search_binfmt_handler(misc, bprm);} /** * binfmt_misc_find_interp - find a bound interpreter by name * @interps: the interpreters the matched entry was registered with * @name: the name to look for * * Return: the interpreter on success, NULL if @interps has none by that name */const struct binfmt_misc_interp *binfmt_misc_find_interp(const struct list_head *interps, const char *name){ struct binfmt_misc_interp *interp; list_for_each_entry(interp, interps, list) if (!strcmp(interp->name, name)) return interp; return NULL;} /* Undo the open_exec() a pre-opened interpreter file came from. */static void close_interp_file(struct file *f){ if (IS_ERR_OR_NULL(f)) return; exe_file_allow_write_access(f); filp_close(f, NULL);} DEFINE_FREE(close_interp_file, struct file *, close_interp_file(_T)) /* * Open an interpreter @path for execution: now, in the writer's context, * and - since binfmt_misc mounts can be unprivileged - with @cred, the * credentials the control file being written was opened with, not the * writer's own. */static struct file *open_interp_file(const struct cred *cred, const char *path){ struct file *f; scoped_with_creds(cred) f = open_exec(path); if (IS_ERR(f)) pr_notice("register: failed to install interpreter %s\n", path); return f;} /* Release the interpreters an entry was registered with. */static void entry_put_interpreters(struct binfmt_misc_entry *e){ struct binfmt_misc_interp *interp, *tmp; list_for_each_entry_safe(interp, tmp, &e->interps, list) { list_del(&interp->list); close_interp_file(interp->file); dec_ucount(interp->ucounts, UCOUNT_BINFMT_MISC_INTERPRETERS); kfree(interp); }} /** * entry_attach_interpreter - bind an opened interpreter to @e * @e: entry being configured * @name: name the load program will select it by; empty for the fixed * interpreter of a static entry * @path: the path @f was opened from * @f: the interpreter, opened for execution * * Every exec runs a clone of @f, so the path decided which file is bound * and nothing else: it is not resolved again, in any namespace. * * The caller has to have validated @name and @path, established that @e * cannot be matched yet, and owns @f until this succeeds. * * Return: 0 on success, -ENOSPC if the entry is full or the binder is out of * UCOUNT_BINFMT_MISC_INTERPRETERS budget, a negative errno on failure */static int entry_attach_interpreter(struct binfmt_misc_entry *e, const char *name, const char *path, struct file *f){ size_t nlen = strlen(name), plen = strlen(path); struct binfmt_misc_interp *interp; struct ucounts *ucounts; if (binfmt_misc_find_interp(&e->interps, name)) return -EEXIST; if (list_count_nodes(&e->interps) >= BINFMT_MISC_INTERP_MAX) return -ENOSPC; /* The binding keeps a file open, so charge it to whoever binds it. */ ucounts = inc_ucount(current_user_ns(), current_euid(), UCOUNT_BINFMT_MISC_INTERPRETERS); if (!ucounts) return -ENOSPC; /* One allocation, both strings in it, like the entry's own buffer. */ interp = kmalloc_flex(*interp, name, nlen + plen + 2, GFP_KERNEL_ACCOUNT); if (!interp) { dec_ucount(ucounts, UCOUNT_BINFMT_MISC_INTERPRETERS); return -ENOMEM; } interp->path = interp->name + nlen + 1; strscpy(interp->name, name, nlen + 1); strscpy(interp->name + nlen + 1, path, plen + 1); interp->file = f; interp->ucounts = ucounts; /* Publish the node: a lockless cat may be walking the list. */ list_add_tail_rcu(&interp->list, &e->interps); pr_debug("register: interpreter: %s {%s}\n", name, path); return 0;} static void bm_entry_free_rcu(struct rcu_head *rcu){ struct binfmt_misc_entry *e = container_of(rcu, struct binfmt_misc_entry, rcu); /* No walker that could sleep in the handler's programs is left. */ if (e->bpf_ops) binfmt_misc_put_ops(e->bpf_ops); kfree(e);} /** * put_binfmt_handler - put binary handler entry * @e: entry to put * * Free entry syncing with load_misc_binary() and defer final free to * load_misc_binary() in case it is using the binary type handler we were * requested to remove. Also the teardown for a registration that fails * before add_entry() publishes the entry. */static void put_binfmt_handler(struct binfmt_misc_entry *e){ if (IS_ERR_OR_NULL(e)) return; if (refcount_dec_and_test(&e->users)) { entry_put_interpreters(e); /* Walkers may still dereference this entry, even sleeping. */ call_srcu(&bm_entries_srcu, &e->rcu, bm_entry_free_rcu); }} DEFINE_FREE(put_binfmt_handler, struct binfmt_misc_entry *, put_binfmt_handler(_T)) /* Drop everything a load program staged for this exec. */static void drop_staged_selection(struct linux_binprm *bprm){ kfree(bprm->bpf_interp); bprm->bpf_interp = NULL; kfree(bprm->bpf_interp_arg); bprm->bpf_interp_arg = NULL; if (bprm->bpf_interp_file) { fput(bprm->bpf_interp_file); bprm->bpf_interp_file = NULL; } bprm->bpf_flags = 0;} /** * current_binfmt_misc - get the binfmt_misc instance of the caller's user namespace * * If a user namespace doesn't have its own binfmt_misc mount it uses the * handlers of its closest ancestor with one. This mimics the behavior of * pre-namespaced binfmt_misc where all registered handlers were available * to all users and user namespaces on the system. The init user namespace * instance is statically set up so the fallback is never reached in * practice. * * Return: the binfmt_misc instance of the caller's user namespace */static struct binfmt_misc *current_binfmt_misc(void){ const struct user_namespace *user_ns; struct binfmt_misc *misc; for (user_ns = current_user_ns(); user_ns; user_ns = user_ns->parent) { /* Pairs with smp_store_release() in bm_fill_super(). */ misc = smp_load_acquire(&user_ns->binfmt_misc); if (misc) return misc; } return &init_binfmt_misc;} /** * entry_select_interpreter - get the interpreter for the matched @e * @e: matched binary type handler * @bprm: binary that is being executed * * A static entry carries its interpreter path, for a 'B' entry the * handler's load program selects it, either by path or by the name of one * of the interpreters the entry bound. The match is committed, so a failing * program fails the exec. * * Return: the interpreter on success, an ERR_PTR on failure */static const char *entry_select_interpreter(const struct binfmt_misc_entry *e, struct linux_binprm *bprm){ int retval; /* * Drop what a previous chain level staged before anything can pick it * up. A static entry stages nothing but consumes a staged file just * like a 'B' entry does. */ drop_staged_selection(bprm); if (!test_bit(MISC_FMT_BPF_BIT, &e->flags)) return e->interpreter; /* The interpreters this entry lets the program choose from. */ bprm->bpf_interps = &e->interps; retval = e->bpf_ops->load(bprm); bprm->bpf_interps = NULL; if (retval) { /* Keep a program-supplied error within errno range. */ if (retval > 0 || retval < -MAX_ERRNO) retval = -ENOEXEC; goto drop_staged; } /* Selecting an interpreter is part of the contract. */ if (!bprm->bpf_interp) { retval = -ENOEXEC; goto drop_staged; } return bprm->bpf_interp; drop_staged: /* A failing load leaves nothing behind for later entries. */ drop_staged_selection(bprm); 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;Lines 1–500 of 1694. Load more
// SPDX-License-Identifier: GPL-2.0-only /* * binfmt_misc.c * * Copyright (C) 1997 Richard Günther * * binfmt_misc detects binaries via a magic or filename extension and invokes * a specified wrapper. See Documentation/admin-guide/binfmt-misc.rst for more details. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/array_size.h> #include <linux/binfmt_misc.h> #include <linux/binfmts.h> #include <linux/bitops.h> #include <linux/bits.h> #include <linux/bug.h> #include <linux/cleanup.h> #include <linux/cred.h> #include <linux/ctype.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/fs_context.h> #include <linux/init.h> #include <linux/kstrtox.h> #include <linux/limits.h> #include <linux/list.h> #include <linux/magic.h> #include <linux/module.h> #include <linux/printk.h> #include <linux/rculist.h> #include <linux/refcount.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/srcu.h> #include <linux/string.h> #include <linux/string_helpers.h> #include <linux/uaccess.h> #include <linux/user_namespace.h> #include "internal.h" /* Entry status and match type bit numbers. */ enum binfmt_misc_entry_bits { MISC_FMT_ENABLED_BIT = 0, MISC_FMT_MAGIC_BIT = 1, MISC_FMT_BPF_BIT = 2, }; /* Entry behavior flags, fixed at registration time. */ enum binfmt_misc_entry_flags { MISC_FMT_PRESERVE_ARGV0 = (1U << 31), MISC_FMT_OPEN_BINARY = (1U << 30), MISC_FMT_CREDENTIALS = (1U << 29), MISC_FMT_OPEN_FILE = (1U << 28), MISC_FMT_TRANSPARENT = (1U << 27), MISC_FMT_LOADER = (1U << 26), MISC_FMT_DISABLED = (1U << 25), }; /* The flags that shape the invocation; a 'B' handler picks those per exec. */ #define MISC_FMT_INVOCATION_FLAGS (MISC_FMT_PRESERVE_ARGV0 | \ MISC_FMT_OPEN_BINARY | \ MISC_FMT_CREDENTIALS | \ MISC_FMT_OPEN_FILE | \ MISC_FMT_TRANSPARENT | \ MISC_FMT_LOADER) /** * struct binfmt_misc_flag - a flag character of the register string * @c: the character userspace writes and reads back * @flag: the entry flag it sets * @implies: entry flags it turns on in addition * @desc: what it does, for the registration debug output */ struct binfmt_misc_flag { char c; unsigned long flag; unsigned long implies; const char *desc; }; static const struct binfmt_misc_flag misc_flags[] = { { 'P', MISC_FMT_PRESERVE_ARGV0, 0, "preserve argv0" }, { '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" }, { 'L', MISC_FMT_LOADER, 0, "loader substitution" }, { 'D', MISC_FMT_DISABLED, 0, "register disabled" }, }; /* Look up a flag character, NULL if @c is not one. */ static const struct binfmt_misc_flag *misc_flag_by_char(const char c) { for (int i = 0; i < ARRAY_SIZE(misc_flags); i++) if (misc_flags[i].c == c) return &misc_flags[i]; return NULL; } struct binfmt_misc_entry { struct hlist_node node; unsigned long flags; /* type, status, etc. */ int offset; /* offset of magic */ int size; /* size of magic/mask */ char *magic; /* magic or filename extension */ char *mask; /* mask, NULL for exact match */ const char *interpreter; /* filename of interpreter */ char *name; struct dentry *dentry; const struct binfmt_misc_ops *bpf_ops; /* bpf-backed handler ('B') */ const char *bpf_ops_name; struct list_head interps; /* the interpreters it bound */ refcount_t users; /* sync removal with load_misc_binary() */ struct rcu_head rcu; char buf[]; /* register string, fields point in here */ }; /* * Max length of the register string. Determined by: * - 7 delimiters * - name: ~50 bytes * - type: 1 byte * - offset: 3 bytes (has to be smaller than BINPRM_BUF_SIZE) * - magic: 128 bytes (512 in escaped form) * - mask: 128 bytes (512 in escaped form) * - interp: ~50 bytes * - flags: 5 bytes * Round that up a bit, and then back off to hold the internal data * (like struct binfmt_misc_entry). */ #define MAX_REGISTER_LENGTH 1920 /* Trailing delimiter pad so field parsing always terminates at a delimiter. */ #define MISC_DELIM_PAD 8 /* Protects the entry walk in load_misc_binary(), which may sleep in it. */ DEFINE_STATIC_SRCU_FAST(bm_entries_srcu); /* Check if @e's magic matches @bprm's buffer, applying the mask if set. */ static bool entry_matches_magic(const struct binfmt_misc_entry *e, const struct linux_binprm *bprm) { const char *s = bprm->buf + e->offset; int i; if (!e->mask) return !memcmp(s, e->magic, e->size); for (i = 0; i < e->size; i++) if ((s[i] ^ e->magic[i]) & e->mask[i]) return false; return true; } /* Check if @e's registered extension matches @ext, NULL if there is none. */ static bool entry_matches_extension(const struct binfmt_misc_entry *e, const char *ext) { return ext && !strcmp(e->magic, ext); } /** * search_binfmt_handler - search for a binary handler for @bprm * @misc: handle to binfmt_misc instance * @bprm: binary for which we are looking for a handler * * Search for a binary type handler for @bprm in the list of registered binary * type handlers. A 'B' entry's match program decides whether the handler * applies; it may sleep to read the binary. The matched entry is returned * with a reference taken while the walk still held it; a dying entry - * unlinked with its last reference gone - cannot be matched and the walk * moves on. * * The caller must hold the bm_entries_srcu read lock, which allows an * entry's evaluation to sleep. * * Return: referenced binary type list entry on success, NULL on failure */ static struct binfmt_misc_entry * search_binfmt_handler(struct binfmt_misc *misc, struct linux_binprm *bprm) { char *dot = strrchr(bprm->interp, '.'); const char *ext = dot ? dot + 1 : NULL; struct binfmt_misc_entry *e; /* Walk all the registered handlers. */ hlist_for_each_entry_rcu(e, &misc->entries, node, srcu_read_lock_held(&bm_entries_srcu)) { /* * Make sure this one is currently enabled. An entry enters * the list at most once and only whole: its configuration is * ordered before the rcu insertion that makes it visible * here. */ if (!test_bit(MISC_FMT_ENABLED_BIT, &e->flags)) continue; if (test_bit(MISC_FMT_BPF_BIT, &e->flags)) { if (!e->bpf_ops->match(bprm)) continue; } else if (test_bit(MISC_FMT_MAGIC_BIT, &e->flags)) { if (!entry_matches_magic(e, bprm)) continue; } else { if (!entry_matches_extension(e, ext)) continue; } /* A dying entry cannot be matched, walk on. */ if (refcount_inc_not_zero(&e->users)) return e; } return NULL; } /** * get_binfmt_handler - try to find a binary type handler * @misc: handle to binfmt_misc instance * @bprm: binary for which we are looking for a handler * * Try to find a binfmt handler for the binary type. If one is found it is * returned with a reference protecting it against removal via * bm_{entry,status}_write(). * * Return: binary type list entry on success, NULL on failure */ static struct binfmt_misc_entry *get_binfmt_handler(struct binfmt_misc *misc, struct linux_binprm *bprm) { guard(srcu_fast)(&bm_entries_srcu); return search_binfmt_handler(misc, bprm); } /** * binfmt_misc_find_interp - find a bound interpreter by name * @interps: the interpreters the matched entry was registered with * @name: the name to look for * * Return: the interpreter on success, NULL if @interps has none by that name */ const struct binfmt_misc_interp * binfmt_misc_find_interp(const struct list_head *interps, const char *name) { struct binfmt_misc_interp *interp; list_for_each_entry(interp, interps, list) if (!strcmp(interp->name, name)) return interp; return NULL; } /* Undo the open_exec() a pre-opened interpreter file came from. */ static void close_interp_file(struct file *f) { if (IS_ERR_OR_NULL(f)) return; exe_file_allow_write_access(f); filp_close(f, NULL); } DEFINE_FREE(close_interp_file, struct file *, close_interp_file(_T)) /* * Open an interpreter @path for execution: now, in the writer's context, * and - since binfmt_misc mounts can be unprivileged - with @cred, the * credentials the control file being written was opened with, not the * writer's own. */ static struct file *open_interp_file(const struct cred *cred, const char *path) { struct file *f; scoped_with_creds(cred) f = open_exec(path); if (IS_ERR(f)) pr_notice("register: failed to install interpreter %s\n", path); return f; } /* Release the interpreters an entry was registered with. */ static void entry_put_interpreters(struct binfmt_misc_entry *e) { struct binfmt_misc_interp *interp, *tmp; list_for_each_entry_safe(interp, tmp, &e->interps, list) { list_del(&interp->list); close_interp_file(interp->file); dec_ucount(interp->ucounts, UCOUNT_BINFMT_MISC_INTERPRETERS); kfree(interp); } } /** * entry_attach_interpreter - bind an opened interpreter to @e * @e: entry being configured * @name: name the load program will select it by; empty for the fixed * interpreter of a static entry * @path: the path @f was opened from * @f: the interpreter, opened for execution * * Every exec runs a clone of @f, so the path decided which file is bound * and nothing else: it is not resolved again, in any namespace. * * The caller has to have validated @name and @path, established that @e * cannot be matched yet, and owns @f until this succeeds. * * Return: 0 on success, -ENOSPC if the entry is full or the binder is out of * UCOUNT_BINFMT_MISC_INTERPRETERS budget, a negative errno on failure */ static int entry_attach_interpreter(struct binfmt_misc_entry *e, const char *name, const char *path, struct file *f) { size_t nlen = strlen(name), plen = strlen(path); struct binfmt_misc_interp *interp; struct ucounts *ucounts; if (binfmt_misc_find_interp(&e->interps, name)) return -EEXIST; if (list_count_nodes(&e->interps) >= BINFMT_MISC_INTERP_MAX) return -ENOSPC; /* The binding keeps a file open, so charge it to whoever binds it. */ ucounts = inc_ucount(current_user_ns(), current_euid(), UCOUNT_BINFMT_MISC_INTERPRETERS); if (!ucounts) return -ENOSPC; /* One allocation, both strings in it, like the entry's own buffer. */ interp = kmalloc_flex(*interp, name, nlen + plen + 2, GFP_KERNEL_ACCOUNT); if (!interp) { dec_ucount(ucounts, UCOUNT_BINFMT_MISC_INTERPRETERS); return -ENOMEM; } interp->path = interp->name + nlen + 1; strscpy(interp->name, name, nlen + 1); strscpy(interp->name + nlen + 1, path, plen + 1); interp->file = f; interp->ucounts = ucounts; /* Publish the node: a lockless cat may be walking the list. */ list_add_tail_rcu(&interp->list, &e->interps); pr_debug("register: interpreter: %s {%s}\n", name, path); return 0; } static void bm_entry_free_rcu(struct rcu_head *rcu) { struct binfmt_misc_entry *e = container_of(rcu, struct binfmt_misc_entry, rcu); /* No walker that could sleep in the handler's programs is left. */ if (e->bpf_ops) binfmt_misc_put_ops(e->bpf_ops); kfree(e); } /** * put_binfmt_handler - put binary handler entry * @e: entry to put * * Free entry syncing with load_misc_binary() and defer final free to * load_misc_binary() in case it is using the binary type handler we were * requested to remove. Also the teardown for a registration that fails * before add_entry() publishes the entry. */ static void put_binfmt_handler(struct binfmt_misc_entry *e) { if (IS_ERR_OR_NULL(e)) return; if (refcount_dec_and_test(&e->users)) { entry_put_interpreters(e); /* Walkers may still dereference this entry, even sleeping. */ call_srcu(&bm_entries_srcu, &e->rcu, bm_entry_free_rcu); } } DEFINE_FREE(put_binfmt_handler, struct binfmt_misc_entry *, put_binfmt_handler(_T)) /* Drop everything a load program staged for this exec. */ static void drop_staged_selection(struct linux_binprm *bprm) { kfree(bprm->bpf_interp); bprm->bpf_interp = NULL; kfree(bprm->bpf_interp_arg); bprm->bpf_interp_arg = NULL; if (bprm->bpf_interp_file) { fput(bprm->bpf_interp_file); bprm->bpf_interp_file = NULL; } bprm->bpf_flags = 0; } /** * current_binfmt_misc - get the binfmt_misc instance of the caller's user namespace * * If a user namespace doesn't have its own binfmt_misc mount it uses the * handlers of its closest ancestor with one. This mimics the behavior of * pre-namespaced binfmt_misc where all registered handlers were available * to all users and user namespaces on the system. The init user namespace * instance is statically set up so the fallback is never reached in * practice. * * Return: the binfmt_misc instance of the caller's user namespace */ static struct binfmt_misc *current_binfmt_misc(void) { const struct user_namespace *user_ns; struct binfmt_misc *misc; for (user_ns = current_user_ns(); user_ns; user_ns = user_ns->parent) { /* Pairs with smp_store_release() in bm_fill_super(). */ misc = smp_load_acquire(&user_ns->binfmt_misc); if (misc) return misc; } return &init_binfmt_misc; } /** * entry_select_interpreter - get the interpreter for the matched @e * @e: matched binary type handler * @bprm: binary that is being executed * * A static entry carries its interpreter path, for a 'B' entry the * handler's load program selects it, either by path or by the name of one * of the interpreters the entry bound. The match is committed, so a failing * program fails the exec. * * Return: the interpreter on success, an ERR_PTR on failure */ static const char *entry_select_interpreter(const struct binfmt_misc_entry *e, struct linux_binprm *bprm) { int retval; /* * Drop what a previous chain level staged before anything can pick it * up. A static entry stages nothing but consumes a staged file just * like a 'B' entry does. */ drop_staged_selection(bprm); if (!test_bit(MISC_FMT_BPF_BIT, &e->flags)) return e->interpreter; /* The interpreters this entry lets the program choose from. */ bprm->bpf_interps = &e->interps; retval = e->bpf_ops->load(bprm); bprm->bpf_interps = NULL; if (retval) { /* Keep a program-supplied error within errno range. */ if (retval > 0 || retval < -MAX_ERRNO) retval = -ENOEXEC; goto drop_staged; } /* Selecting an interpreter is part of the contract. */ if (!bprm->bpf_interp) { retval = -ENOEXEC; goto drop_staged; } return bprm->bpf_interp; drop_staged: /* A failing load leaves nothing behind for later entries. */ drop_staged_selection(bprm); 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;