fs/binfmt_misc.c

Source file repositories/reference/linux-study-clean/fs/binfmt_misc.c

File Facts

System
Linux kernel
Corpus path
fs/binfmt_misc.c
Extension
.c
Size
25697 bytes
Lines
1048
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations bm_entry_operations = {
	.read		= bm_entry_read,
	.write		= bm_entry_write,
	.llseek		= default_llseek,
};

/* /register */

/* add to filesystem */
static int add_entry(Node *e, struct super_block *sb)
{
	struct dentry *dentry = simple_start_creating(sb->s_root, e->name);
	struct inode *inode;
	struct binfmt_misc *misc;

	if (IS_ERR(dentry))
		return PTR_ERR(dentry);

	inode = bm_get_inode(sb, S_IFREG | 0644);
	if (unlikely(!inode)) {
		simple_done_creating(dentry);
		return -ENOMEM;
	}

	refcount_set(&e->users, 1);
	e->dentry = dentry;
	inode->i_private = e;
	inode->i_fop = &bm_entry_operations;

	d_make_persistent(dentry, inode);
	misc = i_binfmt_misc(inode);
	write_lock(&misc->entries_lock);
	list_add(&e->list, &misc->entries);
	write_unlock(&misc->entries_lock);
	simple_done_creating(dentry);
	return 0;
}

static ssize_t bm_register_write(struct file *file, const char __user *buffer,
			       size_t count, loff_t *ppos)
{
	Node *e;
	struct super_block *sb = file_inode(file)->i_sb;
	int err = 0;
	struct file *f = NULL;

	e = create_entry(buffer, count);

	if (IS_ERR(e))
		return PTR_ERR(e);

	if (e->flags & MISC_FMT_OPEN_FILE) {
		/*
		 * Now that we support unprivileged binfmt_misc mounts make
		 * sure we use the credentials that the register @file was
		 * opened with to also open the interpreter. Before that this
		 * didn't matter much as only a privileged process could open
		 * the register file.
		 */
		scoped_with_creds(file->f_cred)
			f = open_exec(e->interpreter);
		if (IS_ERR(f)) {
			pr_notice("register: failed to install interpreter file %s\n",
				 e->interpreter);
			kfree(e);
			return PTR_ERR(f);
		}
		e->interp_file = f;
	}

	err = add_entry(e, sb);
	if (err) {
		if (f) {
			exe_file_allow_write_access(f);
			filp_close(f, NULL);
		}
		kfree(e);
		return err;
	}
	return count;
}

static const struct file_operations bm_register_operations = {
	.write		= bm_register_write,
	.llseek		= noop_llseek,
};

/* /status */

static ssize_t

Annotation

Implementation Notes