SlideShare a Scribd company logo
1 of 42
grsecurity and PaX
Gili Yankovitch, Nyx Software Security Solutions
Prerequisites
● Knowledge with kernel internals (duh!)
● Knowledge of the Memory Management model
● Slab Memory allocation
...
○ But I’ll cover anything anyway...
Key Points
● What is grsecurity and PaX
● How to apply it
○ Configuration variations
● PaX Memory Manager features
○ PAX_USERCOPY
○ PAX_MEMORY_SANITIZE
○ PAX_ASLR
■ PAX_RANDSTACK
Linus Torvalds
● Linus is not a big fan of security...
“One reason I refuse to bother with the whole security circus is that I think it glorifies - and
thus encourages - the wrong behavior. It makes "heroes" out of security people, as if the people
who don't just fix normal bugs aren't as important.”
grsecurity - Technical details
● PaX is a set of features within the grsecurity (grsecurity.net) patch
● Linux Kernel patch
● Stable for versions 3.2.72 and 3.14.54
● Test for 4.3.5
● Was free until 08/2015
○ Stopped being free because of copyright infringement
● Supports all major architectures
○ x86/x64, arm, ppc, mips
Applying the patch
● Very hard.
● Doesn’t always work.
● Needs to use specific commands depending your machine.
● But some say this works:
$ patch -p1 < grsecurity-3.1-4.3.5-201602032209.patch
● So now, well, you don’t have any excuse not to use it.
● Now grsecurity is applied to your kernel.
● Even just by doing this we improve our system’s security. You’ll see...
Activating specific features
● grsecurity supports automatic configuration
● Automatic configuration depends on choosing between two factors:
○ Performance
○ Security
● They usually don’t go hand in hand...
$ make menuconfig
Security options --->
Grsecurity --->
Memory Manager Refresher
● Classical memory model within the Linux Kernel is of Zones
● There are 3 major zones in classic kernel architecture:
○ ZONE_HIGHMEM
○ ZONE_NORMAL
○ ZONE_DMA
ZONE_DMA
ZONE_NORMAL
ZONE_HIGHMEM
0x00000000
KERNEL
USER
0x00000000
0xC0000000
0xFFFFFFFF
Virtual Memory Physical Memory
© All Rights Reserved
Memory abstraction
Physical
Memory
Virtual
Memory
Buddy
System
SLUB
Allocator
kmalloc
© All Rights Reserved
ZONE_HIGHMEM ZONE_NORMAL
PAX_USERCOPY
copy_from_user
● Not many use this function
● Eventually leads to this piece of code:
static __always_inline __must_check
unsigned long __copy_from_user_nocheck(void *dst, const void __user *src, unsigned long size)
{
size_t sz = __compiletime_object_size(dst);
unsigned ret = 0;
if (size > INT_MAX)
return size;
check_object_size(dst, size, false);
arch/x86/include/asm/uaccess_64.h
● Lets focus on check_object_size()
check_object_size()
void __check_object_size(const void *ptr, unsigned long n, bool to_user, bool const_size)
{
#ifdef CONFIG_PAX_USERCOPY
const char *type;
#endif
...
#ifdef CONFIG_PAX_USERCOPY
if (!n)
return;
type = check_heap_object(ptr, n);
if (!type) {
int ret = check_stack_object(ptr, n);
if (ret == 1 || ret == 2)
return;
if (ret == 0) {
if (check_kernel_text_object((unsigned long)ptr, (unsigned long)ptr + n))
type = "";
else
return;
} else
type = "";
}
pax_report_usercopy(ptr, n, to_user, type);
#endif
fs/exec.c
check_heap_object()
const char *check_heap_object(const void *ptr, unsigned long n)
{
struct page *page;
struct kmem_cache *s;
unsigned long offset;
if (ZERO_OR_NULL_PTR(ptr))
return "<null>";
if (!virt_addr_valid(ptr))
return NULL;
page = virt_to_head_page(ptr);
if (!PageSlab(page))
return NULL;
s = page->slab_cache;
if (!(s->flags & SLAB_USERCOPY))
return s->name;
offset = (ptr - page_address(page)) % s->size;
if (offset <= s->object_size && n <= s->object_size - offset)
return NULL;
return s->name;
}
mm/slub.c
check_stack_object()
● First, few basic checks
#ifdef CONFIG_PAX_USERCOPY
/* 0: not at all, 1: fully, 2: fully inside frame, -1: partially (implies an error) */
static noinline int check_stack_object(const void *obj, unsigned long len)
{
const void * const stack = task_stack_page(current);
const void * const stackend = stack + THREAD_SIZE;
#if defined(CONFIG_FRAME_POINTER) && defined(CONFIG_X86)
const void *frame = NULL;
const void *oldframe;
#endif
if (obj + len < obj)
return -1;
if (obj + len <= stack || stackend <= obj)
return 0;
if (obj < stack || stackend < obj + len)
return -1;
fs/exec.c
All hail gcc features!
● gcc has many wonderful features
○ Some of them documented, some of them undocumented.
○ One of those documented:— Built-in Function: void * __builtin_frame_address (unsigned int level)
This function is similar to __builtin_return_address, but it returns the address of the function frame rather than the return address of the function.
Calling __builtin_frame_address with a value of 0 yields the frame address of the current function, a value of 1 yields the frame address of the caller
of the current function, and so forth.
...
check_stack_object() cont.
#if defined(CONFIG_FRAME_POINTER) && defined(CONFIG_X86)
oldframe = __builtin_frame_address(1);
if (oldframe)
frame = __builtin_frame_address(2);
...
while (stack <= frame && frame < stackend) {
...
if (obj + len <= frame)
return obj >= oldframe + 2 *
sizeof(void *) ? 2 : -1;
oldframe = frame;
frame = *(const void * const *)frame;
}
return -1;
#else
return 1;
#endif
}
fs/exec.c 0xFF...
0x00...
frame -> oldframe
oldframe
frame
Stack Grows Down
(Lower Addresses)
Stack
obj
obj+len
© All Rights Reserved
check_kernel_text_object()
● Now all there is to do is that we are not reading/writing from .text
#ifdef CONFIG_PAX_USERCOPY
static inline bool check_kernel_text_object(unsigned long low, unsigned long high)
{
...
unsigned long textlow = (unsigned long)_stext;
unsigned long texthigh = (unsigned long)_etext;
/* check against linear mapping as well */
if (high > (unsigned long)__va(__pa(textlow)) &&
low < (unsigned long)__va(__pa(texthigh)))
return true;
if (high <= textlow || low >= texthigh)
return false;
else
return true;
}
#endif
fs/exec.c
check_object_size() - Again, now from the other side
void __check_object_size(const void *ptr, unsigned long n, bool to_user, bool const_size)
{
#ifdef CONFIG_PAX_USERCOPY
const char *type;
#endif
...
#ifdef CONFIG_PAX_USERCOPY
if (!n)
return;
type = check_heap_object(ptr, n);
if (!type) {
int ret = check_stack_object(ptr, n);
if (ret == 1 || ret == 2)
return;
if (ret == 0) {
if (check_kernel_text_object((unsigned long)ptr, (unsigned long)ptr + n))
type = "";
else
return;
} else
type = "";
}
pax_report_usercopy(ptr, n, to_user, type);
#endif
fs/exec.c
✔
✔
✔
PAX_MEMORY_SANITIZE
How you’d imagine it
● Generally, what this means is that on every deallocation, we’d like to sanitize
the memory.
● If you ask me, it should look something like this:
void kfree(const void *block)
{
/* Some kfree() logic */
…
memset(block, 0x42, len);
}
kernel/lets_hope_its_that_way.c
Security is configurable! (not really…)
● PaX is configured for fast sanitization by default
○ Configurable via kernel command line
#ifdef CONFIG_PAX_MEMORY_SANITIZE
enum pax_sanitize_mode pax_sanitize_slab __read_only = PAX_SANITIZE_SLAB_FAST;
static int __init pax_sanitize_slab_setup(char *str)
{
if (!str)
return 0;
if (!strcmp(str, "0") || !strcmp(str, "off")) {
pax_sanitize_slab = PAX_SANITIZE_SLAB_OFF;
} else if (!strcmp(str, "1") || !strcmp(str, "fast")) {
pax_sanitize_slab = PAX_SANITIZE_SLAB_FAST;
} else if (!strcmp(str, "full")) {
pax_sanitize_slab = PAX_SANITIZE_SLAB_FULL;
}
...
}
early_param("pax_sanitize_slab", pax_sanitize_slab_setup);
#endif
mm/slab_common.c
○ But actually PAX_SANITIZE_SLAB_FAST doesn’t do anything. (X_X)
Using the security powder
● In order to use it, pass pax_sanitize_slab=full as kernel argument
● Creating a SLAB that is sanitizable
struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
unsigned long flags, void (*ctor)(void *))
{
...
#ifdef CONFIG_PAX_MEMORY_SANITIZE
if (pax_sanitize_slab == PAX_SANITIZE_SLAB_OFF || (flags & SLAB_DESTROY_BY_RCU))
flags |= SLAB_NO_SANITIZE;
else if (pax_sanitize_slab == PAX_SANITIZE_SLAB_FULL)
flags &= ~SLAB_NO_SANITIZE;
#endif
mm/slab_common.c
● I told you PAX_SANITIZE_SLAB_FAST does nothing...
Before anything else (!)
static int calculate_sizes(struct kmem_cache *s, int forced_order)
{
...
if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) ||
#ifdef CONFIG_PAX_MEMORY_SANITIZE
(!(flags & SLAB_NO_SANITIZE)) ||
#endif
s->ctor)) {
/*
* Relocate free pointer after the object if it is not
* permitted to overwrite the first word of the object on
* kmem_cache_free.
*
* This is the case if we do RCU, have a constructor or
* destructor or are poisoning the objects.
*/
s->offset = size;
size += sizeof(void *);
}
…
static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
{
*(void **)(object + s->offset) = fp;
}
mm/slub.c
SL(U)B internals
● In order to keep track of free slubs, Linux uses free slubs linked list
Slab Cache
Slab Object
Usual case
free
ptr Slab Object Slab Object
free
ptr Slab Object ...
free
ptr
PAX_MEMORY_SANITIZE
offset = 0 offset = object_size
© All Rights Reserved
Finally
● Yeah, it’s pretty straight forward...
static __always_inline void slab_free(struct kmem_cache *s,
struct page *page, void *x, unsigned long addr)
{
...
#ifdef CONFIG_PAX_MEMORY_SANITIZE
if (!(s->flags & SLAB_NO_SANITIZE)) {
memset(x, PAX_MEMORY_SANITIZE_VALUE, s->object_size);
if (s->ctor)
s->ctor(x);
}
#endif
mm/page_alloc.c
● Wait, what does this guy doing here?!
Gotta Clean Them All!
● Also let’s clear pages anyway upon new allocation
static inline void clear_highpage(struct page *page)
{
void *kaddr = kmap_atomic(page);
clear_page(kaddr);
kunmap_atomic(kaddr);
}
static inline void sanitize_highpage(struct page *page)
{
void *kaddr;
unsigned long flags;
local_irq_save(flags);
kaddr = kmap_atomic(page);
clear_page(kaddr);
kunmap_atomic(kaddr);
local_irq_restore(flags);
}
include/linux/highmem.h
PAX_ASLR
+
PAX_RANDMAP
What is ASLR?
● ASLR is a CONCEPT
● Acronym for: Address Space Layout Randomization
● What it basically does is random the address space for each execution
● Does it constrain which binaries we are allowed to run?
● Linux comes with a built-in ASLR
○ But it’s not that good :(
● Activate it with:
$ echo 2 > /proc/sys/kernel/randomize_va_space
Example
● In theory, on every execution the memory map should be different:
Heap
Stack
Code
Heap
Stack
Code
Heap
Stack
Code
Execution #1 Execution #2 Execution #3
Configuring PaX on an ELF basis
● Three (3) types of configuration options (depends on .config)
○ Default configuration (activates all mechanisms all the time)
○ Annotation as part of the ELF header (old method)
○ As part of file system extended attributes
● Check out chpax(1) and paxctl(1)
○ Requires a recompilation with:
■ PAX_PT_PAX_FLAGS / PAX_XATTR_PAX_FLAGS
So what do we REALLY want to random?
● Each process consists of several parts
○ brk (i.e. for malloc)
○ The ELF itself
○ mmap()s
■ For data
■ For dynamic libraries
○ Stack
● Let’s find out what happens to each of them
Brk
● Know load_elf_binary()? Well, you should!
static int load_elf_binary(struct linux_binprm *bprm)
{
...
#ifdef CONFIG_PAX_RANDMMAP
if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
unsigned long start, size, flags;
vm_flags_t vm_flags;
start = ELF_PAGEALIGN(elf_brk);
size = PAGE_SIZE + ((pax_get_random_long() & ((1UL << 22) - 1UL)) << 4);
flags = MAP_FIXED | MAP_PRIVATE;
vm_flags = VM_DONTEXPAND | VM_DONTDUMP;
down_write(current->mm->mmap_sem);
start = get_unmapped_area(NULL, start, PAGE_ALIGN(size), 0, flags);
...
if (retval == 0)
retval = set_brk(start + size, start + size + PAGE_SIZE);
...
}
#endif
fs/binfmt_elf.c
BTW this is basically a call to prandom_u32()
ELF
static int load_elf_binary(struct linux_binprm *bprm)
{
...
load_bias = ELF_ET_DYN_BASE - vaddr;
if (current->flags & PF_RANDOMIZE)
load_bias += arch_mmap_rnd();
load_bias = ELF_PAGESTART(load_bias);
#ifdef CONFIG_PAX_RANDMMAP
/* PaX: randomize base address at the default exe base if requested */
if ((current->mm->pax_flags & MF_PAX_RANDMMAP) && elf_interpreter) {
load_bias = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN) - 1)) <<
PAGE_SHIFT;
load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE - vaddr + load_bias);
elf_flags |= MAP_FIXED;
}
#endif
...
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
elf_prot, elf_flags, total_size);
...
}
#endif
fs/binfmt_elf.c
Regular Linux ASLR
PaX ASLR
Brutal
overwrite
to Linux’s
previous
work
Make sure we map it exactly there
Randomizing the Stack
● This decides where the stack top will be placed
#define STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?SEGMEXEC_TASK_SIZE:TASK_SIZE)
arch/x86/include/asm/processor.h
● And now randomize!
static unsigned long randomize_stack_top(unsigned long stack_top)
{
#ifdef CONFIG_PAX_RANDUSTACK
if (current->mm->pax_flags & MF_PAX_RANDMMAP)
return stack_top - current->mm->delta_stack;
#endif
/* … In load_elf_binary … */
retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
executable_stack);
fs/binfmt_elf.c
Another brutal hijack of PaX
before any original Linux logic
Finally map the stack VMA
int setup_arg_pages(struct linux_binprm *bprm,
unsigned long stack_top,
int executable_stack)
{
struct vm_area_struct *vma = bprm->vma;
...
stack_top = arch_align_stack(stack_top);
stack_top = PAGE_ALIGN(stack_top);
stack_shift = vma->vm_end - stack_top;
bprm->p -= stack_shift;
...
stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages
*/
stack_size = vma->vm_end - vma->vm_start;
rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
if (stack_size + stack_expand > rlim_stack)
stack_base = vma->vm_end - rlim_stack;
else
stack_base = vma->vm_start - stack_expand;
current->mm->start_stack = bprm->p;
ret = expand_stack(vma, stack_base);
fs/exec.c
vma->end
Grows Down
(Lower Addresses)
0x00...
0xFF...
vma->start
rlim_stack
stack_base =
vma->end - rlim_stack
Extended VMA
VMA
VMA
stack_expand
stack_base = vma->start - stack_expand
Stack
© All Rights Reserved
WTF random?
stack_base
0x00...
Reminder for mmap(2)
● We want to random mmap for:
○ Random data locations (i.e. got)
○ Random dynamic libraries locations (dynamic linking)
NAME
mmap, munmap - map or unmap files or devices into memory
SYNOPSIS
#include <sys/mman.h>
void *mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *start, size_t length);
Allegory
A B C
● What you’d expect
● How it is in reality
A B C
D
E
I
G
H
J
F
Randomizing mmap()
void arch_pick_mmap_layout(struct mm_struct *mm)
{
unsigned long random_factor = 0UL;
#ifdef CONFIG_PAX_RANDMMAP
if (!(mm->pax_flags & MF_PAX_RANDMMAP))
#endif
if (current->flags & PF_RANDOMIZE)
random_factor = arch_mmap_rnd();
mm->mmap_legacy_base = mmap_legacy_base(mm, random_factor);
if (mmap_is_legacy()) {
mm->mmap_base = mm->mmap_legacy_base;
mm->get_unmapped_area = arch_get_unmapped_area;
} else {
mm->mmap_base = mmap_base(mm, random_factor);
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
#ifdef CONFIG_PAX_RANDMMAP
if (mm->pax_flags & MF_PAX_RANDMMAP) {
mm->mmap_legacy_base += mm->delta_mmap;
mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
}
#endif
}
arch/x86/mm/mmap.c
Remember these
fellas. We will use
them to allocate new
pages.
Here we use the
random we
generated before
Calling the actual logic
unsigned long
arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
const unsigned long len, const unsigned long pgoff,
const unsigned long flags)
{
...
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
info.length = len;
info.low_limit = PAGE_SIZE;
info.high_limit = mm->mmap_base;
info.align_mask = 0;
info.align_offset = pgoff << PAGE_SHIFT;
if (filp) {
info.align_mask = get_align_mask();
info.align_offset += get_align_bits();
}
info.threadstack_offset = offset;
addr = vm_unmapped_area(&info);
arch/x86/kernel/sys_x86_64.c
A brief on VMAs
● VMA stands for Virtual Memory Area
● Represents a chunk of virtually contiguous pagesstruct vm_area_struct {
/* The first cache line has the info for VMA tree walking. */
unsigned long vm_start; /* Our start address within vm_mm. */
unsigned long vm_end; /* The first byte after our end address
within vm_mm. */
/* linked list of VM areas per task, sorted by address */
struct vm_area_struct *vm_next, *vm_prev;
struct rb_node vm_rb;
/*
* Largest free memory gap in bytes to the left of this VMA.
* Either between this VMA and vma->vm_prev, or between one of the
* VMAs below us in the VMA rbtree and its ->vm_prev. This helps
* get_unmapped_area find a free area of the right size.
*/
unsigned long rb_subtree_gap;
...
} __randomize_layout;
include/linux/mm_types.h
So, let’s allocate some memory!
mm_rb
vma.rb_node
vma.rb_node
vma.rb_node vma.rb_node
vma.rb_node
vma.rb_node
vma.rb_nodevma.rb_node
V
M
A
V
M
A
V
M
A
V
M
A
V
M
A
V
M
A
V
M
A
V
M
A
Doubly-Linked List, Sorted by
Virtual Address
V
M
A
vma.rb_node
info->high_limit
low_limitmmap_base
Cannot allocate in here
gap_start
high_limit
length
1
0
2 34 -> 7
gap_start
gap_end
length
© All Rights
Reserved
Questions? :)

