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

Commit c6993e4a authored by Kees Cook's avatar Kees Cook Committed by James Morris
Browse files

security: allow Yama to be unconditionally stacked



Unconditionally call Yama when CONFIG_SECURITY_YAMA_STACKED is selected,
no matter what LSM module is primary.

Ubuntu and Chrome OS already carry patches to do this, and Fedora
has voiced interest in doing this as well. Instead of having multiple
distributions (or LSM authors) carrying these patches, just allow Yama
to be called unconditionally when selected by the new CONFIG.

Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Acked-by: default avatarSerge E. Hallyn <serge.hallyn@canonical.com>
Acked-by: default avatarEric Paris <eparis@redhat.com>
Acked-by: default avatarJohn Johansen <john.johansen@canonical.com>
Signed-off-by: default avatarJames Morris <james.l.morris@oracle.com>
parent 81198078
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -3021,5 +3021,36 @@ static inline void free_secdata(void *secdata)
{ }
#endif /* CONFIG_SECURITY */

#ifdef CONFIG_SECURITY_YAMA
extern int yama_ptrace_access_check(struct task_struct *child,
				    unsigned int mode);
extern int yama_ptrace_traceme(struct task_struct *parent);
extern void yama_task_free(struct task_struct *task);
extern int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
			   unsigned long arg4, unsigned long arg5);
#else
static inline int yama_ptrace_access_check(struct task_struct *child,
					   unsigned int mode)
{
	return 0;
}

static inline int yama_ptrace_traceme(struct task_struct *parent)
{
	return 0;
}

static inline void yama_task_free(struct task_struct *task)
{
}

static inline int yama_task_prctl(int option, unsigned long arg2,
				  unsigned long arg3, unsigned long arg4,
				  unsigned long arg5)
{
	return -ENOSYS;
}
#endif /* CONFIG_SECURITY_YAMA */

#endif /* ! __LINUX_SECURITY_H */
+21 −0
Original line number Diff line number Diff line
@@ -136,11 +136,23 @@ int __init register_security(struct security_operations *ops)

int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
#ifdef CONFIG_SECURITY_YAMA_STACKED
	int rc;
	rc = yama_ptrace_access_check(child, mode);
	if (rc)
		return rc;
#endif
	return security_ops->ptrace_access_check(child, mode);
}

int security_ptrace_traceme(struct task_struct *parent)
{
#ifdef CONFIG_SECURITY_YAMA_STACKED
	int rc;
	rc = yama_ptrace_traceme(parent);
	if (rc)
		return rc;
#endif
	return security_ops->ptrace_traceme(parent);
}

@@ -761,6 +773,9 @@ int security_task_create(unsigned long clone_flags)

void security_task_free(struct task_struct *task)
{
#ifdef CONFIG_SECURITY_YAMA_STACKED
	yama_task_free(task);
#endif
	security_ops->task_free(task);
}

@@ -876,6 +891,12 @@ 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)
{
#ifdef CONFIG_SECURITY_YAMA_STACKED
	int rc;
	rc = yama_task_prctl(option, arg2, arg3, arg4, arg5);
	if (rc != -ENOSYS)
		return rc;
#endif
	return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
}

+8 −0
Original line number Diff line number Diff line
@@ -11,3 +11,11 @@ config SECURITY_YAMA
	  Further information can be found in Documentation/security/Yama.txt.

	  If you are unsure how to answer this question, answer N.

config SECURITY_YAMA_STACKED
	bool "Yama stacked with other LSMs"
	depends on SECURITY_YAMA
	default n
	help
	  When Yama is built into the kernel, force it to stack with the
	  selected primary LSM.
+10 −4
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ static void yama_ptracer_del(struct task_struct *tracer,
 * yama_task_free - check for task_pid to remove from exception list
 * @task: task being removed
 */
static void yama_task_free(struct task_struct *task)
void yama_task_free(struct task_struct *task)
{
	yama_ptracer_del(task, task);
}
@@ -116,7 +116,7 @@ static void yama_task_free(struct task_struct *task)
 * Return 0 on success, -ve on error.  -ENOSYS is returned when Yama
 * does not handle the given option.
 */
static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
			   unsigned long arg4, unsigned long arg5)
{
	int rc;
@@ -243,7 +243,7 @@ static int ptracer_exception_found(struct task_struct *tracer,
 *
 * Returns 0 if following the ptrace is allowed, -ve on error.
 */
static int yama_ptrace_access_check(struct task_struct *child,
int yama_ptrace_access_check(struct task_struct *child,
				    unsigned int mode)
{
	int rc;
@@ -296,7 +296,7 @@ static int yama_ptrace_access_check(struct task_struct *child,
 *
 * Returns 0 if following the ptrace is allowed, -ve on error.
 */
static int yama_ptrace_traceme(struct task_struct *parent)
int yama_ptrace_traceme(struct task_struct *parent)
{
	int rc;

@@ -330,6 +330,7 @@ static int yama_ptrace_traceme(struct task_struct *parent)
	return rc;
}

#ifndef CONFIG_SECURITY_YAMA_STACKED
static struct security_operations yama_ops = {
	.name =			"yama",

@@ -338,6 +339,7 @@ static struct security_operations yama_ops = {
	.task_prctl =		yama_task_prctl,
	.task_free =		yama_task_free,
};
#endif

#ifdef CONFIG_SYSCTL
static int yama_dointvec_minmax(struct ctl_table *table, int write,
@@ -384,13 +386,17 @@ static struct ctl_table yama_sysctl_table[] = {

static __init int yama_init(void)
{
#ifndef CONFIG_SECURITY_YAMA_STACKED
	if (!security_module_enable(&yama_ops))
		return 0;
#endif

	printk(KERN_INFO "Yama: becoming mindful.\n");

#ifndef CONFIG_SECURITY_YAMA_STACKED
	if (register_security(&yama_ops))
		panic("Yama: kernel registration failed.\n");
#endif

#ifdef CONFIG_SYSCTL
	if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))