Delta Pointers: Buffer Overflow Checks Without the Checks Tadde¨ us Kroes & Koen Koning Erik van der Kouwe Herbert Bos Cristiano Giuffrida June 19, 2018
Preview buffer[10] secret 2
Preview buffer[10] secret buffer[5] 2
Preview buffer[10] secret buffer[5] buffer[11] 2
Preview buffer[10] secret secret buffer[5] buffer[11] 2
Preview buffer[10] secret buffer[5] buffer[11] 2
Preview buffer[10] secret buffer[5] buffer[11] Automatic! FAST! - no branches - no mem access 2
Buffer overflows still very common today 3
Bounds checking is slow � % overhead 150 139% 100 94% 80% 72% 64% 50 0 SGXBounds ASan BaggyBounds Low-Fat Pointers MPX 4
What is bounds checking? void foo(char *buffer, size_t n) { buffer[n] = 10; } 5
What is bounds checking? void foo(char *buffer, size_t n) { buffer[n] = 10; Attacker-controlled? } 5
What is bounds checking? void foo(char *buffer, size_t n) { if (n >= SIZE(buffer)) ERROR("overflow"); buffer[n] = 10; } y a l l c a t i m o u t A d e e r t s i n 5
What is bounds checking? void foo(char *buffer, size_t n) { if (n >= SIZE(buffer)) ERROR("overflow"); buffer[n] = 10; Needs metadata } 5
What is bounds checking? void foo(char *buffer, size_t n) { if (n >= SIZE(buffer)) ERROR("overflow"); Branching buffer[n] = 10; Needs check metadata } 5
What is bounds checking? void foo(char *buffer, size_t n) { if (n >= SIZE(buffer)) ERROR("overflow"); Branching buffer[n] = 10; Needs check metadata } Overhead! 5
What is bounds checking? void foo(char *buffer, size_t n) { if (n >= SIZE(buffer)) ERROR("overflow"); Branching buffer[n] = 10; Needs check metadata } E ffi cient solution: Overhead! pointer tagging 5
What is bounds checking? void foo(char *buffer, size_t n) { if (n >= SIZE(buffer)) ERROR("overflow"); Branching buffer[n] = 10; Needs check metadata } Still slow E ffi cient solution: Overhead! pointer tagging 5
Our approach: Delta Pointers ◮ Use pointer tagging ◮ No memory access for metadata lookup ◮ No need for branches ◮ Delegate checks to (off-the-shelf) hardware instead ◮ Focus on common case: upper bound on x86 64 ◮ Mitigates all CVEs reported by related work 6
Our approach: Delta Pointers ◮ Use pointer tagging ◮ No memory access for metadata lookup ◮ No need for branches ◮ Delegate checks to (off-the-shelf) hardware instead ◮ Focus on common case: upper bound on x86 64 ◮ Mitigates all CVEs reported by related work 6
Our approach: Delta Pointers ◮ Use pointer tagging ◮ No memory access for metadata lookup ◮ No need for branches ◮ Delegate checks to (off-the-shelf) hardware instead ◮ Focus on common case: upper bound on x86 64 ◮ Mitigates all CVEs reported by related work 6
Our approach: Delta Pointers % overhead 150 139% 100 94% 80% 72% 64% 50 35% 0 SGXBounds ASan BaggyBounds Low-Fat Pointers Delta Pointers MPX 7
Regular pointers ext virtual address 16 bit 48 bit 00 00 00 e8 02 0c 40 10 8
Regular pointers ext virtual address 16 bit 48 bit 00 00 00 e8 02 0c 40 10 b i t s 1 6 e r p p U r o e z e b u s t m 8
Regular pointers ext ext virtual address virtual address 16 bit 16 bit 48 bit 48 bit 00 00 00 01 00 e8 02 0c 40 10 00 e8 02 0c 40 10 Non-canonical, MMU faults! 8
Tagged pointers tag virtual address 16 bit 48 bit 12 34 00 e8 02 0c 40 10 o n m a t i o r n f d e i c o E n t s ! d b i s e u n u n i 9
Tagged pointers tag virtual address 32 bit 32 bit 12 34 56 78 02 0c 40 10 Shrink address space for bigger tags 9
Delta Pointers tag virtual address 32 bit 32 bit 00 00 00 18 02 0c 40 10 size Size=24 10
Delta Pointers tag virtual address 32 bit 32 bit 00 00 00 18 02 0c 40 1c size W h a Size=24 t a b i n o u t e t r n a l p o i n t e r s ? 10
Delta Pointers tag virtual address 32 bit 32 bit 00 00 00 0c 02 0c 40 1c distance Check upper bound Distance=12 for any pointer 10
Delta Pointers tag virtual address 32 bit 32 bit ff ff ff f4 02 0c 40 1c -distance 10
Delta Pointers tag virtual address 32 bit 32 bit 0 7f ff ff f4 02 0c 40 1c -distance over fl ow bit Set to 1 if out-of-bounds 10
Delta Pointers delta tag virtual address 32 bit 32 bit 0 7f ff ff f4 02 0c 40 1c -distance over fl ow bit Set to 1 if out-of-bounds 10
Instrumentation char *p = malloc(24); 0 00 00 00 00 02 0c 40 10 11
Instrumentation char *p = malloc(24); 0 00 00 00 00 02 0c 40 10 Distance=24 11
Instrumentation char *p = malloc(24); 0 00 00 00 00 0 00 00 00 00 02 0c 40 10 -distance Distance=24 11
Instrumentation char *p = malloc(24); | (-24 << 32); 0 00 00 00 00 0 7f ff ff e8 02 0c 40 10 -24 Distance=24 11
Instrumentation p += 23; +23 0 7f ff ff e8 02 0c 40 27 11
Instrumentation p += 23; +23 0 7f ff ff e8 02 0c 40 27 Replicate arithmetic on tag 11
Instrumentation p += 23; + (23 << 32); +23 +23 0 7f ff ff e8 0 7f ff ff ff 02 0c 40 27 a n c e = 1 D i s t 11
Instrumentation p += 1 + (1 << 32); carry +1 +1 1 00 00 00 00 02 0c 40 28 Distance=0, over fl owed! 11
Instrumentation p += -1 + (-1 << 32); carry -1 -1 0 7f ff ff ff 02 0c 40 27 Distance=1, in-bounds again 11
Instrumentation p += -1 + (-1 << 32); one operation! carry -1 -1 0 7f ff ff ff 02 0c 40 27 Distance=1, in-bounds again 11
Dereferencing an in-bounds pointer 0 7f ff ff ff 02 0c 40 27 12
Dereferencing an in-bounds pointer 0 7f ff ff ff 02 0c 40 27 & 1 00 00 00 00 ff ff ff ff Strips away distance 12
Dereferencing an in-bounds pointer 0 7f ff ff ff 02 0c 40 27 & 1 00 00 00 00 ff ff ff ff 0 00 00 00 00 02 0c 40 27 12
Dereferencing an in-bounds pointer 0 7f ff ff ff 02 0c 40 27 & 1 00 00 00 00 ff ff ff ff 0 00 00 00 00 02 0c 40 27 Normal (in-bounds) pointer, access OK! 12
Dereferencing an out-of-bounds pointer 1 00 00 00 04 02 0c 40 2c 13
Dereferencing an out-of-bounds pointer 1 00 00 00 04 02 0c 40 2c & 1 00 00 00 00 ff ff ff ff 13
Dereferencing an out-of-bounds pointer 1 00 00 00 04 02 0c 40 2c & 1 00 00 00 00 ff ff ff ff 1 00 00 00 00 02 0c 40 2c 13
Dereferencing an out-of-bounds pointer 1 00 00 00 04 02 0c 40 2c & 1 00 00 00 00 ff ff ff ff 1 00 00 00 00 02 0c 40 2c Non-canonical pointer, MMU faults ! 13
Implementation ◮ LLVM based prototype for C/C++ ◮ Stack + heap + globals ◮ 32-bit address → 4GB address space ◮ 31-bit distance → 2GB allocations ◮ Instrument NULL pointer with distance = − 1 ◮ Optimizations: omit instrumentation on in-bounds pointers 14
Pointer tagging breaks things ◮ Uninstrumented libraries // strdup(ptr); TAG(strdup(MASK(ptr))); ◮ Non-zero NULL pointer ◮ Subtraction, addition, multiplication, vectors, etc. ◮ Incomplete type information (e.g., unions) ◮ Compiler quirks ◮ . . . and more ◮ Solved with TBAA + def-use chain analysis ◮ Details in paper 15
Pointer tagging breaks things ◮ Uninstrumented libraries // strdup(ptr); TAG(strdup(MASK(ptr))); ◮ Non-zero NULL pointer ◮ Subtraction, addition, multiplication, vectors, etc. ◮ Incomplete type information (e.g., unions) ◮ Compiler quirks ◮ . . . and more ◮ Solved with TBAA + def-use chain analysis ◮ Details in paper 15
Pointer tagging breaks things ◮ Uninstrumented libraries // strdup(ptr); TAG(strdup(MASK(ptr))); ◮ Non-zero NULL pointer ◮ Subtraction, addition, multiplication, vectors, etc. ◮ Incomplete type information (e.g., unions) ◮ Compiler quirks ◮ . . . and more ◮ Solved with TBAA + def-use chain analysis ◮ Details in paper 15
Pointer tagging breaks things ◮ Uninstrumented libraries // strdup(ptr); TAG(strdup(MASK(ptr))); ◮ Non-zero NULL pointer ◮ Subtraction, addition, multiplication, vectors, etc. ◮ Incomplete type information (e.g., unions) ◮ Compiler quirks ◮ . . . and more ◮ Solved with TBAA + def-use chain analysis ◮ Details in paper 15
Pointer tagging breaks things ◮ Uninstrumented libraries // strdup(ptr); TAG(strdup(MASK(ptr))); ◮ Non-zero NULL pointer ◮ Subtraction, addition, multiplication, vectors, etc. ◮ Incomplete type information (e.g., unions) ◮ Compiler quirks ◮ . . . and more ◮ Solved with TBAA + def-use chain analysis ◮ Details in paper 15
Pointer tagging breaks things ◮ Uninstrumented libraries // strdup(ptr); TAG(strdup(MASK(ptr))); ◮ Non-zero NULL pointer ◮ Subtraction, addition, multiplication, vectors, etc. ◮ Incomplete type information (e.g., unions) ◮ Compiler quirks ◮ . . . and more ◮ Solved with TBAA + def-use chain analysis ◮ Details in paper 15
Evaluation 16
Nginx 0.6 Baseline 0.5 Delta Pointers Latency (ms) 0.4 0.3 0.2 0.1 0 5 10 15 20 25 30 35 40 45 50 55 60 Throughput (x1000 reqs/s) 3-6% (I/O bound) 17
Recommend
More recommend