Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b1bf12d authored by KOSAKI Motohiro's avatar KOSAKI Motohiro Committed by Linus Torvalds
Browse files

signals: move cred_guard_mutex from task_struct to signal_struct



Oleg Nesterov pointed out we have to prevent multiple-threads-inside-exec
itself and we can reuse ->cred_guard_mutex for it.  Yes, concurrent
execve() has no worth.

Let's move ->cred_guard_mutex from task_struct to signal_struct.  It
naturally prevent multiple-threads-inside-exec.

Signed-off-by: default avatarKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Reviewed-by: default avatarOleg Nesterov <oleg@redhat.com>
Acked-by: default avatarRoland McGrath <roland@redhat.com>
Acked-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b8401150
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -1083,14 +1083,14 @@ EXPORT_SYMBOL(setup_new_exec);
 */
int prepare_bprm_creds(struct linux_binprm *bprm)
{
	if (mutex_lock_interruptible(&current->cred_guard_mutex))
	if (mutex_lock_interruptible(&current->signal->cred_guard_mutex))
		return -ERESTARTNOINTR;

	bprm->cred = prepare_exec_creds();
	if (likely(bprm->cred))
		return 0;

	mutex_unlock(&current->cred_guard_mutex);
	mutex_unlock(&current->signal->cred_guard_mutex);
	return -ENOMEM;
}

@@ -1098,7 +1098,7 @@ void free_bprm(struct linux_binprm *bprm)
{
	free_arg_pages(bprm);
	if (bprm->cred) {
		mutex_unlock(&current->cred_guard_mutex);
		mutex_unlock(&current->signal->cred_guard_mutex);
		abort_creds(bprm->cred);
	}
	kfree(bprm);
@@ -1119,13 +1119,13 @@ void install_exec_creds(struct linux_binprm *bprm)
	 * credentials; any time after this it may be unlocked.
	 */
	security_bprm_committed_creds(bprm);
	mutex_unlock(&current->cred_guard_mutex);
	mutex_unlock(&current->signal->cred_guard_mutex);
}
EXPORT_SYMBOL(install_exec_creds);

/*
 * determine how safe it is to execute the proposed program
 * - the caller must hold current->cred_guard_mutex to protect against
 * - the caller must hold ->cred_guard_mutex to protect against
 *   PTRACE_ATTACH
 */
int check_unsafe_exec(struct linux_binprm *bprm)
+4 −4
Original line number Diff line number Diff line
@@ -226,7 +226,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
{
	struct mm_struct *mm;

	if (mutex_lock_killable(&task->cred_guard_mutex))
	if (mutex_lock_killable(&task->signal->cred_guard_mutex))
		return NULL;

	mm = get_task_mm(task);
@@ -235,7 +235,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
		mmput(mm);
		mm = NULL;
	}
	mutex_unlock(&task->cred_guard_mutex);
	mutex_unlock(&task->signal->cred_guard_mutex);

	return mm;
}
@@ -2354,14 +2354,14 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
		goto out_free;

	/* Guard against adverse ptrace interaction */
	length = mutex_lock_interruptible(&task->cred_guard_mutex);
	length = mutex_lock_interruptible(&task->signal->cred_guard_mutex);
	if (length < 0)
		goto out_free;

	length = security_setprocattr(task,
				      (char*)file->f_path.dentry->d_name.name,
				      (void*)page, count);
	mutex_unlock(&task->cred_guard_mutex);
	mutex_unlock(&task->signal->cred_guard_mutex);
out_free:
	free_page((unsigned long) page);
out:
+2 −2
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ extern struct fs_struct init_fs;
		.running = 0,						\
		.lock = __SPIN_LOCK_UNLOCKED(sig.cputimer.lock),	\
	},								\
	.cred_guard_mutex =						\
		 __MUTEX_INITIALIZER(sig.cred_guard_mutex),		\
}

extern struct nsproxy init_nsproxy;
@@ -145,8 +147,6 @@ extern struct cred init_cred;
	.group_leader	= &tsk,						\
	RCU_INIT_POINTER(.real_cred, &init_cred),			\
	RCU_INIT_POINTER(.cred, &init_cred),				\
	.cred_guard_mutex =						\
		 __MUTEX_INITIALIZER(tsk.cred_guard_mutex),		\
	.comm		= "swapper",					\
	.thread		= INIT_THREAD,					\
	.fs		= &init_fs,					\
+4 −3
Original line number Diff line number Diff line
@@ -626,6 +626,10 @@ struct signal_struct {

	int oom_adj;		/* OOM kill score adjustment (bit shift) */
	int oom_score_adj;	/* OOM kill score adjustment */

	struct mutex cred_guard_mutex;	/* guard against foreign influences on
					 * credential calculations
					 * (notably. ptrace) */
};

/* Context switch must be unlocked if interrupts are to be enabled */
@@ -1305,9 +1309,6 @@ struct task_struct {
					 * credentials (COW) */
	const struct cred __rcu *cred;	/* effective (overridable) subjective task
					 * credentials (COW) */
	struct mutex cred_guard_mutex;	/* guard against foreign influences on
					 * credential calculations
					 * (notably. ptrace) */
	struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */

	char comm[TASK_COMM_LEN]; /* executable name excluding path
+1 −1
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
 *
 * Return %LSM_UNSAFE_* bits applied to an exec because of tracing.
 *
 * @task->cred_guard_mutex is held by the caller through the do_execve().
 * @task->signal->cred_guard_mutex is held by the caller through the do_execve().
 */
static inline int tracehook_unsafe_exec(struct task_struct *task)
{
Loading