More Related Content

What's hot

I/O, You Own: Regaining Control of Your Disk in the Presence of Bootkits
I/O, You Own: Regaining Control of Your Disk in the Presence of BootkitsI/O, You Own: Regaining Control of Your Disk in the Presence of Bootkits
I/O, You Own: Regaining Control of Your Disk in the Presence of Bootkits
CrowdStrike
 
A Kernel of Truth: Intrusion Detection and Attestation with eBPF
A Kernel of Truth: Intrusion Detection and Attestation with eBPFA Kernel of Truth: Intrusion Detection and Attestation with eBPF
A Kernel of Truth: Intrusion Detection and Attestation with eBPF
oholiab
 
The linux networking architecture
The linux networking architectureThe linux networking architecture
The linux networking architecture
hugo lu
 

What's hot (20)

Introduction to eBPF and XDP
Introduction to eBPF and XDPIntroduction to eBPF and XDP
Introduction to eBPF and XDP
 
The TCP/IP Stack in the Linux Kernel
The TCP/IP Stack in the Linux KernelThe TCP/IP Stack in the Linux Kernel
The TCP/IP Stack in the Linux Kernel
 
Berkeley Packet Filters
Berkeley Packet FiltersBerkeley Packet Filters
Berkeley Packet Filters
 
Staging driver sins
Staging driver sinsStaging driver sins
Staging driver sins
 
