linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Will Drewry <wad@chromium.org>
To: Serge Hallyn <serge.hallyn@canonical.com>
Cc: linux-kernel@vger.kernel.org, keescook@chromium.org,
	john.johansen@canonical.com, coreyb@linux.vnet.ibm.com,
	pmoore@redhat.com, eparis@redhat.com, djm@mindrot.org,
	torvalds@linux-foundation.org, segoon@openwall.com,
	rostedt@goodmis.org, jmorris@namei.org, scarybeasts@gmail.com,
	avi@redhat.com, penberg@cs.helsinki.fi, viro@zeniv.linux.org.uk,
	luto@mit.edu, mingo@elte.hu, akpm@linux-foundation.org,
	khilman@ti.com, borislav.petkov@amd.com, amwang@redhat.com,
	oleg@redhat.com, ak@linux.intel.com, eric.dumazet@gmail.com,
	gregkh@suse.de, dhowells@redhat.com, daniel.lezcano@free.fr,
	linux-fsdevel@vger.kernel.org,
	linux-security-module@vger.kernel.org, olofj@chromium.org,
	mhalcrow@google.com, dlaor@redhat.com
Subject: Re: [RFC,PATCH 1/2] seccomp_filters: system call filtering using BPF
Date: Thu, 12 Jan 2012 10:54:16 -0600	[thread overview]
Message-ID: <CABqD9ha6aX+LQ7B3T1HA-5XB-Uc_UWhLPiCsGDS3BxCFc_Pkrg@mail.gmail.com> (raw)
In-Reply-To: <20120112085316.GB16518@peqn>

On Thu, Jan 12, 2012 at 2:53 AM, Serge Hallyn
<serge.hallyn@canonical.com> wrote:
> Quoting Will Drewry (wad@chromium.org):
>> This patch adds support for seccomp mode 2.  This mode enables dynamic
>> enforcement of system call filtering policy in the kernel as specified
>> by a userland task.  The policy is expressed in terms of a BPF program,
>> as is used for userland-exposed socket filtering.  Instead of network
>> data, the BPF program is evaluated over struct user_regs_struct at the
>> time of the system call (as retrieved using regviews).
>>
>> A filter program may be installed by a userland task by calling
>>   prctl(PR_ATTACH_SECCOMP_FILTER, &fprog);
>> where fprog is of type struct sock_fprog.
>>
>> If the first filter program allows subsequent prctl(2) calls, then
>> additional filter programs may be attached.  All attached programs
>> must be evaluated before a system call will be allowed to proceed.
>>
>> To avoid CONFIG_COMPAT related landmines, once a filter program is
>> installed using specific is_compat_task() and current->personality, it
>> is not allowed to make system calls or attach additional filters which
>> use a different combination of is_compat_task() and
>> current->personality.
>>
>> Filter programs may _only_ cross the execve(2) barrier if last filter
>> program was attached by a task with CAP_SYS_ADMIN capabilities in its
>> user namespace.  Once a task-local filter program is attached from a
>> process without privileges, execve will fail.  This ensures that only
>> privileged parent task can affect its privileged children (e.g., setuid
>> binary).
>>
>> There are a number of benefits to this approach. A few of which are
>> as follows:
>> - BPF has been exposed to userland for a long time.
>> - Userland already knows its ABI: expected register layout and system
>>   call numbers.
>> - Full register information is provided which may be relevant for
>>   certain syscalls (fork, rt_sigreturn) or for other userland
>>   filtering tactics (checking the PC).
>> - No time-of-check-time-of-use vulnerable data accesses are possible.
>>
>> This patch includes its own BPF evaluator, but relies on the
>> net/core/filter.c BPF checking code.  It is possible to share
>> evaluators, but the performance sensitive nature of the network
>> filtering path makes it an iterative optimization which (I think :) can
>> be tackled separately via separate patchsets. (And at some point sharing
>> BPF JIT code!)
>>
>> Signed-off-by: Will Drewry <wad@chromium.org>
>
> Hey Will,
>
> A few comments below, but otherwise
>
> Acked-by: Serge Hallyn <serge.hallyn@canonical.com>

