
Oscar: A Practical Page-Permissions-Based Scheme for Thwarting Dangling Pointers Thurston H.Y. Dang, University of California, Berkeley; Petros Maniatis, Google Brain; David Wagner, University of California, Berkeley https://www.usenix.org/conference/usenixsecurity17/technical-sessions/presentation/dang This paper is included in the Proceedings of the 26th USENIX Security Symposium August 16–18, 2017 • Vancouver, BC, Canada ISBN 978-1-931971-40-9 Open access to the Proceedings of the 26th USENIX Security Symposium is sponsored by USENIX Oscar: A Practical Page-Permissions-Based Scheme for Thwarting Dangling Pointers Thurston H.Y. Dang Petros Maniatis David Wagner University of California, Berkeley Google Brain University of California, Berkeley Abstract 1 void( ∗∗ someFuncPtr)() = malloc(sizeof(void ∗)); 2 ∗ someFuncPtr = &Elmo;// At0x05CADA Using memory after it has been freed opens programs up 3 (∗ someFuncPtr) () ;// Correct use. to both data and control-flow exploits. Recent work on 4 void( ∗∗ callback)(); temporal memory safety has focused on using explicit 5 callback = someFuncPtr; lock-and-key mechanisms (objects are assigned a new 6 ... 7 free(someFuncPtr);// Free space. lock upon allocation, and pointers must have the correct 8 userName = malloc(...) ;// Reallocate space. key to be dereferenced) or corrupting the pointer values 9 ...// Overwrite with&Grouch at0x05DEAD. upon free(). Placing objects on separate pages and us- 10 (∗ callback)();// Use after free! ing page permissions to enforce safety is an older, well- known technique that has been maligned as too slow, without comprehensive analysis. We show that both old someFuncPtr and new techniques are conceptually instances of lock- 0 5 C A D A 0 0 callback and-key, and argue that, in principle, page permissions should be the most desirable approach. We then validate callback someFuncPtr this insight experimentally by designing, implementing, 0 5 D E A D 0 0 and evaluating Oscar, a new protection scheme based on userName page permissions. Unlike prior attempts, Oscar does not require source code, is compatible with standard and cus- Figure 1: Top: someFuncPtr and callback refer tom memory allocators, and works correctly with pro- to the function pointer, stored on the heap. Bot- grams that fork. Also, Oscar performs favorably – often tom: userName reuses the freed memory, formerly of by more than an order of magnitude – compared to re- someFuncPtr/callback. cent proposals: overall, it has similar or lower runtime overhead, and lower memory overhead than competing systems. use of the pointer (line 10), some other code could allo- cate the same memory and fill it from an untrusted source – say a network socket. When the de-allocated pointer is 1 Introduction faultily invoked, the program will jump to whatever ad- dress is stored there, say the address of the ROP gadget A temporal memory error occurs when code uses mem- Grouch() at address 0x05DEAD, hijacking control flow. ory that was allocated, but since freed (and therefore pos- Heap temporal memory safety errors are becoming in- sibly in use for another object), i.e., when an object is ac- creasingly important [27, 42]. Stack-allocated variables cessed outside of the time during which it was allocated. are easier to protect, e.g., via escape analysis, which stat- Suppose we have a function pointer stored on the heap ically checks that pointers to a stack variable do not out- that points to function Elmo() (see Figure 1) at address live the enclosing stack frame, or can be reduced to the 0x05CADA. The pointer is used for a bit and then de- heap problem, by converting stack allocations to heap allocated. However, because of a bug, the program ac- allocations [33]. Stack use-after-free is considered rare cesses that pointer again after its deallocation. [42] or difficult to exploit [27]; a 2012 study did not This bug creates a control-flow vulnerability. For ex- find any such vulnerabilities in the CVE database [15]. ample, between the de-allocation (line 7) and faulty re- We therefore focus on temporal memory safety for heap- USENIX Association 26th USENIX Security Symposium 815 allocated objects in the rest of this paper. thought to be an impractical solution – may be the most Various defenses have been tried. A decade ago, Dhur- promising for temporal memory safety. The simplicity jati and Adve [23] proposed using page permissions and of the scheme leads to excellent compatibility, deploya- aliased virtual pages for protection. In their scheme, the bility, and the lowest overhead: for example, on SPEC allocator places each allocated object on a distinct virtual CPU, CETS and FreeSentry have 48% and 30% runtime page, even though different objects may share the same overhead on hmmer respectively, vs. our 0.7% overhead; physical page; when an object is deallocated, the cor- on povray, DangNull has 280% overhead while ours is responding virtual page is rendered inaccessible, caus- < 5%. While DangSan has runtime overhead similar to ing pointer accesses after deallocation to fail. Although Oscar, DangSan’s memory overhead (140%) is higher a combination of the technique with static analysis led than Oscar’s (61.5%). Also, our study of memcached to reasonable memory economy and performance, critics shows that both standard and custom allocators can be found faults with evaluation and generality, and – with- addressed effectively and with reasonable performance. out quantitative comparison – summarily dismissed the general approach as impractical [31, 42], or without even mentioning it [41]. Since then, researchers have pro- 2 Lock-and-Key Schemes posed more elaborate techniques (CETS [31], DangSan [41], Dangling Pointer Nullification [27] (“DangNull”) Use of memory after it has been freed can be seen as an and FreeSentry [42]), relying on combinations of deeper authorization problem: pointers grant access to an allo- static analysis and comprehensive instrumentation of cated memory area and once that area is no longer al- heap operations such as object allocation, access, and located, the pointers should no longer grant access to it. pointer arithmetic. However, these schemes have yielded Some have therefore used a lock-and-key metaphor to mixed results, including poor performance, partial pro- describe the problem of temporal memory safety [31]. In tection, and incompatibility. this section, we show how different published schemes In this work, we first study past solutions, which we map to this metaphor, explicitly and sometimes implic- cast as realizations of a lock-and-key protection scheme itly, and we argue that page-permission-based protection (Section 2). We argue that using page permissions to may be the most promising approach for many work- protect from dangling pointers, an implicit lock-and-key loads (see Table 1 for a summary). scheme with lock changes, is less brittle and complex, and has the potential for superior performance. We then 2.1 Explicit Lock-and-Key: Change the develop Oscar, a new protection mechanism using page permissions, inspired by Dhurjati and Adve’s seminal Lock work [23]. We make the following contributions: In this scheme, each memory allocation is assigned a • We study in detail the overhead contributed by the lock, and each valid pointer to that allocation is assigned distinct factors of the scheme – shared memory the matching key. In Figure 1, the code is modified so mappings, memory-protection system calls invoked in line 1, the allocated object gets a new lock (say 42), during allocation and deallocation, and more page and the matching key is linked to the pointer (see Figure table entries and virtual memory areas – using the 2). Similarly, in line 5, the key linked to someFuncPtr standard SPEC CPU 2006 benchmarks (Section 3). is copied to callback. The code is instrumented so that pointer dereferencing (lines 3 and 10) is preceded by a • We reduce the impact of system calls by care- check that the pointer’s key matches the object’s lock. ful amortization of virtual-memory operations, and When the space is deallocated and reallocated to a new management of the virtul address space (Section 4). object, the new object is given a new lock (say, 43), and • We extend Oscar to handle server workloads, by userName receives the appropriate key in line 8. The supporting programs that fork children and the keys for someFuncPtr and callback no longer match common case of custom memory allocators other the lock past line 7, avoiding use after free (Figure 3). than those in the standard C library (Section 5). Since this scheme creates explicit keys (one per pointer), the memory overhead is proportional to the • We evaluate Oscar experimentally using both SPEC number of pointers. The scheme also creates one lock CPU 2006 and the popular memcached service, per object, but the number of objects is dominated by the showing that Oscar achieves superior performance, number of pointers. while providing more comprehensive protection Example Systems: Compiler-Enforced Temporal than prior approaches. Safety for C (CETS) [31] is an example of this scheme. Our work shows, in principle and experimentally, Although in our figure we have placed the key next to the that protection based on page permissions – previously pointer (similar to bounds-checking schemes that store 816 26th USENIX Security Symposium USENIX Association key: 42 lock: 42 key: 42 lock: 43 someFuncPtr someFuncPtr 0 5 C A D A 0 0 0 5 D E A D 0 0 callback callback key: 42 key: 42 userName key: 43 Figure 2: Each pointer has a key, each object has a lock. Figure 3: Lock change (see Figure 2 for the ’Before’). NULL key: XX lock: 42 someFuncPtr someFuncPtr 0 5 D E A D 0 0 callback callback key: XX userName userName key: 42 Figure 5: After pointer nullification (see Figure 1 for the Figure 4: Key revocation (see Figure 2 for the ’Before’).
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages19 Page
-
File Size-