Linux Network Stack
Linux Network StackLinux Network Stack
Linux Network Stack
 
Understanding eBPF in a Hurry!
Understanding eBPF in a Hurry!Understanding eBPF in a Hurry!
Understanding eBPF in a Hurry!
 
Performance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux KernelPerformance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux Kernel
 
Exploitation of counter overflows in the Linux kernel
Exploitation of counter overflows in the Linux kernelExploitation of counter overflows in the Linux kernel
Exploitation of counter overflows in the Linux kernel
 
Spectre(v1%2 fv2%2fv4) v.s. meltdown(v3)
Spectre(v1%2 fv2%2fv4) v.s. meltdown(v3)Spectre(v1%2 fv2%2fv4) v.s. meltdown(v3)
Spectre(v1%2 fv2%2fv4) v.s. meltdown(v3)
 
eBPF maps 101
eBPF maps 101eBPF maps 101
eBPF maps 101
 
Network sockets
Network socketsNetwork sockets
Network sockets
 
I/O, You Own: Regaining Control of Your Disk in the Presence of Bootkits
I/O, You Own: Regaining Control of Your Disk in the Presence of BootkitsI/O, You Own: Regaining Control of Your Disk in the Presence of Bootkits
I/O, You Own: Regaining Control of Your Disk in the Presence of Bootkits
 
