Message ID | 1299754315-6595-1-git-send-email-sconklin@canonical.com |
---|---|
State | New |
Headers | show |
That should be good now. Acked-by: Stefan Bader <stefan.bader@canonical.com> On 03/10/2011 11:51 AM, Steve Conklin wrote: > From: Tavis Ormandy <taviso@cmpxchg8b.com> > > BugLink: http://bugs.launchpad.net/bugs/731971 > > CVE-2010-4346 > > The install_special_mapping routine (used, for example, to setup the > vdso) skips the security check before insert_vm_struct, allowing a local > attacker to bypass the mmap_min_addr security restriction by limiting > the available pages for special mappings. > > bprm_mm_init() also skips the check, and although I don't think this can > be used to bypass any restrictions, I don't see any reason not to have > the security check. > > $ uname -m > x86_64 > $ cat /proc/sys/vm/mmap_min_addr > 65536 > $ cat install_special_mapping.s > section .bss > resb BSS_SIZE > section .text > global _start > _start: > mov eax, __NR_pause > int 0x80 > $ nasm -D__NR_pause=29 -DBSS_SIZE=0xfffed000 -f elf -o install_special_mapping.o install_special_mapping.s > $ ld -m elf_i386 -Ttext=0x10000 -Tbss=0x11000 -o install_special_mapping install_special_mapping.o > $ ./install_special_mapping & > [1] 14303 > $ cat /proc/14303/maps > 0000f000-00010000 r-xp 00000000 00:00 0 [vdso] > 00010000-00011000 r-xp 00001000 00:19 2453665 /home/taviso/install_special_mapping > 00011000-ffffe000 rwxp 00000000 00:00 0 [stack] > > It's worth noting that Red Hat are shipping with mmap_min_addr set to > 4096. > > Signed-off-by: Tavis Ormandy <taviso@google.com> > Acked-by: Kees Cook <kees@ubuntu.com> > Acked-by: Robert Swiecki <swiecki@google.com> > [ Changed to not drop the error code - akpm ] > Reviewed-by: James Morris <jmorris@namei.org> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > backported from upstream commit 462e635e5b73ba9a4c03913b77138cd57ce4b050 > Signed-off-by: Steve Conklin <sconklin@canonical.com> > --- > fs/exec.c | 5 +++++ > mm/mmap.c | 16 ++++++++++++---- > 2 files changed, 17 insertions(+), 4 deletions(-) > > diff --git a/fs/exec.c b/fs/exec.c > index 1bedd94..9cf5fb5 100644 > --- a/fs/exec.c > +++ b/fs/exec.c > @@ -247,6 +247,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) > vma->vm_start = vma->vm_end - PAGE_SIZE; > vma->vm_flags = VM_STACK_FLAGS; > vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); > + > + err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); > + if (err) > + goto err; > + > err = insert_vm_struct(mm, vma); > if (err) > goto err; > diff --git a/mm/mmap.c b/mm/mmap.c > index ac9cceb..a53ad79 100644 > --- a/mm/mmap.c > +++ b/mm/mmap.c > @@ -2390,6 +2390,7 @@ int install_special_mapping(struct mm_struct *mm, > unsigned long addr, unsigned long len, > unsigned long vm_flags, struct page **pages) > { > + int ret; > struct vm_area_struct *vma; > > vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); > @@ -2406,16 +2407,23 @@ int install_special_mapping(struct mm_struct *mm, > vma->vm_ops = &special_mapping_vmops; > vma->vm_private_data = pages; > > - if (unlikely(insert_vm_struct(mm, vma))) { > - kmem_cache_free(vm_area_cachep, vma); > - return -ENOMEM; > - } > + ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); > + if (ret) > + goto out; > + > + ret = insert_vm_struct(mm, vma); > + if (ret) > + goto out; > > mm->total_vm += len >> PAGE_SHIFT; > > perf_counter_mmap(vma); > > return 0; > + > +out: > + kmem_cache_free(vm_area_cachep, vma); > + return ret; > } > > static DEFINE_MUTEX(mm_all_locks_mutex);
On 03/10/2011 10:51 AM, Steve Conklin wrote: > From: Tavis Ormandy<taviso@cmpxchg8b.com> > > BugLink: http://bugs.launchpad.net/bugs/731971 > > CVE-2010-4346 > > The install_special_mapping routine (used, for example, to setup the > vdso) skips the security check before insert_vm_struct, allowing a local > attacker to bypass the mmap_min_addr security restriction by limiting > the available pages for special mappings. > > bprm_mm_init() also skips the check, and although I don't think this can > be used to bypass any restrictions, I don't see any reason not to have > the security check. > > $ uname -m > x86_64 > $ cat /proc/sys/vm/mmap_min_addr > 65536 > $ cat install_special_mapping.s > section .bss > resb BSS_SIZE > section .text > global _start > _start: > mov eax, __NR_pause > int 0x80 > $ nasm -D__NR_pause=29 -DBSS_SIZE=0xfffed000 -f elf -o install_special_mapping.o install_special_mapping.s > $ ld -m elf_i386 -Ttext=0x10000 -Tbss=0x11000 -o install_special_mapping install_special_mapping.o > $ ./install_special_mapping& > [1] 14303 > $ cat /proc/14303/maps > 0000f000-00010000 r-xp 00000000 00:00 0 [vdso] > 00010000-00011000 r-xp 00001000 00:19 2453665 /home/taviso/install_special_mapping > 00011000-ffffe000 rwxp 00000000 00:00 0 [stack] > > It's worth noting that Red Hat are shipping with mmap_min_addr set to > 4096. > > Signed-off-by: Tavis Ormandy<taviso@google.com> > Acked-by: Kees Cook<kees@ubuntu.com> > Acked-by: Robert Swiecki<swiecki@google.com> > [ Changed to not drop the error code - akpm ] > Reviewed-by: James Morris<jmorris@namei.org> > Signed-off-by: Linus Torvalds<torvalds@linux-foundation.org> > backported from upstream commit 462e635e5b73ba9a4c03913b77138cd57ce4b050 > Signed-off-by: Steve Conklin<sconklin@canonical.com> > --- > fs/exec.c | 5 +++++ > mm/mmap.c | 16 ++++++++++++---- > 2 files changed, 17 insertions(+), 4 deletions(-) > > diff --git a/fs/exec.c b/fs/exec.c > index 1bedd94..9cf5fb5 100644 > --- a/fs/exec.c > +++ b/fs/exec.c > @@ -247,6 +247,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) > vma->vm_start = vma->vm_end - PAGE_SIZE; > vma->vm_flags = VM_STACK_FLAGS; > vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); > + > + err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); > + if (err) > + goto err; > + > err = insert_vm_struct(mm, vma); > if (err) > goto err; > diff --git a/mm/mmap.c b/mm/mmap.c > index ac9cceb..a53ad79 100644 > --- a/mm/mmap.c > +++ b/mm/mmap.c > @@ -2390,6 +2390,7 @@ int install_special_mapping(struct mm_struct *mm, > unsigned long addr, unsigned long len, > unsigned long vm_flags, struct page **pages) > { > + int ret; > struct vm_area_struct *vma; > > vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); > @@ -2406,16 +2407,23 @@ int install_special_mapping(struct mm_struct *mm, > vma->vm_ops =&special_mapping_vmops; > vma->vm_private_data = pages; > > - if (unlikely(insert_vm_struct(mm, vma))) { > - kmem_cache_free(vm_area_cachep, vma); > - return -ENOMEM; > - } > + ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); > + if (ret) > + goto out; > + > + ret = insert_vm_struct(mm, vma); > + if (ret) > + goto out; > > mm->total_vm += len>> PAGE_SHIFT; > > perf_counter_mmap(vma); > > return 0; > + > +out: > + kmem_cache_free(vm_area_cachep, vma); > + return ret; > } > > static DEFINE_MUTEX(mm_all_locks_mutex); Acked-by: Brad Figg <brad.figg@canonical.com>
On Thu, 2011-03-10 at 12:13 +0000, Brad Figg wrote: > On 03/10/2011 10:51 AM, Steve Conklin wrote: > > From: Tavis Ormandy<taviso@cmpxchg8b.com> > > > > BugLink: http://bugs.launchpad.net/bugs/731971 > > > > CVE-2010-4346 > > > > The install_special_mapping routine (used, for example, to setup the > > vdso) skips the security check before insert_vm_struct, allowing a local > > attacker to bypass the mmap_min_addr security restriction by limiting > > the available pages for special mappings. > > > > bprm_mm_init() also skips the check, and although I don't think this can > > be used to bypass any restrictions, I don't see any reason not to have > > the security check. > > > > $ uname -m > > x86_64 > > $ cat /proc/sys/vm/mmap_min_addr > > 65536 > > $ cat install_special_mapping.s > > section .bss > > resb BSS_SIZE > > section .text > > global _start > > _start: > > mov eax, __NR_pause > > int 0x80 > > $ nasm -D__NR_pause=29 -DBSS_SIZE=0xfffed000 -f elf -o install_special_mapping.o install_special_mapping.s > > $ ld -m elf_i386 -Ttext=0x10000 -Tbss=0x11000 -o install_special_mapping install_special_mapping.o > > $ ./install_special_mapping& > > [1] 14303 > > $ cat /proc/14303/maps > > 0000f000-00010000 r-xp 00000000 00:00 0 [vdso] > > 00010000-00011000 r-xp 00001000 00:19 2453665 /home/taviso/install_special_mapping > > 00011000-ffffe000 rwxp 00000000 00:00 0 [stack] > > > > It's worth noting that Red Hat are shipping with mmap_min_addr set to > > 4096. > > > > Signed-off-by: Tavis Ormandy<taviso@google.com> > > Acked-by: Kees Cook<kees@ubuntu.com> > > Acked-by: Robert Swiecki<swiecki@google.com> > > [ Changed to not drop the error code - akpm ] > > Reviewed-by: James Morris<jmorris@namei.org> > > Signed-off-by: Linus Torvalds<torvalds@linux-foundation.org> > > backported from upstream commit 462e635e5b73ba9a4c03913b77138cd57ce4b050 > > Signed-off-by: Steve Conklin<sconklin@canonical.com> > > --- > > fs/exec.c | 5 +++++ > > mm/mmap.c | 16 ++++++++++++---- > > 2 files changed, 17 insertions(+), 4 deletions(-) > > > > diff --git a/fs/exec.c b/fs/exec.c > > index 1bedd94..9cf5fb5 100644 > > --- a/fs/exec.c > > +++ b/fs/exec.c > > @@ -247,6 +247,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) > > vma->vm_start = vma->vm_end - PAGE_SIZE; > > vma->vm_flags = VM_STACK_FLAGS; > > vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); > > + > > + err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); > > + if (err) > > + goto err; > > + > > err = insert_vm_struct(mm, vma); > > if (err) > > goto err; > > diff --git a/mm/mmap.c b/mm/mmap.c > > index ac9cceb..a53ad79 100644 > > --- a/mm/mmap.c > > +++ b/mm/mmap.c > > @@ -2390,6 +2390,7 @@ int install_special_mapping(struct mm_struct *mm, > > unsigned long addr, unsigned long len, > > unsigned long vm_flags, struct page **pages) > > { > > + int ret; > > struct vm_area_struct *vma; > > > > vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); > > @@ -2406,16 +2407,23 @@ int install_special_mapping(struct mm_struct *mm, > > vma->vm_ops =&special_mapping_vmops; > > vma->vm_private_data = pages; > > > > - if (unlikely(insert_vm_struct(mm, vma))) { > > - kmem_cache_free(vm_area_cachep, vma); > > - return -ENOMEM; > > - } > > + ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); > > + if (ret) > > + goto out; > > + > > + ret = insert_vm_struct(mm, vma); > > + if (ret) > > + goto out; > > > > mm->total_vm += len>> PAGE_SHIFT; > > > > perf_counter_mmap(vma); > > > > return 0; > > + > > +out: > > + kmem_cache_free(vm_area_cachep, vma); > > + return ret; > > } > > > > static DEFINE_MUTEX(mm_all_locks_mutex); > > Acked-by: Brad Figg <brad.figg@canonical.com> > > -- > Brad Figg brad.figg@canonical.com http://www.canonical.com >
diff --git a/fs/exec.c b/fs/exec.c index 1bedd94..9cf5fb5 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -247,6 +247,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) vma->vm_start = vma->vm_end - PAGE_SIZE; vma->vm_flags = VM_STACK_FLAGS; vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + + err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); + if (err) + goto err; + err = insert_vm_struct(mm, vma); if (err) goto err; diff --git a/mm/mmap.c b/mm/mmap.c index ac9cceb..a53ad79 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2390,6 +2390,7 @@ int install_special_mapping(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long vm_flags, struct page **pages) { + int ret; struct vm_area_struct *vma; vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); @@ -2406,16 +2407,23 @@ int install_special_mapping(struct mm_struct *mm, vma->vm_ops = &special_mapping_vmops; vma->vm_private_data = pages; - if (unlikely(insert_vm_struct(mm, vma))) { - kmem_cache_free(vm_area_cachep, vma); - return -ENOMEM; - } + ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); + if (ret) + goto out; + + ret = insert_vm_struct(mm, vma); + if (ret) + goto out; mm->total_vm += len >> PAGE_SHIFT; perf_counter_mmap(vma); return 0; + +out: + kmem_cache_free(vm_area_cachep, vma); + return ret; } static DEFINE_MUTEX(mm_all_locks_mutex);