Thanks! Unimportant responses below.  Fixes will be incorporated in
the next round (along with Oleg's feedback).

cheers,
will

> thanks,
> -serge
>
>> ---
>>  fs/exec.c               |    5 +
>>  include/linux/prctl.h   |    3 +
>>  include/linux/seccomp.h |   70 +++++-
>>  kernel/Makefile         |    1 +
>>  kernel/fork.c           |    4 +
>>  kernel/seccomp.c        |    8 +
>>  kernel/seccomp_filter.c |  639 +++++++++++++++++++++++++++++++++++++++++++++++
>>  kernel/sys.c            |    4 +
>>  security/Kconfig        |   12 +
>>  9 files changed, 743 insertions(+), 3 deletions(-)
>>  create mode 100644 kernel/seccomp_filter.c
>>
>> diff --git a/fs/exec.c b/fs/exec.c
>> index 3625464..e9cc89c 100644
>> --- a/fs/exec.c
>> +++ b/fs/exec.c
>> @@ -44,6 +44,7 @@
>>  #include <linux/namei.h>
>>  #include <linux/mount.h>
>>  #include <linux/security.h>
>> +#include <linux/seccomp.h>
>>  #include <linux/syscalls.h>
>>  #include <linux/tsacct_kern.h>
>>  #include <linux/cn_proc.h>
>> @@ -1477,6 +1478,10 @@ static int do_execve_common(const char *filename,
>>       if (retval)
>>               goto out_ret;
>>
>> +     retval = seccomp_check_exec();
>> +     if (retval)
>> +             goto out_ret;
>> +
>>       retval = -ENOMEM;
>>       bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
>>       if (!bprm)
>> diff --git a/include/linux/prctl.h b/include/linux/prctl.h
>> index a3baeb2..15e2460 100644
>> --- a/include/linux/prctl.h
>> +++ b/include/linux/prctl.h
>> @@ -64,6 +64,9 @@
>>  #define PR_GET_SECCOMP       21
>>  #define PR_SET_SECCOMP       22
>>
>> +/* Set process seccomp filters */
>> +#define PR_ATTACH_SECCOMP_FILTER     36
>> +
>>  /* Get/set the capability bounding set (as per security/commoncap.c) */
>>  #define PR_CAPBSET_READ 23
>>  #define PR_CAPBSET_DROP 24
>> diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
>> index cc7a4e9..99d163e 100644
>> --- a/include/linux/seccomp.h
>> +++ b/include/linux/seccomp.h
>> @@ -5,9 +5,28 @@
>>  #ifdef CONFIG_SECCOMP
>>
>>  #include <linux/thread_info.h>
>> +#include <linux/types.h>
>>  #include <asm/seccomp.h>
>>
>> -typedef struct { int mode; } seccomp_t;
>> +struct seccomp_filter;
>> +/**
>> + * struct seccomp_struct - the state of a seccomp'ed process
>> + *
>> + * @mode:
>> + *     if this is 0, seccomp is not in use.
>> + *             is 1, the process is under standard seccomp rules.
>> + *             is 2, the process is only allowed to make system calls where
>> + *                   associated filters evaluate successfully.
>> + * @filter: Metadata for filter if using CONFIG_SECCOMP_FILTER.
>> + *          @filter must only be accessed from the context of current as there
>> + *          is no guard.
>> + */
>> +typedef struct seccomp_struct {
>> +     int mode;
>> +#ifdef CONFIG_SECCOMP_FILTER
>> +     struct seccomp_filter *filter;
>> +#endif
>> +} seccomp_t;
>>
>>  extern void __secure_computing(int);
>>  static inline void secure_computing(int this_syscall)
>> @@ -28,8 +47,7 @@ static inline int seccomp_mode(seccomp_t *s)
>>
>>  #include <linux/errno.h>
>>
>> -typedef struct { } seccomp_t;
>> -
>> +typedef struct seccomp_struct { } seccomp_t;
>>  #define secure_computing(x) do { } while (0)
>>
>>  static inline long prctl_get_seccomp(void)
>> @@ -49,4 +67,50 @@ static inline int seccomp_mode(seccomp_t *s)
>>
>>  #endif /* CONFIG_SECCOMP */
>>
>> +#ifdef CONFIG_SECCOMP_FILTER
>> +
>> +#define seccomp_filter_init_task(_tsk) do { \
>> +     (_tsk)->seccomp.filter = NULL; \
>> +} while (0);
>> +
>> +/* No locking is needed here because the task_struct will
>> + * have no parallel consumers.
>> + */
>> +#define seccomp_filter_free_task(_tsk) do { \
>> +     put_seccomp_filter((_tsk)->seccomp.filter); \
>> +} while (0);
>> +
>> +extern int seccomp_check_exec(void);
>> +
>> +extern long prctl_attach_seccomp_filter(char __user *);
>> +
>> +extern struct seccomp_filter *get_seccomp_filter(struct seccomp_filter *);
>> +extern void put_seccomp_filter(struct seccomp_filter *);
>> +
>> +extern int seccomp_test_filters(int);
>> +extern void seccomp_filter_log_failure(int);
>> +extern void seccomp_filter_fork(struct task_struct *child,
>> +                             struct task_struct *parent);
>> +
>> +#else  /* CONFIG_SECCOMP_FILTER */
>> +
>> +#include <linux/errno.h>
>> +
>> +struct seccomp_filter { };
>> +#define seccomp_filter_init_task(_tsk) do { } while (0);
>> +#define seccomp_filter_fork(_tsk, _orig) do { } while (0);
>> +#define seccomp_filter_free_task(_tsk) do { } while (0);
>> +
>> +static inline int seccomp_check_exec(void)
>> +{
>> +     return 0;
>> +}
>> +
>> +
>> +static inline long prctl_attach_seccomp_filter(char __user *a2)
>> +{
>> +     return -ENOSYS;
>> +}
>> +
>> +#endif  /* CONFIG_SECCOMP_FILTER */
>>  #endif /* _LINUX_SECCOMP_H */
>> diff --git a/kernel/Makefile b/kernel/Makefile
>> index e898c5b..0584090 100644
>> --- a/kernel/Makefile
>> +++ b/kernel/Makefile
>> @@ -79,6 +79,7 @@ obj-$(CONFIG_DETECT_HUNG_TASK) += hung_task.o
>>  obj-$(CONFIG_LOCKUP_DETECTOR) += watchdog.o
>>  obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
>>  obj-$(CONFIG_SECCOMP) += seccomp.o
>> +obj-$(CONFIG_SECCOMP_FILTER) += seccomp_filter.o
>>  obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
>>  obj-$(CONFIG_TREE_RCU) += rcutree.o
>>  obj-$(CONFIG_TREE_PREEMPT_RCU) += rcutree.o
>> diff --git a/kernel/fork.c b/kernel/fork.c
>> index da4a6a1..cc1d628 100644
>> --- a/kernel/fork.c
>> +++ b/kernel/fork.c
>> @@ -34,6 +34,7 @@
>>  #include <linux/cgroup.h>
>>  #include <linux/security.h>
>>  #include <linux/hugetlb.h>
>> +#include <linux/seccomp.h>
>>  #include <linux/swap.h>
>>  #include <linux/syscalls.h>
>>  #include <linux/jiffies.h>
>> @@ -166,6 +167,7 @@ void free_task(struct task_struct *tsk)
>>       free_thread_info(tsk->stack);
>>       rt_mutex_debug_task_free(tsk);
>>       ftrace_graph_exit_task(tsk);
>> +     seccomp_filter_free_task(tsk);
>>       free_task_struct(tsk);
>>  }
>>  EXPORT_SYMBOL(free_task);
>> @@ -1209,6 +1211,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
>>       /* Perform scheduler related setup. Assign this task to a CPU. */
>>       sched_fork(p);
>>
>> +     seccomp_filter_init_task(p);
>>       retval = perf_event_init_task(p);
>>       if (retval)
>>               goto bad_fork_cleanup_policy;
>> @@ -1375,6 +1378,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
>>       if (clone_flags & CLONE_THREAD)
>>               threadgroup_fork_read_unlock(current);
>>       perf_event_fork(p);
>> +     seccomp_filter_fork(p, current);
>>       return p;
>>
>>  bad_fork_free_pid:
>> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
>> index 57d4b13..78719be 100644
>> --- a/kernel/seccomp.c
>> +++ b/kernel/seccomp.c
>> @@ -47,6 +47,14 @@ void __secure_computing(int this_syscall)
>>                               return;
>>               } while (*++syscall);
>>               break;
>> +#ifdef CONFIG_SECCOMP_FILTER
>> +     case 2:
>> +             if (seccomp_test_filters(this_syscall) == 0)
>> +                     return;
>> +
>> +             seccomp_filter_log_failure(this_syscall);
>> +             break;
>> +#endif
>>       default:
>>               BUG();
>>       }
>> diff --git a/kernel/seccomp_filter.c b/kernel/seccomp_filter.c
>> new file mode 100644
>> index 0000000..4770847
>> --- /dev/null
>> +++ b/kernel/seccomp_filter.c
>> @@ -0,0 +1,639 @@
>> +/* bpf program-based system call filtering
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
>> + *
>> + * Copyright (C) 2011 The Chromium OS Authors <chromium-os-dev@chromium.org>
>> + */
>> +
>> +#include <linux/capability.h>
>> +#include <linux/compat.h>
>> +#include <linux/err.h>
>> +#include <linux/errno.h>
>> +#include <linux/rculist.h>
>> +#include <linux/filter.h>
>> +#include <linux/kallsyms.h>
>> +#include <linux/kref.h>
>> +#include <linux/module.h>
>> +#include <linux/pid.h>
>> +#include <linux/prctl.h>
>> +#include <linux/ptrace.h>
>> +#include <linux/ratelimit.h>
>> +#include <linux/reciprocal_div.h>
>> +#include <linux/regset.h>
>> +#include <linux/seccomp.h>
>> +#include <linux/security.h>
>> +#include <linux/sched.h>
>> +#include <linux/slab.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/user.h>
>> +
>> +
>> +/**
>> + * struct seccomp_filter - container for seccomp BPF programs
>> + *
>> + * @usage: reference count to manage the object lifetime.
>> + *         get/put helpers should be used when accessing an instance
>> + *         outside of a lifetime-guarded section.  In general, this
>> + *         is only needed for handling filters shared across tasks.
>> + * @creator: pointer to the pid that created this filter
>> + * @parent: pointer to the ancestor which this filter will be composed with.
>> + * @flags: provide information about filter from creation time.
>> + * @personality: personality of the process at filter creation time.
>> + * @insns: the BPF program instructions to evaluate
>> + * @count: the number of instructions in the program.
>> + *
>> + * seccomp_filter objects should never be modified after being attached
>> + * to a task_struct (other than @usage).
>> + */
>> +struct seccomp_filter {
>> +     struct kref usage;
>> +     struct pid *creator;
>> +     struct seccomp_filter *parent;
>> +     struct {
>> +             uint32_t admin:1,  /* can allow execve */
>> +                      compat:1,  /* CONFIG_COMPAT */
>> +                      __reserved:30;
>> +     } flags;
>> +     int personality;
>> +     unsigned short count;  /* Instruction count */
>> +     struct sock_filter insns[0];
>> +};
>> +
>> +static unsigned int seccomp_run_filter(const u8 *buf,
>> +                                    const size_t buflen,
>> +                                    const struct sock_filter *);
>> +
>> +/**
>> + * seccomp_filter_alloc - allocates a new filter object
>> + * @padding: size of the insns[0] array in bytes
>> + *
>> + * The @padding should be a multiple of
>> + * sizeof(struct sock_filter).
>> + *
>> + * Returns ERR_PTR on error or an allocated object.
>> + */
>> +static struct seccomp_filter *seccomp_filter_alloc(unsigned long padding)
>> +{
>> +     struct seccomp_filter *f;
>> +     unsigned long bpf_blocks = padding / sizeof(struct sock_filter);
>> +
>> +     /* Drop oversized requests. */
>> +     if (bpf_blocks == 0 || bpf_blocks > BPF_MAXINSNS)
>> +             return ERR_PTR(-EINVAL);
>> +
>> +     /* Padding should always be in sock_filter increments. */
>> +     BUG_ON(padding % sizeof(struct sock_filter));
>
> I still think the BUG_ON here is harsh given that the progsize is passed
> in by userspace.  Was there a reason not to return -EINVAL here?

I've changed it in the next revision.  As is, I don't believe
userspace can control
the size of padding directly, just the increment since it specifies
its length in terms
of bpf blocks (sizeof(struct sock_filter)).  But EINVAL is certainly
less aggressive :)