Direct Code Execution @ CoNEXT 2013
Direct Code Execution @ CoNEXT 2013Direct Code Execution @ CoNEXT 2013
Direct Code Execution @ CoNEXT 2013
 
Spying on the Linux kernel for fun and profit
Spying on the Linux kernel for fun and profitSpying on the Linux kernel for fun and profit
Spying on the Linux kernel for fun and profit
 
BPF - All your packets belong to me
BPF - All your packets belong to meBPF - All your packets belong to me
BPF - All your packets belong to me
 
Bpf performance tools chapter 4 bcc
Bpf performance tools chapter 4   bccBpf performance tools chapter 4   bcc
Bpf performance tools chapter 4 bcc
 
A Kernel of Truth: Intrusion Detection and Attestation with eBPF
A Kernel of Truth: Intrusion Detection and Attestation with eBPFA Kernel of Truth: Intrusion Detection and Attestation with eBPF
A Kernel of Truth: Intrusion Detection and Attestation with eBPF
 
The linux networking architecture
The linux networking architectureThe linux networking architecture
The linux networking architecture
 
Zn task - defcon russia 20
Zn task  - defcon russia 20Zn task  - defcon russia 20
Zn task - defcon russia 20
 
eBPF Basics
eBPF BasicseBPF Basics
eBPF Basics
 

Similar to grsecurity and PaX

ExperiencesSharingOnEmbeddedSystemDevelopment_20160321
ExperiencesSharingOnEmbeddedSystemDevelopment_20160321ExperiencesSharingOnEmbeddedSystemDevelopment_20160321
ExperiencesSharingOnEmbeddedSystemDevelopment_20160321
Teddy Hsiung
 
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
eugeniadean34240
 
C++tutorial
C++tutorialC++tutorial
C++tutorial
dips17
 
C aptitude questions
C aptitude questionsC aptitude questions
C aptitude questions
Srikanth
 
C - aptitude3
C - aptitude3C - aptitude3
C - aptitude3
Srikanth
 

Similar to grsecurity and PaX (20)

Linux kernel tracing superpowers in the cloud
Linux kernel tracing superpowers in the cloudLinux kernel tracing superpowers in the cloud
Linux kernel tracing superpowers in the cloud
 
Beyond Breakpoints: A Tour of Dynamic Analysis
Beyond Breakpoints: A Tour of Dynamic AnalysisBeyond Breakpoints: A Tour of Dynamic Analysis
Beyond Breakpoints: A Tour of Dynamic Analysis
 
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
PVS-Studio 5.00, a solution for developers of modern resource-intensive appl...
 
Post Exploitation Bliss: Loading Meterpreter on a Factory iPhone, Black Hat U...
Post Exploitation Bliss: Loading Meterpreter on a Factory iPhone, Black Hat U...Post Exploitation Bliss: Loading Meterpreter on a Factory iPhone, Black Hat U...
Post Exploitation Bliss: Loading Meterpreter on a Factory iPhone, Black Hat U...
 
Writing MySQL UDFs
Writing MySQL UDFsWriting MySQL UDFs
Writing MySQL UDFs
 
Quiz 9
Quiz 9Quiz 9
Quiz 9
 
Day 1
Day 1Day 1
Day 1
 
ExperiencesSharingOnEmbeddedSystemDevelopment_20160321
ExperiencesSharingOnEmbeddedSystemDevelopment_20160321ExperiencesSharingOnEmbeddedSystemDevelopment_20160321
ExperiencesSharingOnEmbeddedSystemDevelopment_20160321
 
Why learn Internals?
Why learn Internals?Why learn Internals?
Why learn Internals?
 
NativeBoost
NativeBoostNativeBoost
NativeBoost
 
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
 
Scope Stack Allocation
Scope Stack AllocationScope Stack Allocation
Scope Stack Allocation
 
C++tutorial
C++tutorialC++tutorial
C++tutorial
 
Static analysis of C++ source code
Static analysis of C++ source codeStatic analysis of C++ source code
Static analysis of C++ source code
 
