Commit cf10015a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull execve fixes from Kees Cook:

 - Fix error handling in begin_new_exec() (Bernd Edlinger)

 - MAINTAINERS: specifically mention ELF (Alexey Dobriyan)

 - Various cleanups related to earlier open() (Askar Safin, Kees Cook)

* tag 'execve-v6.8-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  exec: Distinguish in_execve from in_exec
  exec: Fix error handling in begin_new_exec()
  exec: Add do_close_execat() helper
  exec: remove useless comment
  ELF, MAINTAINERS: specifically mention ELF
parents 3eab8301 90383cc0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -7955,12 +7955,13 @@ L: rust-for-linux@vger.kernel.org
S:	Maintained
F:	rust/kernel/net/phy.rs
EXEC & BINFMT API
EXEC & BINFMT API, ELF
R:	Eric Biederman <ebiederm@xmission.com>
R:	Kees Cook <keescook@chromium.org>
L:	linux-mm@kvack.org
S:	Supported
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/execve
F:	Documentation/userspace-api/ELF.rst
F:	fs/*binfmt_*.c
F:	fs/exec.c
F:	include/linux/binfmts.h
+30 −9
Original line number Diff line number Diff line
@@ -904,6 +904,10 @@ EXPORT_SYMBOL(transfer_args_to_stack);

#endif /* CONFIG_MMU */

/*
 * On success, caller must call do_close_execat() on the returned
 * struct file to close it.
 */
static struct file *do_open_execat(int fd, struct filename *name, int flags)
{
	struct file *file;
@@ -948,6 +952,17 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
	return ERR_PTR(err);
}

/**
 * open_exec - Open a path name for execution
 *
 * @name: path name to open with the intent of executing it.
 *
 * Returns ERR_PTR on failure or allocated struct file on success.
 *
 * As this is a wrapper for the internal do_open_execat(), callers
 * must call allow_write_access() before fput() on release. Also see
 * do_close_execat().
 */
struct file *open_exec(const char *name)
{
	struct filename *filename = getname_kernel(name);
@@ -1409,6 +1424,9 @@ int begin_new_exec(struct linux_binprm * bprm)

out_unlock:
	up_write(&me->signal->exec_update_lock);
	if (!bprm->cred)
		mutex_unlock(&me->signal->cred_guard_mutex);

out:
	return retval;
}
@@ -1484,6 +1502,15 @@ static int prepare_bprm_creds(struct linux_binprm *bprm)
	return -ENOMEM;
}

/* Matches do_open_execat() */
static void do_close_execat(struct file *file)
{
	if (!file)
		return;
	allow_write_access(file);
	fput(file);
}

static void free_bprm(struct linux_binprm *bprm)
{
	if (bprm->mm) {
@@ -1495,10 +1522,7 @@ static void free_bprm(struct linux_binprm *bprm)
		mutex_unlock(&current->signal->cred_guard_mutex);
		abort_creds(bprm->cred);
	}
	if (bprm->file) {
		allow_write_access(bprm->file);
		fput(bprm->file);
	}
	do_close_execat(bprm->file);
	if (bprm->executable)
		fput(bprm->executable);
	/* If a binfmt changed the interp, free it. */
@@ -1520,8 +1544,7 @@ static struct linux_binprm *alloc_bprm(int fd, struct filename *filename, int fl

	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
	if (!bprm) {
		allow_write_access(file);
		fput(file);
		do_close_execat(file);
		return ERR_PTR(-ENOMEM);
	}

@@ -1610,6 +1633,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
	}
	rcu_read_unlock();

	/* "users" and "in_exec" locked for copy_fs() */
	if (p->fs->users > n_fs)
		bprm->unsafe |= LSM_UNSAFE_SHARE;
	else
@@ -1826,9 +1850,6 @@ static int exec_binprm(struct linux_binprm *bprm)
	return 0;
}

/*
 * sys_execve() executes a new program.
 */
static int bprm_execve(struct linux_binprm *bprm)
{
	int retval;
+1 −1
Original line number Diff line number Diff line
@@ -920,7 +920,7 @@ struct task_struct {
	unsigned			sched_rt_mutex:1;
#endif

	/* Bit to tell LSMs we're in execve(): */
	/* Bit to tell TOMOYO we're in execve(): */
	unsigned			in_execve:1;
	unsigned			in_iowait:1;
#ifndef TIF_RESTORE_SIGMASK
+1 −0
Original line number Diff line number Diff line
@@ -1748,6 +1748,7 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
	if (clone_flags & CLONE_FS) {
		/* tsk->fs is already what we want */
		spin_lock(&fs->lock);
		/* "users" and "in_exec" locked for check_unsafe_exec() */
		if (fs->in_exec) {
			spin_unlock(&fs->lock);
			return -EAGAIN;