From patchwork Wed Mar 9 14:24:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Conklin X-Patchwork-Id: 86118 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id C89BCB6F9B for ; Thu, 10 Mar 2011 01:25:14 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1PxKK3-0004OC-Jh; Wed, 09 Mar 2011 14:25:07 +0000 Received: from adelie.canonical.com ([91.189.90.139]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1PxKK0-0004M0-KZ for kernel-team@lists.ubuntu.com; Wed, 09 Mar 2011 14:25:04 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1PxKK0-0002TC-3Q for ; Wed, 09 Mar 2011 14:25:04 +0000 Received: from [91.189.88.12] (helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1PxKJz-0006so-Vw for kernel-team@lists.ubuntu.com; Wed, 09 Mar 2011 14:25:04 +0000 From: Steve Conklin To: kernel-team@lists.ubuntu.com Subject: [CVE-2010-4346 Hardy] install_special_mapping skips security_file_mmap check. CVE-2010-4346 Date: Wed, 9 Mar 2011 14:24:48 +0000 Message-Id: <1299680688-8672-1-git-send-email-sconklin@canonical.com> X-Mailer: git-send-email 1.7.0.4 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Tavis Ormandy 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 Acked-by: Kees Cook Acked-by: Robert Swiecki [ Changed to not drop the error code - akpm ] Reviewed-by: James Morris Signed-off-by: Linus Torvalds backported from upstream commit 462e635e5b73ba9a4c03913b77138cd57ce4b050 Signed-off-by: Steve Conklin --- fs/exec.c | 7 +++++++ mm/mmap.c | 16 ++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 1340386..9338b4f 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -235,6 +235,13 @@ static int __bprm_mm_init(struct linux_binprm *bprm) vma->vm_flags = VM_STACK_FLAGS; vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + + INIT_LIST_HEAD(&vma->anon_vma_chain); + + err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); + if (err) + goto err; + err = insert_vm_struct(mm, vma); if (err) { up_write(&mm->mmap_sem); diff --git a/mm/mmap.c b/mm/mmap.c index 6f9b289..974ecc0 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2210,6 +2210,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); @@ -2226,12 +2227,19 @@ 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; return 0; + +out: + kmem_cache_free(vm_area_cachep, vma); + return ret; }