Static analysis of C++ source code
Static analysis of C++ source codeStatic analysis of C++ source code
Static analysis of C++ source code
 
Introduction to c part -3
Introduction to c   part -3Introduction to c   part -3
Introduction to c part -3
 
printf tricks
printf tricksprintf tricks
printf tricks
 
C aptitude questions
C aptitude questionsC aptitude questions
C aptitude questions
 
C - aptitude3
C - aptitude3C - aptitude3
C - aptitude3
 
dynamic-allocation.pdf
dynamic-allocation.pdfdynamic-allocation.pdf
dynamic-allocation.pdf
 

More from Kernel TLV

More from Kernel TLV (20)

DPDK In Depth
DPDK In DepthDPDK In Depth
DPDK In Depth
 
SGX Trusted Execution Environment
SGX Trusted Execution EnvironmentSGX Trusted Execution Environment
SGX Trusted Execution Environment
 
Fun with FUSE
Fun with FUSEFun with FUSE
Fun with FUSE
 
Kernel Proc Connector and Containers
Kernel Proc Connector and ContainersKernel Proc Connector and Containers
Kernel Proc Connector and Containers
 
Present Absence of Linux Filesystem Security
Present Absence of Linux Filesystem SecurityPresent Absence of Linux Filesystem Security
Present Absence of Linux Filesystem Security
 
OpenWrt From Top to Bottom
OpenWrt From Top to BottomOpenWrt From Top to Bottom
OpenWrt From Top to Bottom
 
Make Your Containers Faster: Linux Container Performance Tools
Make Your Containers Faster: Linux Container Performance ToolsMake Your Containers Faster: Linux Container Performance Tools
Make Your Containers Faster: Linux Container Performance Tools
 
Emerging Persistent Memory Hardware and ZUFS - PM-based File Systems in User ...
Emerging Persistent Memory Hardware and ZUFS - PM-based File Systems in User ...Emerging Persistent Memory Hardware and ZUFS - PM-based File Systems in User ...
Emerging Persistent Memory Hardware and ZUFS - PM-based File Systems in User ...
 
File Systems: Why, How and Where
File Systems: Why, How and WhereFile Systems: Why, How and Where
File Systems: Why, How and Where
 
KernelTLV Speaker Guidelines
KernelTLV Speaker GuidelinesKernelTLV Speaker Guidelines
KernelTLV Speaker Guidelines
 
Userfaultfd: Current Features, Limitations and Future Development
Userfaultfd: Current Features, Limitations and Future DevelopmentUserfaultfd: Current Features, Limitations and Future Development
Userfaultfd: Current Features, Limitations and Future Development
 
The Linux Block Layer - Built for Fast Storage
The Linux Block Layer - Built for Fast StorageThe Linux Block Layer - Built for Fast Storage
The Linux Block Layer - Built for Fast Storage
 
Linux Kernel Cryptographic API and Use Cases
Linux Kernel Cryptographic API and Use CasesLinux Kernel Cryptographic API and Use Cases
Linux Kernel Cryptographic API and Use Cases
 
DMA Survival Guide
DMA Survival GuideDMA Survival Guide
DMA Survival Guide
 
FD.IO Vector Packet Processing
FD.IO Vector Packet ProcessingFD.IO Vector Packet Processing
FD.IO Vector Packet Processing
 
WiFi and the Beast
WiFi and the BeastWiFi and the Beast
WiFi and the Beast
 
Introduction to DPDK
Introduction to DPDKIntroduction to DPDK
Introduction to DPDK
 
Linux Interrupts
Linux InterruptsLinux Interrupts
Linux Interrupts
 
Userfaultfd and Post-Copy Migration
Userfaultfd and Post-Copy MigrationUserfaultfd and Post-Copy Migration
Userfaultfd and Post-Copy Migration
 
Switchdev - No More SDK
Switchdev - No More SDKSwitchdev - No More SDK
Switchdev - No More SDK
 

Recently uploaded

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Recently uploaded (20)

Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 

