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

Commit ab83798b authored by Stephen Smalley's avatar Stephen Smalley Committed by Greg Kroah-Hartman
Browse files

security,selinux,smack: kill security_task_wait hook



commit 3a2f5a59a695a73e0cde9a61e0feae5fa730e936 upstream.

As reported by yangshukui, a permission denial from security_task_wait()
can lead to a soft lockup in zap_pid_ns_processes() since it only expects
sys_wait4() to return 0 or -ECHILD. Further, security_task_wait() can
in general lead to zombies; in the absence of some way to automatically
reparent a child process upon a denial, the hook is not useful.  Remove
the security hook and its implementations in SELinux and Smack.  Smack
already removed its check from its hook.

Reported-by: default avataryangshukui <yangshukui@huawei.com>
Signed-off-by: default avatarStephen Smalley <sds@tycho.nsa.gov>
Acked-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
Signed-off-by: default avatarAlexander Grund <theflamefire89@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 65be5f56
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -666,11 +666,6 @@
 *	@sig contains the signal value.
 *	@secid contains the sid of the process where the signal originated
 *	Return 0 if permission is granted.
 * @task_wait:
 *	Check permission before allowing a process to reap a child process @p
 *	and collect its status information.
 *	@p contains the task_struct for process.
 *	Return 0 if permission is granted.
 * @task_prctl:
 *	Check permission before performing a process control operation on the
 *	current process.
@@ -1507,7 +1502,6 @@ union security_list_options {
	int (*task_movememory)(struct task_struct *p);
	int (*task_kill)(struct task_struct *p, struct siginfo *info,
				int sig, u32 secid);
	int (*task_wait)(struct task_struct *p);
	int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3,
				unsigned long arg4, unsigned long arg5);
	void (*task_to_inode)(struct task_struct *p, struct inode *inode);
@@ -1768,7 +1762,6 @@ struct security_hook_heads {
	struct list_head task_getscheduler;
	struct list_head task_movememory;
	struct list_head task_kill;
	struct list_head task_wait;
	struct list_head task_prctl;
	struct list_head task_to_inode;
	struct list_head ipc_permission;
+0 −6
Original line number Diff line number Diff line
@@ -332,7 +332,6 @@ int security_task_getscheduler(struct task_struct *p);
int security_task_movememory(struct task_struct *p);
int security_task_kill(struct task_struct *p, struct siginfo *info,
			int sig, u32 secid);
int security_task_wait(struct task_struct *p);
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
			unsigned long arg4, unsigned long arg5);
void security_task_to_inode(struct task_struct *p, struct inode *inode);
@@ -980,11 +979,6 @@ static inline int security_task_kill(struct task_struct *p,
	return 0;
}

static inline int security_task_wait(struct task_struct *p)
{
	return 0;
}

static inline int security_task_prctl(int option, unsigned long arg2,
				      unsigned long arg3,
				      unsigned long arg4,
+2 −17
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@
#include <linux/tty.h>
#include <linux/iocontext.h>
#include <linux/key.h>
#include <linux/security.h>
#include <linux/cpu.h>
#include <linux/acct.h>
#include <linux/tsacct_kern.h>
@@ -1342,7 +1341,7 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
 * Returns nonzero for a final return, when we have unlocked tasklist_lock.
 * Returns zero if the search for a child should continue;
 * then ->notask_error is 0 if @p is an eligible child,
 * or another error from security_task_wait(), or still -ECHILD.
 * or still -ECHILD.
 */
static int wait_consider_task(struct wait_opts *wo, int ptrace,
				struct task_struct *p)
@@ -1362,20 +1361,6 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
	if (!ret)
		return ret;

	ret = security_task_wait(p);
	if (unlikely(ret < 0)) {
		/*
		 * If we have not yet seen any eligible child,
		 * then let this error code replace -ECHILD.
		 * A permission error will give the user a clue
		 * to look for security policy problems, rather
		 * than for mysterious wait bugs.
		 */
		if (wo->notask_error)
			wo->notask_error = ret;
		return 0;
	}

	if (unlikely(exit_state == EXIT_TRACE)) {
		/*
		 * ptrace == 0 means we are the natural parent. In this case
@@ -1468,7 +1453,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
 * Returns nonzero for a final return, when we have unlocked tasklist_lock.
 * Returns zero if the search for a child should continue; then
 * ->notask_error is 0 if there were any eligible children,
 * or another error from security_task_wait(), or still -ECHILD.
 * or still -ECHILD.
 */
static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk)
{
+0 −6
Original line number Diff line number Diff line
@@ -1032,11 +1032,6 @@ int security_task_kill(struct task_struct *p, struct siginfo *info,
	return call_int_hook(task_kill, 0, p, info, sig, secid);
}

int security_task_wait(struct task_struct *p)
{
	return call_int_hook(task_wait, 0, p);
}

int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
			 unsigned long arg4, unsigned long arg5)
{
@@ -1776,7 +1771,6 @@ struct security_hook_heads security_hook_heads = {
	.task_movememory =
		LIST_HEAD_INIT(security_hook_heads.task_movememory),
	.task_kill =	LIST_HEAD_INIT(security_hook_heads.task_kill),
	.task_wait =	LIST_HEAD_INIT(security_hook_heads.task_wait),
	.task_prctl =	LIST_HEAD_INIT(security_hook_heads.task_prctl),
	.task_to_inode =
		LIST_HEAD_INIT(security_hook_heads.task_to_inode),
+0 −6
Original line number Diff line number Diff line
@@ -3951,11 +3951,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
	return rc;
}

static int selinux_task_wait(struct task_struct *p)
{
	return task_has_perm(p, current, PROCESS__SIGCHLD);
}

static void selinux_task_to_inode(struct task_struct *p,
				  struct inode *inode)
{
@@ -6220,7 +6215,6 @@ static struct security_hook_list selinux_hooks[] = {
	LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
	LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
	LSM_HOOK_INIT(task_kill, selinux_task_kill),
	LSM_HOOK_INIT(task_wait, selinux_task_wait),
	LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),

	LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
Loading