* [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect @ 2012-08-14 19:11 Ard Biesheuvel 2012-08-20 18:00 ` Kees Cook 0 siblings, 1 reply; 23+ messages in thread From: Ard Biesheuvel @ 2012-08-14 19:11 UTC (permalink / raw) This patch adds support for the PROT_FINAL flag to the mmap() and mprotect() syscalls. The PROT_FINAL flag indicates that the requested set of protection bits should be final, i.e., it shall not be allowed for a subsequent mprotect call to set protection bits that were not set already. This is mainly intended for the dynamic linker, which sets up the address space on behalf of dynamic binaries. By using this flag, it can prevent exploited code from remapping read-only executable code or data sections read-write. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@gmail.com> --- arch/powerpc/include/asm/mman.h | 3 ++- include/asm-generic/mman-common.h | 1 + include/linux/mman.h | 3 ++- mm/mmap.c | 9 +++++++++ mm/mprotect.c | 8 ++++++++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/include/asm/mman.h b/arch/powerpc/include/asm/mman.h index d4a7f64..c0014eb 100644 --- a/arch/powerpc/include/asm/mman.h +++ b/arch/powerpc/include/asm/mman.h @@ -52,7 +52,8 @@ static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags) static inline int arch_validate_prot(unsigned long prot) { - if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_SAO)) + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM + | PROT_SAO | PROT_FINAL)) return 0; if ((prot & PROT_SAO) && !cpu_has_feature(CPU_FTR_SAO)) return 0; diff --git a/include/asm-generic/mman-common.h b/include/asm-generic/mman-common.h index d030d2c..5687993 100644 --- a/include/asm-generic/mman-common.h +++ b/include/asm-generic/mman-common.h @@ -10,6 +10,7 @@ #define PROT_WRITE 0x2 /* page can be written */ #define PROT_EXEC 0x4 /* page can be executed */ #define PROT_SEM 0x8 /* page may be used for atomic ops */ +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ #define PROT_NONE 0x0 /* page can not be accessed */ #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ diff --git a/include/linux/mman.h b/include/linux/mman.h index 8b74e9b..c11b1ab 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -51,7 +51,8 @@ static inline void vm_unacct_memory(long pages) */ static inline int arch_validate_prot(unsigned long prot) { - return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) == 0; + return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC + | PROT_SEM | PROT_FINAL)) == 0; } #define arch_validate_prot arch_validate_prot #endif diff --git a/mm/mmap.c b/mm/mmap.c index e3e8691..a043fa9 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1101,6 +1101,15 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, } } + /* + * PROT_FINAL indicates that prot bits not requested by this + * mmap() call cannot be added later + */ + if (prot & PROT_FINAL) + vm_flags &= ~(VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + | (vm_flags << 4); + + return mmap_region(file, addr, len, flags, vm_flags, pgoff); } diff --git a/mm/mprotect.c b/mm/mprotect.c index a409926..7a39f73 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -301,6 +301,14 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len, goto out; } + /* + * PROT_FINAL indicates that prot bits removed by this + * mprotect() call cannot be added later + */ + if (prot & PROT_FINAL) + newflags &= ~(VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + | (newflags << 4); + error = security_file_mprotect(vma, reqprot, prot); if (error) goto out; -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-08-14 19:11 [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect Ard Biesheuvel @ 2012-08-20 18:00 ` Kees Cook 2012-08-20 21:48 ` Ard Biesheuvel 0 siblings, 1 reply; 23+ messages in thread From: Kees Cook @ 2012-08-20 18:00 UTC (permalink / raw) To: Ard Biesheuvel; +Cc: linux-kernel Hi, On Tue, Aug 14, 2012 at 09:11:11PM +0200, Ard Biesheuvel wrote: > This patch adds support for the PROT_FINAL flag to > the mmap() and mprotect() syscalls. > > The PROT_FINAL flag indicates that the requested set > of protection bits should be final, i.e., it shall > not be allowed for a subsequent mprotect call to > set protection bits that were not set already. > > This is mainly intended for the dynamic linker, > which sets up the address space on behalf of > dynamic binaries. By using this flag, it can > prevent exploited code from remapping read-only > executable code or data sections read-write. > > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@gmail.com> Reviewed-by: Kees Cook <keescook@chromium.org> This seems like a good idea to me. It would allow more than just the loader to harden userspace allocations. It's a more direct version of PaX's "MPROTECT" feature[1]. That feature hardens existing loaders, but doesn't play nice with JITs (like Java), but this lets a loader (or JIT) opt-in to the protection and have some direct control over it. It seems like there needs to be a sensible way to detect that this flag is available, though. -Kees [1] http://pax.grsecurity.net/docs/mprotect.txt -- Kees Cook @outflux.net ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-08-20 18:00 ` Kees Cook @ 2012-08-20 21:48 ` Ard Biesheuvel 2012-10-02 20:34 ` Kees Cook 0 siblings, 1 reply; 23+ messages in thread From: Ard Biesheuvel @ 2012-08-20 21:48 UTC (permalink / raw) To: Kees Cook; +Cc: linux-kernel > This seems like a good idea to me. It would allow more than just the > loader to harden userspace allocations. It's a more direct version of > PaX's "MPROTECT" feature[1]. That feature hardens existing loaders, > but doesn't play nice with JITs (like Java), but this lets a loader > (or JIT) opt-in to the protection and have some direct control over it. > If desired, additional restrictions can be imposed by using the security framework, e.g,, disallow non-final r-x mappings. > It seems like there needs to be a sensible way to detect that this flag is > available, though. > I am open for suggestions to address this. Our particular implementation of the loader (on an embedded system) tries to set it on the first mmap invocation, and stops trying if it fails. Not the most elegant approach, I know ... -- Ard. > -Kees > > [1] http://pax.grsecurity.net/docs/mprotect.txt > > -- > Kees Cook @outflux.net ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-08-20 21:48 ` Ard Biesheuvel @ 2012-10-02 20:34 ` Kees Cook 2012-10-02 21:41 ` Ard Biesheuvel 0 siblings, 1 reply; 23+ messages in thread From: Kees Cook @ 2012-10-02 20:34 UTC (permalink / raw) To: Ard Biesheuvel; +Cc: linux-kernel Hi, On Mon, Aug 20, 2012 at 2:48 PM, Ard Biesheuvel <ard.biesheuvel@gmail.com> wrote: >> This seems like a good idea to me. It would allow more than just the >> loader to harden userspace allocations. It's a more direct version of >> PaX's "MPROTECT" feature[1]. That feature hardens existing loaders, >> but doesn't play nice with JITs (like Java), but this lets a loader >> (or JIT) opt-in to the protection and have some direct control over it. > > If desired, additional restrictions can be imposed by using the > security framework, e.g,, disallow non-final r-x mappings. Interesting; what kind of interface did you have in mind? >> It seems like there needs to be a sensible way to detect that this flag is >> available, though. > > I am open for suggestions to address this. Our particular > implementation of the loader (on an embedded system) tries to set it > on the first mmap invocation, and stops trying if it fails. Not the > most elegant approach, I know ... Actually, that seems easiest. Has there been any more progress on this patch over-all? -Kees -- Kees Cook Chrome OS Security ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-02 20:34 ` Kees Cook @ 2012-10-02 21:41 ` Ard Biesheuvel 2012-10-02 22:10 ` Kees Cook 0 siblings, 1 reply; 23+ messages in thread From: Ard Biesheuvel @ 2012-10-02 21:41 UTC (permalink / raw) To: Kees Cook; +Cc: linux-kernel 2012/10/2 Kees Cook <keescook@chromium.org>: >> If desired, additional restrictions can be imposed by using the >> security framework, e.g,, disallow non-final r-x mappings. > > Interesting; what kind of interface did you have in mind? > The 'interface' we use is a LSM .ko which registers handlers for mmap() and mprotect() that fail the respective invocations if the passed arguments do not adhere to the policy. >>> It seems like there needs to be a sensible way to detect that this flag is >>> available, though. >> >> I am open for suggestions to address this. Our particular >> implementation of the loader (on an embedded system) tries to set it >> on the first mmap invocation, and stops trying if it fails. Not the >> most elegant approach, I know ... > > Actually, that seems easiest. > > Has there been any more progress on this patch over-all? > No progress. -- Ard. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-02 21:41 ` Ard Biesheuvel @ 2012-10-02 22:10 ` Kees Cook 2012-10-02 22:38 ` Andrew Morton 0 siblings, 1 reply; 23+ messages in thread From: Kees Cook @ 2012-10-02 22:10 UTC (permalink / raw) To: Ard Biesheuvel Cc: linux-kernel, Al Viro, Andrew Morton, Ingo Molnar, Srikar Dronamraju, KOSAKI Motohiro, James Morris, Konstantin Khlebnikov, linux-mm On Tue, Oct 2, 2012 at 2:41 PM, Ard Biesheuvel <ard.biesheuvel@gmail.com> wrote: > 2012/10/2 Kees Cook <keescook@chromium.org>: >>> If desired, additional restrictions can be imposed by using the >>> security framework, e.g,, disallow non-final r-x mappings. >> >> Interesting; what kind of interface did you have in mind? > > The 'interface' we use is a LSM .ko which registers handlers for > mmap() and mprotect() that fail the respective invocations if the > passed arguments do not adhere to the policy. Seems reasonable. >>>> It seems like there needs to be a sensible way to detect that this flag is >>>> available, though. >>> >>> I am open for suggestions to address this. Our particular >>> implementation of the loader (on an embedded system) tries to set it >>> on the first mmap invocation, and stops trying if it fails. Not the >>> most elegant approach, I know ... >> >> Actually, that seems easiest. >> >> Has there been any more progress on this patch over-all? > > No progress. Al, Andrew, anyone? Thoughts on this? (First email is https://lkml.org/lkml/2012/8/14/448) -Kees -- Kees Cook Chrome OS Security ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-02 22:10 ` Kees Cook @ 2012-10-02 22:38 ` Andrew Morton 2012-10-03 0:43 ` Hugh Dickins 0 siblings, 1 reply; 23+ messages in thread From: Andrew Morton @ 2012-10-02 22:38 UTC (permalink / raw) To: Kees Cook Cc: Ard Biesheuvel, linux-kernel, Al Viro, Ingo Molnar, Srikar Dronamraju, KOSAKI Motohiro, James Morris, Konstantin Khlebnikov, linux-mm On Tue, 2 Oct 2012 15:10:56 -0700 Kees Cook <keescook@chromium.org> wrote: > >> Has there been any more progress on this patch over-all? > > > > No progress. > > Al, Andrew, anyone? Thoughts on this? > (First email is https://lkml.org/lkml/2012/8/14/448) Wasn't cc'ed, missed it. The patch looks straightforward enough. Have the maintainers of the runtime linker (I guess that's glibc) provided any feedback on the proposal? ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-02 22:38 ` Andrew Morton @ 2012-10-03 0:43 ` Hugh Dickins 2012-10-03 14:43 ` Updated: " Ard Biesheuvel 0 siblings, 1 reply; 23+ messages in thread From: Hugh Dickins @ 2012-10-03 0:43 UTC (permalink / raw) To: Andrew Morton Cc: Kees Cook, Ard Biesheuvel, linux-kernel, Al Viro, Ingo Molnar, Srikar Dronamraju, KOSAKI Motohiro, James Morris, Konstantin Khlebnikov, linux-mm On Tue, 2 Oct 2012, Andrew Morton wrote: > On Tue, 2 Oct 2012 15:10:56 -0700 > Kees Cook <keescook@chromium.org> wrote: > > > >> Has there been any more progress on this patch over-all? > > > > > > No progress. > > > > Al, Andrew, anyone? Thoughts on this? > > (First email is https://lkml.org/lkml/2012/8/14/448) > > Wasn't cc'ed, missed it. > > The patch looks straightforward enough. Have the maintainers of the > runtime linker (I guess that's glibc) provided any feedback on the > proposal? It looks reasonable to me too. I checked through VM_MAYflag handling and don't expect surprises (a few places already turn off VM_MAYWRITE in much the same way that this does, I hadn't realized). I'm disappointed to find that our mmap() is lax about checking its PROT and MAP args, so old kernels will accept PROT_FINAL but do nothing with it. Luckily mprotect() is stricter, so that can be used to check for whether it's supported. The patch does need to be slightly extended though: alpha, mips, parisc and xtensa have their own include/asm/mman.h, which does not include asm-generic/mman-common.h at all. Hugh ^ permalink raw reply [flat|nested] 23+ messages in thread
* Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 0:43 ` Hugh Dickins @ 2012-10-03 14:43 ` Ard Biesheuvel 2012-10-03 16:25 ` Kees Cook ` (3 more replies) 0 siblings, 4 replies; 23+ messages in thread From: Ard Biesheuvel @ 2012-10-03 14:43 UTC (permalink / raw) To: Hugh Dickins; +Cc: Andrew Morton, Kees Cook, linux-kernel This patch adds support for the PROT_FINAL flag to the mmap() and mprotect() syscalls. The PROT_FINAL flag indicates that the requested set of protection bits should be final, i.e., it shall not be allowed for a subsequent mprotect call to set protection bits that were not set already. This is mainly intended for the dynamic linker, which sets up the address space on behalf of dynamic binaries. By using this flag, it can prevent exploited code from remapping read-only executable code or data sections read-write. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@gmail.com> --- arch/alpha/include/asm/mman.h | 1 + arch/mips/include/asm/mman.h | 1 + arch/parisc/include/asm/mman.h | 1 + arch/powerpc/include/asm/mman.h | 3 ++- arch/xtensa/include/asm/mman.h | 1 + include/asm-generic/mman-common.h | 1 + include/linux/mman.h | 3 ++- mm/mmap.c | 8 ++++++++ mm/mprotect.c | 8 ++++++++ 9 files changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/alpha/include/asm/mman.h b/arch/alpha/include/asm/mman.h index cbeb361..ab46252 100644 --- a/arch/alpha/include/asm/mman.h +++ b/arch/alpha/include/asm/mman.h @@ -6,6 +6,7 @@ #define PROT_EXEC 0x4 /* page can be executed */ #define PROT_SEM 0x8 /* page may be used for atomic ops */ #define PROT_NONE 0x0 /* page can not be accessed */ +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ diff --git a/arch/mips/include/asm/mman.h b/arch/mips/include/asm/mman.h index 46d3da0..9cd50e4 100644 --- a/arch/mips/include/asm/mman.h +++ b/arch/mips/include/asm/mman.h @@ -20,6 +20,7 @@ #define PROT_EXEC 0x04 /* page can be executed */ /* 0x08 reserved for PROT_EXEC_NOFLUSH */ #define PROT_SEM 0x10 /* page may be used for atomic ops */ +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ diff --git a/arch/parisc/include/asm/mman.h b/arch/parisc/include/asm/mman.h index 12219eb..0cf18e3 100644 --- a/arch/parisc/include/asm/mman.h +++ b/arch/parisc/include/asm/mman.h @@ -6,6 +6,7 @@ #define PROT_EXEC 0x4 /* page can be executed */ #define PROT_SEM 0x8 /* page may be used for atomic ops */ #define PROT_NONE 0x0 /* page can not be accessed */ +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ diff --git a/arch/powerpc/include/asm/mman.h b/arch/powerpc/include/asm/mman.h index d4a7f64..c0014eb 100644 --- a/arch/powerpc/include/asm/mman.h +++ b/arch/powerpc/include/asm/mman.h @@ -52,7 +52,8 @@ static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags) static inline int arch_validate_prot(unsigned long prot) { - if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_SAO)) + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM + | PROT_SAO | PROT_FINAL)) return 0; if ((prot & PROT_SAO) && !cpu_has_feature(CPU_FTR_SAO)) return 0; diff --git a/arch/xtensa/include/asm/mman.h b/arch/xtensa/include/asm/mman.h index 25bc6c1..680b3c4 100644 --- a/arch/xtensa/include/asm/mman.h +++ b/arch/xtensa/include/asm/mman.h @@ -27,6 +27,7 @@ #define PROT_EXEC 0x4 /* page can be executed */ #define PROT_SEM 0x10 /* page may be used for atomic ops */ +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end fo growsup vma */ diff --git a/include/asm-generic/mman-common.h b/include/asm-generic/mman-common.h index d030d2c..5687993 100644 --- a/include/asm-generic/mman-common.h +++ b/include/asm-generic/mman-common.h @@ -10,6 +10,7 @@ #define PROT_WRITE 0x2 /* page can be written */ #define PROT_EXEC 0x4 /* page can be executed */ #define PROT_SEM 0x8 /* page may be used for atomic ops */ +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ #define PROT_NONE 0x0 /* page can not be accessed */ #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ diff --git a/include/linux/mman.h b/include/linux/mman.h index 8b74e9b..c11b1ab 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -51,7 +51,8 @@ static inline void vm_unacct_memory(long pages) */ static inline int arch_validate_prot(unsigned long prot) { - return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) == 0; + return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC + | PROT_SEM | PROT_FINAL)) == 0; } #define arch_validate_prot arch_validate_prot #endif diff --git a/mm/mmap.c b/mm/mmap.c index 872441e..292f988 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1101,6 +1101,14 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, } } + /* + * PROT_FINAL indicates that prot bits not requested by this + * mmap() call cannot be added later + */ + if (prot & PROT_FINAL) + vm_flags &= ~(VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + | (vm_flags << 4); + return mmap_region(file, addr, len, flags, vm_flags, pgoff); } diff --git a/mm/mprotect.c b/mm/mprotect.c index a409926..7a39f73 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -301,6 +301,14 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len, goto out; } + /* + * PROT_FINAL indicates that prot bits removed by this + * mprotect() call cannot be added later + */ + if (prot & PROT_FINAL) + newflags &= ~(VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + | (newflags << 4); + error = security_file_mprotect(vma, reqprot, prot); if (error) goto out; -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 14:43 ` Updated: " Ard Biesheuvel @ 2012-10-03 16:25 ` Kees Cook 2012-10-03 19:44 ` Hugh Dickins ` (2 subsequent siblings) 3 siblings, 0 replies; 23+ messages in thread From: Kees Cook @ 2012-10-03 16:25 UTC (permalink / raw) To: Ard Biesheuvel; +Cc: Hugh Dickins, Andrew Morton, linux-kernel On Wed, Oct 3, 2012 at 7:43 AM, Ard Biesheuvel <ard.biesheuvel@gmail.com> wrote: > This patch adds support for the PROT_FINAL flag to > the mmap() and mprotect() syscalls. > > The PROT_FINAL flag indicates that the requested set > of protection bits should be final, i.e., it shall > not be allowed for a subsequent mprotect call to > set protection bits that were not set already. > > This is mainly intended for the dynamic linker, > which sets up the address space on behalf of > dynamic binaries. By using this flag, it can > prevent exploited code from remapping read-only > executable code or data sections read-write. > > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@gmail.com> Reviewed-by: Kees Cook <keescook@chromium.org> If it wasn't clear before, I like this idea. :) -Kees -- Kees Cook Chrome OS Security ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 14:43 ` Updated: " Ard Biesheuvel 2012-10-03 16:25 ` Kees Cook @ 2012-10-03 19:44 ` Hugh Dickins 2012-10-03 21:18 ` Andrew Morton 2012-10-04 8:18 ` Mikael Pettersson 3 siblings, 0 replies; 23+ messages in thread From: Hugh Dickins @ 2012-10-03 19:44 UTC (permalink / raw) To: Ard Biesheuvel; +Cc: Andrew Morton, Kees Cook, linux-kernel On Wed, 3 Oct 2012, Ard Biesheuvel wrote: > This patch adds support for the PROT_FINAL flag to > the mmap() and mprotect() syscalls. > > The PROT_FINAL flag indicates that the requested set > of protection bits should be final, i.e., it shall > not be allowed for a subsequent mprotect call to > set protection bits that were not set already. > > This is mainly intended for the dynamic linker, > which sets up the address space on behalf of > dynamic binaries. By using this flag, it can > prevent exploited code from remapping read-only > executable code or data sections read-write. > > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@gmail.com> Acked-by: Hugh Dickins <hughd@google.com> (and I rather enjoy the way you ask PROT_GROWSDOWN for an alibi, in case someone accuses the PROT_FINAL comment of a checkpatch linelength crime.) > --- > arch/alpha/include/asm/mman.h | 1 + > arch/mips/include/asm/mman.h | 1 + > arch/parisc/include/asm/mman.h | 1 + > arch/powerpc/include/asm/mman.h | 3 ++- > arch/xtensa/include/asm/mman.h | 1 + > include/asm-generic/mman-common.h | 1 + > include/linux/mman.h | 3 ++- > mm/mmap.c | 8 ++++++++ > mm/mprotect.c | 8 ++++++++ > 9 files changed, 25 insertions(+), 2 deletions(-) > > diff --git a/arch/alpha/include/asm/mman.h b/arch/alpha/include/asm/mman.h > index cbeb361..ab46252 100644 > --- a/arch/alpha/include/asm/mman.h > +++ b/arch/alpha/include/asm/mman.h > @@ -6,6 +6,7 @@ > #define PROT_EXEC 0x4 /* page can be executed */ > #define PROT_SEM 0x8 /* page may be used for atomic ops */ > #define PROT_NONE 0x0 /* page can not be accessed */ > +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ > #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ > #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ > > diff --git a/arch/mips/include/asm/mman.h b/arch/mips/include/asm/mman.h > index 46d3da0..9cd50e4 100644 > --- a/arch/mips/include/asm/mman.h > +++ b/arch/mips/include/asm/mman.h > @@ -20,6 +20,7 @@ > #define PROT_EXEC 0x04 /* page can be executed */ > /* 0x08 reserved for PROT_EXEC_NOFLUSH */ > #define PROT_SEM 0x10 /* page may be used for atomic ops */ > +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ > #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ > #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ > > diff --git a/arch/parisc/include/asm/mman.h b/arch/parisc/include/asm/mman.h > index 12219eb..0cf18e3 100644 > --- a/arch/parisc/include/asm/mman.h > +++ b/arch/parisc/include/asm/mman.h > @@ -6,6 +6,7 @@ > #define PROT_EXEC 0x4 /* page can be executed */ > #define PROT_SEM 0x8 /* page may be used for atomic ops */ > #define PROT_NONE 0x0 /* page can not be accessed */ > +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ > #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ > #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ > > diff --git a/arch/powerpc/include/asm/mman.h b/arch/powerpc/include/asm/mman.h > index d4a7f64..c0014eb 100644 > --- a/arch/powerpc/include/asm/mman.h > +++ b/arch/powerpc/include/asm/mman.h > @@ -52,7 +52,8 @@ static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags) > > static inline int arch_validate_prot(unsigned long prot) > { > - if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_SAO)) > + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM > + | PROT_SAO | PROT_FINAL)) > return 0; > if ((prot & PROT_SAO) && !cpu_has_feature(CPU_FTR_SAO)) > return 0; > diff --git a/arch/xtensa/include/asm/mman.h b/arch/xtensa/include/asm/mman.h > index 25bc6c1..680b3c4 100644 > --- a/arch/xtensa/include/asm/mman.h > +++ b/arch/xtensa/include/asm/mman.h > @@ -27,6 +27,7 @@ > #define PROT_EXEC 0x4 /* page can be executed */ > > #define PROT_SEM 0x10 /* page may be used for atomic ops */ > +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ > #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ > #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end fo growsup vma */ > > diff --git a/include/asm-generic/mman-common.h b/include/asm-generic/mman-common.h > index d030d2c..5687993 100644 > --- a/include/asm-generic/mman-common.h > +++ b/include/asm-generic/mman-common.h > @@ -10,6 +10,7 @@ > #define PROT_WRITE 0x2 /* page can be written */ > #define PROT_EXEC 0x4 /* page can be executed */ > #define PROT_SEM 0x8 /* page may be used for atomic ops */ > +#define PROT_FINAL 0x80 /* unset page prot bits cannot be set later */ > #define PROT_NONE 0x0 /* page can not be accessed */ > #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ > #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ > diff --git a/include/linux/mman.h b/include/linux/mman.h > index 8b74e9b..c11b1ab 100644 > --- a/include/linux/mman.h > +++ b/include/linux/mman.h > @@ -51,7 +51,8 @@ static inline void vm_unacct_memory(long pages) > */ > static inline int arch_validate_prot(unsigned long prot) > { > - return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) == 0; > + return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC > + | PROT_SEM | PROT_FINAL)) == 0; > } > #define arch_validate_prot arch_validate_prot > #endif > diff --git a/mm/mmap.c b/mm/mmap.c > index 872441e..292f988 100644 > --- a/mm/mmap.c > +++ b/mm/mmap.c > @@ -1101,6 +1101,14 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, > } > } > > + /* > + * PROT_FINAL indicates that prot bits not requested by this > + * mmap() call cannot be added later > + */ > + if (prot & PROT_FINAL) > + vm_flags &= ~(VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) > + | (vm_flags << 4); > + > return mmap_region(file, addr, len, flags, vm_flags, pgoff); > } > > diff --git a/mm/mprotect.c b/mm/mprotect.c > index a409926..7a39f73 100644 > --- a/mm/mprotect.c > +++ b/mm/mprotect.c > @@ -301,6 +301,14 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len, > goto out; > } > > + /* > + * PROT_FINAL indicates that prot bits removed by this > + * mprotect() call cannot be added later > + */ > + if (prot & PROT_FINAL) > + newflags &= ~(VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) > + | (newflags << 4); > + > error = security_file_mprotect(vma, reqprot, prot); > if (error) > goto out; > -- > 1.7.9.5 > > > ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 14:43 ` Updated: " Ard Biesheuvel 2012-10-03 16:25 ` Kees Cook 2012-10-03 19:44 ` Hugh Dickins @ 2012-10-03 21:18 ` Andrew Morton 2012-10-03 22:19 ` Kees Cook 2012-10-04 8:18 ` Mikael Pettersson 3 siblings, 1 reply; 23+ messages in thread From: Andrew Morton @ 2012-10-03 21:18 UTC (permalink / raw) To: Ard Biesheuvel; +Cc: Hugh Dickins, Kees Cook, linux-kernel On Wed, 03 Oct 2012 16:43:53 +0200 Ard Biesheuvel <ard.biesheuvel@gmail.com> wrote: > This patch adds support for the PROT_FINAL flag to > the mmap() and mprotect() syscalls. > > The PROT_FINAL flag indicates that the requested set > of protection bits should be final, i.e., it shall > not be allowed for a subsequent mprotect call to > set protection bits that were not set already. > > This is mainly intended for the dynamic linker, > which sets up the address space on behalf of > dynamic binaries. By using this flag, it can > prevent exploited code from remapping read-only > executable code or data sections read-write. Again: has this proposal been reviewed by the glibc maintainers? If so, what was their position on it? Also, you earlier stated that "It's a more direct version of PaX's "MPROTECT" feature[1]". This is useful information. Please update the changelog to describe that PaX feature and to describe the difference between the two, and the reasons for that difference. It sounds as though the PaX developers could provide useful review input on this proposal. Do they know about it? If so, what is their position? Thanks. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 21:18 ` Andrew Morton @ 2012-10-03 22:19 ` Kees Cook 2012-10-03 22:25 ` Roland McGrath ` (2 more replies) 0 siblings, 3 replies; 23+ messages in thread From: Kees Cook @ 2012-10-03 22:19 UTC (permalink / raw) To: Andrew Morton Cc: Ard Biesheuvel, Hugh Dickins, linux-kernel, pageexec, Roland McGrath On Wed, Oct 3, 2012 at 2:18 PM, Andrew Morton <akpm@linux-foundation.org> wrote: > On Wed, 03 Oct 2012 16:43:53 +0200 > Ard Biesheuvel <ard.biesheuvel@gmail.com> wrote: > >> This patch adds support for the PROT_FINAL flag to >> the mmap() and mprotect() syscalls. >> >> The PROT_FINAL flag indicates that the requested set >> of protection bits should be final, i.e., it shall >> not be allowed for a subsequent mprotect call to >> set protection bits that were not set already. >> >> This is mainly intended for the dynamic linker, >> which sets up the address space on behalf of >> dynamic binaries. By using this flag, it can >> prevent exploited code from remapping read-only >> executable code or data sections read-write. > > Again: has this proposal been reviewed by the glibc maintainers? If > so, what was their position on it? Ard have you talked with them? I would expect it would be welcomed. Roland, do you know who would be the right person to ask about this for glibc? (patch: https://lkml.org/lkml/2012/10/3/262) > Also, you earlier stated that "It's a more direct version of PaX's > "MPROTECT" feature[1]". This is useful information. Please update the > changelog to describe that PaX feature and to describe the difference > between the two, and the reasons for that difference. AIUI, it's much more aggressive. It tries to protect all processes automatically (rather than this which is at the request of the process) and gets in the way of things like Java that expect to be able to do w+x mappings. > It sounds as though the PaX developers could provide useful review > input on this proposal. Do they know about it? If so, what is their > position? I'd rather not speak for them, but I understood it to be along the lines of "that's nice, we'll keep ours." :) (Now added to CC.) -Kees -- Kees Cook Chrome OS Security ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 22:19 ` Kees Cook @ 2012-10-03 22:25 ` Roland McGrath 2012-10-04 8:26 ` Ard Biesheuvel 2012-10-04 12:51 ` PaX Team 2 siblings, 0 replies; 23+ messages in thread From: Roland McGrath @ 2012-10-03 22:25 UTC (permalink / raw) To: Kees Cook Cc: Andrew Morton, Ard Biesheuvel, Hugh Dickins, linux-kernel, pageexec > > Again: has this proposal been reviewed by the glibc maintainers? If > > so, what was their position on it? > > Ard have you talked with them? I would expect it would be welcomed. > Roland, do you know who would be the right person to ask about this > for glibc? (patch: https://lkml.org/lkml/2012/10/3/262) It's me and others. Someone should post (avoiding lots of cross-posting, please) to libc-alpha@sourceware.org with a straightforward description of the userland semantics being introduced (we don't need to see kernel patches) and (ideally) a proposed patch for the dynamic linker code to make use of it (a strawman example is OK to begin with). Thanks, Roland ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 22:19 ` Kees Cook 2012-10-03 22:25 ` Roland McGrath @ 2012-10-04 8:26 ` Ard Biesheuvel 2012-10-04 12:51 ` PaX Team 2 siblings, 0 replies; 23+ messages in thread From: Ard Biesheuvel @ 2012-10-04 8:26 UTC (permalink / raw) To: Kees Cook Cc: Andrew Morton, Hugh Dickins, linux-kernel, pageexec, Roland McGrath, Nick Kralevich, enh 2012/10/4 Kees Cook <keescook@chromium.org>: > On Wed, Oct 3, 2012 at 2:18 PM, Andrew Morton <akpm@linux-foundation.org> wrote: >> Again: has this proposal been reviewed by the glibc maintainers? If >> so, what was their position on it? > > Ard have you talked with them? I would expect it would be welcomed. > Roland, do you know who would be the right person to ask about this > for glibc? (patch: https://lkml.org/lkml/2012/10/3/262) > I haven't spoken to the glibc people. However, I have been in contact with the Android/Bionic people (on CC) to merge back some of the security/hardening enhancements I have been making to Android on behalf of my employer. This change is part of that. I will post to the libc mailing list and once I get some feedback I will post the summary here. >> Also, you earlier stated that "It's a more direct version of PaX's >> "MPROTECT" feature[1]". This is useful information. Please update the >> changelog to describe that PaX feature and to describe the difference >> between the two, and the reasons for that difference. > > AIUI, it's much more aggressive. It tries to protect all processes > automatically (rather than this which is at the request of the > process) and gets in the way of things like Java that expect to be > able to do w+x mappings. > The main difference is that PROT_FINAL is just a feature. It is completely up to the userland to decide in which cases (if at all) to use it, which -as Kees points out- makes it a lot easier to allow certain cases (ashmem filebacked rwx mappings for the JIT heap) while ruling out all others. By implementing it in the loader, the vast majority of code, rodata and relro mappings are hardened while explicit uses of mmap/mprotect in userland code are completely unaffected. OTOH PaX's MPROTECT is a full blown policy implemented inside the kernel. It imposes rules on which of the various combinations of VM_* and VM_MAY* are permissible with little or no control from userland. -- Ard. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 22:19 ` Kees Cook 2012-10-03 22:25 ` Roland McGrath 2012-10-04 8:26 ` Ard Biesheuvel @ 2012-10-04 12:51 ` PaX Team 2012-10-04 13:56 ` Ard Biesheuvel 2 siblings, 1 reply; 23+ messages in thread From: PaX Team @ 2012-10-04 12:51 UTC (permalink / raw) To: Andrew Morton, Kees Cook Cc: Ard Biesheuvel, Hugh Dickins, linux-kernel, Roland McGrath On 3 Oct 2012 at 15:19, Kees Cook wrote: > On Wed, Oct 3, 2012 at 2:18 PM, Andrew Morton <akpm@linux-foundation.org> wrote: > > It sounds as though the PaX developers could provide useful review > > input on this proposal. Do they know about it? If so, what is their > > position? > > I'd rather not speak for them, but I understood it to be along the > lines of "that's nice, we'll keep ours." :) (Now added to CC.) thanks for the heads up Kees ;). i've read through the thread since the first post in August and i have one big lingering question before i can say anything about the implementation: what is the whole point of this exercise? in particular, what kind of threat model underlies the design? what do we expect from an attacker? what restrictions does he operate under? i'm asking these basic questions because i have the feeling that there's some misundertanding here. the following is my speculation based on Ard's first post that was quoted below already (https://lkml.org/lkml/2012/8/14/448): > >> This patch adds support for the PROT_FINAL flag to > >> the mmap() and mprotect() syscalls. > >> > >> The PROT_FINAL flag indicates that the requested set > >> of protection bits should be final, i.e., it shall > >> not be allowed for a subsequent mprotect call to > >> set protection bits that were not set already. > >> > >> This is mainly intended for the dynamic linker, > >> which sets up the address space on behalf of > >> dynamic binaries. By using this flag, it can > >> prevent exploited code from remapping read-only > >> executable code or data sections read-write. now this last paragraph/sentence seems to be the closest thing that describes a scenario where we have some vulnerability (i'm guessing of the memory corruption kind) that allows an attacker (exploit writer) to force the attacked vulnerable application to perform a gratuitous mprotect(PROT_WRITE|PROT_EXEC) on some library/etc mapping and prepare it for shellcode injection/execution (a.k.a. 'game over' or the 'holy grail' ;). so far so good. the question that arises here is that what prevents the same exploit technique (say, ret2libc in this case) from executing an open/mmap(PROT_WRITE|PROT_EXEC) of the very same library that PROT_FINAL would protect? or just a plain anon mmap that is just as good for shellcode execution? in other words, if the attacker can make the attacked application execute mprotect with arbitrary parameters, then why can't the same attacker execute open/mmap/etc as well, completely circumventing the proposed solution? i hope you see now why this issue has to be settled before anyone looks into the implementation details. now later in the thread Ard said this: > The 'interface' we use is a LSM .ko which registers handlers for > mmap() and mprotect() that fail the respective invocations if the > passed arguments do not adhere to the policy. i'm guessing again that their LSM tries to tackle the above described scenarios except we don't know if this LSM will ever become public, whether/how other LSMs will acquire the same capabilities and why it's not mentioned in the PROT_FINAL submission that by itself this feature doesn't increase security. i'm also wondering what kind of policy can allow ld.so to load a library but forbid it a second time, it doesn't seem compatible with real-life cases (think dynamically loaded and unloaded plugins), not to mention the control of anonymous mappings. last but not least, just saw this from Ard while not on CC: > ptrace() doesn't care whether or not the process itself can write to > its .text segment. ptrace cares about VM_MAYWRITE which PROT_FINAL can take away (under PaX MPROTECT'ed processes cannot be debugged with sw breakpoints). > Could we at least agree on the fundamental notion that the special > powers the loader has to modify .text and .rodata sections are hardly > ever needed by the programs themselves? In that sense, this is similar > to dropping root privileges when not required anymore, and that is > typically recognized as a sensible idea. the difference is that the uid is a process-wide attribute, whereas PROT_FINAL isn't, unlike PaX's MPROTECT. in other words, dropping root is irreversible but PROT_FINAL isn't, one just has to create an entirely new mapping to acquire the access rights that PROT_FINAL was supposed to prevent (again, all this modulo an LSM and policies). > > Again: has this proposal been reviewed by the glibc maintainers? If > > Also, you earlier stated that "It's a more direct version of PaX's > > "MPROTECT" feature[1]". This is useful information. Please update the > > changelog to describe that PaX feature and to describe the difference > > between the two, and the reasons for that difference. > > AIUI, it's much more aggressive. It tries to protect all processes > automatically (rather than this which is at the request of the > process) and gets in the way of things like Java that expect to be > able to do w+x mappings. for the gory details: http://pax.grsecurity.net/docs/mprotect.txt. the basic idea is that you either grant a process the ability to generate code at runtime (in whatever form) or you take it away for good, as nobody has come up with a secure middle-ground so far (it's a very non-trivial exercise to create such a mechanism assuming the generic 'attacker can read/write arbitrary memory' model). as for java/etc, PaX has a per-process control mechanism to disable this enforcement, but it's static (decided at process creation time, ideally from a MAC system), not dynamic (something an attack could abuse). cheers, PaX Team ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-04 12:51 ` PaX Team @ 2012-10-04 13:56 ` Ard Biesheuvel 2012-10-06 13:11 ` PaX Team 0 siblings, 1 reply; 23+ messages in thread From: Ard Biesheuvel @ 2012-10-04 13:56 UTC (permalink / raw) To: pageexec Cc: Andrew Morton, Kees Cook, Hugh Dickins, linux-kernel, Roland McGrath 2012/10/4 PaX Team <pageexec@freemail.hu>: Thanks for taking a look at this matter. >> >> This is mainly intended for the dynamic linker, >> >> which sets up the address space on behalf of >> >> dynamic binaries. By using this flag, it can >> >> prevent exploited code from remapping read-only >> >> executable code or data sections read-write. > > now this last paragraph/sentence seems to be the closest thing that > describes a scenario where we have some vulnerability (i'm guessing > of the memory corruption kind) that allows an attacker (exploit writer) > to force the attacked vulnerable application to perform a gratuitous > mprotect(PROT_WRITE|PROT_EXEC) on some library/etc mapping and prepare > it for shellcode injection/execution (a.k.a. 'game over' or the 'holy > grail' ;). so far so good. the question that arises here is that what > prevents the same exploit technique (say, ret2libc in this case) from > executing an open/mmap(PROT_WRITE|PROT_EXEC) of the very same library > that PROT_FINAL would protect? or just a plain anon mmap that is just as > good for shellcode execution? in other words, if the attacker can make > the attacked application execute mprotect with arbitrary parameters, > then why can't the same attacker execute open/mmap/etc as well, completely > circumventing the proposed solution? i hope you see now why this issue > has to be settled before anyone looks into the implementation details. > The main difference here is that it is much easier to doctor a set of stack frames that issues a mprotect(+PROT_EXEC) on the whole address space than it is to re-issue the exact same mmap() call (with MAP_FIXED this time, and the exact offset the kernel decided to load it this time around) that will put the same code/data in exactly the same place in memory (relocated and all) without blowing up your process. In our specific implementation, it is mainly about rodata (public keys) rather than executable code, but the same applies; for us, it is more about rigging binaries: the attacker may not be interested in hijacking the whole process, but just nop'ing out some code that makes the process behave more to his liking. >> The 'interface' we use is a LSM .ko which registers handlers for >> mmap() and mprotect() that fail the respective invocations if the >> passed arguments do not adhere to the policy. > > i'm guessing again that their LSM tries to tackle the above described > scenarios except we don't know if this LSM will ever become public, > whether/how other LSMs will acquire the same capabilities and why it's > not mentioned in the PROT_FINAL submission that by itself this feature > doesn't increase security. i'm also wondering what kind of policy can > allow ld.so to load a library but forbid it a second time, it doesn't > seem compatible with real-life cases (think dynamically loaded and > unloaded plugins), not to mention the control of anonymous mappings. > The LSM encapsulates the policy, and relies on the PROT_FINAL feature. The fact that the policy can impose the use of PROT_FINAL in particular cases makes the implementation of the policy potentially much simpler than that of PaX MPROTECT (but not necessarily as secure). However, let's decide first whether there is a point to having some control over the VM_MAY* flags directly. If yes, then the patch makes sense, otherwise it doesn't. How policies may be built on top of that is part of another debate. > last but not least, just saw this from Ard while not on CC: > >> ptrace() doesn't care whether or not the process itself can write to >> its .text segment. > > ptrace cares about VM_MAYWRITE which PROT_FINAL can take away (under > PaX MPROTECT'ed processes cannot be debugged with sw breakpoints). > My bad: I spent some time looking at access_process_vm() but could not find any references to the vma permissions. >> Could we at least agree on the fundamental notion that the special >> powers the loader has to modify .text and .rodata sections are hardly >> ever needed by the programs themselves? In that sense, this is similar >> to dropping root privileges when not required anymore, and that is >> typically recognized as a sensible idea. > > the difference is that the uid is a process-wide attribute, whereas > PROT_FINAL isn't, unlike PaX's MPROTECT. in other words, dropping root > is irreversible but PROT_FINAL isn't, one just has to create an entirely > new mapping to acquire the access rights that PROT_FINAL was supposed to > prevent (again, all this modulo an LSM and policies). > There remains a fundamental difference between the ability to manipulate existing mappings and creating entirely new ones. Especially when trying to manipulate GOT/PLT or vtable entries or tweak the behavior of a program in other subtle ways, mmap()'ing the same file again is just not going to cut it. Regards, Ard. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-04 13:56 ` Ard Biesheuvel @ 2012-10-06 13:11 ` PaX Team 2012-10-07 7:43 ` Ard Biesheuvel 0 siblings, 1 reply; 23+ messages in thread From: PaX Team @ 2012-10-06 13:11 UTC (permalink / raw) To: Ard Biesheuvel Cc: Andrew Morton, Kees Cook, Hugh Dickins, linux-kernel, Roland McGrath, spender On 4 Oct 2012 at 15:56, Ard Biesheuvel wrote: > 2012/10/4 PaX Team <pageexec@freemail.hu>: > The main difference here is that it is much easier to doctor a set of > stack frames that issues a mprotect(+PROT_EXEC) on the whole address > space than it is to re-issue the exact same mmap() call (with > MAP_FIXED this time, and the exact offset the kernel decided to load > it this time around) that will put the same code/data in exactly the > same place in memory (relocated and all) without blowing up your > process. sadly, this is not true at all, for multiple reasons: 1. not all archs pass (all) parameters on the stack (arm, amd64 come to mind), so the content of the stack at the time the bug is triggered is not too relevant, gadgets can be used to construct anything later. 2. the exploit payload doesn't need to be on the process/thread stack at all. in fact, the more reliable exploits have for long used some form of heap spraying and stack pivoting to increase the chances of success. see also https://www.corelan.be/index.php/2010/06/16/exploit-writing-tutorial-part-10-chaining-dep-with-rop-the-rubikstm-cube/ 3. exploit techniques moved away from simple linear stack overwrites and shellcode execution over a decade ago, the relevant methods all rely on ret2libc/ROP style exploitation. this has been automated to the point that tools can analyze binaries to extract a gadget dictionary (think 'insn set') and feed it into a gadget compiler that will produce a working and reliable exploit automatically. suggested reading: http://users.ece.cmu.edu/~ejschwar/bib/schwartz_2011_rop-abstract.html 4. for your particular suggestions about mprotect vs. mmap: mprotect cannot be called with arbitrary parameters either, the start address must fall inside a mapping and the end address must fall within the process address space limit and the protection bits can't have arbitrary bits set either. regarding reissuing the exact same mmap call: i just mentioned this to show that the PROT_FINAL proposal is circumventible (easily so, if we assume the attacker you mention in the changelog), obviously in a real life exploit scenario we wouldn't care about this, the attacker would simply create an rwx mapping and copy the shellcode there and execute it from there. and if for some reason rwx mappings are prevented otherwise, an rw mapping will do perfectly fine for a gadget based exploit (to the point that iOS jailbreaks implement *kernel* exploits with gadgets). > In our specific implementation, it is mainly about rodata > (public keys) rather than executable code, but the same applies; for > us, it is more about rigging binaries: the attacker may not be > interested in hijacking the whole process, but just nop'ing out some > code that makes the process behave more to his liking. and how do you prevent an attack from overmapping that rodata map? is there something in your LSM that 'cements' specific mappings into the address space (and some mechanism that does the same to all writable pointers that refer to said mappings)? also what about mprotect(PROT_NONE), i.e., instead of trying to acquire more rights, degrade them? is that allowed? does your app handle this properly? (these are side questions, just trying to poke holes ;) > > i'm guessing again that their LSM tries to tackle the above described > > scenarios except we don't know if this LSM will ever become public, > > whether/how other LSMs will acquire the same capabilities and why it's > > not mentioned in the PROT_FINAL submission that by itself this feature > > doesn't increase security. i'm also wondering what kind of policy can > > allow ld.so to load a library but forbid it a second time, it doesn't > > seem compatible with real-life cases (think dynamically loaded and > > unloaded plugins), not to mention the control of anonymous mappings. > > > > The LSM encapsulates the policy, and relies on the PROT_FINAL feature. > The fact that the policy can impose the use of PROT_FINAL in > particular cases[...] i don't understand something here: if your kernel can detect when to use PROT_FINAL, then why do you need it at all? why doesn't the kernel at that point simply enforce the behaviour of PROT_FINAL itself (not unlike PaX/MPROTECT does with runtime codegen)? in other words, why do you need userland to tell the kernel about PROT_FINAL when your kernel can already detect its need (dictated by the policy you mentioned above). > [...]makes the implementation of the policy potentially > much simpler than that of PaX MPROTECT (but not necessarily as > secure). the 'policy' to manage PaX/MPROTECT is very simple. you enable it in the kernel, and you get MPROTECT enabled on all apps by default. if you want to disable it on an app, you set it in the binary or in grsec's RBAC policy (a single line per subject), i don't think you can get it done any simpler than that. but it'd certainly help to see more details about how you intend to use this and equally importantly, how the other LSMs could make use of it. and by 'use' i mean 'increase security of the system'. > However, let's decide first whether there is a point to having some > control over the VM_MAY* flags directly. If yes, then the patch makes > sense, otherwise it doesn't. How policies may be built on top of that > is part of another debate. there's certainly a point (i've been doing it for 12 years now), but to make an mprotect flag into an actual security feature, it had better pass simple tests, such as non-circumventability. any method relying on userland playing nice is already suspect of being the wrong way and right now i don't see how PROT_FINAL could be used for actual security. > > ptrace cares about VM_MAYWRITE which PROT_FINAL can take away (under > > PaX MPROTECT'ed processes cannot be debugged with sw breakpoints). > > > > My bad: I spent some time looking at access_process_vm() but could not > find any references to the vma permissions. look at get_user_pages and how the 'force' parameter is passed down/handled later. > >> Could we at least agree on the fundamental notion that the special > >> powers the loader has to modify .text and .rodata sections are hardly > >> ever needed by the programs themselves? In that sense, this is similar > >> to dropping root privileges when not required anymore, and that is > >> typically recognized as a sensible idea. > > > > the difference is that the uid is a process-wide attribute, whereas > > PROT_FINAL isn't, unlike PaX's MPROTECT. in other words, dropping root > > is irreversible but PROT_FINAL isn't, one just has to create an entirely > > new mapping to acquire the access rights that PROT_FINAL was supposed to > > prevent (again, all this modulo an LSM and policies). > > > > There remains a fundamental difference between the ability to > manipulate existing mappings and creating entirely new ones. what would be that fundamental difference? for an exploit writer it's the same (even automated) effort. > Especially when trying to manipulate GOT/PLT or vtable entries or > tweak the behavior of a program in other subtle ways, mmap()'ing the > same file again is just not going to cut it. don't get too hooked up on mapping the same file, i just mentioned it to prove that userland can circumvent the PROT_FINAL feature as designed. a real exploit would of course do something different after the initial control flow hijacking. as a sidenote, the GOT is already read-only these days under RELRO and BIND_NOW. cheers, PaX Team ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-06 13:11 ` PaX Team @ 2012-10-07 7:43 ` Ard Biesheuvel 2012-10-08 0:23 ` PaX Team 0 siblings, 1 reply; 23+ messages in thread From: Ard Biesheuvel @ 2012-10-07 7:43 UTC (permalink / raw) To: pageexec Cc: Andrew Morton, Kees Cook, Hugh Dickins, linux-kernel, Roland McGrath, spender 2012/10/6 PaX Team <pageexec@freemail.hu>: > sadly, this is not true at all, for multiple reasons: > .. snip ... > > cheers, > PaX Team > So can I summarize your position as that there is no merit at all in the ability to inhibit future permissions of existing mappings? -- Ard. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-07 7:43 ` Ard Biesheuvel @ 2012-10-08 0:23 ` PaX Team 2012-10-10 18:26 ` halfdog 0 siblings, 1 reply; 23+ messages in thread From: PaX Team @ 2012-10-08 0:23 UTC (permalink / raw) To: Ard Biesheuvel Cc: Andrew Morton, Kees Cook, Hugh Dickins, linux-kernel, Roland McGrath, spender On 7 Oct 2012 at 9:43, Ard Biesheuvel wrote: > 2012/10/6 PaX Team <pageexec@freemail.hu>: > > sadly, this is not true at all, for multiple reasons: > > > .. snip ... > > > > cheers, > > PaX Team > > > > So can I summarize your position as that there is no merit at all in > the ability to inhibit future permissions of existing mappings? i believe i answered this in the previous mail already: > there's certainly a point (i've been doing it for 12 years now), but to > make an mprotect flag into an actual security feature, it had better pass > simple tests, such as non-circumventability. any method relying on > userland playing nice is already suspect of being the wrong way and right > now i don't see how PROT_FINAL could be used for actual security. so if PROT_FINAL wants to be useful, you'd have to present a case of how it does something useful *while* an exploited userland cannot get around it. in fact i think i already told you that presenting your own use case in more detail (read: source code, policy, etc) would be a great step in 'selling the idea'. the fact that you seem to be reluctant to follow up on this leaves me somewhat uneasy as it may be the sign of a proprietary vendor's trying to push some code into mainline that nobody else has a clear idea how it'd benefit the rest of us. you see, you're asking for a change in a system call, which is a very important boundary for kernel developers as they'll have to maintain it indefinitely. so the burden is on you to prove that either this is the only way to implement a useful feature or at least it is the optimal way as opposed to other approaches. i suggested you ways to both attack the initially presented concept and also how it may be improved, but i got no answers to them yet. cheers, PaX Team ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-08 0:23 ` PaX Team @ 2012-10-10 18:26 ` halfdog 0 siblings, 0 replies; 23+ messages in thread From: halfdog @ 2012-10-10 18:26 UTC (permalink / raw) To: pageexec Cc: Ard Biesheuvel, Andrew Morton, Kees Cook, Hugh Dickins, linux-kernel, Roland McGrath, spender PaX Team wrote: > On 7 Oct 2012 at 9:43, Ard Biesheuvel wrote: > >> 2012/10/6 PaX Team <pageexec@freemail.hu>: >>> sadly, this is not true at all, for multiple reasons: >>> >> .. snip ... >>> >>> cheers, >>> PaX Team >>> >> >> So can I summarize your position as that there is no merit at all in >> the ability to inhibit future permissions of existing mappings? > > i believe i answered this in the previous mail already: > >> there's certainly a point (i've been doing it for 12 years now), but to >> make an mprotect flag into an actual security feature, it had better pass >> simple tests, such as non-circumventability. any method relying on >> userland playing nice is already suspect of being the wrong way and right >> now i don't see how PROT_FINAL could be used for actual security. > > so if PROT_FINAL wants to be useful, you'd have to present a case of > how it does something useful *while* an exploited userland cannot get > around it. in fact i think i already told you that presenting your own > use case in more detail (read: source code, policy, etc) would be a > great step in 'selling the idea'. I like the idea of final memory protection, but I guess it is quite tricky to make it non-circumventable for reading or non-modification. To block code execution, this feature makes it harder but does not prevent anyway: if you can execute already (e.g. ROP), one still has ways to exec more of anything, e.g. load more stack data and stay ROPed, map new segments, write to file and map it r-x or exec the new file, .... but per-application policies to prevent that could be simpler than without PROT_FINAL. >From my point of view, when protecting against reading/modifiction, it would make only sense when current vm and all clones stay protected, e.g. against proc/$$/mem-reading, ptrace attaching of process to self or clones, not core-dumpable. Otherwise, except for the latest issue, it should be possible, that the process forks, parent modify child via ptrace or proc/mem, then parent just waits or commits suicide. If the content in memory or modification of running process is that important for success of attack, efforts might be taken to do that. But if PROT_FINAL could be made that solid, it might be quite interesting, especially with some proc-fs settings like final-modification-action: ignore (do not check final, e.g. for debugging), log (log and fail), kill (get rid of process immediately). With kernel-wide default and e.g. uid-0 modification of policy per process, that would still allow all debugging also. -- http://www.halfdog.net/ PGP: 156A AE98 B91F 0114 FE88 2BD8 C459 9386 feed a bee ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-03 14:43 ` Updated: " Ard Biesheuvel ` (2 preceding siblings ...) 2012-10-03 21:18 ` Andrew Morton @ 2012-10-04 8:18 ` Mikael Pettersson 2012-10-04 10:33 ` Ard Biesheuvel 3 siblings, 1 reply; 23+ messages in thread From: Mikael Pettersson @ 2012-10-04 8:18 UTC (permalink / raw) To: Ard Biesheuvel; +Cc: Hugh Dickins, Andrew Morton, Kees Cook, linux-kernel Ard Biesheuvel writes: > This patch adds support for the PROT_FINAL flag to > the mmap() and mprotect() syscalls. > > The PROT_FINAL flag indicates that the requested set > of protection bits should be final, i.e., it shall > not be allowed for a subsequent mprotect call to > set protection bits that were not set already. > > This is mainly intended for the dynamic linker, > which sets up the address space on behalf of > dynamic binaries. By using this flag, it can > prevent exploited code from remapping read-only > executable code or data sections read-write. I can see why you might think this is a good idea, but I don't like it for several reasons: - If .text is mapped non-writable and final, how would a debugger (or any ptrace-using monitor-like application) plant a large number of breakpoints in a target process? Breakpoint registers aren't enough because (a) they're few in number, and (b) not all CPUs have them. - You're proposing to give one component (the dynamic linker/ loader) absolute power to impose new policies on all applications. How would an application that _deliberately_ does something the new policies don't allow tell the dynamic linker or kernel to get out of its way? This clearly changes the de-facto ABIs, and as such I think it needs much more detailed analysis than what you've done here. At the very least I think this change should be opt-in, but that would require a kernel option or sysctl, or some config file for the user-space dynamic linker/loader. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Updated: [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect 2012-10-04 8:18 ` Mikael Pettersson @ 2012-10-04 10:33 ` Ard Biesheuvel 0 siblings, 0 replies; 23+ messages in thread From: Ard Biesheuvel @ 2012-10-04 10:33 UTC (permalink / raw) To: Mikael Pettersson; +Cc: Hugh Dickins, Andrew Morton, Kees Cook, linux-kernel 2012/10/4 Mikael Pettersson <mikpe@it.uu.se>: > - If .text is mapped non-writable and final, how would a debugger > (or any ptrace-using monitor-like application) plant a large > number of breakpoints in a target process? Breakpoint registers > aren't enough because (a) they're few in number, and (b) not > all CPUs have them. > ptrace() doesn't care whether or not the process itself can write to its .text segment. > - You're proposing to give one component (the dynamic linker/ > loader) absolute power to impose new policies on all > applications. How would an application that _deliberately_ > does something the new policies don't allow tell the dynamic > linker or kernel to get out of its way? > You are debating cases in which the userland would choose not to use the feature. That is exactly the point of this patch: the kernel supplies the feature and it is up to the userland to use it when desired. If not in the loader, perhaps processes running setuid binaries or browser sandboxes could choose to call mprotect() to finalize some of their existing mappings (their stack?) before handing over to less trusted code or opening up to the network. > This clearly changes the de-facto ABIs, and as such I think > it needs much more detailed analysis than what you've done > here. > Could we at least agree on the fundamental notion that the special powers the loader has to modify .text and .rodata sections are hardly ever needed by the programs themselves? In that sense, this is similar to dropping root privileges when not required anymore, and that is typically recognized as a sensible idea. > At the very least I think this change should be opt-in, but > that would require a kernel option or sysctl, or some config > file for the user-space dynamic linker/loader. As long as the kernel does not impose its use, I don't see a reason for an interface into the kernel to deactivate it. I would be interested in learning about example cases that have a valid need to modify their own code and constant data, as understanding those would greatly help in designing the ways userland should be able to have control over this. Regards, Ard. ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2012-10-10 18:26 UTC | newest] Thread overview: 23+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-08-14 19:11 [PATCH] hardening: add PROT_FINAL prot flag to mmap/mprotect Ard Biesheuvel 2012-08-20 18:00 ` Kees Cook 2012-08-20 21:48 ` Ard Biesheuvel 2012-10-02 20:34 ` Kees Cook 2012-10-02 21:41 ` Ard Biesheuvel 2012-10-02 22:10 ` Kees Cook 2012-10-02 22:38 ` Andrew Morton 2012-10-03 0:43 ` Hugh Dickins 2012-10-03 14:43 ` Updated: " Ard Biesheuvel 2012-10-03 16:25 ` Kees Cook 2012-10-03 19:44 ` Hugh Dickins 2012-10-03 21:18 ` Andrew Morton 2012-10-03 22:19 ` Kees Cook 2012-10-03 22:25 ` Roland McGrath 2012-10-04 8:26 ` Ard Biesheuvel 2012-10-04 12:51 ` PaX Team 2012-10-04 13:56 ` Ard Biesheuvel 2012-10-06 13:11 ` PaX Team 2012-10-07 7:43 ` Ard Biesheuvel 2012-10-08 0:23 ` PaX Team 2012-10-10 18:26 ` halfdog 2012-10-04 8:18 ` Mikael Pettersson 2012-10-04 10:33 ` Ard Biesheuvel
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).