Re: [PATCH] fs/open: Fix most outstanding security bugs
From: Kees Cook
Date: Mon Apr 01 2019 - 17:27:18 EST
On Mon, Apr 1, 2019 at 10:50 AM Dmitry Vyukov <dvyukov@xxxxxxxxxx> wrote:
>
> On Mon, Apr 1, 2019 at 4:14 PM Nikolay Borisov <nborisov@xxxxxxxx> wrote:
> > On 1.04.19 Ð. 12:01 Ñ., Johannes Thumshirn wrote:
> > > One common pattern in most of these security related reports is processes
> > > called "syzkaller", "trinity" or "syz-executor" opening files and then
> > > abuse kernel interfaces causing kernel crashes or even worse threats using
> > > memory overwrites or by exploiting race conditions.
> > >
> > > Hunting down these bugs has become time consuming and very expensive, so
> > > I've decided to put an end to it.
> > >
> > > If one of the above mentioned processes tries opening a file, return -EPERM
> > > indicating this process does not have the permission to open files on Linux
> > > anymore.
> > >
> > > Signed-off-by: Johannes Thumshirn <jthumshirn@xxxxxxx>
> >
> > Ack-by: Nikolay Borisov <nborisov@xxxxxxxx>
>
> Reviewed-by: Dmitry Vyukov <dvyukov@xxxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx # v1.0+
>
> Do we want to extend this to other subsystems?
> Should it be a default secomp filter?
Yes, this protection could make those processes fail too many syscalls. I
agree: it would be better to have all syscalls return 0 with a seccomp
filter. I have updated the patch:
Subject: [PATCH] exec: Fix most outstanding security bugs
From: Kees Cook <keescook@xxxxxxxxxxxx>
Over the last 20 years, the Linux kernel has accumulated hundreds if
not thousands of security vulnerabilities.
One common pattern in most of these security related reports is processes
called "syzkaller", "trinity" or "syz-executor" opening files and then
abuse kernel interfaces causing kernel crashes or even worse threats
using memory overwrites or by exploiting race conditions.
Hunting down these bugs has become time consuming and very expensive,
so we've decided to put an end to it.
If one of the above mentioned processes tries to execute a system
call, the call will be skipped but will return zero. This will keep
the process happy without changing kernel state, keeping things safe.
Co-developed-by: Johannes Thumshirn <jthumshirn@xxxxxxx>
Signed-off-by: Johannes Thumshirn <jthumshirn@xxxxxxx>
Suggested-by: Dmitry Vyukov <dvyukov@xxxxxxxxxx>
Singed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
---
fs/exec.c | 1 +
include/linux/seccomp.h | 2 ++
kernel/seccomp.c | 39 +++++++++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+)
diff --git a/fs/exec.c b/fs/exec.c
index 2e0033348d8e..c0a73c8e22ff 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1393,6 +1393,7 @@ void finalize_exec(struct linux_binprm *bprm)
task_lock(current->group_leader);
current->signal->rlim[RLIMIT_STACK] = bprm->rlim_stack;
task_unlock(current->group_leader);
+ seccomp_default(current);
}
EXPORT_SYMBOL(finalize_exec);
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 84868d37b35d..2d98cd0d79ed 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -45,6 +45,7 @@ extern void secure_computing_strict(int this_syscall);
extern long prctl_get_seccomp(void);
extern long prctl_set_seccomp(unsigned long, void __user *);
+extern void seccomp_default(struct task_struct *task);
static inline int seccomp_mode(struct seccomp *s)
{
@@ -73,6 +74,7 @@ static inline long prctl_set_seccomp(unsigned long arg2, char __user *arg3)
{
return -EINVAL;
}
+static inline void seccomp_default(struct task_struct *task) { }
static inline int seccomp_mode(struct seccomp *s)
{
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 54a0347ca812..92faee4cded4 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1395,6 +1395,45 @@ SYSCALL_DEFINE3(seccomp, unsigned int, op, unsigned int, flags,
return do_seccomp(op, flags, uargs);
}
+/* Certain processes should see all syscalls succeed. */
+void seccomp_default(struct task_struct *task)
+{
+ struct sock_filter filter[] = {
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | 0),
+ };
+ struct sock_fprog prog = {
+ .len = ARRAY_SIZE(filter),
+ .filter = filter,
+ };
+ static const char * const list[] = {
+ "syzkaller",
+ "syz-executor",
+ "trinity",
+ };
+ char comm[TASK_COMM_LEN];
+ mm_segment_t old_fs;
+ bool found = false;
+ int i;
+
+ get_task_comm(comm, task);
+
+ for (i = 0; i < ARRAY_SIZE(list); i++) {
+ if (!strncmp(comm, list[i], strlen(list[i]))) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ seccomp_set_mode_filter(0, (void * __user)&prog);
+ set_fs(old_fs);
+}
+EXPORT_SYMBOL_GPL(seccomp_default);
+
/**
* prctl_set_seccomp: configures current->seccomp.mode
* @seccomp_mode: requested mode to use
--
2.17.1
--
Kees Cook