Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On Fri, 2013-03-15 at 11:45 -0700, Kees Cook wrote: > On Fri, Mar 15, 2013 at 11:28 AM, Nicolas Schichan > wrote: > > diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h > > index 6f19cfd..af27494 100644 > > --- a/include/linux/seccomp.h > > +++ b/include/linux/seccomp.h > > @@ -6,6 +6,7 @@ > > #ifdef CONFIG_SECCOMP > > > > #include > > +#include > > #include > > > > struct seccomp_filter; > > @@ -47,6 +48,44 @@ static inline int seccomp_mode(struct seccomp *s) > > return s->mode; > > } > > > > +/** > > + * 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. > > + * @prev: points to a previously installed, or inherited, filter > > + * @len: the number of instructions in the program > > + * @insns: the BPF program instructions to evaluate > > This should be updated to include the new bpf_func field. > > Regardless, it'd be better to not expose this structure to userspace. This is fine include/uapi/linux/seccomp.h is exposed to userspace include/linux/seccomp.h is kernel internal -Eric -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On 03/15/2013 08:22 PM, Kees Cook wrote: On Fri, Mar 15, 2013 at 12:10 PM, Nicolas Schichan wrote: On 03/15/2013 07:45 PM, Kees Cook wrote: Yes, I did not realise that this header was exported to userspace. Do you know any place not exported to userspace where the structure definition would be appropriate ? Nothing really jumps to mind. :( We should probably do the uapi split, so that this can stay here, but the public stuff is in the other file. I'm not actually sure what's needed to do that split, though. Would putting the structure definition in a file be acceptable ? Or is there some preprocessor macro that could prevent part of an include file ending up in uapi (similar to __KERNEL__ or __ASSEMBLY__). Regarding JIT spraying, I believe ARM is actually worse than x86 in that regard, since the values appearing in the literal pool can be quite easily controlled by an attacker. Yeah, same for x86, really. Masking these would be nice, but is probably a separate discussion. I meant that ARM makes it even easier in that you don't even have to interleave the evil immediate between instruction. The instruction sequence will appear verbatim in the litteral pool. For instance the following BPF code: struct sock_filter code[] = { { BPF_LD, 0, 0, 0xe3a01a02 }, { BPF_LD, 0, 0, 0xe2411001 }, { BPF_LD, 0, 0, 0xe00d1001 }, { BPF_LD, 0, 0, 0xe59111a0 }, { BPF_LD, 0, 0, 0xe3a02000 }, { BPF_LD, 0, 0, 0xe5812004 }, { BPF_LD, 0, 0, 0xe1a0f00e }, { BPF_RET, 0, 0, 0 }, }; Produces this ARM code: BPF JIT code: bf00: e92d0010 e3a04000 e59f4020 e59f4020 BPF JIT code: bf10: e59f4020 e59f4020 e59f4020 e59f4020 BPF JIT code: bf20: e59f4020 e3a0 e8bd0010 e12fff1e BPF JIT code: bf30: e3a01a02 e2411001 e00d1001 e59111a0 BPF JIT code: bf40: e3a02000 e5812004 e1a0f00e Parts of which disassembles to (only eye-tested): mov r1, #8192 sub r1, r1, #1 @ r1 = THREAD_SIZE - 1 and r1, sp, r1 @ get current. ldr r1, [r1, #416] @ get current->real_cred mov r2, #0 str r2, [r1, #4] @ store 0 in current->real_cread->uid. mov pc, lr Userland can insert code to change the uid of the current process quite easily in an executable page. The only remaining task is to trick the kernel into executing it :) Regards, -- Nicolas Schichan Freebox SAS -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On Fri, Mar 15, 2013 at 12:10 PM, Nicolas Schichan wrote: > On 03/15/2013 07:45 PM, Kees Cook wrote: >> >> On Fri, Mar 15, 2013 at 11:28 AM, Nicolas Schichan >> wrote: >>> >>> +/** >>> + * 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. >>> + * @prev: points to a previously installed, or inherited, filter >>> + * @len: the number of instructions in the program >>> + * @insns: the BPF program instructions to evaluate >> >> >> This should be updated to include the new bpf_func field. > > Sure, I'll fix this in a re-spin of the patch serie. > >> Regardless, it'd be better to not expose this structure to userspace. > > Yes, I did not realise that this header was exported to userspace. Do you > know any place not exported to userspace where the structure definition > would be appropriate ? Nothing really jumps to mind. :( We should probably do the uapi split, so that this can stay here, but the public stuff is in the other file. I'm not actually sure what's needed to do that split, though. >>> @@ -213,7 +185,7 @@ static u32 seccomp_run_filters(int syscall) >>> * value always takes priority (ignoring the DATA). >>> */ >>> for (f = current->seccomp.filter; f; f = f->prev) { >>> - u32 cur_ret = sk_run_filter(NULL, f->insns); >>> + u32 cur_ret = f->bpf_func(NULL, f->insns); >> >> This will make bpf_func a rather attractive target inside the kernel. >> I wonder if there could be ways to harden it against potential attack. > > I'm not sure I follow, but is it because any user can install a SECCOMP > filter which will trigger JIT code generation with potential JIT spraying > attack payload ? I actually mean that when an arbitrary write vulnerability is used against the kernel, finding bpf_func may make a good target since it hangs off the process stack. There are plenty of targets, but just wonder if there would be some trivial way to handle this. Probably not. :) > In that case, the same problem exists with struct sk_filter->bpf_func, as > SO_ATTACH_FILTER, with BPT JIT enabled, does not require any particular > privilege AFAICS. Yeah, these problems aren't unique to seccomp, unfortunately. > Regarding JIT spraying, I believe ARM is actually worse than x86 in that > regard, since the values appearing in the literal pool can be quite easily > controlled by an attacker. Yeah, same for x86, really. Masking these would be nice, but is probably a separate discussion. > Thanks for the review. Sure thing! I think Will Drewry may have more suggestions as well. -Kees -- Kees Cook Chrome OS Security -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On 03/15/2013 07:45 PM, Kees Cook wrote: On Fri, Mar 15, 2013 at 11:28 AM, Nicolas Schichan wrote: +/** + * 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. + * @prev: points to a previously installed, or inherited, filter + * @len: the number of instructions in the program + * @insns: the BPF program instructions to evaluate This should be updated to include the new bpf_func field. Sure, I'll fix this in a re-spin of the patch serie. Regardless, it'd be better to not expose this structure to userspace. Yes, I did not realise that this header was exported to userspace. Do you know any place not exported to userspace where the structure definition would be appropriate ? @@ -213,7 +185,7 @@ static u32 seccomp_run_filters(int syscall) * value always takes priority (ignoring the DATA). */ for (f = current->seccomp.filter; f; f = f->prev) { - u32 cur_ret = sk_run_filter(NULL, f->insns); + u32 cur_ret = f->bpf_func(NULL, f->insns); This will make bpf_func a rather attractive target inside the kernel. I wonder if there could be ways to harden it against potential attack. I'm not sure I follow, but is it because any user can install a SECCOMP filter which will trigger JIT code generation with potential JIT spraying attack payload ? In that case, the same problem exists with struct sk_filter->bpf_func, as SO_ATTACH_FILTER, with BPT JIT enabled, does not require any particular privilege AFAICS. Regarding JIT spraying, I believe ARM is actually worse than x86 in that regard, since the values appearing in the literal pool can be quite easily controlled by an attacker. Thanks for the review. Regards, -- Nicolas Schichan Freebox SAS -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On Fri, Mar 15, 2013 at 11:28 AM, Nicolas Schichan wrote: > Architecture must select HAVE_SECCOMP_FILTER_JIT and implement > seccomp_jit_compile() and seccomp_jit_free() if they intend to support > jitted seccomp filters. > > struct seccomp_filter has been moved to to make its > content available to the jit compilation code. > > In a way similar to the net BPF, the jit compilation code is expected > to updates struct seccomp_filter.bpf_func pointer to the generated > code. Exciting. :) Thanks for working on this! > > Signed-off-by: Nicolas Schichan > --- > arch/Kconfig| 14 ++ > include/linux/seccomp.h | 39 +++ > kernel/seccomp.c| 34 +- > 3 files changed, 58 insertions(+), 29 deletions(-) > > diff --git a/arch/Kconfig b/arch/Kconfig > index 5a1779c..1284367 100644 > --- a/arch/Kconfig > +++ b/arch/Kconfig > @@ -339,6 +339,10 @@ config HAVE_ARCH_SECCOMP_FILTER > - secure_computing return value is checked and a return value of -1 > results in the system call being skipped immediately. > > +# Used by archs to tell that they support SECCOMP_FILTER_JIT > +config HAVE_SECCOMP_FILTER_JIT > + bool > + > config SECCOMP_FILTER > def_bool y > depends on HAVE_ARCH_SECCOMP_FILTER && SECCOMP && NET > @@ -349,6 +353,16 @@ config SECCOMP_FILTER > > See Documentation/prctl/seccomp_filter.txt for details. > > +config SECCOMP_FILTER_JIT > + bool "enable Seccomp filter Just In Time compiler" > + depends on HAVE_SECCOMP_FILTER_JIT && BPF_JIT && SECCOMP_FILTER > + help > + Seccomp syscall filtering capabilities are normally handled > + by an interpreter. This option allows kernel to generate a native > + code when filter is loaded in memory. This should speedup > + syscall filtering. Note : Admin should enable this feature > + changing /proc/sys/net/core/bpf_jit_enable > + > config HAVE_CONTEXT_TRACKING > bool > help > diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h > index 6f19cfd..af27494 100644 > --- a/include/linux/seccomp.h > +++ b/include/linux/seccomp.h > @@ -6,6 +6,7 @@ > #ifdef CONFIG_SECCOMP > > #include > +#include > #include > > struct seccomp_filter; > @@ -47,6 +48,44 @@ static inline int seccomp_mode(struct seccomp *s) > return s->mode; > } > > +/** > + * 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. > + * @prev: points to a previously installed, or inherited, filter > + * @len: the number of instructions in the program > + * @insns: the BPF program instructions to evaluate This should be updated to include the new bpf_func field. Regardless, it'd be better to not expose this structure to userspace. > + * > + * seccomp_filter objects are organized in a tree linked via the @prev > + * pointer. For any task, it appears to be a singly-linked list starting > + * with current->seccomp.filter, the most recently attached or inherited > filter. > + * However, multiple filters may share a @prev node, by way of fork(), which > + * results in a unidirectional tree existing in memory. This is similar to > + * how namespaces work. > + * > + * seccomp_filter objects should never be modified after being attached > + * to a task_struct (other than @usage). > + */ > +struct seccomp_filter { > + atomic_t usage; > + struct seccomp_filter *prev; > + unsigned short len; /* Instruction count */ > + unsigned int (*bpf_func)(const struct sk_buff *skb, > +const struct sock_filter *filter); > + struct sock_filter insns[]; > +}; > + > +#ifdef CONFIG_SECCOMP_FILTER_JIT > +extern void seccomp_jit_compile(struct seccomp_filter *fp); > +extern void seccomp_jit_free(struct seccomp_filter *fp); > +#else > +static inline void seccomp_jit_compile(struct seccomp_filter *fp) { } > +static inline void seccomp_jit_free(struct seccomp_filter *fp) { } > +#endif > + > #else /* CONFIG_SECCOMP */ > > #include > diff --git a/kernel/seccomp.c b/kernel/seccomp.c > index b7a1004..a1aadaa 100644 > --- a/kernel/seccomp.c > +++ b/kernel/seccomp.c > @@ -30,34 +30,6 @@ > #include > #include > > -/** > - * 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. > - * @prev: points to a previously installed, or inherited, filter > - * @len: the number of
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On 03/15/2013 07:28 PM, Nicolas Schichan wrote: [Sorry, I forgot to put the mailing lists as the receivers of the introductory message] Hi, This patch serie adds support for jitted seccomp BPF filters, with the required modifications to make it work on the ARM architecture. - The first patch in the serie adds the required boiler plate in the core kernel seccomp code to invoke the JIT compilation/free code. - The second patch reworks the ARM BPF JIT code to make the generation process less dependent on struct sk_filter. - The last patch actually implements the ARM part in the BPF jit code. Some benchmarks, on a 1.6Ghz 88f6282 CPU: Each system call is tested in two way (fast/slow): - on the fast version, the tested system call is accepted immediately after checking the architecture (5 BPF instructions). - on the slow version, the tested system call is accepted after previously checking for 85 syscall (90 instructions, including the architecture check). The tested syscall is invoked in a loop 100 time, the reported time is the time spent in the loop in seconds. Without Seccomp JIT: Syscall Time-Fast Time-Slow --- -- -- gettimeofday0.389 1.633 getpid 0.406 1.688 getresuid 1.003 2.266 getcwd 1.342 2.128 With Seccomp JIT: Syscall Time-Fast Time-Slow --- --- - gettimeofday0.348 0.428 getpid 0.365 0.480 getresuid 0.981 1.060 getcwd 1.237 1.294 For reference, the same code without any seccomp filter: Syscall Time --- - gettimeofday0.119 getpid 0.137 getresuid 0.747 getcwd 1.021 The activation of the BPF JIT for seccomp is still controled with the /proc/sys/net/core/bpf_jit_enable sysctl knob. Those changes are based on the latest rmk-for-next branch. Regards, -- Nicolas Schichan Freebox SAS -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
Architecture must select HAVE_SECCOMP_FILTER_JIT and implement seccomp_jit_compile() and seccomp_jit_free() if they intend to support jitted seccomp filters. struct seccomp_filter has been moved to to make its content available to the jit compilation code. In a way similar to the net BPF, the jit compilation code is expected to updates struct seccomp_filter.bpf_func pointer to the generated code. Signed-off-by: Nicolas Schichan --- arch/Kconfig| 14 ++ include/linux/seccomp.h | 39 +++ kernel/seccomp.c| 34 +- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 5a1779c..1284367 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -339,6 +339,10 @@ config HAVE_ARCH_SECCOMP_FILTER - secure_computing return value is checked and a return value of -1 results in the system call being skipped immediately. +# Used by archs to tell that they support SECCOMP_FILTER_JIT +config HAVE_SECCOMP_FILTER_JIT + bool + config SECCOMP_FILTER def_bool y depends on HAVE_ARCH_SECCOMP_FILTER && SECCOMP && NET @@ -349,6 +353,16 @@ config SECCOMP_FILTER See Documentation/prctl/seccomp_filter.txt for details. +config SECCOMP_FILTER_JIT + bool "enable Seccomp filter Just In Time compiler" + depends on HAVE_SECCOMP_FILTER_JIT && BPF_JIT && SECCOMP_FILTER + help + Seccomp syscall filtering capabilities are normally handled + by an interpreter. This option allows kernel to generate a native + code when filter is loaded in memory. This should speedup + syscall filtering. Note : Admin should enable this feature + changing /proc/sys/net/core/bpf_jit_enable + config HAVE_CONTEXT_TRACKING bool help diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index 6f19cfd..af27494 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -6,6 +6,7 @@ #ifdef CONFIG_SECCOMP #include +#include #include struct seccomp_filter; @@ -47,6 +48,44 @@ static inline int seccomp_mode(struct seccomp *s) return s->mode; } +/** + * 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. + * @prev: points to a previously installed, or inherited, filter + * @len: the number of instructions in the program + * @insns: the BPF program instructions to evaluate + * + * seccomp_filter objects are organized in a tree linked via the @prev + * pointer. For any task, it appears to be a singly-linked list starting + * with current->seccomp.filter, the most recently attached or inherited filter. + * However, multiple filters may share a @prev node, by way of fork(), which + * results in a unidirectional tree existing in memory. This is similar to + * how namespaces work. + * + * seccomp_filter objects should never be modified after being attached + * to a task_struct (other than @usage). + */ +struct seccomp_filter { + atomic_t usage; + struct seccomp_filter *prev; + unsigned short len; /* Instruction count */ + unsigned int (*bpf_func)(const struct sk_buff *skb, +const struct sock_filter *filter); + struct sock_filter insns[]; +}; + +#ifdef CONFIG_SECCOMP_FILTER_JIT +extern void seccomp_jit_compile(struct seccomp_filter *fp); +extern void seccomp_jit_free(struct seccomp_filter *fp); +#else +static inline void seccomp_jit_compile(struct seccomp_filter *fp) { } +static inline void seccomp_jit_free(struct seccomp_filter *fp) { } +#endif + #else /* CONFIG_SECCOMP */ #include diff --git a/kernel/seccomp.c b/kernel/seccomp.c index b7a1004..a1aadaa 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -30,34 +30,6 @@ #include #include -/** - * 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. - * @prev: points to a previously installed, or inherited, filter - * @len: the number of instructions in the program - * @insns: the BPF program instructions to evaluate - * - * seccomp_filter objects are organized in a tree linked via the @prev - * pointer. For any task, it appears to be a singly-linked list starting - * with current->seccomp.filter, the most recently attached or inherited filter. - * However, multiple filters may share a @prev node, by way of fork(), which - * results in a unidirectional tree existing in memory. This is
[PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
Architecture must select HAVE_SECCOMP_FILTER_JIT and implement seccomp_jit_compile() and seccomp_jit_free() if they intend to support jitted seccomp filters. struct seccomp_filter has been moved to linux/seccomp.h to make its content available to the jit compilation code. In a way similar to the net BPF, the jit compilation code is expected to updates struct seccomp_filter.bpf_func pointer to the generated code. Signed-off-by: Nicolas Schichan nschic...@freebox.fr --- arch/Kconfig| 14 ++ include/linux/seccomp.h | 39 +++ kernel/seccomp.c| 34 +- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 5a1779c..1284367 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -339,6 +339,10 @@ config HAVE_ARCH_SECCOMP_FILTER - secure_computing return value is checked and a return value of -1 results in the system call being skipped immediately. +# Used by archs to tell that they support SECCOMP_FILTER_JIT +config HAVE_SECCOMP_FILTER_JIT + bool + config SECCOMP_FILTER def_bool y depends on HAVE_ARCH_SECCOMP_FILTER SECCOMP NET @@ -349,6 +353,16 @@ config SECCOMP_FILTER See Documentation/prctl/seccomp_filter.txt for details. +config SECCOMP_FILTER_JIT + bool enable Seccomp filter Just In Time compiler + depends on HAVE_SECCOMP_FILTER_JIT BPF_JIT SECCOMP_FILTER + help + Seccomp syscall filtering capabilities are normally handled + by an interpreter. This option allows kernel to generate a native + code when filter is loaded in memory. This should speedup + syscall filtering. Note : Admin should enable this feature + changing /proc/sys/net/core/bpf_jit_enable + config HAVE_CONTEXT_TRACKING bool help diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index 6f19cfd..af27494 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -6,6 +6,7 @@ #ifdef CONFIG_SECCOMP #include linux/thread_info.h +#include linux/filter.h #include asm/seccomp.h struct seccomp_filter; @@ -47,6 +48,44 @@ static inline int seccomp_mode(struct seccomp *s) return s-mode; } +/** + * 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. + * @prev: points to a previously installed, or inherited, filter + * @len: the number of instructions in the program + * @insns: the BPF program instructions to evaluate + * + * seccomp_filter objects are organized in a tree linked via the @prev + * pointer. For any task, it appears to be a singly-linked list starting + * with current-seccomp.filter, the most recently attached or inherited filter. + * However, multiple filters may share a @prev node, by way of fork(), which + * results in a unidirectional tree existing in memory. This is similar to + * how namespaces work. + * + * seccomp_filter objects should never be modified after being attached + * to a task_struct (other than @usage). + */ +struct seccomp_filter { + atomic_t usage; + struct seccomp_filter *prev; + unsigned short len; /* Instruction count */ + unsigned int (*bpf_func)(const struct sk_buff *skb, +const struct sock_filter *filter); + struct sock_filter insns[]; +}; + +#ifdef CONFIG_SECCOMP_FILTER_JIT +extern void seccomp_jit_compile(struct seccomp_filter *fp); +extern void seccomp_jit_free(struct seccomp_filter *fp); +#else +static inline void seccomp_jit_compile(struct seccomp_filter *fp) { } +static inline void seccomp_jit_free(struct seccomp_filter *fp) { } +#endif + #else /* CONFIG_SECCOMP */ #include linux/errno.h diff --git a/kernel/seccomp.c b/kernel/seccomp.c index b7a1004..a1aadaa 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -30,34 +30,6 @@ #include linux/tracehook.h #include linux/uaccess.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. - * @prev: points to a previously installed, or inherited, filter - * @len: the number of instructions in the program - * @insns: the BPF program instructions to evaluate - * - * seccomp_filter objects are organized in a tree linked via the @prev - * pointer. For any task, it appears to be a singly-linked list starting - * with current-seccomp.filter, the most recently attached or inherited filter. - * However, multiple filters may
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On 03/15/2013 07:28 PM, Nicolas Schichan wrote: [Sorry, I forgot to put the mailing lists as the receivers of the introductory message] Hi, This patch serie adds support for jitted seccomp BPF filters, with the required modifications to make it work on the ARM architecture. - The first patch in the serie adds the required boiler plate in the core kernel seccomp code to invoke the JIT compilation/free code. - The second patch reworks the ARM BPF JIT code to make the generation process less dependent on struct sk_filter. - The last patch actually implements the ARM part in the BPF jit code. Some benchmarks, on a 1.6Ghz 88f6282 CPU: Each system call is tested in two way (fast/slow): - on the fast version, the tested system call is accepted immediately after checking the architecture (5 BPF instructions). - on the slow version, the tested system call is accepted after previously checking for 85 syscall (90 instructions, including the architecture check). The tested syscall is invoked in a loop 100 time, the reported time is the time spent in the loop in seconds. Without Seccomp JIT: Syscall Time-Fast Time-Slow --- -- -- gettimeofday0.389 1.633 getpid 0.406 1.688 getresuid 1.003 2.266 getcwd 1.342 2.128 With Seccomp JIT: Syscall Time-Fast Time-Slow --- --- - gettimeofday0.348 0.428 getpid 0.365 0.480 getresuid 0.981 1.060 getcwd 1.237 1.294 For reference, the same code without any seccomp filter: Syscall Time --- - gettimeofday0.119 getpid 0.137 getresuid 0.747 getcwd 1.021 The activation of the BPF JIT for seccomp is still controled with the /proc/sys/net/core/bpf_jit_enable sysctl knob. Those changes are based on the latest rmk-for-next branch. Regards, -- Nicolas Schichan Freebox SAS -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On Fri, Mar 15, 2013 at 11:28 AM, Nicolas Schichan nschic...@freebox.fr wrote: Architecture must select HAVE_SECCOMP_FILTER_JIT and implement seccomp_jit_compile() and seccomp_jit_free() if they intend to support jitted seccomp filters. struct seccomp_filter has been moved to linux/seccomp.h to make its content available to the jit compilation code. In a way similar to the net BPF, the jit compilation code is expected to updates struct seccomp_filter.bpf_func pointer to the generated code. Exciting. :) Thanks for working on this! Signed-off-by: Nicolas Schichan nschic...@freebox.fr --- arch/Kconfig| 14 ++ include/linux/seccomp.h | 39 +++ kernel/seccomp.c| 34 +- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 5a1779c..1284367 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -339,6 +339,10 @@ config HAVE_ARCH_SECCOMP_FILTER - secure_computing return value is checked and a return value of -1 results in the system call being skipped immediately. +# Used by archs to tell that they support SECCOMP_FILTER_JIT +config HAVE_SECCOMP_FILTER_JIT + bool + config SECCOMP_FILTER def_bool y depends on HAVE_ARCH_SECCOMP_FILTER SECCOMP NET @@ -349,6 +353,16 @@ config SECCOMP_FILTER See Documentation/prctl/seccomp_filter.txt for details. +config SECCOMP_FILTER_JIT + bool enable Seccomp filter Just In Time compiler + depends on HAVE_SECCOMP_FILTER_JIT BPF_JIT SECCOMP_FILTER + help + Seccomp syscall filtering capabilities are normally handled + by an interpreter. This option allows kernel to generate a native + code when filter is loaded in memory. This should speedup + syscall filtering. Note : Admin should enable this feature + changing /proc/sys/net/core/bpf_jit_enable + config HAVE_CONTEXT_TRACKING bool help diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index 6f19cfd..af27494 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -6,6 +6,7 @@ #ifdef CONFIG_SECCOMP #include linux/thread_info.h +#include linux/filter.h #include asm/seccomp.h struct seccomp_filter; @@ -47,6 +48,44 @@ static inline int seccomp_mode(struct seccomp *s) return s-mode; } +/** + * 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. + * @prev: points to a previously installed, or inherited, filter + * @len: the number of instructions in the program + * @insns: the BPF program instructions to evaluate This should be updated to include the new bpf_func field. Regardless, it'd be better to not expose this structure to userspace. + * + * seccomp_filter objects are organized in a tree linked via the @prev + * pointer. For any task, it appears to be a singly-linked list starting + * with current-seccomp.filter, the most recently attached or inherited filter. + * However, multiple filters may share a @prev node, by way of fork(), which + * results in a unidirectional tree existing in memory. This is similar to + * how namespaces work. + * + * seccomp_filter objects should never be modified after being attached + * to a task_struct (other than @usage). + */ +struct seccomp_filter { + atomic_t usage; + struct seccomp_filter *prev; + unsigned short len; /* Instruction count */ + unsigned int (*bpf_func)(const struct sk_buff *skb, +const struct sock_filter *filter); + struct sock_filter insns[]; +}; + +#ifdef CONFIG_SECCOMP_FILTER_JIT +extern void seccomp_jit_compile(struct seccomp_filter *fp); +extern void seccomp_jit_free(struct seccomp_filter *fp); +#else +static inline void seccomp_jit_compile(struct seccomp_filter *fp) { } +static inline void seccomp_jit_free(struct seccomp_filter *fp) { } +#endif + #else /* CONFIG_SECCOMP */ #include linux/errno.h diff --git a/kernel/seccomp.c b/kernel/seccomp.c index b7a1004..a1aadaa 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -30,34 +30,6 @@ #include linux/tracehook.h #include linux/uaccess.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. - * @prev: points to a previously installed, or inherited, filter - * @len: the
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On 03/15/2013 07:45 PM, Kees Cook wrote: On Fri, Mar 15, 2013 at 11:28 AM, Nicolas Schichan nschic...@freebox.fr wrote: +/** + * 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. + * @prev: points to a previously installed, or inherited, filter + * @len: the number of instructions in the program + * @insns: the BPF program instructions to evaluate This should be updated to include the new bpf_func field. Sure, I'll fix this in a re-spin of the patch serie. Regardless, it'd be better to not expose this structure to userspace. Yes, I did not realise that this header was exported to userspace. Do you know any place not exported to userspace where the structure definition would be appropriate ? @@ -213,7 +185,7 @@ static u32 seccomp_run_filters(int syscall) * value always takes priority (ignoring the DATA). */ for (f = current-seccomp.filter; f; f = f-prev) { - u32 cur_ret = sk_run_filter(NULL, f-insns); + u32 cur_ret = f-bpf_func(NULL, f-insns); This will make bpf_func a rather attractive target inside the kernel. I wonder if there could be ways to harden it against potential attack. I'm not sure I follow, but is it because any user can install a SECCOMP filter which will trigger JIT code generation with potential JIT spraying attack payload ? In that case, the same problem exists with struct sk_filter-bpf_func, as SO_ATTACH_FILTER, with BPT JIT enabled, does not require any particular privilege AFAICS. Regarding JIT spraying, I believe ARM is actually worse than x86 in that regard, since the values appearing in the literal pool can be quite easily controlled by an attacker. Thanks for the review. Regards, -- Nicolas Schichan Freebox SAS -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On Fri, Mar 15, 2013 at 12:10 PM, Nicolas Schichan nschic...@freebox.fr wrote: On 03/15/2013 07:45 PM, Kees Cook wrote: On Fri, Mar 15, 2013 at 11:28 AM, Nicolas Schichan nschic...@freebox.fr wrote: +/** + * 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. + * @prev: points to a previously installed, or inherited, filter + * @len: the number of instructions in the program + * @insns: the BPF program instructions to evaluate This should be updated to include the new bpf_func field. Sure, I'll fix this in a re-spin of the patch serie. Regardless, it'd be better to not expose this structure to userspace. Yes, I did not realise that this header was exported to userspace. Do you know any place not exported to userspace where the structure definition would be appropriate ? Nothing really jumps to mind. :( We should probably do the uapi split, so that this can stay here, but the public stuff is in the other file. I'm not actually sure what's needed to do that split, though. @@ -213,7 +185,7 @@ static u32 seccomp_run_filters(int syscall) * value always takes priority (ignoring the DATA). */ for (f = current-seccomp.filter; f; f = f-prev) { - u32 cur_ret = sk_run_filter(NULL, f-insns); + u32 cur_ret = f-bpf_func(NULL, f-insns); This will make bpf_func a rather attractive target inside the kernel. I wonder if there could be ways to harden it against potential attack. I'm not sure I follow, but is it because any user can install a SECCOMP filter which will trigger JIT code generation with potential JIT spraying attack payload ? I actually mean that when an arbitrary write vulnerability is used against the kernel, finding bpf_func may make a good target since it hangs off the process stack. There are plenty of targets, but just wonder if there would be some trivial way to handle this. Probably not. :) In that case, the same problem exists with struct sk_filter-bpf_func, as SO_ATTACH_FILTER, with BPT JIT enabled, does not require any particular privilege AFAICS. Yeah, these problems aren't unique to seccomp, unfortunately. Regarding JIT spraying, I believe ARM is actually worse than x86 in that regard, since the values appearing in the literal pool can be quite easily controlled by an attacker. Yeah, same for x86, really. Masking these would be nice, but is probably a separate discussion. Thanks for the review. Sure thing! I think Will Drewry may have more suggestions as well. -Kees -- Kees Cook Chrome OS Security -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On 03/15/2013 08:22 PM, Kees Cook wrote: On Fri, Mar 15, 2013 at 12:10 PM, Nicolas Schichan nschic...@freebox.fr wrote: On 03/15/2013 07:45 PM, Kees Cook wrote: Yes, I did not realise that this header was exported to userspace. Do you know any place not exported to userspace where the structure definition would be appropriate ? Nothing really jumps to mind. :( We should probably do the uapi split, so that this can stay here, but the public stuff is in the other file. I'm not actually sure what's needed to do that split, though. Would putting the structure definition in a linux/seccomp_priv.h file be acceptable ? Or is there some preprocessor macro that could prevent part of an include file ending up in uapi (similar to __KERNEL__ or __ASSEMBLY__). Regarding JIT spraying, I believe ARM is actually worse than x86 in that regard, since the values appearing in the literal pool can be quite easily controlled by an attacker. Yeah, same for x86, really. Masking these would be nice, but is probably a separate discussion. I meant that ARM makes it even easier in that you don't even have to interleave the evil immediate between instruction. The instruction sequence will appear verbatim in the litteral pool. For instance the following BPF code: struct sock_filter code[] = { { BPF_LD, 0, 0, 0xe3a01a02 }, { BPF_LD, 0, 0, 0xe2411001 }, { BPF_LD, 0, 0, 0xe00d1001 }, { BPF_LD, 0, 0, 0xe59111a0 }, { BPF_LD, 0, 0, 0xe3a02000 }, { BPF_LD, 0, 0, 0xe5812004 }, { BPF_LD, 0, 0, 0xe1a0f00e }, { BPF_RET, 0, 0, 0 }, }; Produces this ARM code: BPF JIT code: bf00: e92d0010 e3a04000 e59f4020 e59f4020 BPF JIT code: bf10: e59f4020 e59f4020 e59f4020 e59f4020 BPF JIT code: bf20: e59f4020 e3a0 e8bd0010 e12fff1e BPF JIT code: bf30: e3a01a02 e2411001 e00d1001 e59111a0 BPF JIT code: bf40: e3a02000 e5812004 e1a0f00e Parts of which disassembles to (only eye-tested): mov r1, #8192 sub r1, r1, #1 @ r1 = THREAD_SIZE - 1 and r1, sp, r1 @ get current. ldr r1, [r1, #416] @ get current-real_cred mov r2, #0 str r2, [r1, #4] @ store 0 in current-real_cread-uid. mov pc, lr Userland can insert code to change the uid of the current process quite easily in an executable page. The only remaining task is to trick the kernel into executing it :) Regards, -- Nicolas Schichan Freebox SAS -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RFC 1/3] seccomp: add generic code for jitted seccomp filters.
On Fri, 2013-03-15 at 11:45 -0700, Kees Cook wrote: On Fri, Mar 15, 2013 at 11:28 AM, Nicolas Schichan nschic...@freebox.fr wrote: diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index 6f19cfd..af27494 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -6,6 +6,7 @@ #ifdef CONFIG_SECCOMP #include linux/thread_info.h +#include linux/filter.h #include asm/seccomp.h struct seccomp_filter; @@ -47,6 +48,44 @@ static inline int seccomp_mode(struct seccomp *s) return s-mode; } +/** + * 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. + * @prev: points to a previously installed, or inherited, filter + * @len: the number of instructions in the program + * @insns: the BPF program instructions to evaluate This should be updated to include the new bpf_func field. Regardless, it'd be better to not expose this structure to userspace. This is fine include/uapi/linux/seccomp.h is exposed to userspace include/linux/seccomp.h is kernel internal -Eric -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/