CVE-2009-1895: Linux kernel PER_CLEAR_ON_SETID Personality Bypass
This was discovered and disclosed on 26 June 2009 by Julien Tinnes and Tavis Ormandy. As they explain in their detailed blog post, they wanted to exploit a NULL pointer dereference vulnerability in the Linux kernel but they had difficulties in bypassing mmap_min_addr protection. To do this, they found a SUID binary (pulseaudio) and they used it to execute code through its -L (load module) feature. However, PER_CLEAR_ON_SETID personality which is used in suid binaries does not check for MMAP_PAGE_ZERO allocations. Consequently, any suid binary can map NULL regardless of mmap_min_addr setting. Until 2.6.30 its personality was:
/*
* Flags for bug emulation.
*
* These occupy the top three bytes.
*/
enum {
ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors
* (signal handling)
*/
MMAP_PAGE_ZERO = 0x0100000,
ADDR_COMPAT_LAYOUT = 0x0200000,
READ_IMPLIES_EXEC = 0x0400000,
ADDR_LIMIT_32BIT = 0x0800000,
SHORT_INODE = 0x1000000,
WHOLE_SECONDS = 0x2000000,
STICKY_TIMEOUTS = 0x4000000,
ADDR_LIMIT_3GB = 0x8000000,
};
/*
* Security-relevant compatibility flags that must be
* cleared upon setuid or setgid exec:
*/
#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC|ADDR_NO_RANDOMIZE)
This code can be found at include/linux/personality.h and as you can see, PER_CLEAR_ON_SETID includes only two flags. READ_IMPLIES_EXEC which is quite self explanatory and ADDR_NO_RANDOMIZE that disables virtual address space randomization. This was fixed by applying a patch to include two more flags.
* cleared upon setuid or setgid exec: */ -#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC|ADDR_NO_RANDOMIZE) +#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC|ADDR_NO_RANDOMIZE|ADDR_COMPAT_LAYOUT|MMAP_PAGE_ZERO) /*
Using this, apart from MMAP_PAGE_ZERO which is used to include mmap_min_addr restrictions even in suid binaries, another flag, ADDR_COMPAT_LAYOUT was included. As J. Tinnes said, this missing flag will result in randomization only in the stack segment.
