Bug 662189 (CVE-2010-4346)

Summary: CVE-2010-4346 kernel: install_special_mapping skips security_file_mmap check
Product: [Other] Security Response Reporter: Petr Matousek <pmatouse>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED ERRATA QA Contact:
Severity: low Docs Contact:
Priority: low    
Version: unspecifiedCC: arozansk, bhu, dhoward, dougsland, fhrbata, gansalmon, itamar, jkacur, jonathan, kernel-maint, kernel-mgr, kmcmartin, kzhang, lgoncalv, lwang, madhu.chinakonda, plyons, rkhan, rt-maint, solar, tcallawa, vkrizan, williams
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-07-29 13:31:09 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 662195, 662196, 662197, 662198, 662199    
Bug Blocks:    
Attachments:
Description Flags
Patch proposed by Tavis Ormandi
none
RHEL5'ish patch proposed by Solar Designer none

Description Petr Matousek 2010-12-10 20:28:43 UTC
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.

Reference:
https://lkml.org/lkml/2010/12/9/222
http://seclists.org/oss-sec/2010/q4/307

Acknowledgements:
Red Hat would like to thank Tavis Ormandy for reporting this issue.

Comment 2 Petr Matousek 2010-12-10 20:31:27 UTC
Statement:

The Linux kernel as shipped with Red Hat Enterprise Linux 4 is not vulnerable because it checks for mmap_min_addr even in special cases.

The Linux kernel as shipped with Red Hat Enterprise Linux 5, 6, and Red Hat Enterprise MRG have mmap_min_addr sysctl tunable set to 4096, and therefore are not affected by this issue. However, as a preventive measure (for example, for administrators who have increased mmap_min_addr), we have addressed this in Red Hat Enterprise Linux 5, 6 and MRG via https://rhn.redhat.com/errata/RHSA-2011-0429.html, https://rhn.redhat.com/errata/RHSA-2011-0421.html, and https://rhn.redhat.com/errata/RHSA-2011-0330.html.

Comment 3 Petr Matousek 2010-12-10 20:40:10 UTC
Created attachment 468055 [details]
Patch proposed by Tavis Ormandi

Comment 4 Petr Matousek 2010-12-10 20:41:34 UTC
Created attachment 468057 [details]
RHEL5'ish patch proposed by Solar Designer

