diff --git a/include/linux/security.h b/include/linux/security.h index 3dea6a9d568f416ccd1b704eec1d4bff9dea6d90..01ef030b94099edab9e884de3ebc3cf2d3749fae 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -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 */ diff --git a/security/security.c b/security/security.c index 860aeb349cb337bbccf4346d99120d4d1fd51c90..68c1b9b45d93e23576be375027012f3c3a45e252 100644 --- a/security/security.c +++ b/security/security.c @@ -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); } diff --git a/security/yama/Kconfig b/security/yama/Kconfig index 51d6709d8bbd3fdd065ae119c3608149ee94d1cd..20ef5143c0c06bbedbfaf4114bf08c4579d75011 100644 --- a/security/yama/Kconfig +++ b/security/yama/Kconfig @@ -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. diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index d51b7c76c37da3e60ab23e7b47c2fe03249b4707..9ca43c1ea630772cc50f82e684b6e0e8eb1b8e2e 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -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))