grsecurity and PaX

  • 1. grsecurity and PaX Gili Yankovitch, Nyx Software Security Solutions
  • 2. Prerequisites ● Knowledge with kernel internals (duh!) ● Knowledge of the Memory Management model ● Slab Memory allocation ... ○ But I’ll cover anything anyway...
  • 3. Key Points ● What is grsecurity and PaX ● How to apply it ○ Configuration variations ● PaX Memory Manager features ○ PAX_USERCOPY ○ PAX_MEMORY_SANITIZE ○ PAX_ASLR ■ PAX_RANDSTACK
  • 4. Linus Torvalds ● Linus is not a big fan of security... “One reason I refuse to bother with the whole security circus is that I think it glorifies - and thus encourages - the wrong behavior. It makes "heroes" out of security people, as if the people who don't just fix normal bugs aren't as important.”
  • 5. grsecurity - Technical details ● PaX is a set of features within the grsecurity (grsecurity.net) patch ● Linux Kernel patch ● Stable for versions 3.2.72 and 3.14.54 ● Test for 4.3.5 ● Was free until 08/2015 ○ Stopped being free because of copyright infringement ● Supports all major architectures ○ x86/x64, arm, ppc, mips
  • 6. Applying the patch ● Very hard. ● Doesn’t always work. ● Needs to use specific commands depending your machine. ● But some say this works: $ patch -p1 < grsecurity-3.1-4.3.5-201602032209.patch ● So now, well, you don’t have any excuse not to use it. ● Now grsecurity is applied to your kernel. ● Even just by doing this we improve our system’s security. You’ll see...
  • 7. Activating specific features ● grsecurity supports automatic configuration ● Automatic configuration depends on choosing between two factors: ○ Performance ○ Security ● They usually don’t go hand in hand... $ make menuconfig Security options ---> Grsecurity --->
  • 8. Memory Manager Refresher ● Classical memory model within the Linux Kernel is of Zones ● There are 3 major zones in classic kernel architecture: ○ ZONE_HIGHMEM ○ ZONE_NORMAL ○ ZONE_DMA ZONE_DMA ZONE_NORMAL ZONE_HIGHMEM 0x00000000 KERNEL USER 0x00000000 0xC0000000 0xFFFFFFFF Virtual Memory Physical Memory © All Rights Reserved
  • 11. copy_from_user ● Not many use this function ● Eventually leads to this piece of code: static __always_inline __must_check unsigned long __copy_from_user_nocheck(void *dst, const void __user *src, unsigned long size) { size_t sz = __compiletime_object_size(dst); unsigned ret = 0; if (size > INT_MAX) return size; check_object_size(dst, size, false); arch/x86/include/asm/uaccess_64.h ● Lets focus on check_object_size()
  • 12. check_object_size() void __check_object_size(const void *ptr, unsigned long n, bool to_user, bool const_size) { #ifdef CONFIG_PAX_USERCOPY const char *type; #endif ... #ifdef CONFIG_PAX_USERCOPY if (!n) return; type = check_heap_object(ptr, n); if (!type) { int ret = check_stack_object(ptr, n); if (ret == 1 || ret == 2) return; if (ret == 0) { if (check_kernel_text_object((unsigned long)ptr, (unsigned long)ptr + n)) type = ""; else return; } else type = ""; } pax_report_usercopy(ptr, n, to_user, type); #endif fs/exec.c
  • 13. check_heap_object() const char *check_heap_object(const void *ptr, unsigned long n) { struct page *page; struct kmem_cache *s; unsigned long offset; if (ZERO_OR_NULL_PTR(ptr)) return "<null>"; if (!virt_addr_valid(ptr)) return NULL; page = virt_to_head_page(ptr); if (!PageSlab(page)) return NULL; s = page->slab_cache; if (!(s->flags & SLAB_USERCOPY)) return s->name; offset = (ptr - page_address(page)) % s->size; if (offset <= s->object_size && n <= s->object_size - offset) return NULL; return s->name; } mm/slub.c
  • 14. check_stack_object() ● First, few basic checks #ifdef CONFIG_PAX_USERCOPY /* 0: not at all, 1: fully, 2: fully inside frame, -1: partially (implies an error) */ static noinline int check_stack_object(const void *obj, unsigned long len) { const void * const stack = task_stack_page(current); const void * const stackend = stack + THREAD_SIZE; #if defined(CONFIG_FRAME_POINTER) && defined(CONFIG_X86) const void *frame = NULL; const void *oldframe; #endif if (obj + len < obj) return -1; if (obj + len <= stack || stackend <= obj) return 0; if (obj < stack || stackend < obj + len) return -1; fs/exec.c
  • 15. All hail gcc features! ● gcc has many wonderful features ○ Some of them documented, some of them undocumented. ○ One of those documented:— Built-in Function: void * __builtin_frame_address (unsigned int level) This function is similar to __builtin_return_address, but it returns the address of the function frame rather than the return address of the function. Calling __builtin_frame_address with a value of 0 yields the frame address of the current function, a value of 1 yields the frame address of the caller of the current function, and so forth. ...
  • 16. check_stack_object() cont. #if defined(CONFIG_FRAME_POINTER) && defined(CONFIG_X86) oldframe = __builtin_frame_address(1); if (oldframe) frame = __builtin_frame_address(2); ... while (stack <= frame && frame < stackend) { ... if (obj + len <= frame) return obj >= oldframe + 2 * sizeof(void *) ? 2 : -1; oldframe = frame; frame = *(const void * const *)frame; } return -1; #else return 1; #endif } fs/exec.c 0xFF... 0x00... frame -> oldframe oldframe frame Stack Grows Down (Lower Addresses) Stack obj obj+len © All Rights Reserved
  • 17. check_kernel_text_object() ● Now all there is to do is that we are not reading/writing from .text #ifdef CONFIG_PAX_USERCOPY static inline bool check_kernel_text_object(unsigned long low, unsigned long high) { ... unsigned long textlow = (unsigned long)_stext; unsigned long texthigh = (unsigned long)_etext; /* check against linear mapping as well */ if (high > (unsigned long)__va(__pa(textlow)) && low < (unsigned long)__va(__pa(texthigh))) return true; if (high <= textlow || low >= texthigh) return false; else return true; } #endif fs/exec.c
  • 18. check_object_size() - Again, now from the other side void __check_object_size(const void *ptr, unsigned long n, bool to_user, bool const_size) { #ifdef CONFIG_PAX_USERCOPY const char *type; #endif ... #ifdef CONFIG_PAX_USERCOPY if (!n) return; type = check_heap_object(ptr, n); if (!type) { int ret = check_stack_object(ptr, n); if (ret == 1 || ret == 2) return; if (ret == 0) { if (check_kernel_text_object((unsigned long)ptr, (unsigned long)ptr + n)) type = ""; else return; } else type = ""; } pax_report_usercopy(ptr, n, to_user, type); #endif fs/exec.c ✔ ✔ ✔
  • 20. How you’d imagine it ● Generally, what this means is that on every deallocation, we’d like to sanitize the memory. ● If you ask me, it should look something like this: void kfree(const void *block) { /* Some kfree() logic */ … memset(block, 0x42, len); } kernel/lets_hope_its_that_way.c
  • 21. Security is configurable! (not really…) ● PaX is configured for fast sanitization by default ○ Configurable via kernel command line #ifdef CONFIG_PAX_MEMORY_SANITIZE enum pax_sanitize_mode pax_sanitize_slab __read_only = PAX_SANITIZE_SLAB_FAST; static int __init pax_sanitize_slab_setup(char *str) { if (!str) return 0; if (!strcmp(str, "0") || !strcmp(str, "off")) { pax_sanitize_slab = PAX_SANITIZE_SLAB_OFF; } else if (!strcmp(str, "1") || !strcmp(str, "fast")) { pax_sanitize_slab = PAX_SANITIZE_SLAB_FAST; } else if (!strcmp(str, "full")) { pax_sanitize_slab = PAX_SANITIZE_SLAB_FULL; } ... } early_param("pax_sanitize_slab", pax_sanitize_slab_setup); #endif mm/slab_common.c ○ But actually PAX_SANITIZE_SLAB_FAST doesn’t do anything. (X_X)
  • 22. Using the security powder ● In order to use it, pass pax_sanitize_slab=full as kernel argument ● Creating a SLAB that is sanitizable struct kmem_cache * kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { ... #ifdef CONFIG_PAX_MEMORY_SANITIZE if (pax_sanitize_slab == PAX_SANITIZE_SLAB_OFF || (flags & SLAB_DESTROY_BY_RCU)) flags |= SLAB_NO_SANITIZE; else if (pax_sanitize_slab == PAX_SANITIZE_SLAB_FULL) flags &= ~SLAB_NO_SANITIZE; #endif mm/slab_common.c ● I told you PAX_SANITIZE_SLAB_FAST does nothing...
  • 23. Before anything else (!) static int calculate_sizes(struct kmem_cache *s, int forced_order) { ... if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) || #ifdef CONFIG_PAX_MEMORY_SANITIZE (!(flags & SLAB_NO_SANITIZE)) || #endif s->ctor)) { /* * Relocate free pointer after the object if it is not * permitted to overwrite the first word of the object on * kmem_cache_free. * * This is the case if we do RCU, have a constructor or * destructor or are poisoning the objects. */ s->offset = size; size += sizeof(void *); } … static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) { *(void **)(object + s->offset) = fp; } mm/slub.c
  • 24. SL(U)B internals ● In order to keep track of free slubs, Linux uses free slubs linked list Slab Cache Slab Object Usual case free ptr Slab Object Slab Object free ptr Slab Object ... free ptr PAX_MEMORY_SANITIZE offset = 0 offset = object_size © All Rights Reserved
  • 25. Finally ● Yeah, it’s pretty straight forward... static __always_inline void slab_free(struct kmem_cache *s, struct page *page, void *x, unsigned long addr) { ... #ifdef CONFIG_PAX_MEMORY_SANITIZE if (!(s->flags & SLAB_NO_SANITIZE)) { memset(x, PAX_MEMORY_SANITIZE_VALUE, s->object_size); if (s->ctor) s->ctor(x); } #endif mm/page_alloc.c ● Wait, what does this guy doing here?!
  • 26. Gotta Clean Them All! ● Also let’s clear pages anyway upon new allocation static inline void clear_highpage(struct page *page) { void *kaddr = kmap_atomic(page); clear_page(kaddr); kunmap_atomic(kaddr); } static inline void sanitize_highpage(struct page *page) { void *kaddr; unsigned long flags; local_irq_save(flags); kaddr = kmap_atomic(page); clear_page(kaddr); kunmap_atomic(kaddr); local_irq_restore(flags); } include/linux/highmem.h
  • 28. What is ASLR? ● ASLR is a CONCEPT ● Acronym for: Address Space Layout Randomization ● What it basically does is random the address space for each execution ● Does it constrain which binaries we are allowed to run? ● Linux comes with a built-in ASLR ○ But it’s not that good :( ● Activate it with: $ echo 2 > /proc/sys/kernel/randomize_va_space
  • 29. Example ● In theory, on every execution the memory map should be different: Heap Stack Code Heap Stack Code Heap Stack Code Execution #1 Execution #2 Execution #3
  • 30. Configuring PaX on an ELF basis ● Three (3) types of configuration options (depends on .config) ○ Default configuration (activates all mechanisms all the time) ○ Annotation as part of the ELF header (old method) ○ As part of file system extended attributes ● Check out chpax(1) and paxctl(1) ○ Requires a recompilation with: ■ PAX_PT_PAX_FLAGS / PAX_XATTR_PAX_FLAGS
  • 31. So what do we REALLY want to random? ● Each process consists of several parts ○ brk (i.e. for malloc) ○ The ELF itself ○ mmap()s ■ For data ■ For dynamic libraries ○ Stack ● Let’s find out what happens to each of them
  • 32. Brk ● Know load_elf_binary()? Well, you should! static int load_elf_binary(struct linux_binprm *bprm) { ... #ifdef CONFIG_PAX_RANDMMAP if (current->mm->pax_flags & MF_PAX_RANDMMAP) { unsigned long start, size, flags; vm_flags_t vm_flags; start = ELF_PAGEALIGN(elf_brk); size = PAGE_SIZE + ((pax_get_random_long() & ((1UL << 22) - 1UL)) << 4); flags = MAP_FIXED | MAP_PRIVATE; vm_flags = VM_DONTEXPAND | VM_DONTDUMP; down_write(current->mm->mmap_sem); start = get_unmapped_area(NULL, start, PAGE_ALIGN(size), 0, flags); ... if (retval == 0) retval = set_brk(start + size, start + size + PAGE_SIZE); ... } #endif fs/binfmt_elf.c BTW this is basically a call to prandom_u32()
  • 33. ELF static int load_elf_binary(struct linux_binprm *bprm) { ... load_bias = ELF_ET_DYN_BASE - vaddr; if (current->flags & PF_RANDOMIZE) load_bias += arch_mmap_rnd(); load_bias = ELF_PAGESTART(load_bias); #ifdef CONFIG_PAX_RANDMMAP /* PaX: randomize base address at the default exe base if requested */ if ((current->mm->pax_flags & MF_PAX_RANDMMAP) && elf_interpreter) { load_bias = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN) - 1)) << PAGE_SHIFT; load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE - vaddr + load_bias); elf_flags |= MAP_FIXED; } #endif ... error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags, total_size); ... } #endif fs/binfmt_elf.c Regular Linux ASLR PaX ASLR Brutal overwrite to Linux’s previous work Make sure we map it exactly there
  • 34. Randomizing the Stack ● This decides where the stack top will be placed #define STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?SEGMEXEC_TASK_SIZE:TASK_SIZE) arch/x86/include/asm/processor.h ● And now randomize! static unsigned long randomize_stack_top(unsigned long stack_top) { #ifdef CONFIG_PAX_RANDUSTACK if (current->mm->pax_flags & MF_PAX_RANDMMAP) return stack_top - current->mm->delta_stack; #endif /* … In load_elf_binary … */ retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), executable_stack); fs/binfmt_elf.c Another brutal hijack of PaX before any original Linux logic
  • 35. Finally map the stack VMA int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack) { struct vm_area_struct *vma = bprm->vma; ... stack_top = arch_align_stack(stack_top); stack_top = PAGE_ALIGN(stack_top); stack_shift = vma->vm_end - stack_top; bprm->p -= stack_shift; ... stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */ stack_size = vma->vm_end - vma->vm_start; rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK; if (stack_size + stack_expand > rlim_stack) stack_base = vma->vm_end - rlim_stack; else stack_base = vma->vm_start - stack_expand; current->mm->start_stack = bprm->p; ret = expand_stack(vma, stack_base); fs/exec.c vma->end Grows Down (Lower Addresses) 0x00... 0xFF... vma->start rlim_stack stack_base = vma->end - rlim_stack Extended VMA VMA VMA stack_expand stack_base = vma->start - stack_expand Stack © All Rights Reserved WTF random? stack_base 0x00...
  • 36. Reminder for mmap(2) ● We want to random mmap for: ○ Random data locations (i.e. got) ○ Random dynamic libraries locations (dynamic linking) NAME mmap, munmap - map or unmap files or devices into memory SYNOPSIS #include <sys/mman.h> void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *start, size_t length);
  • 37. Allegory A B C ● What you’d expect ● How it is in reality A B C D E I G H J F
  • 38. Randomizing mmap() void arch_pick_mmap_layout(struct mm_struct *mm) { unsigned long random_factor = 0UL; #ifdef CONFIG_PAX_RANDMMAP if (!(mm->pax_flags & MF_PAX_RANDMMAP)) #endif if (current->flags & PF_RANDOMIZE) random_factor = arch_mmap_rnd(); mm->mmap_legacy_base = mmap_legacy_base(mm, random_factor); if (mmap_is_legacy()) { mm->mmap_base = mm->mmap_legacy_base; mm->get_unmapped_area = arch_get_unmapped_area; } else { mm->mmap_base = mmap_base(mm, random_factor); mm->get_unmapped_area = arch_get_unmapped_area_topdown; } #ifdef CONFIG_PAX_RANDMMAP if (mm->pax_flags & MF_PAX_RANDMMAP) { mm->mmap_legacy_base += mm->delta_mmap; mm->mmap_base -= mm->delta_mmap + mm->delta_stack; } #endif } arch/x86/mm/mmap.c Remember these fellas. We will use them to allocate new pages. Here we use the random we generated before
  • 39. Calling the actual logic unsigned long arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, const unsigned long len, const unsigned long pgoff, const unsigned long flags) { ... info.flags = VM_UNMAPPED_AREA_TOPDOWN; info.length = len; info.low_limit = PAGE_SIZE; info.high_limit = mm->mmap_base; info.align_mask = 0; info.align_offset = pgoff << PAGE_SHIFT; if (filp) { info.align_mask = get_align_mask(); info.align_offset += get_align_bits(); } info.threadstack_offset = offset; addr = vm_unmapped_area(&info); arch/x86/kernel/sys_x86_64.c
  • 40. A brief on VMAs ● VMA stands for Virtual Memory Area ● Represents a chunk of virtually contiguous pagesstruct vm_area_struct { /* The first cache line has the info for VMA tree walking. */ unsigned long vm_start; /* Our start address within vm_mm. */ unsigned long vm_end; /* The first byte after our end address within vm_mm. */ /* linked list of VM areas per task, sorted by address */ struct vm_area_struct *vm_next, *vm_prev; struct rb_node vm_rb; /* * Largest free memory gap in bytes to the left of this VMA. * Either between this VMA and vma->vm_prev, or between one of the * VMAs below us in the VMA rbtree and its ->vm_prev. This helps * get_unmapped_area find a free area of the right size. */ unsigned long rb_subtree_gap; ... } __randomize_layout; include/linux/mm_types.h
  • 41. So, let’s allocate some memory! mm_rb vma.rb_node vma.rb_node vma.rb_node vma.rb_node vma.rb_node vma.rb_node vma.rb_nodevma.rb_node V M A V M A V M A V M A V M A V M A V M A V M A Doubly-Linked List, Sorted by Virtual Address V M A vma.rb_node info->high_limit low_limitmmap_base Cannot allocate in here gap_start high_limit length 1 0 2 34 -> 7 gap_start gap_end length © All Rights Reserved

Editor's Notes

  1. ZONE_DMA is for DMA controllers ZONE_NORMAL implements the Buddy System ZONE_HIGHMEM is for everything else: temporary mappings, usermode memory etc… Focus on ZONE_NORMAL. Implements Slab Allocator (kmalloc uses it!) Slab is implemented on top of the Buddy System. Using it for fast access to memory
  2. Note that copy_from/to_user is ARCHITECTURE DEPENDANT. Why? Every architecture has a different way of invalidating caches, loading/unloading pages to swap etc...
  3. Eventually, we want to execute this function so we avoid pax_report_usercopy.
  4. The purpose of this function is mainly looking up the pointer’s slab. First make some basic sanity checks (not null, is mapped (virt_addr_valid)) Then get the first page of the page chain for this pointer Then check if this pointer is even backed by any slab cache This protection adds a parameter to SLABs to be marked so they can be used for communication with usermode. If this SLAB is not one of these, then we shouldn’t allow a copy. Finally, check that the copy is within the size of a single object of the SLAB Otherwise, return the name of the SLAB so the previous function will fail.
  5. Few basic checks: Len does not overflow The object is not inside the (kernel!!) stack The object does not overrun the stack partially.
  6. We travel the entire stack frame by frame For each frame, we make sure the object ends before the next frame... ...and starts after the current frame + 2 pointers Know what they are? Psst: return address and frame pointer For those that attend my previous lecture, does anyone see a semi-problem here? Do note that this DOES NOT comply with CONFIG_CC_STACKPROTECTOR
  7. Very basic. Checks against start of text and end of text symbols. Double check for any case of double mapping (i.e. vector table)
  8. Eventually, we want to execute this function so we avoid pax_report_usercopy.
  9. PAX_SANITIZE_SLAB_FAST doesn’t do anything. Use PAX_SANITIZE_SLAB_FULL
  10. This shows PAX_SANITIZE_SLAB_FAST doesn’t do anything. Doesn’t really show anything else… :P
  11. Why is this? Anyone knows why this is? Well, the answer is written in the comment...
  12. Why is this? Anyone knows why this is? Well, the answer is written in the comment… The CTor is here because we don’t wanna waste time on initializing a SLAB on an allocation. It’s important to know when your functions are called!
  13. Why does it suspend the interrupts? Well, zeroing the entire page might take a while and we don’t want anyone using it in the meantime...
  14. Yes. ASLR is a concept. Constraint: (generally!) only position independent code. In practice: position dependent code has a much lower entropy.
  15. Yes. ASLR is a concept.
  16. Stuff to random Brk ELF mmap()s Data Libraries Stack
  17. Basically, this reserves a random size for the BRK area Then sets the brk as start+size.
  18. This is pretty straight forward Note Linux’s basic ASLR Note that PaX brutally overwrites Linux’s work for load_bias
  19. First part of the function defines the higher-most address of the stack VMA [p] is not very indicative. It indicates the highest address in memory. So there are two possible actions here: Either we exceed the rlimit, so we will shrink the stack Or we will expand the stack according to this weird “random” const All in all, the randomness of the stack is conveyed by the vma->end address we use as stack_top
  20. We are going to execute arch_get_unmapped_area_topdown() to allocate new memory. Using mmap_base as the boundary for our allocation.
  21. Just highlight the info.high_limit Notice that this is the only thing that is being randomized. So actually, mmap randomness is based on disallowing processes to allocate any higher than a certain address.
  22. VMA consists of a start address and an end address. It is linked to the other VMAs of the process via two datatypes Doubly linked list Red-Black tree. It also has a “gap” member that resembles the largest unmapped area between VMAs of the current subtree (of the Red-Black tree).