>> +
>> +     f = kzalloc(sizeof(struct seccomp_filter) + padding, GFP_KERNEL);
>> +     if (!f)
>> +             return ERR_PTR(-ENOMEM);
>> +     kref_init(&f->usage);
>> +     f->creator = get_task_pid(current, PIDTYPE_PID);
>> +     f->count = bpf_blocks;
>> +     return f;
>> +}
>> +
>> +/**
>> + * seccomp_filter_free - frees the allocated filter.
>> + * @filter: NULL or live object to be completely destructed.
>> + */
>> +static void seccomp_filter_free(struct seccomp_filter *filter)
>> +{
>> +     if (!filter)
>> +             return;
>> +     put_seccomp_filter(filter->parent);
>> +     put_pid(filter->creator);
>> +     kfree(filter);
>> +}
>> +
>> +static void __put_seccomp_filter(struct kref *kref)
>> +{
>> +     struct seccomp_filter *orig =
>> +             container_of(kref, struct seccomp_filter, usage);
>> +     seccomp_filter_free(orig);
>> +}
>> +
>> +void seccomp_filter_log_failure(int syscall)
>> +{
>> +     pr_info("%s[%d]: system call %d blocked at 0x%lx\n",
>> +             current->comm, task_pid_nr(current), syscall,
>> +             KSTK_EIP(current));
>> +}
>> +
>> +/* put_seccomp_filter - decrements the ref count of @orig and may free. */
>> +void put_seccomp_filter(struct seccomp_filter *orig)
>> +{
>> +     if (!orig)
>> +             return;
>> +     kref_put(&orig->usage, __put_seccomp_filter);
>> +}
>> +
>> +/* get_seccomp_filter - increments the reference count of @orig. */
>> +struct seccomp_filter *get_seccomp_filter(struct seccomp_filter *orig)
>> +{
>> +     if (!orig)
>> +             return NULL;
>> +     kref_get(&orig->usage);
>> +     return orig;
>> +}
>> +
>> +static int seccomp_check_personality(struct seccomp_filter *filter)
>> +{
>> +     if (filter->personality != current->personality)
>> +             return -EACCES;
>> +#ifdef CONFIG_COMPAT
>> +     if (filter->flags.compat != (!!(is_compat_task())))
>> +             return -EACCES;
>> +#endif
>> +     return 0;
>> +}
>> +
>> +static const struct user_regset *
>> +find_prstatus(const struct user_regset_view *view)
>> +{
>> +     const struct user_regset *regset;
>> +     int n;
>> +
>> +     /* Skip 0. */
>> +     for (n = 1; n < view->n; ++n) {
>> +             regset = view->regsets + n;
>> +             if (regset->core_note_type == NT_PRSTATUS)
>> +                     return regset;
>> +     }
>> +
>> +     return NULL;
>> +}
>> +
>> +/**
>> + * seccomp_get_regs - returns a pointer to struct user_regs_struct
>> + * @scratch: preallocated storage of size @available
>> + * @available: pointer to the size of scratch.
>> + *
>> + * Returns NULL if the registers cannot be acquired or copied.
>> + * Returns a populated pointer to @scratch by default.
>> + * Otherwise, returns a pointer to a a u8 array containing the struct
>> + * user_regs_struct appropriate for the task personality.  The pointer
>> + * may be to the beginning of @scratch or to an externally managed data
>> + * structure.  On success, @available should be updated with the
>> + * valid region size of the returned pointer.
>> + *
>> + * If the architecture overrides the linkage, then the pointer may pointer to
>> + * another location.
>> + */
>> +__weak u8 *seccomp_get_regs(u8 *scratch, size_t *available)
>> +{
>> +     /* regset is usually returned based on task personality, not current
>> +      * system call convention.  This behavior makes it unsafe to execute
>> +      * BPF programs over regviews if is_compat_task or the personality
>> +      * have changed since the program was installed.
>> +      */
>> +     const struct user_regset_view *view = task_user_regset_view(current);
>> +     const struct user_regset *regset = &view->regsets[0];
>> +     size_t scratch_size = *available;
>> +     if (regset->core_note_type != NT_PRSTATUS) {
>> +             /* The architecture should override this method for speed. */
>> +             regset = find_prstatus(view);
>> +             if (!regset)
>> +                     return NULL;
>> +     }
>> +     *available = regset->n * regset->size;
>> +     /* Make sure the scratch space isn't exceeded. */
>> +     if (*available > scratch_size)
>> +             *available = scratch_size;
>> +     if (regset->get(current, regset, 0, *available, scratch, NULL))
>> +             return NULL;
>> +     return scratch;
>> +}
>> +
>> +/**
>> + * seccomp_test_filters - tests 'current' against the given syscall
>> + * @syscall: number of the system call to test
>> + *
>> + * Returns 0 on ok and non-zero on error/failure.
>> + */
>> +int seccomp_test_filters(int syscall)
>> +{
>> +     struct seccomp_filter *filter;
>> +     u8 regs_tmp[sizeof(struct user_regs_struct)], *regs;
>> +     size_t regs_size = sizeof(struct user_regs_struct);
>> +     int ret = -EACCES;
>> +
>> +     filter = current->seccomp.filter; /* uses task ref */
>> +     if (!filter)
>> +             goto out;
>> +
>> +     /* All filters in the list are required to share the same system call
>> +      * convention so only the first filter is ever checked.
>> +      */
>> +     if (seccomp_check_personality(filter))
>> +             goto out;
>> +
>> +     /* Grab the user_regs_struct.  Normally, regs == &regs_tmp, but
>> +      * that is not mandatory.  E.g., it may return a point to
>> +      * task_pt_regs(current).  NULL checking is mandatory.
>> +      */
>> +     regs = seccomp_get_regs(regs_tmp, &regs_size);
>> +     if (!regs)
>> +             goto out;
>> +
>> +     /* Only allow a system call if it is allowed in all ancestors. */
>> +     ret = 0;
>> +     for ( ; filter != NULL; filter = filter->parent) {
>> +             /* Allowed if return value is the size of the data supplied. */
>> +             if (seccomp_run_filter(regs, regs_size, filter->insns) !=
>> +                 regs_size)
>> +                     ret = -EACCES;
>> +     }
>> +out:
>> +     return ret;
>> +}
>> +
>> +/**
>> + * seccomp_attach_filter: Attaches a seccomp filter to current.
>> + * @fprog: BPF program to install
>> + *
>> + * Context: User context only. This function may sleep on allocation and
>> + *          operates on current. current must be attempting a system call
>> + *          when this is called (usually prctl).
>> + *
>> + * This function may be called repeatedly to install additional filters.
>> + * Every filter successfully installed will be evaluated (in reverse order)
>> + * for each system call the thread makes.
>> + *
>> + * Returns 0 on success or an errno on failure.
>> + */
>> +long seccomp_attach_filter(struct sock_fprog *fprog)
>> +{
>> +     struct seccomp_filter *filter = NULL;
>> +     /* Note, len is a short so overflow should be impossible. */
>> +     unsigned long fp_size = fprog->len * sizeof(struct sock_filter);
>> +     long ret = -EPERM;
>> +
>> +     /* Allocate a new seccomp_filter */
>> +     filter = seccomp_filter_alloc(fp_size);
>> +     if (IS_ERR(filter)) {
>> +             ret = PTR_ERR(filter);
>> +             goto out;
>> +     }
>> +
>> +     /* Lock the process personality and calling convention. */
>> +#ifdef CONFIG_COMPAT
>> +     if (is_compat_task())
>> +             filter->flags.compat = 1;
>> +#endif
>> +     filter->personality = current->personality;
>> +
>> +     /* Auditing is not needed since the capability wasn't requested */
>> +     if (security_real_capable_noaudit(current, current_user_ns(),
>> +                                       CAP_SYS_ADMIN) == 0)
>> +             filter->flags.admin = 1;
>> +
>> +     /* Copy the instructions from fprog. */
>> +     ret = -EFAULT;
>> +     if (copy_from_user(filter->insns, fprog->filter, fp_size))
>> +             goto out;
>> +
>> +     /* Check the fprog */
>> +     ret = sk_chk_filter(filter->insns, filter->count);
>> +     if (ret)
>> +             goto out;
>> +
>> +     /* If there is an existing filter, make it the parent
>> +      * and reuse the existing task-based ref.
>> +      */
>> +     filter->parent = current->seccomp.filter;
>> +
>> +     /* Force all filters to use one system call convention. */
>> +     ret = -EINVAL;
>> +     if (filter->parent) {
>> +             if (filter->parent->flags.compat != filter->flags.compat)
>> +                     goto out;
>> +             if (filter->parent->personality != filter->personality)
>> +                     goto out;
>> +     }
>> +
>> +     /* Double claim the new filter so we can release it below simplifying
>> +      * the error paths earlier.
>> +      */
>> +     ret = 0;
>> +     get_seccomp_filter(filter);
>> +     current->seccomp.filter = filter;
>> +     /* Engage seccomp if it wasn't. This doesn't use PR_SET_SECCOMP. */
>> +     if (!current->seccomp.mode) {
>> +             current->seccomp.mode = 2;
>> +             set_thread_flag(TIF_SECCOMP);
>> +     }
>> +
>> +out:
>> +     put_seccomp_filter(filter);  /* for get or task, on err */
>> +     return ret;
>> +}
>> +
>> +long prctl_attach_seccomp_filter(char __user *user_filter)
>> +{
>> +     struct sock_fprog fprog;
>> +     long ret = -EINVAL;
>> +
>> +     ret = -EFAULT;
>> +     if (!user_filter)
>> +             goto out;
>> +
>> +     if (copy_from_user(&fprog, user_filter, sizeof(fprog)))
>> +             goto out;
>> +
>> +     ret = seccomp_attach_filter(&fprog);
>> +out:
>> +     return ret;
>> +}
>> +
>> +/**
>> + * seccomp_check_exec: determines if exec is allowed for current
>> + * Returns 0 if allowed.
>> + */
>> +int seccomp_check_exec(void)
>> +{
>> +     if (current->seccomp.mode != 2)
>> +             return 0;
>> +     /* We can rely on the task refcount for the filter. */
>> +     if (!current->seccomp.filter)
>> +             return -EPERM;
>> +     /* The last attached filter set for the process is checked. It must
>> +      * have been installed with CAP_SYS_ADMIN capabilities.
>
> This comment is confusing.  By 'It must' you mean that if not, it's
> denied.  But if I didn't know better I would read that as "we can't
> get to this code unless".  Can you change it to something like
> "Exec is refused unless the filter was installed with CAP_SYS_ADMIN
> privilege"?

Sounds good!

>> +      */
>> +     if (current->seccomp.filter->flags.admin)
>> +             return 0;
>> +     return -EPERM;
>> +}
>> +
>> +/* seccomp_filter_fork: manages inheritance on fork
>> + * @child: forkee
>> + * @parent: forker
>> + * Ensures that @child inherit a seccomp_filter iff seccomp is enabled
>> + * and the set of filters is marked as 'enabled'.
>> + */
>> +void seccomp_filter_fork(struct task_struct *child,
>> +                      struct task_struct *parent)
>> +{
>> +     if (!parent->seccomp.mode)
>> +             return;
>> +     child->seccomp.mode = parent->seccomp.mode;
>> +     child->seccomp.filter = get_seccomp_filter(parent->seccomp.filter);
>> +}
>> +
>> +/* Returns a pointer to the BPF evaluator after checking the offset and size
>> + * boundaries.  The signature almost matches the signature from
>> + * net/core/filter.c with the hopes of sharing code in the future.
>> + */
>> +static const void *load_pointer(const u8 *buf, size_t buflen,
>> +                             int offset, size_t size,
>> +                             void *unused)
>> +{
>> +     if (offset >= buflen)
>> +             goto fail;
>> +     if (offset < 0)
>> +             goto fail;
>> +     if (size > buflen - offset)
>> +             goto fail;
>> +     return buf + offset;
>> +fail:
>> +     return NULL;
>> +}
>> +
>> +/**
>> + * seccomp_run_filter - evaluate BPF (over user_regs_struct)
>> + *   @buf: buffer to execute the filter over
>> + *   @buflen: length of the buffer
>> + *   @fentry: filter to apply
>> + *
>> + * Decode and apply filter instructions to the buffer.
>> + * Return length to keep, 0 for none. @buf is a regset we are
>> + * filtering, @filter is the array of filter instructions.
>> + * Because all jumps are guaranteed to be before last instruction,
>> + * and last instruction guaranteed to be a RET, we dont need to check
>> + * flen.
>> + *
>> + * See core/net/filter.c as this is nearly an exact copy.
>> + * At some point, it would be nice to merge them to take advantage of
>> + * optimizations (like JIT).
>> + *
>> + * A successful filter must return the full length of the data. Anything less
>> + * will currently result in a seccomp failure.  In the future, it may be
>> + * possible to use that for hard filtering registers on the fly so it is
>> + * ideal for consumers to return 0 on intended failure.
>> + */
>> +static unsigned int seccomp_run_filter(const u8 *buf,
>> +                                    const size_t buflen,
>> +                                    const struct sock_filter *fentry)
>> +{
>> +     const void *ptr;
>> +     u32 A = 0;                      /* Accumulator */
>> +     u32 X = 0;                      /* Index Register */
>> +     u32 mem[BPF_MEMWORDS];          /* Scratch Memory Store */
>> +     u32 tmp;
>> +     int k;
>> +
>> +     /*
>> +      * Process array of filter instructions.
>> +      */
>> +     for (;; fentry++) {
>> +#if defined(CONFIG_X86_32)
>> +#define      K (fentry->k)
>> +#else
>> +             const u32 K = fentry->k;
>> +#endif
>> +
>> +             switch (fentry->code) {
>> +             case BPF_S_ALU_ADD_X:
>> +                     A += X;
>> +                     continue;
>> +             case BPF_S_ALU_ADD_K:
>> +                     A += K;
>> +                     continue;
>> +             case BPF_S_ALU_SUB_X:
>> +                     A -= X;
>> +                     continue;
>> +             case BPF_S_ALU_SUB_K:
>> +                     A -= K;
>> +                     continue;
>> +             case BPF_S_ALU_MUL_X:
>> +                     A *= X;
>> +                     continue;
>> +             case BPF_S_ALU_MUL_K:
>> +                     A *= K;
>> +                     continue;
>> +             case BPF_S_ALU_DIV_X:
>> +                     if (X == 0)
>> +                             return 0;
>> +                     A /= X;
>> +                     continue;
>> +             case BPF_S_ALU_DIV_K:
>> +                     A = reciprocal_divide(A, K);
>> +                     continue;
>> +             case BPF_S_ALU_AND_X:
>> +                     A &= X;
>> +                     continue;
>> +             case BPF_S_ALU_AND_K:
>> +                     A &= K;
>> +                     continue;
>> +             case BPF_S_ALU_OR_X:
>> +                     A |= X;
>> +                     continue;
>> +             case BPF_S_ALU_OR_K:
>> +                     A |= K;
>> +                     continue;
>> +             case BPF_S_ALU_LSH_X:
>> +                     A <<= X;
>> +                     continue;
>> +             case BPF_S_ALU_LSH_K:
>> +                     A <<= K;
>> +                     continue;
>> +             case BPF_S_ALU_RSH_X:
>> +                     A >>= X;
>> +                     continue;
>> +             case BPF_S_ALU_RSH_K:
>> +                     A >>= K;
>> +                     continue;
>> +             case BPF_S_ALU_NEG:
>> +                     A = -A;
>> +                     continue;
>> +             case BPF_S_JMP_JA:
>> +                     fentry += K;
>> +                     continue;
>> +             case BPF_S_JMP_JGT_K:
>> +                     fentry += (A > K) ? fentry->jt : fentry->jf;
>> +                     continue;
>> +             case BPF_S_JMP_JGE_K:
>> +                     fentry += (A >= K) ? fentry->jt : fentry->jf;
>> +                     continue;
>> +             case BPF_S_JMP_JEQ_K:
>> +                     fentry += (A == K) ? fentry->jt : fentry->jf;
>> +                     continue;
>> +             case BPF_S_JMP_JSET_K:
>> +                     fentry += (A & K) ? fentry->jt : fentry->jf;
>> +                     continue;
>> +             case BPF_S_JMP_JGT_X:
>> +                     fentry += (A > X) ? fentry->jt : fentry->jf;
>> +                     continue;
>> +             case BPF_S_JMP_JGE_X:
>> +                     fentry += (A >= X) ? fentry->jt : fentry->jf;
>> +                     continue;
>> +             case BPF_S_JMP_JEQ_X:
>> +                     fentry += (A == X) ? fentry->jt : fentry->jf;
>> +                     continue;
>> +             case BPF_S_JMP_JSET_X:
>> +                     fentry += (A & X) ? fentry->jt : fentry->jf;
>> +                     continue;
>> +             case BPF_S_LD_W_ABS:
>> +                     k = K;
>> +load_w:
>> +                     ptr = load_pointer(buf, buflen, k, 4, &tmp);
>> +                     if (ptr != NULL) {
>> +                             /* Note, unlike on network data, values are not
>> +                              * byte swapped.
>> +                              */
>> +                             A = *(const u32 *)ptr;
>> +                             continue;
>> +                     }
>> +                     return 0;
>> +             case BPF_S_LD_H_ABS:
>> +                     k = K;
>> +load_h:
>> +                     ptr = load_pointer(buf, buflen, k, 2, &tmp);
>> +                     if (ptr != NULL) {
>> +                             A = *(const u16 *)ptr;
>> +                             continue;
>> +                     }
>> +                     return 0;
>> +             case BPF_S_LD_B_ABS:
>> +                     k = K;
>> +load_b:
>> +                     ptr = load_pointer(buf, buflen, k, 1, &tmp);
>> +                     if (ptr != NULL) {
>> +                             A = *(const u8 *)ptr;
>> +                             continue;
>> +                     }
>> +                     return 0;
>> +             case BPF_S_LD_W_LEN:
>> +                     A = buflen;
>> +                     continue;
>> +             case BPF_S_LDX_W_LEN:
>> +                     X = buflen;
>> +                     continue;
>> +             case BPF_S_LD_W_IND:
>> +                     k = X + K;
>> +                     goto load_w;
>> +             case BPF_S_LD_H_IND:
>> +                     k = X + K;
>> +                     goto load_h;
>> +             case BPF_S_LD_B_IND:
>> +                     k = X + K;
>> +                     goto load_b;
>> +             case BPF_S_LDX_B_MSH:
>> +                     ptr = load_pointer(buf, buflen, K, 1, &tmp);
>> +                     if (ptr != NULL) {
>> +                             X = (*(u8 *)ptr & 0xf) << 2;
>> +                             continue;
>> +                     }
>> +                     return 0;
>> +             case BPF_S_LD_IMM:
>> +                     A = K;
>> +                     continue;
>> +             case BPF_S_LDX_IMM:
>> +                     X = K;
>> +                     continue;
>> +             case BPF_S_LD_MEM:
>> +                     A = mem[K];
>> +                     continue;
>> +             case BPF_S_LDX_MEM:
>> +                     X = mem[K];
>> +                     continue;
>> +             case BPF_S_MISC_TAX:
>> +                     X = A;
>> +                     continue;
>> +             case BPF_S_MISC_TXA:
>> +                     A = X;
>> +                     continue;
>> +             case BPF_S_RET_K:
>> +                     return K;
>> +             case BPF_S_RET_A:
>> +                     return A;
>> +             case BPF_S_ST:
>> +                     mem[K] = A;
>> +                     continue;
>> +             case BPF_S_STX:
>> +                     mem[K] = X;
>> +                     continue;
>> +             case BPF_S_ANC_PROTOCOL:
>> +             case BPF_S_ANC_PKTTYPE:
>> +             case BPF_S_ANC_IFINDEX:
>> +             case BPF_S_ANC_MARK:
>> +             case BPF_S_ANC_QUEUE:
>> +             case BPF_S_ANC_HATYPE:
>> +             case BPF_S_ANC_RXHASH:
>> +             case BPF_S_ANC_CPU:
>> +             case BPF_S_ANC_NLATTR:
>> +             case BPF_S_ANC_NLATTR_NEST:
>> +                     /* ignored */
>> +                     continue;
>> +             default:
>> +                     WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n",
>> +                                    fentry->code, fentry->jt,
>> +                                    fentry->jf, fentry->k);
>> +                     return 0;
>> +             }
>> +     }
>> +
>> +     return 0;
>> +}
>> diff --git a/kernel/sys.c b/kernel/sys.c
>> index 481611f..77f2eda 100644
>> --- a/kernel/sys.c
>> +++ b/kernel/sys.c
>> @@ -1783,6 +1783,10 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
>>               case PR_SET_SECCOMP:
>>                       error = prctl_set_seccomp(arg2);
>>                       break;
>> +             case PR_ATTACH_SECCOMP_FILTER:
>> +                     error = prctl_attach_seccomp_filter((char __user *)
>> +                                                             arg2);
>> +                     break;
>>               case PR_GET_TSC:
>>                       error = GET_TSC_CTL(arg2);
>>                       break;
>> diff --git a/security/Kconfig b/security/Kconfig
>> index 51bd5a0..77b1106 100644
>> --- a/security/Kconfig
>> +++ b/security/Kconfig
>> @@ -84,6 +84,18 @@ config SECURITY_DMESG_RESTRICT
>>
>>         If you are unsure how to answer this question, answer N.
>>
>> +config SECCOMP_FILTER
>> +     bool "Enable seccomp-based system call filtering"
>> +     select SECCOMP
>> +     depends on EXPERIMENTAL
>> +     help
>> +       This kernel feature expands CONFIG_SECCOMP to allow computing
>> +       in environments with reduced kernel access dictated by a system
>> +       call filter, expressed in BPF, installed by the application itself
>> +       through prctl(2).
>> +
>> +       See Documentation/prctl/seccomp_filter.txt for more detail.
>> +
>>  config SECURITY
>>       bool "Enable different security models"
>>       depends on SYSFS
>> --
>> 1.7.5.4
>>

  reply	other threads:[~2012-01-12 16:54 UTC|newest]