Comment 6 Alexander Peslyak 2010-12-10 21:46:55 UTC
(In reply to comment #2)
> The Linux kernel as shipped with Red Hat Enterprise Linux 5, 6, and Red Hat
> Enterprise MRG have mmap_min_addr sysctl tunable set to 4096, and therefore are
> not affected by this issue.

I think this is a misunderstanding.  Your setting of mmap_min_addr to 4096 is precisely what makes you vulnerable to the fullest extent: the attack demonstrated by Tavis allows to map a page at exactly one page below mmap_min_addr, and you only have exactly one page - so it should get mapped at 0 (NULL).  Isn't this what happens when you try Tavis' PoC program on a clean RHEL 5 or 6 system?  I must admit I have not tried.  There might be something that prevents this from happening, but no one has mentioned such a thing so far (or have I missed it?)

Comment 7 Petr Matousek 2010-12-10 22:17:49 UTC
(In reply to comment #6)
> (In reply to comment #2)
> > The Linux kernel as shipped with Red Hat Enterprise Linux 5, 6, and Red Hat
> > Enterprise MRG have mmap_min_addr sysctl tunable set to 4096, and therefore are
> > not affected by this issue.
> 
> I think this is a misunderstanding.  Your setting of mmap_min_addr to 4096 is
> precisely what makes you vulnerable to the fullest extent: the attack
> demonstrated by Tavis allows to map a page at exactly one page below
> mmap_min_addr, and you only have exactly one page - so it should get mapped at
> 0 (NULL).  Isn't this what happens when you try Tavis' PoC program on a clean
> RHEL 5 or 6 system?  I must admit I have not tried.  There might be something
> that prevents this from happening, but no one has mentioned such a thing so far
> (or have I missed it?)

Update:
The following seems to be true for RHEL6. On both systems vm.overcommit_memory=1 might be needed. On my testing RHEL5 system vdso keeps to be mapped to 0xffffe000 which looks like COMPAT_VDSO. Either way I was not able to use intstall_special_mapping() to map anything to address 0 on RHEL.

--

This is what I was thinking first as well and tried to make the vdso getting mapped to address 0. I tested it on a a 2.6.35 upstream kernel, but on RHEL it's the same (32bit program on x86-64, on 32bit it's similar):

cynique@gentoo64 ~ $ cat /proc/2588/maps
00001000-00002000 r-xp 00001000 03:03 230335   /home/cynique/nada
00002000-ffff2000 rwxp 00000000 00:00 0       [stack]
ffff2000-ffff3000 r-xp 00000000 00:00 0       [vdso]
cynique@gentoo64 ~ $ nasm -D__NR_pause=29 -DBSS_SIZE=0xffffc000 -f elf -o nada.o nada.s
cynique@gentoo64 ~ $ ld -m elf_i386 -Ttext=0x1000 -Tbss=0x2000 -o nada nada.o   cynique@gentoo64 ~ $ ./nada
Killed
cynique@gentoo64 ~ $

breakpoint 4, arch_get_unmapped_area_topdown (filp=0x0, addr0=0x0, len=0x1000, pgoff=0x0, flags=0x0) at arch/x86/kernel/sys_x86_64.c:192
192		} while (len < vma->vm_start);
gdb> p len
$23 = 0x1000
gdb> p vma->vm_start
$24 = 0x1000
gdb> 

The problem AFAIK is in the while condition: the len is 0x1000 because we are looking for one page and the next vma->vm_start is 0x1000 as that is a vma with /home/cynique/nada. The condition (len < vma->vm_start) effectively skips the free page.

After the "} while (len <= vma->vm_start);" patch

cynique@gentoo64 ~ $ nasm -D__NR_pause=29 -DBSS_SIZE=0xffffc000 -f elf -o nada.o nada.s
cynique@gentoo64 ~ $ ld -m elf_i386 -Ttext=0x1000 -Tbss=0x2000 -o nada nada.o
cynique@gentoo64 ~ $ ./nada &
[1] 2555
cynique@gentoo64 ~ $ cat /proc/2555/maps
00000000-00001000 r-xp 00000000 00:00 0          [vdso]
00001000-00002000 r-xp 00001000 03:03 230335     /home/cynique/nada
00002000-ffffe000 rwxp 00000000 00:00 0          [stack]
cynique@gentoo64 ~ $ cat /proc/sys/vm/mmap_min_addr
4096
cynique@gentoo64 ~ $

Comment 8 Frantisek Hrbata 2011-01-10 11:04:57 UTC
Upstream commit 462e635e5b73ba9a4c03913b77138cd57ce4b050
http://git.kernel.org/linus/462e635e5b73ba9a4c03913b77138cd57ce4b050

Comment 10 errata-xmlrpc 2011-03-10 20:04:50 UTC
This issue has been addressed in following products:

  MRG for RHEL-5

Via RHSA-2011:0330 https://rhn.redhat.com/errata/RHSA-2011-0330.html

Comment 11 errata-xmlrpc 2011-04-08 02:57:29 UTC
This issue has been addressed in following products:

  Red Hat Enterprise Linux 6

Via RHSA-2011:0421 https://rhn.redhat.com/errata/RHSA-2011-0421.html

Comment 12 errata-xmlrpc 2011-04-12 18:20:07 UTC
This issue has been addressed in following products:

  Red Hat Enterprise Linux 5

Via RHSA-2011:0429 https://rhn.redhat.com/errata/RHSA-2011-0429.html