1694 lines · 47.4 KB · C
RawDownload
// 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.