Thread overview: 235+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-11 17:25 [RFC,PATCH 0/2] dynamic seccomp policies (using BPF filters) Will Drewry
2012-01-11 17:25 ` [RFC,PATCH 1/2] seccomp_filters: system call filtering using BPF Will Drewry
2012-01-12  8:53   ` Serge Hallyn
2012-01-12 16:54     ` Will Drewry [this message]
2012-01-12 14:50   ` Oleg Nesterov
2012-01-12 16:55     ` Will Drewry
2012-01-12 15:43   ` Steven Rostedt
2012-01-12 16:14     ` Oleg Nesterov
2012-01-12 16:38       ` Steven Rostedt
2012-01-12 16:47         ` Oleg Nesterov
2012-01-12 17:08           ` Will Drewry
2012-01-12 17:30         ` Jamie Lokier
2012-01-12 17:40           ` Steven Rostedt
2012-01-12 17:44             ` Jamie Lokier
2012-01-12 17:56               ` Steven Rostedt
2012-01-12 23:27                 ` Alan Cox
2012-01-12 23:38                   ` Linus Torvalds
2012-01-12 22:18             ` Will Drewry
2012-01-12 23:00               ` Andrew Lutomirski
2012-01-12 16:14     ` Andrew Lutomirski
2012-01-12 16:27       ` Steven Rostedt
2012-01-12 16:51         ` Andrew Lutomirski
2012-01-12 17:09         ` Linus Torvalds
2012-01-12 17:17           ` Steven Rostedt
2012-01-12 18:18           ` Andrew Lutomirski
2012-01-12 18:32             ` Linus Torvalds
2012-01-12 18:44               ` Andrew Lutomirski
2012-01-12 19:08                 ` Kyle Moffett
2012-01-12 23:05                   ` Eric Paris
2012-01-12 23:33                     ` Andrew Lutomirski
2012-01-12 19:40                 ` Will Drewry
2012-01-12 19:42                   ` Will Drewry
2012-01-12 19:46                   ` Andrew Lutomirski
2012-01-12 20:00                     ` Linus Torvalds
2012-01-12 16:59     ` Will Drewry
2012-01-12 17:22       ` Jamie Lokier
2012-01-12 17:35         ` Will Drewry
2012-01-12 17:57           ` Jamie Lokier
2012-01-12 18:03             ` Will Drewry
2012-01-13  1:34               ` Jamie Lokier
2012-01-13  2:44             ` Indan Zupancic
2012-01-13  6:33             ` Chris Evans
2012-01-12 17:36     ` Jamie Lokier
2012-01-12 16:18   ` Alan Cox
2012-01-12 17:03     ` Will Drewry
2012-01-12 17:11       ` Alan Cox
2012-01-12 17:52         ` Will Drewry
2012-01-13  1:31     ` James Morris
2012-01-12 16:22   ` Oleg Nesterov
2012-01-12 17:10     ` Will Drewry
2012-01-12 17:23       ` Oleg Nesterov
2012-01-12 17:51         ` Will Drewry
2012-01-13 17:31           ` Oleg Nesterov
2012-01-13 19:01             ` Will Drewry
2012-01-13 23:10               ` Will Drewry
2012-01-13 23:12                 ` Will Drewry
2012-01-13 23:30                 ` Eric Paris
2012-01-15  3:40                 ` Indan Zupancic
2012-01-16  1:40                   ` Will Drewry
2012-01-16  6:49                     ` Indan Zupancic
2012-01-16 20:12                       ` Will Drewry
2012-01-17  6:46                         ` Indan Zupancic
2012-01-17 17:37                           ` Will Drewry
2012-01-18  4:06                             ` Indan Zupancic
2012-01-18  4:38                               ` Will Drewry
2012-01-17 20:34                           ` Kees Cook
2012-01-17 20:42                             ` Will Drewry
2012-01-17 21:09                               ` Will Drewry
2012-01-18  4:47                               ` Indan Zupancic
2012-01-16 18:37                 ` Oleg Nesterov
2012-01-16 20:15                   ` Will Drewry
2012-01-17 16:45                     ` Oleg Nesterov
2012-01-17 16:56                       ` Will Drewry
2012-01-17 17:01                         ` Andrew Lutomirski
2012-01-17 17:05                           ` Oleg Nesterov
2012-01-17 17:45                             ` Andrew Lutomirski
2012-01-18  0:56                               ` Compat 32-bit syscall entry from 64-bit task!? [was: Re: [RFC,PATCH 1/2] seccomp_filters: system call filtering using BPF] Indan Zupancic
2012-01-18  1:01                                 ` Andrew Lutomirski
2012-01-19  1:06                                   ` Indan Zupancic
2012-01-19  1:19                                     ` Andrew Lutomirski
2012-01-19  1:47                                       ` Indan Zupancic
2012-01-18  1:07                                 ` Roland McGrath
2012-01-18  1:47                                   ` Indan Zupancic
2012-01-18  1:48                                 ` Jamie Lokier
2012-01-18  1:50                                 ` Andi Kleen
2012-01-18  2:00                                   ` Steven Rostedt
2012-01-18  2:04                                   ` Jamie Lokier
2012-01-18  2:22                                     ` Andi Kleen
2012-01-18  2:25                                       ` Andrew Lutomirski
2012-01-18  4:22                                       ` Indan Zupancic
2012-01-18  5:23                                         ` Linus Torvalds
2012-01-18  6:25                                           ` Linus Torvalds
2012-01-18 13:12                                             ` Compat 32-bit syscall entry from 64-bit task!? Indan Zupancic
2012-01-18 19:31                                               ` Linus Torvalds
2012-01-18 19:36                                                 ` Andi Kleen
2012-01-18 19:39                                                   ` Linus Torvalds
2012-01-18 19:44                                                     ` Andi Kleen
2012-01-18 19:47                                                       ` Linus Torvalds
2012-01-18 19:52                                                         ` Will Drewry
2012-01-18 19:58                                                           ` Will Drewry
2012-01-18 19:41                                                   ` Martin Mares
2012-01-18 19:38                                                 ` Andrew Lutomirski
2012-01-19 16:01                                                   ` Jamie Lokier
2012-01-19 16:13                                                     ` Andrew Lutomirski
2012-01-19 19:21                                                     ` Linus Torvalds
2012-01-19 19:30                                                       ` Andrew Lutomirski
2012-01-19 19:37                                                         ` Linus Torvalds
2012-01-19 19:41                                                           ` Linus Torvalds
2012-01-19 23:54                                                       ` Jamie Lokier
2012-01-20  0:05                                                         ` Linus Torvalds
2012-01-20 15:35                                                       ` Will Drewry
2012-01-20 17:56                                                         ` Roland McGrath
2012-01-20 19:45                                                           ` Will Drewry
2012-01-18 20:26                                                 ` Linus Torvalds
2012-01-18 20:55                                                   ` H. Peter Anvin
2012-01-18 21:01                                                     ` Linus Torvalds
2012-01-18 21:04                                                       ` H. Peter Anvin
2012-01-18 21:21                                                         ` H. Peter Anvin
2012-01-18 21:51                                                           ` Roland McGrath
2012-01-18 21:53                                                             ` H. Peter Anvin
2012-01-18 23:28                                                               ` Linus Torvalds
2012-01-19  0:38                                                                 ` H. Peter Anvin
2012-01-20 21:51                                                                   ` Denys Vlasenko
2012-01-20 22:40                                                                     ` Roland McGrath
2012-01-20 22:41                                                                       ` H. Peter Anvin
2012-01-20 23:49                                                                         ` Indan Zupancic
2012-01-20 23:55                                                                           ` Roland McGrath
2012-01-20 23:58                                                                             ` hpanvin@gmail.com
2012-01-23  2:14                                                                             ` Indan Zupancic
2012-01-21  0:07                                                                           ` Denys Vlasenko
2012-01-21  0:10                                                                             ` Roland McGrath
2012-01-21  1:23                                                                               ` Jamie Lokier
2012-01-23  2:37                                                                                 ` Indan Zupancic
2012-01-23 16:48                                                                                   ` Oleg Nesterov
2012-01-24  8:19                                                                       ` Indan Zupancic
2012-02-06 20:30                                                                       ` H. Peter Anvin
2012-02-06 20:39                                                                         ` Roland McGrath
2012-02-06 20:42                                                                           ` H. Peter Anvin
2012-01-18 21:26                                                         ` Linus Torvalds
2012-01-18 21:30                                                           ` H. Peter Anvin
2012-01-18 21:42                                                             ` Linus Torvalds
2012-01-18 21:47                                                               ` H. Peter Anvin
2012-01-19  1:45                                                           ` Indan Zupancic
2012-01-19  2:16                                                             ` H. Peter Anvin
2012-02-06  8:32                                                   ` Indan Zupancic
2012-02-06 17:02                                                     ` H. Peter Anvin
2012-02-07  1:52                                                       ` Indan Zupancic
2012-02-09  0:19                                                         ` H. Peter Anvin
2012-02-09  4:20                                                           ` Indan Zupancic
2012-02-09  4:29                                                             ` H. Peter Anvin
2012-02-09  6:03                                                               ` Indan Zupancic
2012-02-09 14:47                                                                 ` H. Peter Anvin
2012-02-09 16:00                                                               ` H.J. Lu
2012-02-10  1:09                                                                 ` Indan Zupancic
2012-02-10  1:15                                                                   ` H. Peter Anvin
2012-02-10  2:29                                                                     ` Indan Zupancic
2012-02-10  2:47                                                                       ` H. Peter Anvin
     [not found]                                                                       ` <cc95fcf4b1c28ee6f73e373d04593634.squirrel@webmail.greenhost.nl>
2012-02-10 15:53                                                                         ` H. Peter Anvin
2012-02-10 22:42                                                                           ` Indan Zupancic
2012-02-10 22:56                                                                             ` H. Peter Anvin
2012-02-12 12:07                                                                               ` Indan Zupancic
2012-01-25 19:36                                                 ` Oleg Nesterov
2012-01-25 20:20                                                   ` Pedro Alves
2012-01-25 23:36                                                     ` Denys Vlasenko
2012-01-25 23:32                                                   ` Denys Vlasenko
2012-01-26  0:40                                                     ` Indan Zupancic
2012-01-26  1:08                                                       ` Jamie Lokier
2012-01-26  1:22                                                         ` Denys Vlasenko
2012-01-26  6:34                                                         ` Indan Zupancic
2012-01-26 10:31                                                           ` Jamie Lokier
2012-01-26 10:40                                                             ` Denys Vlasenko
2012-01-26 11:01                                                               ` Jamie Lokier
2012-01-26 14:02                                                                 ` Denys Vlasenko
2012-01-26 11:19                                                               ` Indan Zupancic
2012-01-26 11:20                                                             ` Indan Zupancic
2012-01-26 11:47                                                               ` Jamie Lokier
2012-01-26 14:05                                                                 ` Denys Vlasenko
2012-01-27  7:23                                                                 ` Indan Zupancic
2012-02-10  2:02                                                                   ` Jamie Lokier
2012-02-10  3:37                                                                     ` Indan Zupancic
2012-02-10 21:19                                                                       ` Denys Vlasenko
2012-01-26  1:09                                                       ` Denys Vlasenko
2012-01-26  3:47                                                         ` Linus Torvalds
2012-01-26 18:03                                                           ` Denys Vlasenko
2017-03-08 23:41                                                             ` Dmitry V. Levin
2017-03-09  4:39                                                               ` Andrew Lutomirski
2017-03-14  2:57                                                                 ` Dmitry V. Levin
2012-01-26  5:57                                                         ` Indan Zupancic
2012-01-26  0:59                                                     ` Jamie Lokier
2012-01-26  1:21                                                       ` Denys Vlasenko
2012-01-26  8:23                                                       ` Pedro Alves
2012-01-26  8:53                                                         ` Denys Vlasenko
2012-01-26  9:51                                                           ` Pedro Alves
2012-01-26 18:44                                                     ` Oleg Nesterov
2012-02-10  2:51                                                       ` Jamie Lokier
2012-01-18 15:04                                             ` Compat 32-bit syscall entry from 64-bit task!? [was: Re: [RFC,PATCH 1/2] seccomp_filters: system call filtering using BPF] Eric Paris
2012-01-18 17:51                                               ` Linus Torvalds
2012-01-18  5:43                                         ` Chris Evans
2012-01-18 12:12                                           ` Indan Zupancic
2012-01-18 21:13                                             ` Chris Evans
2012-01-19  0:14                                               ` Indan Zupancic
2012-01-19  8:16                                                 ` Chris Evans
2012-01-19 11:34                                                   ` Indan Zupancic
2012-01-19 16:11                                                     ` Jamie Lokier
2012-01-19 15:40                                                 ` Jamie Lokier
2012-01-18 17:00                                           ` Oleg Nesterov
2012-01-18 17:12                                             ` Oleg Nesterov
2012-01-18 21:09                                               ` Chris Evans
2012-01-23 16:56                                                 ` Oleg Nesterov
2012-01-23 22:23                                                   ` Chris Evans
2012-02-07 11:45                                               ` Indan Zupancic
2012-01-19  0:29                                             ` Indan Zupancic
2012-01-18  2:27                                     ` Linus Torvalds
2012-01-18  2:31                                       ` Andi Kleen
2012-01-18  2:46                                         ` Linus Torvalds
2012-01-18 14:06                                           ` Martin Mares
2012-01-18 18:24                                             ` Andi Kleen
2012-01-19 16:04                                               ` Jamie Lokier
2012-01-20  0:21                                                 ` Indan Zupancic
2012-01-20  0:53                                                   ` Linus Torvalds
2012-01-20  2:02                                                     ` Indan Zupancic
2012-01-17 17:06                           ` [RFC,PATCH 1/2] seccomp_filters: system call filtering using BPF Will Drewry
2012-01-17 19:35                         ` Will Drewry
2012-01-12 17:02   ` Andrew Lutomirski
2012-01-16 20:28     ` Will Drewry
2012-01-11 17:25 ` [RFC,PATCH 2/2] Documentation: prctl/seccomp_filter Will Drewry
2012-01-11 20:03   ` Jonathan Corbet
2012-01-11 20:10     ` Will Drewry
2012-01-11 23:19       ` [PATCH v2 " Will Drewry
2012-01-12  0:29         ` Will Drewry
2012-01-12 18:16         ` Randy Dunlap
2012-01-12 17:23           ` Will Drewry
2012-01-12 17:34             ` Steven Rostedt
2012-01-12 13:13   ` [RFC,PATCH " Łukasz Sowa
2012-01-12 17:25     ` Will Drewry

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CABqD9ha6aX+LQ7B3T1HA-5XB-Uc_UWhLPiCsGDS3BxCFc_Pkrg@mail.gmail.com \
    --to=wad@chromium.org \
    --cc=ak@linux.intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=amwang@redhat.com \
    --cc=avi@redhat.com \
    --cc=borislav.petkov@amd.com \
    --cc=coreyb@linux.vnet.ibm.com \
    --cc=daniel.lezcano@free.fr \
    --cc=dhowells@redhat.com \
    --cc=djm@mindrot.org \
    --cc=dlaor@redhat.com \
    --cc=eparis@redhat.com \
    --cc=eric.dumazet@gmail.com \
    --cc=gregkh@suse.de \
    --cc=jmorris@namei.org \
    --cc=john.johansen@canonical.com \
    --cc=keescook@chromium.org \
    --cc=khilman@ti.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=luto@mit.edu \
    --cc=mhalcrow@google.com \
    --cc=mingo@elte.hu \
    --cc=oleg@redhat.com \
    --cc=olofj@chromium.org \
    --cc=penberg@cs.helsinki.fi \
    --cc=pmoore@redhat.com \
    --cc=rostedt@goodmis.org \
    --cc=scarybeasts@gmail.com \
    --cc=segoon@openwall.com \
    --cc=serge.hallyn@canonical.com \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).