Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1447449 > unrolled thread
| Started by | Kees Cook <keescook@chromium.org> |
|---|---|
| First post | 2016-07-20 22:40 +0200 |
| Last post | 2016-07-25 20:00 +0200 |
| Articles | 4 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v4 00/12] mm: Hardened usercopy Kees Cook <keescook@chromium.org> - 2016-07-20 22:40 +0200
[PATCH v4 04/12] x86/uaccess: Enable hardened usercopy Kees Cook <keescook@chromium.org> - 2016-07-20 22:40 +0200
Re: [PATCH v4 00/12] mm: Hardened usercopy Laura Abbott <labbott@redhat.com> - 2016-07-23 02:40 +0200
Re: [PATCH v4 00/12] mm: Hardened usercopy Kees Cook <keescook@chromium.org> - 2016-07-25 20:00 +0200
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2016-07-20 22:40 +0200 |
| Subject | [PATCH v4 00/12] mm: Hardened usercopy |
| Message-ID | <rX6hX-67R-3@gated-at.bofh.it> |
Hi,
[This is now in my kspp -next tree, though I'd really love to add some
additional explicit Tested-bys, Reviewed-bys, or Acked-bys. If you've
looked through any part of this or have done any testing, please consider
sending an email with your "*-by:" line. :)]
This is a start of the mainline port of PAX_USERCOPY[1]. After writing
tests (now in lkdtm in -next) for Casey's earlier port[2], I kept tweaking
things further and further until I ended up with a whole new patch series.
To that end, I took Rik, Laura, and other people's feedback along with
additional changes and clean-ups.
Based on my understanding, PAX_USERCOPY was designed to catch a
few classes of flaws (mainly bad bounds checking) around the use of
copy_to_user()/copy_from_user(). These changes don't touch get_user() and
put_user(), since these operate on constant sized lengths, and tend to be
much less vulnerable. There are effectively three distinct protections in
the whole series, each of which I've given a separate CONFIG, though this
patch set is only the first of the three intended protections. (Generally
speaking, PAX_USERCOPY covers what I'm calling CONFIG_HARDENED_USERCOPY
(this) and CONFIG_HARDENED_USERCOPY_WHITELIST (future), and
PAX_USERCOPY_SLABS covers CONFIG_HARDENED_USERCOPY_SPLIT_KMALLOC
(future).)
This series, which adds CONFIG_HARDENED_USERCOPY, checks that objects
being copied to/from userspace meet certain criteria:
- if address is a heap object, the size must not exceed the object's
allocated size. (This will catch all kinds of heap overflow flaws.)
- if address range is in the current process stack, it must be within the
a valid stack frame (if such checking is possible) or at least entirely
within the current process's stack. (This could catch large lengths that
would have extended beyond the current process stack, or overflows if
their length extends back into the original stack.)
- if the address range is part of kernel data, rodata, or bss, allow it.
- if address range is page-allocated, that it doesn't span multiple
allocations (excepting Reserved and CMA pages).
- if address is within the kernel text, reject it.
- everything else is accepted
The patches in the series are:
- Support for examination of CMA page types:
1- mm: Add is_migrate_cma_page
- Support for arch-specific stack frame checking (which will likely be
replaced in the future by Josh's more comprehensive unwinder):
2- mm: Implement stack frame object validation
- The core copy_to/from_user() checks, without the slab object checks:
3- mm: Hardened usercopy
- Per-arch enablement of the protection:
4- x86/uaccess: Enable hardened usercopy
5- ARM: uaccess: Enable hardened usercopy
6- arm64/uaccess: Enable hardened usercopy
7- ia64/uaccess: Enable hardened usercopy
8- powerpc/uaccess: Enable hardened usercopy
9- sparc/uaccess: Enable hardened usercopy
10- s390/uaccess: Enable hardened usercopy
- The heap allocator implementation of object size checking:
11- mm: SLAB hardened usercopy support
12- mm: SLUB hardened usercopy support
Some notes:
- This is expected to apply on top of -next which contains fixes for the
position of _etext on both arm and arm64, though it has some conflicts
with KASAN that should be trivial to fix up. Also in -next are the
tests for this protection (in lkdtm), prefixed with USERCOPY_.
- I couldn't detect a measurable performance change with these features
enabled. Kernel build times were unchanged, hackbench was unchanged,
etc. I think we could flip this to "on by default" at some point, but
for now, I'm leaving it off until I can get some more definitive
measurements. I would love if someone with greater familiarity with
perf could give this a spin and report results.
- The SLOB support extracted from grsecurity seems entirely broken. I
have no idea what's going on there, I spent my time testing SLAB and
SLUB. Having someone else look at SLOB would be nice, but this series
doesn't depend on it.
Additional features that would be nice, but aren't blocking this series:
- Needs more architecture support for stack frame checking (only x86 now,
but it seems Josh will have a good solution for this soon).
Thanks!
-Kees
[1] https://grsecurity.net/download.php "grsecurity - test kernel patch"
[2] http://www.openwall.com/lists/kernel-hardening/2016/05/19/5
v4:
- handle CMA pages, labbott
- update stack checker comments, labbott
- check for vmalloc addresses, labbott
- deal with KASAN in -next changing arm64 copy*user calls
- check for linear mappings at runtime instead of via CONFIG
v3:
- switch to using BUG for better Oops integration
- when checking page allocations, check each for Reserved
- use enums for the stack check return for readability
v2:
- added s390 support
- handle slub red zone
- disallow writes to rodata area
- stack frame walker now CONFIG-controlled arch-specific helper
[toc] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2016-07-20 22:40 +0200 |
| Subject | [PATCH v4 04/12] x86/uaccess: Enable hardened usercopy |
| Message-ID | <rX6rD-6b4-23@gated-at.bofh.it> |
| In reply to | #1447449 |
Enables CONFIG_HARDENED_USERCOPY checks on x86. This is done both in
copy_*_user() and __copy_*_user() because copy_*_user() actually calls
down to _copy_*_user() and not __copy_*_user().
Based on code from PaX and grsecurity.
Signed-off-by: Kees Cook <keescook@chromium.org>
Tested-by: Valdis Kletnieks <valdis.kletnieks@vt.edu>
---
arch/x86/Kconfig | 1 +
arch/x86/include/asm/uaccess.h | 10 ++++++----
arch/x86/include/asm/uaccess_32.h | 2 ++
arch/x86/include/asm/uaccess_64.h | 2 ++
4 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 4407f596b72c..762a0349633c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -80,6 +80,7 @@ config X86
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_AOUT if X86_32
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_ARCH_HARDENED_USERCOPY
select HAVE_ARCH_HUGE_VMAP if X86_64 || X86_PAE
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_KASAN if X86_64 && SPARSEMEM_VMEMMAP
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 2982387ba817..d3312f0fcdfc 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -742,9 +742,10 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
* case, and do only runtime checking for non-constant sizes.
*/
- if (likely(sz < 0 || sz >= n))
+ if (likely(sz < 0 || sz >= n)) {
+ check_object_size(to, n, false);
n = _copy_from_user(to, from, n);
- else if(__builtin_constant_p(n))
+ } else if (__builtin_constant_p(n))
copy_from_user_overflow();
else
__copy_from_user_overflow(sz, n);
@@ -762,9 +763,10 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
might_fault();
/* See the comment in copy_from_user() above. */
- if (likely(sz < 0 || sz >= n))
+ if (likely(sz < 0 || sz >= n)) {
+ check_object_size(from, n, true);
n = _copy_to_user(to, from, n);
- else if(__builtin_constant_p(n))
+ } else if (__builtin_constant_p(n))
copy_to_user_overflow();
else
__copy_to_user_overflow(sz, n);
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 4b32da24faaf..7d3bdd1ed697 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -37,6 +37,7 @@ unsigned long __must_check __copy_from_user_ll_nocache_nozero
static __always_inline unsigned long __must_check
__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
{
+ check_object_size(from, n, true);
return __copy_to_user_ll(to, from, n);
}
@@ -95,6 +96,7 @@ static __always_inline unsigned long
__copy_from_user(void *to, const void __user *from, unsigned long n)
{
might_fault();
+ check_object_size(to, n, false);
if (__builtin_constant_p(n)) {
unsigned long ret;
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 2eac2aa3e37f..673059a109fe 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -54,6 +54,7 @@ int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size)
{
int ret = 0;
+ check_object_size(dst, size, false);
if (!__builtin_constant_p(size))
return copy_user_generic(dst, (__force void *)src, size);
switch (size) {
@@ -119,6 +120,7 @@ int __copy_to_user_nocheck(void __user *dst, const void *src, unsigned size)
{
int ret = 0;
+ check_object_size(src, size, true);
if (!__builtin_constant_p(size))
return copy_user_generic((__force void *)dst, src, size);
switch (size) {
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Laura Abbott <labbott@redhat.com> |
|---|---|
| Date | 2016-07-23 02:40 +0200 |
| Message-ID | <rXT8Z-4s0-5@gated-at.bofh.it> |
| In reply to | #1447449 |
On 07/20/2016 01:26 PM, Kees Cook wrote: > Hi, > > [This is now in my kspp -next tree, though I'd really love to add some > additional explicit Tested-bys, Reviewed-bys, or Acked-bys. If you've > looked through any part of this or have done any testing, please consider > sending an email with your "*-by:" line. :)] > > This is a start of the mainline port of PAX_USERCOPY[1]. After writing > tests (now in lkdtm in -next) for Casey's earlier port[2], I kept tweaking > things further and further until I ended up with a whole new patch series. > To that end, I took Rik, Laura, and other people's feedback along with > additional changes and clean-ups. > > Based on my understanding, PAX_USERCOPY was designed to catch a > few classes of flaws (mainly bad bounds checking) around the use of > copy_to_user()/copy_from_user(). These changes don't touch get_user() and > put_user(), since these operate on constant sized lengths, and tend to be > much less vulnerable. There are effectively three distinct protections in > the whole series, each of which I've given a separate CONFIG, though this > patch set is only the first of the three intended protections. (Generally > speaking, PAX_USERCOPY covers what I'm calling CONFIG_HARDENED_USERCOPY > (this) and CONFIG_HARDENED_USERCOPY_WHITELIST (future), and > PAX_USERCOPY_SLABS covers CONFIG_HARDENED_USERCOPY_SPLIT_KMALLOC > (future).) > > This series, which adds CONFIG_HARDENED_USERCOPY, checks that objects > being copied to/from userspace meet certain criteria: > - if address is a heap object, the size must not exceed the object's > allocated size. (This will catch all kinds of heap overflow flaws.) > - if address range is in the current process stack, it must be within the > a valid stack frame (if such checking is possible) or at least entirely > within the current process's stack. (This could catch large lengths that > would have extended beyond the current process stack, or overflows if > their length extends back into the original stack.) > - if the address range is part of kernel data, rodata, or bss, allow it. > - if address range is page-allocated, that it doesn't span multiple > allocations (excepting Reserved and CMA pages). > - if address is within the kernel text, reject it. > - everything else is accepted > > The patches in the series are: > - Support for examination of CMA page types: > 1- mm: Add is_migrate_cma_page > - Support for arch-specific stack frame checking (which will likely be > replaced in the future by Josh's more comprehensive unwinder): > 2- mm: Implement stack frame object validation > - The core copy_to/from_user() checks, without the slab object checks: > 3- mm: Hardened usercopy > - Per-arch enablement of the protection: > 4- x86/uaccess: Enable hardened usercopy > 5- ARM: uaccess: Enable hardened usercopy > 6- arm64/uaccess: Enable hardened usercopy > 7- ia64/uaccess: Enable hardened usercopy > 8- powerpc/uaccess: Enable hardened usercopy > 9- sparc/uaccess: Enable hardened usercopy > 10- s390/uaccess: Enable hardened usercopy > - The heap allocator implementation of object size checking: > 11- mm: SLAB hardened usercopy support > 12- mm: SLUB hardened usercopy support > > Some notes: > > - This is expected to apply on top of -next which contains fixes for the > position of _etext on both arm and arm64, though it has some conflicts > with KASAN that should be trivial to fix up. Also in -next are the > tests for this protection (in lkdtm), prefixed with USERCOPY_. > > - I couldn't detect a measurable performance change with these features > enabled. Kernel build times were unchanged, hackbench was unchanged, > etc. I think we could flip this to "on by default" at some point, but > for now, I'm leaving it off until I can get some more definitive > measurements. I would love if someone with greater familiarity with > perf could give this a spin and report results. > > - The SLOB support extracted from grsecurity seems entirely broken. I > have no idea what's going on there, I spent my time testing SLAB and > SLUB. Having someone else look at SLOB would be nice, but this series > doesn't depend on it. > > Additional features that would be nice, but aren't blocking this series: > > - Needs more architecture support for stack frame checking (only x86 now, > but it seems Josh will have a good solution for this soon). > > > Thanks! > > -Kees > > [1] https://grsecurity.net/download.php "grsecurity - test kernel patch" > [2] http://www.openwall.com/lists/kernel-hardening/2016/05/19/5 > > v4: > - handle CMA pages, labbott > - update stack checker comments, labbott > - check for vmalloc addresses, labbott > - deal with KASAN in -next changing arm64 copy*user calls > - check for linear mappings at runtime instead of via CONFIG > > v3: > - switch to using BUG for better Oops integration > - when checking page allocations, check each for Reserved > - use enums for the stack check return for readability > > v2: > - added s390 support > - handle slub red zone > - disallow writes to rodata area > - stack frame walker now CONFIG-controlled arch-specific helper > Do you have/plan to have LKDTM or the like tests for this? I started reviewing the slub code and was about to write some test cases for myself. I did that for CMA as well which is a decent indicator these should all go somewhere. Thanks, Laura
[toc] | [prev] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2016-07-25 20:00 +0200 |
| Message-ID | <rYSkx-7wc-13@gated-at.bofh.it> |
| In reply to | #1448853 |
On Fri, Jul 22, 2016 at 5:36 PM, Laura Abbott <labbott@redhat.com> wrote: > On 07/20/2016 01:26 PM, Kees Cook wrote: >> >> Hi, >> >> [This is now in my kspp -next tree, though I'd really love to add some >> additional explicit Tested-bys, Reviewed-bys, or Acked-bys. If you've >> looked through any part of this or have done any testing, please consider >> sending an email with your "*-by:" line. :)] >> >> This is a start of the mainline port of PAX_USERCOPY[1]. After writing >> tests (now in lkdtm in -next) for Casey's earlier port[2], I kept tweaking >> things further and further until I ended up with a whole new patch series. >> To that end, I took Rik, Laura, and other people's feedback along with >> additional changes and clean-ups. >> >> Based on my understanding, PAX_USERCOPY was designed to catch a >> few classes of flaws (mainly bad bounds checking) around the use of >> copy_to_user()/copy_from_user(). These changes don't touch get_user() and >> put_user(), since these operate on constant sized lengths, and tend to be >> much less vulnerable. There are effectively three distinct protections in >> the whole series, each of which I've given a separate CONFIG, though this >> patch set is only the first of the three intended protections. (Generally >> speaking, PAX_USERCOPY covers what I'm calling CONFIG_HARDENED_USERCOPY >> (this) and CONFIG_HARDENED_USERCOPY_WHITELIST (future), and >> PAX_USERCOPY_SLABS covers CONFIG_HARDENED_USERCOPY_SPLIT_KMALLOC >> (future).) >> >> This series, which adds CONFIG_HARDENED_USERCOPY, checks that objects >> being copied to/from userspace meet certain criteria: >> - if address is a heap object, the size must not exceed the object's >> allocated size. (This will catch all kinds of heap overflow flaws.) >> - if address range is in the current process stack, it must be within the >> a valid stack frame (if such checking is possible) or at least entirely >> within the current process's stack. (This could catch large lengths that >> would have extended beyond the current process stack, or overflows if >> their length extends back into the original stack.) >> - if the address range is part of kernel data, rodata, or bss, allow it. >> - if address range is page-allocated, that it doesn't span multiple >> allocations (excepting Reserved and CMA pages). >> - if address is within the kernel text, reject it. >> - everything else is accepted >> >> The patches in the series are: >> - Support for examination of CMA page types: >> 1- mm: Add is_migrate_cma_page >> - Support for arch-specific stack frame checking (which will likely be >> replaced in the future by Josh's more comprehensive unwinder): >> 2- mm: Implement stack frame object validation >> - The core copy_to/from_user() checks, without the slab object checks: >> 3- mm: Hardened usercopy >> - Per-arch enablement of the protection: >> 4- x86/uaccess: Enable hardened usercopy >> 5- ARM: uaccess: Enable hardened usercopy >> 6- arm64/uaccess: Enable hardened usercopy >> 7- ia64/uaccess: Enable hardened usercopy >> 8- powerpc/uaccess: Enable hardened usercopy >> 9- sparc/uaccess: Enable hardened usercopy >> 10- s390/uaccess: Enable hardened usercopy >> - The heap allocator implementation of object size checking: >> 11- mm: SLAB hardened usercopy support >> 12- mm: SLUB hardened usercopy support >> >> Some notes: >> >> - This is expected to apply on top of -next which contains fixes for the >> position of _etext on both arm and arm64, though it has some conflicts >> with KASAN that should be trivial to fix up. Also in -next are the >> tests for this protection (in lkdtm), prefixed with USERCOPY_. >> >> - I couldn't detect a measurable performance change with these features >> enabled. Kernel build times were unchanged, hackbench was unchanged, >> etc. I think we could flip this to "on by default" at some point, but >> for now, I'm leaving it off until I can get some more definitive >> measurements. I would love if someone with greater familiarity with >> perf could give this a spin and report results. >> >> - The SLOB support extracted from grsecurity seems entirely broken. I >> have no idea what's going on there, I spent my time testing SLAB and >> SLUB. Having someone else look at SLOB would be nice, but this series >> doesn't depend on it. >> >> Additional features that would be nice, but aren't blocking this series: >> >> - Needs more architecture support for stack frame checking (only x86 now, >> but it seems Josh will have a good solution for this soon). >> >> >> Thanks! >> >> -Kees >> >> [1] https://grsecurity.net/download.php "grsecurity - test kernel patch" >> [2] http://www.openwall.com/lists/kernel-hardening/2016/05/19/5 >> >> v4: >> - handle CMA pages, labbott >> - update stack checker comments, labbott >> - check for vmalloc addresses, labbott >> - deal with KASAN in -next changing arm64 copy*user calls >> - check for linear mappings at runtime instead of via CONFIG >> >> v3: >> - switch to using BUG for better Oops integration >> - when checking page allocations, check each for Reserved >> - use enums for the stack check return for readability >> >> v2: >> - added s390 support >> - handle slub red zone >> - disallow writes to rodata area >> - stack frame walker now CONFIG-controlled arch-specific helper >> > > Do you have/plan to have LKDTM or the like tests for this? I started > reviewing > the slub code and was about to write some test cases for myself. I did that > for CMA as well which is a decent indicator these should all go somewhere. Yeah, there is an entire section of tests in lkdtm for the usercopy protection. I didn't add anything for CMA or multipage allocations yet, though. Feel free to add those if you have a moment! :) It's on my todo list. -Kees -- Kees Cook Chrome OS & Brillo Security
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web