diff options
Diffstat (limited to 'security/sandbox/chromium')
381 files changed, 0 insertions, 80078 deletions
diff --git a/security/sandbox/chromium/LICENSE b/security/sandbox/chromium/LICENSE deleted file mode 100644 index a32e00ce6..000000000 --- a/security/sandbox/chromium/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/security/sandbox/chromium/base/at_exit.cc b/security/sandbox/chromium/base/at_exit.cc deleted file mode 100644 index 0fba35569..000000000 --- a/security/sandbox/chromium/base/at_exit.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/at_exit.h" - -#include <stddef.h> -#include <ostream> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" - -namespace base { - -// Keep a stack of registered AtExitManagers. We always operate on the most -// recent, and we should never have more than one outside of testing (for a -// statically linked version of this library). Testing may use the shadow -// version of the constructor, and if we are building a dynamic library we may -// end up with multiple AtExitManagers on the same process. We don't protect -// this for thread-safe access, since it will only be modified in testing. -static AtExitManager* g_top_manager = NULL; - -AtExitManager::AtExitManager() : next_manager_(g_top_manager) { -// If multiple modules instantiate AtExitManagers they'll end up living in this -// module... they have to coexist. -#if !defined(COMPONENT_BUILD) - DCHECK(!g_top_manager); -#endif - g_top_manager = this; -} - -AtExitManager::~AtExitManager() { - if (!g_top_manager) { - NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager"; - return; - } - DCHECK_EQ(this, g_top_manager); - - ProcessCallbacksNow(); - g_top_manager = next_manager_; -} - -// static -void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) { - DCHECK(func); - RegisterTask(base::Bind(func, param)); -} - -// static -void AtExitManager::RegisterTask(base::Closure task) { - if (!g_top_manager) { - NOTREACHED() << "Tried to RegisterCallback without an AtExitManager"; - return; - } - - AutoLock lock(g_top_manager->lock_); - g_top_manager->stack_.push(task); -} - -// static -void AtExitManager::ProcessCallbacksNow() { - if (!g_top_manager) { - NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager"; - return; - } - - AutoLock lock(g_top_manager->lock_); - - while (!g_top_manager->stack_.empty()) { - base::Closure task = g_top_manager->stack_.top(); - task.Run(); - g_top_manager->stack_.pop(); - } -} - -AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) { - DCHECK(shadow || !g_top_manager); - g_top_manager = this; -} - -} // namespace base diff --git a/security/sandbox/chromium/base/at_exit.h b/security/sandbox/chromium/base/at_exit.h deleted file mode 100644 index 04e3f7642..000000000 --- a/security/sandbox/chromium/base/at_exit.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_AT_EXIT_H_ -#define BASE_AT_EXIT_H_ - -#include <stack> - -#include "base/base_export.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" - -namespace base { - -// This class provides a facility similar to the CRT atexit(), except that -// we control when the callbacks are executed. Under Windows for a DLL they -// happen at a really bad time and under the loader lock. This facility is -// mostly used by base::Singleton. -// -// The usage is simple. Early in the main() or WinMain() scope create an -// AtExitManager object on the stack: -// int main(...) { -// base::AtExitManager exit_manager; -// -// } -// When the exit_manager object goes out of scope, all the registered -// callbacks and singleton destructors will be called. - -class BASE_EXPORT AtExitManager { - public: - typedef void (*AtExitCallbackType)(void*); - - AtExitManager(); - - // The dtor calls all the registered callbacks. Do not try to register more - // callbacks after this point. - ~AtExitManager(); - - // Registers the specified function to be called at exit. The prototype of - // the callback function is void func(void*). - static void RegisterCallback(AtExitCallbackType func, void* param); - - // Registers the specified task to be called at exit. - static void RegisterTask(base::Closure task); - - // Calls the functions registered with RegisterCallback in LIFO order. It - // is possible to register new callbacks after calling this function. - static void ProcessCallbacksNow(); - - protected: - // This constructor will allow this instance of AtExitManager to be created - // even if one already exists. This should only be used for testing! - // AtExitManagers are kept on a global stack, and it will be removed during - // destruction. This allows you to shadow another AtExitManager. - explicit AtExitManager(bool shadow); - - private: - base::Lock lock_; - std::stack<base::Closure> stack_; - AtExitManager* next_manager_; // Stack of managers to allow shadowing. - - DISALLOW_COPY_AND_ASSIGN(AtExitManager); -}; - -#if defined(UNIT_TEST) -class ShadowingAtExitManager : public AtExitManager { - public: - ShadowingAtExitManager() : AtExitManager(true) {} -}; -#endif // defined(UNIT_TEST) - -} // namespace base - -#endif // BASE_AT_EXIT_H_ diff --git a/security/sandbox/chromium/base/atomic_ref_count.h b/security/sandbox/chromium/base/atomic_ref_count.h deleted file mode 100644 index 2ab724200..000000000 --- a/security/sandbox/chromium/base/atomic_ref_count.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a low level implementation of atomic semantics for reference -// counting. Please use base/memory/ref_counted.h directly instead. - -#ifndef BASE_ATOMIC_REF_COUNT_H_ -#define BASE_ATOMIC_REF_COUNT_H_ - -#include "base/atomicops.h" - -namespace base { - -typedef subtle::Atomic32 AtomicRefCount; - -// Increment a reference count by "increment", which must exceed 0. -inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr, - AtomicRefCount increment) { - subtle::NoBarrier_AtomicIncrement(ptr, increment); -} - -// Decrement a reference count by "decrement", which must exceed 0, -// and return whether the result is non-zero. -// Insert barriers to ensure that state written before the reference count -// became zero will be visible to a thread that has just made the count zero. -inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr, - AtomicRefCount decrement) { - bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0); - return res; -} - -// Increment a reference count by 1. -inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) { - base::AtomicRefCountIncN(ptr, 1); -} - -// Decrement a reference count by 1 and return whether the result is non-zero. -// Insert barriers to ensure that state written before the reference count -// became zero will be visible to a thread that has just made the count zero. -inline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) { - return base::AtomicRefCountDecN(ptr, 1); -} - -// Return whether the reference count is one. If the reference count is used -// in the conventional way, a refrerence count of 1 implies that the current -// thread owns the reference and no other thread shares it. This call performs -// the test for a reference count of one, and performs the memory barrier -// needed for the owning thread to act on the object, knowing that it has -// exclusive access to the object. -inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) { - bool res = (subtle::Acquire_Load(ptr) == 1); - return res; -} - -// Return whether the reference count is zero. With conventional object -// referencing counting, the object will be destroyed, so the reference count -// should never be zero. Hence this is generally used for a debug check. -inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) { - bool res = (subtle::Acquire_Load(ptr) == 0); - return res; -} - -} // namespace base - -#endif // BASE_ATOMIC_REF_COUNT_H_ diff --git a/security/sandbox/chromium/base/atomic_sequence_num.h b/security/sandbox/chromium/base/atomic_sequence_num.h deleted file mode 100644 index 59b0d2551..000000000 --- a/security/sandbox/chromium/base/atomic_sequence_num.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_ATOMIC_SEQUENCE_NUM_H_ -#define BASE_ATOMIC_SEQUENCE_NUM_H_ - -#include "base/atomicops.h" -#include "base/macros.h" - -namespace base { - -class AtomicSequenceNumber; - -// Static (POD) AtomicSequenceNumber that MUST be used in global scope (or -// non-function scope) ONLY. This implementation does not generate any static -// initializer. Note that it does not implement any constructor which means -// that its fields are not initialized except when it is stored in the global -// data section (.data in ELF). If you want to allocate an atomic sequence -// number on the stack (or heap), please use the AtomicSequenceNumber class -// declared below. -class StaticAtomicSequenceNumber { - public: - inline int GetNext() { - return static_cast<int>( - base::subtle::NoBarrier_AtomicIncrement(&seq_, 1) - 1); - } - - private: - friend class AtomicSequenceNumber; - - inline void Reset() { - base::subtle::Release_Store(&seq_, 0); - } - - base::subtle::Atomic32 seq_; -}; - -// AtomicSequenceNumber that can be stored and used safely (i.e. its fields are -// always initialized as opposed to StaticAtomicSequenceNumber declared above). -// Please use StaticAtomicSequenceNumber if you want to declare an atomic -// sequence number in the global scope. -class AtomicSequenceNumber { - public: - AtomicSequenceNumber() { - seq_.Reset(); - } - - inline int GetNext() { - return seq_.GetNext(); - } - - private: - StaticAtomicSequenceNumber seq_; - DISALLOW_COPY_AND_ASSIGN(AtomicSequenceNumber); -}; - -} // namespace base - -#endif // BASE_ATOMIC_SEQUENCE_NUM_H_ diff --git a/security/sandbox/chromium/base/atomicops.h b/security/sandbox/chromium/base/atomicops.h deleted file mode 100644 index 3428fe87a..000000000 --- a/security/sandbox/chromium/base/atomicops.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// For atomic operations on reference counts, see atomic_refcount.h. -// For atomic operations on sequence numbers, see atomic_sequence_num.h. - -// The routines exported by this module are subtle. If you use them, even if -// you get the code right, it will depend on careful reasoning about atomicity -// and memory ordering; it will be less readable, and harder to maintain. If -// you plan to use these routines, you should have a good reason, such as solid -// evidence that performance would otherwise suffer, or there being no -// alternative. You should assume only properties explicitly guaranteed by the -// specifications in this file. You are almost certainly _not_ writing code -// just for the x86; if you assume x86 semantics, x86 hardware bugs and -// implementations on other archtectures will cause your code to break. If you -// do not know what you are doing, avoid these routines, and use a Mutex. -// -// It is incorrect to make direct assignments to/from an atomic variable. -// You should use one of the Load or Store routines. The NoBarrier -// versions are provided when no barriers are needed: -// NoBarrier_Store() -// NoBarrier_Load() -// Although there are currently no compiler enforcement, you are encouraged -// to use these. -// - -#ifndef BASE_ATOMICOPS_H_ -#define BASE_ATOMICOPS_H_ - -#include <stdint.h> - -// Small C++ header which defines implementation specific macros used to -// identify the STL implementation. -// - libc++: captures __config for _LIBCPP_VERSION -// - libstdc++: captures bits/c++config.h for __GLIBCXX__ -#include <cstddef> - -#include "base/base_export.h" -#include "build/build_config.h" - -#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS) -// windows.h #defines this (only on x64). This causes problems because the -// public API also uses MemoryBarrier at the public name for this fence. So, on -// X64, undef it, and call its documented -// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx) -// implementation directly. -#undef MemoryBarrier -#endif - -namespace base { -namespace subtle { - -typedef int32_t Atomic32; -#ifdef ARCH_CPU_64_BITS -// We need to be able to go between Atomic64 and AtomicWord implicitly. This -// means Atomic64 and AtomicWord should be the same type on 64-bit. -#if defined(__ILP32__) || defined(OS_NACL) -// NaCl's intptr_t is not actually 64-bits on 64-bit! -// http://code.google.com/p/nativeclient/issues/detail?id=1162 -typedef int64_t Atomic64; -#else -typedef intptr_t Atomic64; -#endif -#endif - -// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or -// Atomic64 routines below, depending on your architecture. -typedef intptr_t AtomicWord; - -// Atomically execute: -// result = *ptr; -// if (*ptr == old_value) -// *ptr = new_value; -// return result; -// -// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". -// Always return the old value of "*ptr" -// -// This routine implies no memory barriers. -Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); - -Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment); - -// These following lower-level operations are typically useful only to people -// implementing higher-level synchronization operations like spinlocks, -// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or -// a store with appropriate memory-ordering instructions. "Acquire" operations -// ensure that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory -// access. -Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); -Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); - -void MemoryBarrier(); -void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); -void Acquire_Store(volatile Atomic32* ptr, Atomic32 value); -void Release_Store(volatile Atomic32* ptr, Atomic32 value); - -Atomic32 NoBarrier_Load(volatile const Atomic32* ptr); -Atomic32 Acquire_Load(volatile const Atomic32* ptr); -Atomic32 Release_Load(volatile const Atomic32* ptr); - -// 64-bit atomic operations (only available on 64-bit processors). -#ifdef ARCH_CPU_64_BITS -Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); -Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); -Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); - -Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); -void Acquire_Store(volatile Atomic64* ptr, Atomic64 value); -void Release_Store(volatile Atomic64* ptr, Atomic64 value); -Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); -Atomic64 Acquire_Load(volatile const Atomic64* ptr); -Atomic64 Release_Load(volatile const Atomic64* ptr); -#endif // ARCH_CPU_64_BITS - -} // namespace subtle -} // namespace base - -#if defined(OS_WIN) -// TODO(jfb): The MSVC header includes windows.h, which other files end up -// relying on. Fix this as part of crbug.com/559247. -# include "base/atomicops_internals_x86_msvc.h" -#else -# include "base/atomicops_internals_portable.h" -#endif - -// On some platforms we need additional declarations to make -// AtomicWord compatible with our other Atomic* types. -#if defined(OS_MACOSX) || defined(OS_OPENBSD) -#include "base/atomicops_internals_atomicword_compat.h" -#endif - -#endif // BASE_ATOMICOPS_H_ diff --git a/security/sandbox/chromium/base/atomicops_internals_portable.h b/security/sandbox/chromium/base/atomicops_internals_portable.h deleted file mode 100644 index ee034dee1..000000000 --- a/security/sandbox/chromium/base/atomicops_internals_portable.h +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is an internal atomic implementation, use atomicops.h instead. -// -// This implementation uses C++11 atomics' member functions. The code base is -// currently written assuming atomicity revolves around accesses instead of -// C++11's memory locations. The burden is on the programmer to ensure that all -// memory locations accessed atomically are never accessed non-atomically (tsan -// should help with this). -// -// TODO(jfb) Modify the atomicops.h API and user code to declare atomic -// locations as truly atomic. See the static_assert below. -// -// Of note in this implementation: -// * All NoBarrier variants are implemented as relaxed. -// * All Barrier variants are implemented as sequentially-consistent. -// * Compare exchange's failure ordering is always the same as the success one -// (except for release, which fails as relaxed): using a weaker ordering is -// only valid under certain uses of compare exchange. -// * Acquire store doesn't exist in the C11 memory model, it is instead -// implemented as a relaxed store followed by a sequentially consistent -// fence. -// * Release load doesn't exist in the C11 memory model, it is instead -// implemented as sequentially consistent fence followed by a relaxed load. -// * Atomic increment is expected to return the post-incremented value, whereas -// C11 fetch add returns the previous value. The implementation therefore -// needs to increment twice (which the compiler should be able to detect and -// optimize). - -#ifndef BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ -#define BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ - -#include <atomic> - -#include "build/build_config.h" - -namespace base { -namespace subtle { - -// This implementation is transitional and maintains the original API for -// atomicops.h. This requires casting memory locations to the atomic types, and -// assumes that the API and the C++11 implementation are layout-compatible, -// which isn't true for all implementations or hardware platforms. The static -// assertion should detect this issue, were it to fire then this header -// shouldn't be used. -// -// TODO(jfb) If this header manages to stay committed then the API should be -// modified, and all call sites updated. -typedef volatile std::atomic<Atomic32>* AtomicLocation32; -static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32), - "incompatible 32-bit atomic layout"); - -inline void MemoryBarrier() { -#if defined(__GLIBCXX__) - // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but - // not defined, leading to the linker complaining about undefined references. - __atomic_thread_fence(std::memory_order_seq_cst); -#else - std::atomic_thread_fence(std::memory_order_seq_cst); -#endif -} - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - ((AtomicLocation32)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_relaxed, - std::memory_order_relaxed); - return old_value; -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - return ((AtomicLocation32)ptr) - ->exchange(new_value, std::memory_order_relaxed); -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return increment + - ((AtomicLocation32)ptr) - ->fetch_add(increment, std::memory_order_relaxed); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return increment + ((AtomicLocation32)ptr)->fetch_add(increment); -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - ((AtomicLocation32)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_acquire, - std::memory_order_acquire); - return old_value; -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - ((AtomicLocation32)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_release, - std::memory_order_relaxed); - return old_value; -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed); - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - ((AtomicLocation32)ptr)->store(value, std::memory_order_release); -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - return ((AtomicLocation32)ptr)->load(std::memory_order_acquire); -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrier(); - return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed); -} - -#if defined(ARCH_CPU_64_BITS) - -typedef volatile std::atomic<Atomic64>* AtomicLocation64; -static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64), - "incompatible 64-bit atomic layout"); - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - ((AtomicLocation64)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_relaxed, - std::memory_order_relaxed); - return old_value; -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - return ((AtomicLocation64)ptr) - ->exchange(new_value, std::memory_order_relaxed); -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return increment + - ((AtomicLocation64)ptr) - ->fetch_add(increment, std::memory_order_relaxed); -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return increment + ((AtomicLocation64)ptr)->fetch_add(increment); -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - ((AtomicLocation64)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_acquire, - std::memory_order_acquire); - return old_value; -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - ((AtomicLocation64)ptr) - ->compare_exchange_strong(old_value, - new_value, - std::memory_order_release, - std::memory_order_relaxed); - return old_value; -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed); -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed); - MemoryBarrier(); -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - ((AtomicLocation64)ptr)->store(value, std::memory_order_release); -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - return ((AtomicLocation64)ptr)->load(std::memory_order_acquire); -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrier(); - return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed); -} - -#endif // defined(ARCH_CPU_64_BITS) -} // namespace subtle -} // namespace base - -#endif // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ diff --git a/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h b/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h deleted file mode 100644 index 9f05b7e78..000000000 --- a/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is an internal atomic implementation, use base/atomicops.h instead. - -#ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ -#define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ - -#include <windows.h> - -#include <intrin.h> - -#include "base/macros.h" -#include "build/build_config.h" - -#if defined(ARCH_CPU_64_BITS) -// windows.h #defines this (only on x64). This causes problems because the -// public API also uses MemoryBarrier at the public name for this fence. So, on -// X64, undef it, and call its documented -// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx) -// implementation directly. -#undef MemoryBarrier -#endif - -namespace base { -namespace subtle { - -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - LONG result = _InterlockedCompareExchange( - reinterpret_cast<volatile LONG*>(ptr), - static_cast<LONG>(new_value), - static_cast<LONG>(old_value)); - return static_cast<Atomic32>(result); -} - -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, - Atomic32 new_value) { - LONG result = _InterlockedExchange( - reinterpret_cast<volatile LONG*>(ptr), - static_cast<LONG>(new_value)); - return static_cast<Atomic32>(result); -} - -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return _InterlockedExchangeAdd( - reinterpret_cast<volatile LONG*>(ptr), - static_cast<LONG>(increment)) + increment; -} - -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, - Atomic32 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - -inline void MemoryBarrier() { -#if defined(ARCH_CPU_64_BITS) - // See #undef and note at the top of this file. - __faststorefence(); -#else - // We use MemoryBarrier from WinNT.h - ::MemoryBarrier(); -#endif -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { - NoBarrier_AtomicExchange(ptr, value); - // acts as a barrier in this implementation -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - *ptr = value; // works w/o barrier for current Intel chips as of June 2005 - // See comments in Atomic64 version of Release_Store() below. -} - -inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { - return *ptr; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - return value; -} - -inline Atomic32 Release_Load(volatile const Atomic32* ptr) { - MemoryBarrier(); - return *ptr; -} - -#if defined(_WIN64) - -// 64-bit low-level operations on 64-bit platform. - -static_assert(sizeof(Atomic64) == sizeof(PVOID), "atomic word is atomic"); - -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - PVOID result = InterlockedCompareExchangePointer( - reinterpret_cast<volatile PVOID*>(ptr), - reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value)); - return reinterpret_cast<Atomic64>(result); -} - -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, - Atomic64 new_value) { - PVOID result = InterlockedExchangePointer( - reinterpret_cast<volatile PVOID*>(ptr), - reinterpret_cast<PVOID>(new_value)); - return reinterpret_cast<Atomic64>(result); -} - -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return InterlockedExchangeAdd64( - reinterpret_cast<volatile LONGLONG*>(ptr), - static_cast<LONGLONG>(increment)) + increment; -} - -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, - Atomic64 increment) { - return Barrier_AtomicIncrement(ptr, increment); -} - -inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; -} - -inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { - NoBarrier_AtomicExchange(ptr, value); - // acts as a barrier in this implementation -} - -inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { - *ptr = value; // works w/o barrier for current Intel chips as of June 2005 - - // When new chips come out, check: - // IA-32 Intel Architecture Software Developer's Manual, Volume 3: - // System Programming Guide, Chatper 7: Multiple-processor management, - // Section 7.2, Memory Ordering. - // Last seen at: - // http://developer.intel.com/design/pentium4/manuals/index_new.htm -} - -inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { - return *ptr; -} - -inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { - Atomic64 value = *ptr; - return value; -} - -inline Atomic64 Release_Load(volatile const Atomic64* ptr) { - MemoryBarrier(); - return *ptr; -} - -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - -inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value) { - return NoBarrier_CompareAndSwap(ptr, old_value, new_value); -} - - -#endif // defined(_WIN64) - -} // namespace subtle -} // namespace base - -#endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_ diff --git a/security/sandbox/chromium/base/base_export.h b/security/sandbox/chromium/base/base_export.h deleted file mode 100644 index cf7ebd781..000000000 --- a/security/sandbox/chromium/base/base_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_BASE_EXPORT_H_ -#define BASE_BASE_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(BASE_IMPLEMENTATION) -#define BASE_EXPORT __declspec(dllexport) -#else -#define BASE_EXPORT __declspec(dllimport) -#endif // defined(BASE_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(BASE_IMPLEMENTATION) -#define BASE_EXPORT __attribute__((visibility("default"))) -#else -#define BASE_EXPORT -#endif // defined(BASE_IMPLEMENTATION) -#endif - -#else // defined(COMPONENT_BUILD) -#define BASE_EXPORT -#endif - -#endif // BASE_BASE_EXPORT_H_ diff --git a/security/sandbox/chromium/base/base_paths.h b/security/sandbox/chromium/base/base_paths.h deleted file mode 100644 index 26b2fd4c9..000000000 --- a/security/sandbox/chromium/base/base_paths.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_BASE_PATHS_H_ -#define BASE_BASE_PATHS_H_ - -// This file declares path keys for the base module. These can be used with -// the PathService to access various special directories and files. - -#include "build/build_config.h" - -#if defined(OS_WIN) -#include "base/base_paths_win.h" -#elif defined(OS_MACOSX) -#include "base/base_paths_mac.h" -#elif defined(OS_ANDROID) -#include "base/base_paths_android.h" -#endif - -#if defined(OS_POSIX) -#include "base/base_paths_posix.h" -#endif - -namespace base { - -enum BasePathKey { - PATH_START = 0, - - DIR_CURRENT, // Current directory. - DIR_EXE, // Directory containing FILE_EXE. - DIR_MODULE, // Directory containing FILE_MODULE. - DIR_TEMP, // Temporary directory. - DIR_HOME, // User's root home directory. On Windows this will look - // like "C:\Users\you" (or on XP - // "C:\Document and Settings\you") which isn't necessarily - // a great place to put files. - FILE_EXE, // Path and filename of the current executable. - FILE_MODULE, // Path and filename of the module containing the code for - // the PathService (which could differ from FILE_EXE if the - // PathService were compiled into a shared object, for - // example). - DIR_SOURCE_ROOT, // Returns the root of the source tree. This key is useful - // for tests that need to locate various resources. It - // should not be used outside of test code. - DIR_USER_DESKTOP, // The current user's Desktop. - - DIR_TEST_DATA, // Used only for testing. - - PATH_END -}; - -} // namespace base - -#endif // BASE_BASE_PATHS_H_ diff --git a/security/sandbox/chromium/base/base_paths_win.h b/security/sandbox/chromium/base/base_paths_win.h deleted file mode 100644 index d9dbc39f9..000000000 --- a/security/sandbox/chromium/base/base_paths_win.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_BASE_PATHS_WIN_H_ -#define BASE_BASE_PATHS_WIN_H_ - -// This file declares windows-specific path keys for the base module. -// These can be used with the PathService to access various special -// directories and files. - -namespace base { - -enum { - PATH_WIN_START = 100, - - DIR_WINDOWS, // Windows directory, usually "c:\windows" - DIR_SYSTEM, // Usually c:\windows\system32" - // 32-bit 32-bit on 64-bit 64-bit on 64-bit - // DIR_PROGRAM_FILES 1 2 1 - // DIR_PROGRAM_FILESX86 1 2 2 - // DIR_PROGRAM_FILES6432 1 1 1 - // 1 - C:\Program Files 2 - C:\Program Files (x86) - DIR_PROGRAM_FILES, // See table above. - DIR_PROGRAM_FILESX86, // See table above. - DIR_PROGRAM_FILES6432, // See table above. - - DIR_IE_INTERNET_CACHE, // Temporary Internet Files directory. - DIR_COMMON_START_MENU, // Usually "C:\Documents and Settings\All Users\ - // Start Menu\Programs" - DIR_START_MENU, // Usually "C:\Documents and Settings\<user>\ - // Start Menu\Programs" - DIR_APP_DATA, // Application Data directory under the user profile. - DIR_LOCAL_APP_DATA, // "Local Settings\Application Data" directory under - // the user profile. - DIR_COMMON_APP_DATA, // W2K, XP, W2K3: "C:\Documents and Settings\ - // All Users\Application Data". - // Vista, W2K8 and above: "C:\ProgramData". - DIR_APP_SHORTCUTS, // Where tiles on the start screen are stored, only - // for Windows 8. Maps to "Local\AppData\Microsoft\ - // Windows\Application Shortcuts\". - DIR_COMMON_DESKTOP, // Directory for the common desktop (visible - // on all user's Desktop). - DIR_USER_QUICK_LAUNCH, // Directory for the quick launch shortcuts. - DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar - // (Win7-8) via base::win::PinShortcutToTaskbar(). - DIR_WINDOWS_FONTS, // Usually C:\Windows\Fonts. - - PATH_WIN_END -}; - -} // namespace base - -#endif // BASE_BASE_PATHS_WIN_H_ diff --git a/security/sandbox/chromium/base/base_switches.cc b/security/sandbox/chromium/base/base_switches.cc deleted file mode 100644 index 02b222988..000000000 --- a/security/sandbox/chromium/base/base_switches.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/base_switches.h" -#include "build/build_config.h" - -namespace switches { - -// Disables the crash reporting. -const char kDisableBreakpad[] = "disable-breakpad"; - -// Indicates that crash reporting should be enabled. On platforms where helper -// processes cannot access to files needed to make this decision, this flag is -// generated internally. -const char kEnableCrashReporter[] = "enable-crash-reporter"; - -// Makes memory allocators keep track of their allocations and context, so a -// detailed breakdown of memory usage can be presented in chrome://tracing when -// the memory-infra category is enabled. -const char kEnableHeapProfiling[] = "enable-heap-profiling"; - -// Generates full memory crash dump. -const char kFullMemoryCrashReport[] = "full-memory-crash-report"; - -// Force low-end device mode when set. -const char kEnableLowEndDeviceMode[] = "enable-low-end-device-mode"; - -// Force disabling of low-end device mode when set. -const char kDisableLowEndDeviceMode[] = "disable-low-end-device-mode"; - -// This option can be used to force field trials when testing changes locally. -// The argument is a list of name and value pairs, separated by slashes. If a -// trial name is prefixed with an asterisk, that trial will start activated. -// For example, the following argument defines two trials, with the second one -// activated: "GoogleNow/Enable/*MaterialDesignNTP/Default/" This option can -// also be used by the browser process to send the list of trials to a -// non-browser process, using the same format. See -// FieldTrialList::CreateTrialsFromString() in field_trial.h for details. -const char kForceFieldTrials[] = "force-fieldtrials"; - -// Suppresses all error dialogs when present. -const char kNoErrorDialogs[] = "noerrdialogs"; - -// When running certain tests that spawn child processes, this switch indicates -// to the test framework that the current process is a child process. -const char kTestChildProcess[] = "test-child-process"; - -// Gives the default maximal active V-logging level; 0 is the default. -// Normally positive values are used for V-logging levels. -const char kV[] = "v"; - -// Gives the per-module maximal V-logging levels to override the value -// given by --v. E.g. "my_module=2,foo*=3" would change the logging -// level for all code in source files "my_module.*" and "foo*.*" -// ("-inl" suffixes are also disregarded for this matching). -// -// Any pattern containing a forward or backward slash will be tested -// against the whole pathname and not just the module. E.g., -// "*/foo/bar/*=2" would change the logging level for all code in -// source files under a "foo/bar" directory. -const char kVModule[] = "vmodule"; - -// Will wait for 60 seconds for a debugger to come to attach to the process. -const char kWaitForDebugger[] = "wait-for-debugger"; - -// Sends trace events from these categories to a file. -// --trace-to-file on its own sends to default categories. -const char kTraceToFile[] = "trace-to-file"; - -// Specifies the file name for --trace-to-file. If unspecified, it will -// go to a default file name. -const char kTraceToFileName[] = "trace-to-file-name"; - -// Configure whether chrome://profiler will contain timing information. This -// option is enabled by default. A value of "0" will disable profiler timing, -// while all other values will enable it. -const char kProfilerTiming[] = "profiler-timing"; -// Value of the --profiler-timing flag that will disable timing information for -// chrome://profiler. -const char kProfilerTimingDisabledValue[] = "0"; - -#if defined(OS_WIN) -// Disables the USB keyboard detection for blocking the OSK on Win8+. -const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect"; -#endif - -#if defined(OS_POSIX) -// Used for turning on Breakpad crash reporting in a debug environment where -// crash reporting is typically compiled but disabled. -const char kEnableCrashReporterForTesting[] = - "enable-crash-reporter-for-testing"; -#endif - -} // namespace switches diff --git a/security/sandbox/chromium/base/base_switches.h b/security/sandbox/chromium/base/base_switches.h deleted file mode 100644 index c97a629d9..000000000 --- a/security/sandbox/chromium/base/base_switches.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Defines all the "base" command-line switches. - -#ifndef BASE_BASE_SWITCHES_H_ -#define BASE_BASE_SWITCHES_H_ - -#include "build/build_config.h" - -namespace switches { - -extern const char kDisableBreakpad[]; -extern const char kDisableLowEndDeviceMode[]; -extern const char kEnableCrashReporter[]; -extern const char kEnableHeapProfiling[]; -extern const char kEnableLowEndDeviceMode[]; -extern const char kForceFieldTrials[]; -extern const char kFullMemoryCrashReport[]; -extern const char kNoErrorDialogs[]; -extern const char kProfilerTiming[]; -extern const char kProfilerTimingDisabledValue[]; -extern const char kTestChildProcess[]; -extern const char kTraceToFile[]; -extern const char kTraceToFileName[]; -extern const char kV[]; -extern const char kVModule[]; -extern const char kWaitForDebugger[]; - -#if defined(OS_WIN) -extern const char kDisableUsbKeyboardDetect[]; -#endif - -#if defined(OS_POSIX) -extern const char kEnableCrashReporterForTesting[]; -#endif - -} // namespace switches - -#endif // BASE_BASE_SWITCHES_H_ diff --git a/security/sandbox/chromium/base/bind.h b/security/sandbox/chromium/base/bind.h deleted file mode 100644 index 770e45706..000000000 --- a/security/sandbox/chromium/base/bind.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_BIND_H_ -#define BASE_BIND_H_ - -#include "base/bind_internal.h" -#include "base/callback_internal.h" - -// ----------------------------------------------------------------------------- -// Usage documentation -// ----------------------------------------------------------------------------- -// -// See base/callback.h for documentation. -// -// -// ----------------------------------------------------------------------------- -// Implementation notes -// ----------------------------------------------------------------------------- -// -// If you're reading the implementation, before proceeding further, you should -// read the top comment of base/bind_internal.h for a definition of common -// terms and concepts. -// -// RETURN TYPES -// -// Though Bind()'s result is meant to be stored in a Callback<> type, it -// cannot actually return the exact type without requiring a large amount -// of extra template specializations. The problem is that in order to -// discern the correct specialization of Callback<>, Bind would need to -// unwrap the function signature to determine the signature's arity, and -// whether or not it is a method. -// -// Each unique combination of (arity, function_type, num_prebound) where -// function_type is one of {function, method, const_method} would require -// one specialization. We eventually have to do a similar number of -// specializations anyways in the implementation (see the Invoker<>, -// classes). However, it is avoidable in Bind if we return the result -// via an indirection like we do below. -// -// TODO(ajwong): We might be able to avoid this now, but need to test. -// -// It is possible to move most of the static_assert into BindState<>, but it -// feels a little nicer to have the asserts here so people do not need to crack -// open bind_internal.h. On the other hand, it makes Bind() harder to read. - -namespace base { - -template <typename Functor, typename... Args> -base::Callback< - typename internal::BindState< - typename internal::FunctorTraits<Functor>::RunnableType, - typename internal::FunctorTraits<Functor>::RunType, - typename internal::CallbackParamTraits<Args>::StorageType...> - ::UnboundRunType> -Bind(Functor functor, const Args&... args) { - // Type aliases for how to store and run the functor. - using RunnableType = typename internal::FunctorTraits<Functor>::RunnableType; - using RunType = typename internal::FunctorTraits<Functor>::RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks below for bound references need to know what the actual - // functor is going to interpret the argument as. - using BoundRunType = typename RunnableType::RunType; - - using BoundArgs = - internal::TakeTypeListItem<sizeof...(Args), - internal::ExtractArgs<BoundRunType>>; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - static_assert(!internal::HasNonConstReferenceItem<BoundArgs>::value, - "do not bind functions with nonconst ref"); - - const bool is_method = internal::HasIsMethodTag<RunnableType>::value; - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - static_assert(!internal::BindsArrayToFirstArg<is_method, Args...>::value, - "first bound argument to method cannot be array"); - static_assert( - !internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value, - "a parameter is a refcounted type and needs scoped_refptr"); - - using BindState = internal::BindState< - RunnableType, RunType, - typename internal::CallbackParamTraits<Args>::StorageType...>; - - return Callback<typename BindState::UnboundRunType>( - new BindState(internal::MakeRunnable(functor), args...)); -} - -} // namespace base - -#endif // BASE_BIND_H_ diff --git a/security/sandbox/chromium/base/bind_helpers.h b/security/sandbox/chromium/base/bind_helpers.h deleted file mode 100644 index 2add755b4..000000000 --- a/security/sandbox/chromium/base/bind_helpers.h +++ /dev/null @@ -1,658 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This defines a set of argument wrappers and related factory methods that -// can be used specify the refcounting and reference semantics of arguments -// that are bound by the Bind() function in base/bind.h. -// -// It also defines a set of simple functions and utilities that people want -// when using Callback<> and Bind(). -// -// -// ARGUMENT BINDING WRAPPERS -// -// The wrapper functions are base::Unretained(), base::Owned(), base::Passed(), -// base::ConstRef(), and base::IgnoreResult(). -// -// Unretained() allows Bind() to bind a non-refcounted class, and to disable -// refcounting on arguments that are refcounted objects. -// -// Owned() transfers ownership of an object to the Callback resulting from -// bind; the object will be deleted when the Callback is deleted. -// -// Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr) -// through a Callback. Logically, this signifies a destructive transfer of -// the state of the argument into the target function. Invoking -// Callback::Run() twice on a Callback that was created with a Passed() -// argument will CHECK() because the first invocation would have already -// transferred ownership to the target function. -// -// ConstRef() allows binding a constant reference to an argument rather -// than a copy. -// -// IgnoreResult() is used to adapt a function or Callback with a return type to -// one with a void return. This is most useful if you have a function with, -// say, a pesky ignorable bool return that you want to use with PostTask or -// something else that expect a Callback with a void return. -// -// EXAMPLE OF Unretained(): -// -// class Foo { -// public: -// void func() { cout << "Foo:f" << endl; } -// }; -// -// // In some function somewhere. -// Foo foo; -// Closure foo_callback = -// Bind(&Foo::func, Unretained(&foo)); -// foo_callback.Run(); // Prints "Foo:f". -// -// Without the Unretained() wrapper on |&foo|, the above call would fail -// to compile because Foo does not support the AddRef() and Release() methods. -// -// -// EXAMPLE OF Owned(): -// -// void foo(int* arg) { cout << *arg << endl } -// -// int* pn = new int(1); -// Closure foo_callback = Bind(&foo, Owned(pn)); -// -// foo_callback.Run(); // Prints "1" -// foo_callback.Run(); // Prints "1" -// *n = 2; -// foo_callback.Run(); // Prints "2" -// -// foo_callback.Reset(); // |pn| is deleted. Also will happen when -// // |foo_callback| goes out of scope. -// -// Without Owned(), someone would have to know to delete |pn| when the last -// reference to the Callback is deleted. -// -// -// EXAMPLE OF ConstRef(): -// -// void foo(int arg) { cout << arg << endl } -// -// int n = 1; -// Closure no_ref = Bind(&foo, n); -// Closure has_ref = Bind(&foo, ConstRef(n)); -// -// no_ref.Run(); // Prints "1" -// has_ref.Run(); // Prints "1" -// -// n = 2; -// no_ref.Run(); // Prints "1" -// has_ref.Run(); // Prints "2" -// -// Note that because ConstRef() takes a reference on |n|, |n| must outlive all -// its bound callbacks. -// -// -// EXAMPLE OF IgnoreResult(): -// -// int DoSomething(int arg) { cout << arg << endl; } -// -// // Assign to a Callback with a void return type. -// Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething)); -// cb->Run(1); // Prints "1". -// -// // Prints "1" on |ml|. -// ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1); -// -// -// EXAMPLE OF Passed(): -// -// void TakesOwnership(scoped_ptr<Foo> arg) { } -// scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); } -// -// scoped_ptr<Foo> f(new Foo()); -// -// // |cb| is given ownership of Foo(). |f| is now NULL. -// // You can use std::move(f) in place of &f, but it's more verbose. -// Closure cb = Bind(&TakesOwnership, Passed(&f)); -// -// // Run was never called so |cb| still owns Foo() and deletes -// // it on Reset(). -// cb.Reset(); -// -// // |cb| is given a new Foo created by CreateFoo(). -// cb = Bind(&TakesOwnership, Passed(CreateFoo())); -// -// // |arg| in TakesOwnership() is given ownership of Foo(). |cb| -// // no longer owns Foo() and, if reset, would not delete Foo(). -// cb.Run(); // Foo() is now transferred to |arg| and deleted. -// cb.Run(); // This CHECK()s since Foo() already been used once. -// -// Passed() is particularly useful with PostTask() when you are transferring -// ownership of an argument into a task, but don't necessarily know if the -// task will always be executed. This can happen if the task is cancellable -// or if it is posted to a TaskRunner. -// -// -// SIMPLE FUNCTIONS AND UTILITIES. -// -// DoNothing() - Useful for creating a Closure that does nothing when called. -// DeletePointer<T>() - Useful for creating a Closure that will delete a -// pointer when invoked. Only use this when necessary. -// In most cases MessageLoop::DeleteSoon() is a better -// fit. - -#ifndef BASE_BIND_HELPERS_H_ -#define BASE_BIND_HELPERS_H_ - -#include <stddef.h> - -#include <type_traits> -#include <utility> - -#include "base/callback.h" -#include "base/memory/weak_ptr.h" -#include "base/template_util.h" -#include "build/build_config.h" - -namespace base { -namespace internal { - -// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T -// for the existence of AddRef() and Release() functions of the correct -// signature. -// -// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error -// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence -// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison -// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions -// -// The last link in particular show the method used below. -// -// For SFINAE to work with inherited methods, we need to pull some extra tricks -// with multiple inheritance. In the more standard formulation, the overloads -// of Check would be: -// -// template <typename C> -// Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*); -// -// template <typename C> -// No NotTheCheckWeWant(...); -// -// static const bool value = sizeof(NotTheCheckWeWant<T>(0)) == sizeof(Yes); -// -// The problem here is that template resolution will not match -// C::TargetFunc if TargetFunc does not exist directly in C. That is, if -// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match, -// |value| will be false. This formulation only checks for whether or -// not TargetFunc exist directly in the class being introspected. -// -// To get around this, we play a dirty trick with multiple inheritance. -// First, We create a class BaseMixin that declares each function that we -// want to probe for. Then we create a class Base that inherits from both T -// (the class we wish to probe) and BaseMixin. Note that the function -// signature in BaseMixin does not need to match the signature of the function -// we are probing for; thus it's easiest to just use void(). -// -// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an -// ambiguous resolution between BaseMixin and T. This lets us write the -// following: -// -// template <typename C> -// No GoodCheck(Helper<&C::TargetFunc>*); -// -// template <typename C> -// Yes GoodCheck(...); -// -// static const bool value = sizeof(GoodCheck<Base>(0)) == sizeof(Yes); -// -// Notice here that the variadic version of GoodCheck() returns Yes here -// instead of No like the previous one. Also notice that we calculate |value| -// by specializing GoodCheck() on Base instead of T. -// -// We've reversed the roles of the variadic, and Helper overloads. -// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid -// substitution if T::TargetFunc exists. Thus GoodCheck<Base>(0) will resolve -// to the variadic version if T has TargetFunc. If T::TargetFunc does not -// exist, then &C::TargetFunc is not ambiguous, and the overload resolution -// will prefer GoodCheck(Helper<&C::TargetFunc>*). -// -// This method of SFINAE will correctly probe for inherited names, but it cannot -// typecheck those names. It's still a good enough sanity check though. -// -// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008. -// -// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted -// this works well. -// -// TODO(ajwong): Make this check for Release() as well. -// See http://crbug.com/82038. -template <typename T> -class SupportsAddRefAndRelease { - using Yes = char[1]; - using No = char[2]; - - struct BaseMixin { - void AddRef(); - }; - -// MSVC warns when you try to use Base if T has a private destructor, the -// common pattern for refcounted types. It does this even though no attempt to -// instantiate Base is made. We disable the warning for this definition. -#if defined(OS_WIN) -#pragma warning(push) -#pragma warning(disable:4624) -#endif - struct Base : public T, public BaseMixin { - }; -#if defined(OS_WIN) -#pragma warning(pop) -#endif - - template <void(BaseMixin::*)()> struct Helper {}; - - template <typename C> - static No& Check(Helper<&C::AddRef>*); - - template <typename > - static Yes& Check(...); - - public: - enum { value = sizeof(Check<Base>(0)) == sizeof(Yes) }; -}; - -// Helpers to assert that arguments of a recounted type are bound with a -// scoped_refptr. -template <bool IsClasstype, typename T> -struct UnsafeBindtoRefCountedArgHelper : false_type { -}; - -template <typename T> -struct UnsafeBindtoRefCountedArgHelper<true, T> - : integral_constant<bool, SupportsAddRefAndRelease<T>::value> { -}; - -template <typename T> -struct UnsafeBindtoRefCountedArg : false_type { -}; - -template <typename T> -struct UnsafeBindtoRefCountedArg<T*> - : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { -}; - -template <typename T> -class HasIsMethodTag { - using Yes = char[1]; - using No = char[2]; - - template <typename U> - static Yes& Check(typename U::IsMethod*); - - template <typename U> - static No& Check(...); - - public: - enum { value = sizeof(Check<T>(0)) == sizeof(Yes) }; -}; - -template <typename T> -class UnretainedWrapper { - public: - explicit UnretainedWrapper(T* o) : ptr_(o) {} - T* get() const { return ptr_; } - private: - T* ptr_; -}; - -template <typename T> -class ConstRefWrapper { - public: - explicit ConstRefWrapper(const T& o) : ptr_(&o) {} - const T& get() const { return *ptr_; } - private: - const T* ptr_; -}; - -template <typename T> -struct IgnoreResultHelper { - explicit IgnoreResultHelper(T functor) : functor_(functor) {} - - T functor_; -}; - -template <typename T> -struct IgnoreResultHelper<Callback<T> > { - explicit IgnoreResultHelper(const Callback<T>& functor) : functor_(functor) {} - - const Callback<T>& functor_; -}; - -// An alternate implementation is to avoid the destructive copy, and instead -// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to -// a class that is essentially a scoped_ptr<>. -// -// The current implementation has the benefit though of leaving ParamTraits<> -// fully in callback_internal.h as well as avoiding type conversions during -// storage. -template <typename T> -class OwnedWrapper { - public: - explicit OwnedWrapper(T* o) : ptr_(o) {} - ~OwnedWrapper() { delete ptr_; } - T* get() const { return ptr_; } - OwnedWrapper(const OwnedWrapper& other) { - ptr_ = other.ptr_; - other.ptr_ = NULL; - } - - private: - mutable T* ptr_; -}; - -// PassedWrapper is a copyable adapter for a scoper that ignores const. -// -// It is needed to get around the fact that Bind() takes a const reference to -// all its arguments. Because Bind() takes a const reference to avoid -// unnecessary copies, it is incompatible with movable-but-not-copyable -// types; doing a destructive "move" of the type into Bind() would violate -// the const correctness. -// -// This conundrum cannot be solved without either C++11 rvalue references or -// a O(2^n) blowup of Bind() templates to handle each combination of regular -// types and movable-but-not-copyable types. Thus we introduce a wrapper type -// that is copyable to transmit the correct type information down into -// BindState<>. Ignoring const in this type makes sense because it is only -// created when we are explicitly trying to do a destructive move. -// -// Two notes: -// 1) PassedWrapper supports any type that has a move constructor, however -// the type will need to be specifically whitelisted in order for it to be -// bound to a Callback. We guard this explicitly at the call of Passed() -// to make for clear errors. Things not given to Passed() will be forwarded -// and stored by value which will not work for general move-only types. -// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" -// scoper to a Callback and allow the Callback to execute once. -template <typename T> -class PassedWrapper { - public: - explicit PassedWrapper(T&& scoper) - : is_valid_(true), scoper_(std::move(scoper)) {} - PassedWrapper(const PassedWrapper& other) - : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} - T Pass() const { - CHECK(is_valid_); - is_valid_ = false; - return std::move(scoper_); - } - - private: - mutable bool is_valid_; - mutable T scoper_; -}; - -// Unwrap the stored parameters for the wrappers above. -template <typename T> -struct UnwrapTraits { - using ForwardType = const T&; - static ForwardType Unwrap(const T& o) { return o; } -}; - -template <typename T> -struct UnwrapTraits<UnretainedWrapper<T> > { - using ForwardType = T*; - static ForwardType Unwrap(UnretainedWrapper<T> unretained) { - return unretained.get(); - } -}; - -template <typename T> -struct UnwrapTraits<ConstRefWrapper<T> > { - using ForwardType = const T&; - static ForwardType Unwrap(ConstRefWrapper<T> const_ref) { - return const_ref.get(); - } -}; - -template <typename T> -struct UnwrapTraits<scoped_refptr<T> > { - using ForwardType = T*; - static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); } -}; - -template <typename T> -struct UnwrapTraits<WeakPtr<T> > { - using ForwardType = const WeakPtr<T>&; - static ForwardType Unwrap(const WeakPtr<T>& o) { return o; } -}; - -template <typename T> -struct UnwrapTraits<OwnedWrapper<T> > { - using ForwardType = T*; - static ForwardType Unwrap(const OwnedWrapper<T>& o) { - return o.get(); - } -}; - -template <typename T> -struct UnwrapTraits<PassedWrapper<T> > { - using ForwardType = T; - static T Unwrap(PassedWrapper<T>& o) { - return o.Pass(); - } -}; - -// Utility for handling different refcounting semantics in the Bind() -// function. -template <bool is_method, typename... T> -struct MaybeScopedRefPtr; - -template <bool is_method> -struct MaybeScopedRefPtr<is_method> { - MaybeScopedRefPtr() {} -}; - -template <typename T, typename... Rest> -struct MaybeScopedRefPtr<false, T, Rest...> { - MaybeScopedRefPtr(const T&, const Rest&...) {} -}; - -template <typename T, size_t n, typename... Rest> -struct MaybeScopedRefPtr<false, T[n], Rest...> { - MaybeScopedRefPtr(const T*, const Rest&...) {} -}; - -template <typename T, typename... Rest> -struct MaybeScopedRefPtr<true, T, Rest...> { - MaybeScopedRefPtr(const T& o, const Rest&...) {} -}; - -template <typename T, typename... Rest> -struct MaybeScopedRefPtr<true, T*, Rest...> { - MaybeScopedRefPtr(T* o, const Rest&...) : ref_(o) {} - scoped_refptr<T> ref_; -}; - -// No need to additionally AddRef() and Release() since we are storing a -// scoped_refptr<> inside the storage object already. -template <typename T, typename... Rest> -struct MaybeScopedRefPtr<true, scoped_refptr<T>, Rest...> { - MaybeScopedRefPtr(const scoped_refptr<T>&, const Rest&...) {} -}; - -template <typename T, typename... Rest> -struct MaybeScopedRefPtr<true, const T*, Rest...> { - MaybeScopedRefPtr(const T* o, const Rest&...) : ref_(o) {} - scoped_refptr<const T> ref_; -}; - -// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a -// method. It is used internally by Bind() to select the correct -// InvokeHelper that will no-op itself in the event the WeakPtr<> for -// the target object is invalidated. -// -// The first argument should be the type of the object that will be received by -// the method. -template <bool IsMethod, typename... Args> -struct IsWeakMethod : public false_type {}; - -template <typename T, typename... Args> -struct IsWeakMethod<true, WeakPtr<T>, Args...> : public true_type {}; - -template <typename T, typename... Args> -struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T>>, Args...> - : public true_type {}; - - -// Packs a list of types to hold them in a single type. -template <typename... Types> -struct TypeList {}; - -// Used for DropTypeListItem implementation. -template <size_t n, typename List> -struct DropTypeListItemImpl; - -// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure. -template <size_t n, typename T, typename... List> -struct DropTypeListItemImpl<n, TypeList<T, List...>> - : DropTypeListItemImpl<n - 1, TypeList<List...>> {}; - -template <typename T, typename... List> -struct DropTypeListItemImpl<0, TypeList<T, List...>> { - using Type = TypeList<T, List...>; -}; - -template <> -struct DropTypeListItemImpl<0, TypeList<>> { - using Type = TypeList<>; -}; - -// A type-level function that drops |n| list item from given TypeList. -template <size_t n, typename List> -using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type; - -// Used for TakeTypeListItem implementation. -template <size_t n, typename List, typename... Accum> -struct TakeTypeListItemImpl; - -// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure. -template <size_t n, typename T, typename... List, typename... Accum> -struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...> - : TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {}; - -template <typename T, typename... List, typename... Accum> -struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> { - using Type = TypeList<Accum...>; -}; - -template <typename... Accum> -struct TakeTypeListItemImpl<0, TypeList<>, Accum...> { - using Type = TypeList<Accum...>; -}; - -// A type-level function that takes first |n| list item from given TypeList. -// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to -// TypeList<A, B, C>. -template <size_t n, typename List> -using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type; - -// Used for ConcatTypeLists implementation. -template <typename List1, typename List2> -struct ConcatTypeListsImpl; - -template <typename... Types1, typename... Types2> -struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> { - using Type = TypeList<Types1..., Types2...>; -}; - -// A type-level function that concats two TypeLists. -template <typename List1, typename List2> -using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type; - -// Used for MakeFunctionType implementation. -template <typename R, typename ArgList> -struct MakeFunctionTypeImpl; - -template <typename R, typename... Args> -struct MakeFunctionTypeImpl<R, TypeList<Args...>> { - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R Type(Args...); -}; - -// A type-level function that constructs a function type that has |R| as its -// return type and has TypeLists items as its arguments. -template <typename R, typename ArgList> -using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type; - -// Used for ExtractArgs. -template <typename Signature> -struct ExtractArgsImpl; - -template <typename R, typename... Args> -struct ExtractArgsImpl<R(Args...)> { - using Type = TypeList<Args...>; -}; - -// A type-level function that extracts function arguments into a TypeList. -// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>. -template <typename Signature> -using ExtractArgs = typename ExtractArgsImpl<Signature>::Type; - -} // namespace internal - -template <typename T> -static inline internal::UnretainedWrapper<T> Unretained(T* o) { - return internal::UnretainedWrapper<T>(o); -} - -template <typename T> -static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { - return internal::ConstRefWrapper<T>(o); -} - -template <typename T> -static inline internal::OwnedWrapper<T> Owned(T* o) { - return internal::OwnedWrapper<T>(o); -} - -// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and -// is best suited for use with the return value of a function or other temporary -// rvalues. The second takes a pointer to the scoper and is just syntactic sugar -// to avoid having to write Passed(std::move(scoper)). -// -// Both versions of Passed() prevent T from being an lvalue reference. The first -// via use of enable_if, and the second takes a T* which will not bind to T&. -template <typename T, - typename std::enable_if<internal::IsMoveOnlyType<T>::value && - !std::is_lvalue_reference<T>::value>::type* = - nullptr> -static inline internal::PassedWrapper<T> Passed(T&& scoper) { - return internal::PassedWrapper<T>(std::move(scoper)); -} -template <typename T, - typename std::enable_if<internal::IsMoveOnlyType<T>::value>::type* = - nullptr> -static inline internal::PassedWrapper<T> Passed(T* scoper) { - return internal::PassedWrapper<T>(std::move(*scoper)); -} - -template <typename T> -static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { - return internal::IgnoreResultHelper<T>(data); -} - -template <typename T> -static inline internal::IgnoreResultHelper<Callback<T> > -IgnoreResult(const Callback<T>& data) { - return internal::IgnoreResultHelper<Callback<T> >(data); -} - -BASE_EXPORT void DoNothing(); - -template<typename T> -void DeletePointer(T* obj) { - delete obj; -} - -} // namespace base - -#endif // BASE_BIND_HELPERS_H_ diff --git a/security/sandbox/chromium/base/bind_internal.h b/security/sandbox/chromium/base/bind_internal.h deleted file mode 100644 index ac7cd0098..000000000 --- a/security/sandbox/chromium/base/bind_internal.h +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_BIND_INTERNAL_H_ -#define BASE_BIND_INTERNAL_H_ - -#include <stddef.h> - -#include <type_traits> - -#include "base/bind_helpers.h" -#include "base/callback_internal.h" -#include "base/memory/raw_scoped_refptr_mismatch_checker.h" -#include "base/memory/weak_ptr.h" -#include "base/template_util.h" -#include "base/tuple.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include "base/bind_internal_win.h" -#endif - -namespace base { -namespace internal { - -// See base/callback.h for user documentation. -// -// -// CONCEPTS: -// Runnable -- A type (really a type class) that has a single Run() method -// and a RunType typedef that corresponds to the type of Run(). -// A Runnable can declare that it should treated like a method -// call by including a typedef named IsMethod. The value of -// this typedef is NOT inspected, only the existence. When a -// Runnable declares itself a method, Bind() will enforce special -// refcounting + WeakPtr handling semantics for the first -// parameter which is expected to be an object. -// Functor -- A copyable type representing something that should be called. -// All function pointers, Callback<>, and Runnables are functors -// even if the invocation syntax differs. -// RunType -- A function type (as opposed to function _pointer_ type) for -// a Run() function. Usually just a convenience typedef. -// (Bound)Args -- A set of types that stores the arguments. -// -// Types: -// RunnableAdapter<> -- Wraps the various "function" pointer types into an -// object that adheres to the Runnable interface. -// ForceVoidReturn<> -- Helper class for translating function signatures to -// equivalent forms with a "void" return type. -// FunctorTraits<> -- Type traits used determine the correct RunType and -// RunnableType for a Functor. This is where function -// signature adapters are applied. -// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable -// type class that represents the underlying Functor. -// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. -// Handle the differing syntaxes needed for WeakPtr<> -// support, and for ignoring return values. This is separate -// from Invoker to avoid creating multiple version of -// Invoker<>. -// Invoker<> -- Unwraps the curried parameters and executes the Runnable. -// BindState<> -- Stores the curried parameters, and is the main entry point -// into the Bind() system, doing most of the type resolution. -// There are ARITY BindState types. - -// HasNonConstReferenceParam selects true_type when any of the parameters in -// |Sig| is a non-const reference. -// Implementation note: This non-specialized case handles zero-arity case only. -// Non-zero-arity cases should be handled by the specialization below. -template <typename List> -struct HasNonConstReferenceItem : false_type {}; - -// Implementation note: Select true_type if the first parameter is a non-const -// reference. Otherwise, skip the first parameter and check rest of parameters -// recursively. -template <typename T, typename... Args> -struct HasNonConstReferenceItem<TypeList<T, Args...>> - : std::conditional<is_non_const_reference<T>::value, - true_type, - HasNonConstReferenceItem<TypeList<Args...>>>::type {}; - -// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw -// pointer to a RefCounted type. -// Implementation note: This non-specialized case handles zero-arity case only. -// Non-zero-arity cases should be handled by the specialization below. -template <typename... Args> -struct HasRefCountedTypeAsRawPtr : false_type {}; - -// Implementation note: Select true_type if the first parameter is a raw pointer -// to a RefCounted type. Otherwise, skip the first parameter and check rest of -// parameters recursively. -template <typename T, typename... Args> -struct HasRefCountedTypeAsRawPtr<T, Args...> - : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value, - true_type, - HasRefCountedTypeAsRawPtr<Args...>>::type {}; - -// BindsArrayToFirstArg selects true_type when |is_method| is true and the first -// item of |Args| is an array type. -// Implementation note: This non-specialized case handles !is_method case and -// zero-arity case only. Other cases should be handled by the specialization -// below. -template <bool is_method, typename... Args> -struct BindsArrayToFirstArg : false_type {}; - -template <typename T, typename... Args> -struct BindsArrayToFirstArg<true, T, Args...> : is_array<T> {}; - -// HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except -// when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument. -// Implementation note: This non-specialized case handles !is_method case and -// zero-arity case only. Other cases should be handled by the specialization -// below. -template <bool is_method, typename... Args> -struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {}; - -template <typename T, typename... Args> -struct HasRefCountedParamAsRawPtr<true, T, Args...> - : HasRefCountedTypeAsRawPtr<Args...> {}; - -// RunnableAdapter<> -// -// The RunnableAdapter<> templates provide a uniform interface for invoking -// a function pointer, method pointer, or const method pointer. The adapter -// exposes a Run() method with an appropriate signature. Using this wrapper -// allows for writing code that supports all three pointer types without -// undue repetition. Without it, a lot of code would need to be repeated 3 -// times. -// -// For method pointers and const method pointers the first argument to Run() -// is considered to be the received of the method. This is similar to STL's -// mem_fun(). -// -// This class also exposes a RunType typedef that is the function type of the -// Run() function. -// -// If and only if the wrapper contains a method or const method pointer, an -// IsMethod typedef is exposed. The existence of this typedef (NOT the value) -// marks that the wrapper should be considered a method wrapper. - -template <typename Functor> -class RunnableAdapter; - -// Function. -template <typename R, typename... Args> -class RunnableAdapter<R(*)(Args...)> { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(Args...); - - explicit RunnableAdapter(R(*function)(Args...)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<Args>::ForwardType... args) { - return function_(CallbackForward(args)...); - } - - private: - R (*function_)(Args...); -}; - -// Method. -template <typename R, typename T, typename... Args> -class RunnableAdapter<R(T::*)(Args...)> { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(T*, Args...); - using IsMethod = true_type; - - explicit RunnableAdapter(R(T::*method)(Args...)) - : method_(method) { - } - - R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) { - return (object->*method_)(CallbackForward(args)...); - } - - private: - R (T::*method_)(Args...); -}; - -// Const Method. -template <typename R, typename T, typename... Args> -class RunnableAdapter<R(T::*)(Args...) const> { - public: - using RunType = R(const T*, Args...); - using IsMethod = true_type; - - explicit RunnableAdapter(R(T::*method)(Args...) const) - : method_(method) { - } - - R Run(const T* object, - typename CallbackParamTraits<Args>::ForwardType... args) { - return (object->*method_)(CallbackForward(args)...); - } - - private: - R (T::*method_)(Args...) const; -}; - - -// ForceVoidReturn<> -// -// Set of templates that support forcing the function return type to void. -template <typename Sig> -struct ForceVoidReturn; - -template <typename R, typename... Args> -struct ForceVoidReturn<R(Args...)> { - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef void RunType(Args...); -}; - - -// FunctorTraits<> -// -// See description at top of file. -template <typename T> -struct FunctorTraits { - using RunnableType = RunnableAdapter<T>; - using RunType = typename RunnableType::RunType; -}; - -template <typename T> -struct FunctorTraits<IgnoreResultHelper<T>> { - using RunnableType = typename FunctorTraits<T>::RunnableType; - using RunType = - typename ForceVoidReturn<typename RunnableType::RunType>::RunType; -}; - -template <typename T> -struct FunctorTraits<Callback<T>> { - using RunnableType = Callback<T> ; - using RunType = typename Callback<T>::RunType; -}; - - -// MakeRunnable<> -// -// Converts a passed in functor to a RunnableType using type inference. - -template <typename T> -typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { - return RunnableAdapter<T>(t); -} - -template <typename T> -typename FunctorTraits<T>::RunnableType -MakeRunnable(const IgnoreResultHelper<T>& t) { - return MakeRunnable(t.functor_); -} - -template <typename T> -const typename FunctorTraits<Callback<T>>::RunnableType& -MakeRunnable(const Callback<T>& t) { - DCHECK(!t.is_null()); - return t; -} - - -// InvokeHelper<> -// -// There are 3 logical InvokeHelper<> specializations: normal, void-return, -// WeakCalls. -// -// The normal type just calls the underlying runnable. -// -// We need a InvokeHelper to handle void return types in order to support -// IgnoreResult(). Normally, if the Runnable's RunType had a void return, -// the template system would just accept "return functor.Run()" ignoring -// the fact that a void function is being used with return. This piece of -// sugar breaks though when the Runnable's RunType is not void. Thus, we -// need a partial specialization to change the syntax to drop the "return" -// from the invocation call. -// -// WeakCalls similarly need special syntax that is applied to the first -// argument to check if they should no-op themselves. -template <bool IsWeakCall, typename ReturnType, typename Runnable, - typename ArgsType> -struct InvokeHelper; - -template <typename ReturnType, typename Runnable, typename... Args> -struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> { - static ReturnType MakeItSo(Runnable runnable, Args... args) { - return runnable.Run(CallbackForward(args)...); - } -}; - -template <typename Runnable, typename... Args> -struct InvokeHelper<false, void, Runnable, TypeList<Args...>> { - static void MakeItSo(Runnable runnable, Args... args) { - runnable.Run(CallbackForward(args)...); - } -}; - -template <typename Runnable, typename BoundWeakPtr, typename... Args> -struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> { - static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) { - if (!weak_ptr.get()) { - return; - } - runnable.Run(weak_ptr.get(), CallbackForward(args)...); - } -}; - -#if !defined(_MSC_VER) - -template <typename ReturnType, typename Runnable, typename ArgsType> -struct InvokeHelper<true, ReturnType, Runnable, ArgsType> { - // WeakCalls are only supported for functions with a void return type. - // Otherwise, the function result would be undefined if the the WeakPtr<> - // is invalidated. - static_assert(is_void<ReturnType>::value, - "weak_ptrs can only bind to methods without return values"); -}; - -#endif - -// Invoker<> -// -// See description at the top of the file. -template <typename BoundIndices, - typename StorageType, typename Unwrappers, - typename InvokeHelperType, typename UnboundForwardRunType> -struct Invoker; - -template <size_t... bound_indices, - typename StorageType, - typename... Unwrappers, - typename InvokeHelperType, - typename R, - typename... UnboundForwardArgs> -struct Invoker<IndexSequence<bound_indices...>, - StorageType, TypeList<Unwrappers...>, - InvokeHelperType, R(UnboundForwardArgs...)> { - static R Run(BindStateBase* base, - UnboundForwardArgs... unbound_args) { - StorageType* storage = static_cast<StorageType*>(base); - // Local references to make debugger stepping easier. If in a debugger, - // you really want to warp ahead and step through the - // InvokeHelper<>::MakeItSo() call below. - return InvokeHelperType::MakeItSo( - storage->runnable_, - Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))..., - CallbackForward(unbound_args)...); - } -}; - - -// BindState<> -// -// This stores all the state passed into Bind() and is also where most -// of the template resolution magic occurs. -// -// Runnable is the functor we are binding arguments to. -// RunType is type of the Run() function that the Invoker<> should use. -// Normally, this is the same as the RunType of the Runnable, but it can -// be different if an adapter like IgnoreResult() has been used. -// -// BoundArgs contains the storage type for all the bound arguments. -template <typename Runnable, typename RunType, typename... BoundArgs> -struct BindState; - -template <typename Runnable, - typename R, - typename... Args, - typename... BoundArgs> -struct BindState<Runnable, R(Args...), BoundArgs...> final - : public BindStateBase { - private: - using StorageType = BindState<Runnable, R(Args...), BoundArgs...>; - using RunnableType = Runnable; - - // true_type if Runnable is a method invocation and the first bound argument - // is a WeakPtr. - using IsWeakCall = - IsWeakMethod<HasIsMethodTag<Runnable>::value, BoundArgs...>; - - using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>; - using Unwrappers = TypeList<UnwrapTraits<BoundArgs>...>; - using UnboundForwardArgs = DropTypeListItem< - sizeof...(BoundArgs), - TypeList<typename CallbackParamTraits<Args>::ForwardType...>>; - using UnboundForwardRunType = MakeFunctionType<R, UnboundForwardArgs>; - - using InvokeHelperArgs = ConcatTypeLists< - TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>, - UnboundForwardArgs>; - using InvokeHelperType = - InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>; - - using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>; - - public: - using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers, - InvokeHelperType, UnboundForwardRunType>; - using UnboundRunType = MakeFunctionType<R, UnboundArgs>; - - BindState(const Runnable& runnable, const BoundArgs&... bound_args) - : BindStateBase(&Destroy), - runnable_(runnable), - ref_(bound_args...), - bound_args_(bound_args...) {} - - RunnableType runnable_; - MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_; - Tuple<BoundArgs...> bound_args_; - - private: - ~BindState() {} - - static void Destroy(BindStateBase* self) { - delete static_cast<BindState*>(self); - } -}; - -} // namespace internal -} // namespace base - -#endif // BASE_BIND_INTERNAL_H_ diff --git a/security/sandbox/chromium/base/bind_internal_win.h b/security/sandbox/chromium/base/bind_internal_win.h deleted file mode 100644 index 2ee12ef21..000000000 --- a/security/sandbox/chromium/base/bind_internal_win.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Specializations of RunnableAdapter<> for Windows specific calling -// conventions. Please see base/bind_internal.h for more info. - -#ifndef BASE_BIND_INTERNAL_WIN_H_ -#define BASE_BIND_INTERNAL_WIN_H_ - -#include "build/build_config.h" - -// In the x64 architecture in Windows, __fastcall, __stdcall, etc, are all -// the same as __cdecl which would turn the following specializations into -// multiple definitions. -#if !defined(ARCH_CPU_X86_64) - -namespace base { -namespace internal { - -template <typename Functor> -class RunnableAdapter; - -// __stdcall Function. -template <typename R, typename... Args> -class RunnableAdapter<R(__stdcall *)(Args...)> { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(Args...); - - explicit RunnableAdapter(R(__stdcall *function)(Args...)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<Args>::ForwardType... args) { - return function_(args...); - } - - private: - R (__stdcall *function_)(Args...); -}; - -// __fastcall Function. -template <typename R, typename... Args> -class RunnableAdapter<R(__fastcall *)(Args...)> { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(Args...); - - explicit RunnableAdapter(R(__fastcall *function)(Args...)) - : function_(function) { - } - - R Run(typename CallbackParamTraits<Args>::ForwardType... args) { - return function_(args...); - } - - private: - R (__fastcall *function_)(Args...); -}; - -} // namespace internal -} // namespace base - -#endif // !defined(ARCH_CPU_X86_64) - -#endif // BASE_BIND_INTERNAL_WIN_H_ diff --git a/security/sandbox/chromium/base/bit_cast.h b/security/sandbox/chromium/base/bit_cast.h deleted file mode 100644 index b548467e7..000000000 --- a/security/sandbox/chromium/base/bit_cast.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_BIT_CAST_H_ -#define BASE_BIT_CAST_H_ - -#include <string.h> - -// bit_cast<Dest,Source> is a template function that implements the equivalent -// of "*reinterpret_cast<Dest*>(&source)". We need this in very low-level -// functions like the protobuf library and fast math support. -// -// float f = 3.14159265358979; -// int i = bit_cast<int32_t>(f); -// // i = 0x40490fdb -// -// The classical address-casting method is: -// -// // WRONG -// float f = 3.14159265358979; // WRONG -// int i = * reinterpret_cast<int*>(&f); // WRONG -// -// The address-casting method actually produces undefined behavior according to -// the ISO C++98 specification, section 3.10 ("basic.lval"), paragraph 15. -// (This did not substantially change in C++11.) Roughly, this section says: if -// an object in memory has one type, and a program accesses it with a different -// type, then the result is undefined behavior for most values of "different -// type". -// -// This is true for any cast syntax, either *(int*)&f or -// *reinterpret_cast<int*>(&f). And it is particularly true for conversions -// between integral lvalues and floating-point lvalues. -// -// The purpose of this paragraph is to allow optimizing compilers to assume that -// expressions with different types refer to different memory. Compilers are -// known to take advantage of this. So a non-conforming program quietly -// produces wildly incorrect output. -// -// The problem is not the use of reinterpret_cast. The problem is type punning: -// holding an object in memory of one type and reading its bits back using a -// different type. -// -// The C++ standard is more subtle and complex than this, but that is the basic -// idea. -// -// Anyways ... -// -// bit_cast<> calls memcpy() which is blessed by the standard, especially by the -// example in section 3.9 . Also, of course, bit_cast<> wraps up the nasty -// logic in one place. -// -// Fortunately memcpy() is very fast. In optimized mode, compilers replace -// calls to memcpy() with inline object code when the size argument is a -// compile-time constant. On a 32-bit system, memcpy(d,s,4) compiles to one -// load and one store, and memcpy(d,s,8) compiles to two loads and two stores. -// -// WARNING: if Dest or Source is a non-POD type, the result of the memcpy -// is likely to surprise you. - -template <class Dest, class Source> -inline Dest bit_cast(const Source& source) { - static_assert(sizeof(Dest) == sizeof(Source), - "bit_cast requires source and destination to be the same size"); - - Dest dest; - memcpy(&dest, &source, sizeof(dest)); - return dest; -} - -#endif // BASE_BIT_CAST_H_ diff --git a/security/sandbox/chromium/base/callback.h b/security/sandbox/chromium/base/callback.h deleted file mode 100644 index 3bf0008b6..000000000 --- a/security/sandbox/chromium/base/callback.h +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_CALLBACK_H_ -#define BASE_CALLBACK_H_ - -#include "base/callback_forward.h" -#include "base/callback_internal.h" -#include "base/template_util.h" - -// NOTE: Header files that do not require the full definition of Callback or -// Closure should #include "base/callback_forward.h" instead of this file. - -// ----------------------------------------------------------------------------- -// Introduction -// ----------------------------------------------------------------------------- -// -// The templated Callback class is a generalized function object. Together -// with the Bind() function in bind.h, they provide a type-safe method for -// performing partial application of functions. -// -// Partial application (or "currying") is the process of binding a subset of -// a function's arguments to produce another function that takes fewer -// arguments. This can be used to pass around a unit of delayed execution, -// much like lexical closures are used in other languages. For example, it -// is used in Chromium code to schedule tasks on different MessageLoops. -// -// A callback with no unbound input parameters (base::Callback<void()>) -// is called a base::Closure. Note that this is NOT the same as what other -// languages refer to as a closure -- it does not retain a reference to its -// enclosing environment. -// -// MEMORY MANAGEMENT AND PASSING -// -// The Callback objects themselves should be passed by const-reference, and -// stored by copy. They internally store their state via a refcounted class -// and thus do not need to be deleted. -// -// The reason to pass via a const-reference is to avoid unnecessary -// AddRef/Release pairs to the internal state. -// -// -// ----------------------------------------------------------------------------- -// Quick reference for basic stuff -// ----------------------------------------------------------------------------- -// -// BINDING A BARE FUNCTION -// -// int Return5() { return 5; } -// base::Callback<int()> func_cb = base::Bind(&Return5); -// LOG(INFO) << func_cb.Run(); // Prints 5. -// -// BINDING A CLASS METHOD -// -// The first argument to bind is the member function to call, the second is -// the object on which to call it. -// -// class Ref : public base::RefCountedThreadSafe<Ref> { -// public: -// int Foo() { return 3; } -// void PrintBye() { LOG(INFO) << "bye."; } -// }; -// scoped_refptr<Ref> ref = new Ref(); -// base::Callback<void()> ref_cb = base::Bind(&Ref::Foo, ref); -// LOG(INFO) << ref_cb.Run(); // Prints out 3. -// -// By default the object must support RefCounted or you will get a compiler -// error. If you're passing between threads, be sure it's -// RefCountedThreadSafe! See "Advanced binding of member functions" below if -// you don't want to use reference counting. -// -// RUNNING A CALLBACK -// -// Callbacks can be run with their "Run" method, which has the same -// signature as the template argument to the callback. -// -// void DoSomething(const base::Callback<void(int, std::string)>& callback) { -// callback.Run(5, "hello"); -// } -// -// Callbacks can be run more than once (they don't get deleted or marked when -// run). However, this precludes using base::Passed (see below). -// -// void DoSomething(const base::Callback<double(double)>& callback) { -// double myresult = callback.Run(3.14159); -// myresult += callback.Run(2.71828); -// } -// -// PASSING UNBOUND INPUT PARAMETERS -// -// Unbound parameters are specified at the time a callback is Run(). They are -// specified in the Callback template type: -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback<void(int, const std::string&)> cb = base::Bind(&MyFunc); -// cb.Run(23, "hello, world"); -// -// PASSING BOUND INPUT PARAMETERS -// -// Bound parameters are specified when you create thee callback as arguments -// to Bind(). They will be passed to the function and the Run()ner of the -// callback doesn't see those values or even know that the function it's -// calling. -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback<void()> cb = base::Bind(&MyFunc, 23, "hello world"); -// cb.Run(); -// -// A callback with no unbound input parameters (base::Callback<void()>) -// is called a base::Closure. So we could have also written: -// -// base::Closure cb = base::Bind(&MyFunc, 23, "hello world"); -// -// When calling member functions, bound parameters just go after the object -// pointer. -// -// base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world"); -// -// PARTIAL BINDING OF PARAMETERS -// -// You can specify some parameters when you create the callback, and specify -// the rest when you execute the callback. -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback<void(const std::string&)> cb = base::Bind(&MyFunc, 23); -// cb.Run("hello world"); -// -// When calling a function bound parameters are first, followed by unbound -// parameters. -// -// -// ----------------------------------------------------------------------------- -// Quick reference for advanced binding -// ----------------------------------------------------------------------------- -// -// BINDING A CLASS METHOD WITH WEAK POINTERS -// -// base::Bind(&MyClass::Foo, GetWeakPtr()); -// -// The callback will not be run if the object has already been destroyed. -// DANGER: weak pointers are not threadsafe, so don't use this -// when passing between threads! -// -// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT -// -// base::Bind(&MyClass::Foo, base::Unretained(this)); -// -// This disables all lifetime management on the object. You're responsible -// for making sure the object is alive at the time of the call. You break it, -// you own it! -// -// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS -// -// MyClass* myclass = new MyClass; -// base::Bind(&MyClass::Foo, base::Owned(myclass)); -// -// The object will be deleted when the callback is destroyed, even if it's -// not run (like if you post a task during shutdown). Potentially useful for -// "fire and forget" cases. -// -// IGNORING RETURN VALUES -// -// Sometimes you want to call a function that returns a value in a callback -// that doesn't expect a return value. -// -// int DoSomething(int arg) { cout << arg << endl; } -// base::Callback<void(int)> cb = -// base::Bind(base::IgnoreResult(&DoSomething)); -// -// -// ----------------------------------------------------------------------------- -// Quick reference for binding parameters to Bind() -// ----------------------------------------------------------------------------- -// -// Bound parameters are specified as arguments to Bind() and are passed to the -// function. A callback with no parameters or no unbound parameters is called a -// Closure (base::Callback<void()> and base::Closure are the same thing). -// -// PASSING PARAMETERS OWNED BY THE CALLBACK -// -// void Foo(int* arg) { cout << *arg << endl; } -// int* pn = new int(1); -// base::Closure foo_callback = base::Bind(&foo, base::Owned(pn)); -// -// The parameter will be deleted when the callback is destroyed, even if it's -// not run (like if you post a task during shutdown). -// -// PASSING PARAMETERS AS A scoped_ptr -// -// void TakesOwnership(scoped_ptr<Foo> arg) {} -// scoped_ptr<Foo> f(new Foo); -// // f becomes null during the following call. -// base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f)); -// -// Ownership of the parameter will be with the callback until the it is run, -// when ownership is passed to the callback function. This means the callback -// can only be run once. If the callback is never run, it will delete the -// object when it's destroyed. -// -// PASSING PARAMETERS AS A scoped_refptr -// -// void TakesOneRef(scoped_refptr<Foo> arg) {} -// scoped_refptr<Foo> f(new Foo) -// base::Closure cb = base::Bind(&TakesOneRef, f); -// -// This should "just work." The closure will take a reference as long as it -// is alive, and another reference will be taken for the called function. -// -// PASSING PARAMETERS BY REFERENCE -// -// Const references are *copied* unless ConstRef is used. Example: -// -// void foo(const int& arg) { printf("%d %p\n", arg, &arg); } -// int n = 1; -// base::Closure has_copy = base::Bind(&foo, n); -// base::Closure has_ref = base::Bind(&foo, base::ConstRef(n)); -// n = 2; -// foo(n); // Prints "2 0xaaaaaaaaaaaa" -// has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" -// has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa" -// -// Normally parameters are copied in the closure. DANGER: ConstRef stores a -// const reference instead, referencing the original parameter. This means -// that you must ensure the object outlives the callback! -// -// -// ----------------------------------------------------------------------------- -// Implementation notes -// ----------------------------------------------------------------------------- -// -// WHERE IS THIS DESIGN FROM: -// -// The design Callback and Bind is heavily influenced by C++'s -// tr1::function/tr1::bind, and by the "Google Callback" system used inside -// Google. -// -// -// HOW THE IMPLEMENTATION WORKS: -// -// There are three main components to the system: -// 1) The Callback classes. -// 2) The Bind() functions. -// 3) The arguments wrappers (e.g., Unretained() and ConstRef()). -// -// The Callback classes represent a generic function pointer. Internally, -// it stores a refcounted piece of state that represents the target function -// and all its bound parameters. Each Callback specialization has a templated -// constructor that takes an BindState<>*. In the context of the constructor, -// the static type of this BindState<> pointer uniquely identifies the -// function it is representing, all its bound parameters, and a Run() method -// that is capable of invoking the target. -// -// Callback's constructor takes the BindState<>* that has the full static type -// and erases the target function type as well as the types of the bound -// parameters. It does this by storing a pointer to the specific Run() -// function, and upcasting the state of BindState<>* to a -// BindStateBase*. This is safe as long as this BindStateBase pointer -// is only used with the stored Run() pointer. -// -// To BindState<> objects are created inside the Bind() functions. -// These functions, along with a set of internal templates, are responsible for -// -// - Unwrapping the function signature into return type, and parameters -// - Determining the number of parameters that are bound -// - Creating the BindState storing the bound parameters -// - Performing compile-time asserts to avoid error-prone behavior -// - Returning an Callback<> with an arity matching the number of unbound -// parameters and that knows the correct refcounting semantics for the -// target object if we are binding a method. -// -// The Bind functions do the above using type-inference, and template -// specializations. -// -// By default Bind() will store copies of all bound parameters, and attempt -// to refcount a target object if the function being bound is a class method. -// These copies are created even if the function takes parameters as const -// references. (Binding to non-const references is forbidden, see bind.h.) -// -// To change this behavior, we introduce a set of argument wrappers -// (e.g., Unretained(), and ConstRef()). These are simple container templates -// that are passed by value, and wrap a pointer to argument. See the -// file-level comment in base/bind_helpers.h for more info. -// -// These types are passed to the Unwrap() functions, and the MaybeRefcount() -// functions respectively to modify the behavior of Bind(). The Unwrap() -// and MaybeRefcount() functions change behavior by doing partial -// specialization based on whether or not a parameter is a wrapper type. -// -// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium. -// -// -// WHY NOT TR1 FUNCTION/BIND? -// -// Direct use of tr1::function and tr1::bind was considered, but ultimately -// rejected because of the number of copy constructors invocations involved -// in the binding of arguments during construction, and the forwarding of -// arguments during invocation. These copies will no longer be an issue in -// C++0x because C++0x will support rvalue reference allowing for the compiler -// to avoid these copies. However, waiting for C++0x is not an option. -// -// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the -// tr1::bind call itself will invoke a non-trivial copy constructor three times -// for each bound parameter. Also, each when passing a tr1::function, each -// bound argument will be copied again. -// -// In addition to the copies taken at binding and invocation, copying a -// tr1::function causes a copy to be made of all the bound parameters and -// state. -// -// Furthermore, in Chromium, it is desirable for the Callback to take a -// reference on a target object when representing a class method call. This -// is not supported by tr1. -// -// Lastly, tr1::function and tr1::bind has a more general and flexible API. -// This includes things like argument reordering by use of -// tr1::bind::placeholder, support for non-const reference parameters, and some -// limited amount of subtyping of the tr1::function object (e.g., -// tr1::function<int(int)> is convertible to tr1::function<void(int)>). -// -// These are not features that are required in Chromium. Some of them, such as -// allowing for reference parameters, and subtyping of functions, may actually -// become a source of errors. Removing support for these features actually -// allows for a simpler implementation, and a terser Currying API. -// -// -// WHY NOT GOOGLE CALLBACKS? -// -// The Google callback system also does not support refcounting. Furthermore, -// its implementation has a number of strange edge cases with respect to type -// conversion of its arguments. In particular, the argument's constness must -// at times match exactly the function signature, or the type-inference might -// break. Given the above, writing a custom solution was easier. -// -// -// MISSING FUNCTIONALITY -// - Invoking the return of Bind. Bind(&foo).Run() does not work; -// - Binding arrays to functions that take a non-const pointer. -// Example: -// void Foo(const char* ptr); -// void Bar(char* ptr); -// Bind(&Foo, "test"); -// Bind(&Bar, "test"); // This fails because ptr is not const. - -namespace base { - -// First, we forward declare the Callback class template. This informs the -// compiler that the template only has 1 type parameter which is the function -// signature that the Callback is representing. -// -// After this, create template specializations for 0-7 parameters. Note that -// even though the template typelist grows, the specialization still -// only has one type: the function signature. -// -// If you are thinking of forward declaring Callback in your own header file, -// please include "base/callback_forward.h" instead. - -namespace internal { -template <typename Runnable, typename RunType, typename... BoundArgsType> -struct BindState; -} // namespace internal - -template <typename R, typename... Args> -class Callback<R(Args...)> : public internal::CallbackBase { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(Args...); - - Callback() : CallbackBase(nullptr) { } - - template <typename Runnable, typename BindRunType, typename... BoundArgsType> - explicit Callback( - internal::BindState<Runnable, BindRunType, BoundArgsType...>* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &internal::BindState<Runnable, BindRunType, BoundArgsType...> - ::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename internal::CallbackParamTraits<Args>::ForwardType... args) - const { - PolymorphicInvoke f = - reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - - return f(bind_state_.get(), internal::CallbackForward(args)...); - } - - private: - using PolymorphicInvoke = - R(*)(internal::BindStateBase*, - typename internal::CallbackParamTraits<Args>::ForwardType...); -}; - -} // namespace base - -#endif // BASE_CALLBACK_H_ diff --git a/security/sandbox/chromium/base/callback_forward.h b/security/sandbox/chromium/base/callback_forward.h deleted file mode 100644 index a9a263a50..000000000 --- a/security/sandbox/chromium/base/callback_forward.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_CALLBACK_FORWARD_H_ -#define BASE_CALLBACK_FORWARD_H_ - -namespace base { - -template <typename Sig> -class Callback; - -// Syntactic sugar to make Callback<void()> easier to declare since it -// will be used in a lot of APIs with delayed execution. -using Closure = Callback<void()>; - -} // namespace base - -#endif // BASE_CALLBACK_FORWARD_H_ diff --git a/security/sandbox/chromium/base/callback_internal.cc b/security/sandbox/chromium/base/callback_internal.cc deleted file mode 100644 index 2553fe7e1..000000000 --- a/security/sandbox/chromium/base/callback_internal.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/callback_internal.h" - -#include "base/logging.h" - -namespace base { -namespace internal { - -void BindStateBase::AddRef() { - AtomicRefCountInc(&ref_count_); -} - -void BindStateBase::Release() { - if (!AtomicRefCountDec(&ref_count_)) - destructor_(this); -} - -CallbackBase::CallbackBase(const CallbackBase& c) = default; -CallbackBase& CallbackBase::operator=(const CallbackBase& c) = default; - -void CallbackBase::Reset() { - polymorphic_invoke_ = NULL; - // NULL the bind_state_ last, since it may be holding the last ref to whatever - // object owns us, and we may be deleted after that. - bind_state_ = NULL; -} - -bool CallbackBase::Equals(const CallbackBase& other) const { - return bind_state_.get() == other.bind_state_.get() && - polymorphic_invoke_ == other.polymorphic_invoke_; -} - -CallbackBase::CallbackBase(BindStateBase* bind_state) - : bind_state_(bind_state), - polymorphic_invoke_(NULL) { - DCHECK(!bind_state_.get() || bind_state_->ref_count_ == 1); -} - -CallbackBase::~CallbackBase() { -} - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/callback_internal.h b/security/sandbox/chromium/base/callback_internal.h deleted file mode 100644 index d1d8ab8ec..000000000 --- a/security/sandbox/chromium/base/callback_internal.h +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains utility functions and classes that help the -// implementation, and management of the Callback objects. - -#ifndef BASE_CALLBACK_INTERNAL_H_ -#define BASE_CALLBACK_INTERNAL_H_ - -#include <stddef.h> -#include <memory> -#include <type_traits> - -#include "base/atomic_ref_count.h" -#include "base/base_export.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/template_util.h" - -namespace base { -namespace internal { -class CallbackBase; - -// BindStateBase is used to provide an opaque handle that the Callback -// class can use to represent a function object with bound arguments. It -// behaves as an existential type that is used by a corresponding -// DoInvoke function to perform the function execution. This allows -// us to shield the Callback class from the types of the bound argument via -// "type erasure." -// At the base level, the only task is to add reference counting data. Don't use -// RefCountedThreadSafe since it requires the destructor to be a virtual method. -// Creating a vtable for every BindState template instantiation results in a lot -// of bloat. Its only task is to call the destructor which can be done with a -// function pointer. -class BindStateBase { - protected: - explicit BindStateBase(void (*destructor)(BindStateBase*)) - : ref_count_(0), destructor_(destructor) {} - ~BindStateBase() = default; - - private: - friend class scoped_refptr<BindStateBase>; - friend class CallbackBase; - - void AddRef(); - void Release(); - - AtomicRefCount ref_count_; - - // Pointer to a function that will properly destroy |this|. - void (*destructor_)(BindStateBase*); - - DISALLOW_COPY_AND_ASSIGN(BindStateBase); -}; - -// Holds the Callback methods that don't require specialization to reduce -// template bloat. -class BASE_EXPORT CallbackBase { - public: - CallbackBase(const CallbackBase& c); - CallbackBase& operator=(const CallbackBase& c); - - // Returns true if Callback is null (doesn't refer to anything). - bool is_null() const { return bind_state_.get() == NULL; } - - // Returns the Callback into an uninitialized state. - void Reset(); - - protected: - // In C++, it is safe to cast function pointers to function pointers of - // another type. It is not okay to use void*. We create a InvokeFuncStorage - // that that can store our function pointer, and then cast it back to - // the original type on usage. - using InvokeFuncStorage = void(*)(); - - // Returns true if this callback equals |other|. |other| may be null. - bool Equals(const CallbackBase& other) const; - - // Allow initializing of |bind_state_| via the constructor to avoid default - // initialization of the scoped_refptr. We do not also initialize - // |polymorphic_invoke_| here because doing a normal assignment in the - // derived Callback templates makes for much nicer compiler errors. - explicit CallbackBase(BindStateBase* bind_state); - - // Force the destructor to be instantiated inside this translation unit so - // that our subclasses will not get inlined versions. Avoids more template - // bloat. - ~CallbackBase(); - - scoped_refptr<BindStateBase> bind_state_; - InvokeFuncStorage polymorphic_invoke_; -}; - -// A helper template to determine if given type is non-const move-only-type, -// i.e. if a value of the given type should be passed via std::move() in a -// destructive way. Types are considered to be move-only if they have a -// sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using -// the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro. -// It would be easy to generalize this trait to all move-only types... but this -// confuses template deduction in VS2013 with certain types such as -// std::unique_ptr. -// TODO(dcheng): Revisit this when Windows switches to VS2015 by default. -template <typename T> struct IsMoveOnlyType { - template <typename U> - static YesType Test(const typename U::MoveOnlyTypeForCPP03*); - - template <typename U> - static NoType Test(...); - - static const bool value = sizeof((Test<T>(0))) == sizeof(YesType) && - !is_const<T>::value; -}; - -// Specialization of IsMoveOnlyType so that std::unique_ptr is still considered -// move-only, even without the sentinel member. -template <typename T> -struct IsMoveOnlyType<std::unique_ptr<T>> : std::true_type {}; - -template <typename> -struct CallbackParamTraitsForMoveOnlyType; - -template <typename> -struct CallbackParamTraitsForNonMoveOnlyType; - -// TODO(tzik): Use a default parameter once MSVS supports variadic templates -// with default values. -// http://connect.microsoft.com/VisualStudio/feedbackdetail/view/957801/compilation-error-with-variadic-templates -// -// This is a typetraits object that's used to take an argument type, and -// extract a suitable type for storing and forwarding arguments. -// -// In particular, it strips off references, and converts arrays to -// pointers for storage; and it avoids accidentally trying to create a -// "reference of a reference" if the argument is a reference type. -// -// This array type becomes an issue for storage because we are passing bound -// parameters by const reference. In this case, we end up passing an actual -// array type in the initializer list which C++ does not allow. This will -// break passing of C-string literals. -template <typename T> -struct CallbackParamTraits - : std::conditional<IsMoveOnlyType<T>::value, - CallbackParamTraitsForMoveOnlyType<T>, - CallbackParamTraitsForNonMoveOnlyType<T>>::type { -}; - -template <typename T> -struct CallbackParamTraitsForNonMoveOnlyType { - using ForwardType = const T&; - using StorageType = T; -}; - -// The Storage should almost be impossible to trigger unless someone manually -// specifies type of the bind parameters. However, in case they do, -// this will guard against us accidentally storing a reference parameter. -// -// The ForwardType should only be used for unbound arguments. -template <typename T> -struct CallbackParamTraitsForNonMoveOnlyType<T&> { - using ForwardType = T&; - using StorageType = T; -}; - -// Note that for array types, we implicitly add a const in the conversion. This -// means that it is not possible to bind array arguments to functions that take -// a non-const pointer. Trying to specialize the template based on a "const -// T[n]" does not seem to match correctly, so we are stuck with this -// restriction. -template <typename T, size_t n> -struct CallbackParamTraitsForNonMoveOnlyType<T[n]> { - using ForwardType = const T*; - using StorageType = const T*; -}; - -// See comment for CallbackParamTraits<T[n]>. -template <typename T> -struct CallbackParamTraitsForNonMoveOnlyType<T[]> { - using ForwardType = const T*; - using StorageType = const T*; -}; - -// Parameter traits for movable-but-not-copyable scopers. -// -// Callback<>/Bind() understands movable-but-not-copyable semantics where -// the type cannot be copied but can still have its state destructively -// transferred (aka. moved) to another instance of the same type by calling a -// helper function. When used with Bind(), this signifies transferal of the -// object's state to the target function. -// -// For these types, the ForwardType must not be a const reference, or a -// reference. A const reference is inappropriate, and would break const -// correctness, because we are implementing a destructive move. A non-const -// reference cannot be used with temporaries which means the result of a -// function or a cast would not be usable with Callback<> or Bind(). -template <typename T> -struct CallbackParamTraitsForMoveOnlyType { - using ForwardType = T; - using StorageType = T; -}; - -// CallbackForward() is a very limited simulation of C++11's std::forward() -// used by the Callback/Bind system for a set of movable-but-not-copyable -// types. It is needed because forwarding a movable-but-not-copyable -// argument to another function requires us to invoke the proper move -// operator to create a rvalue version of the type. The supported types are -// whitelisted below as overloads of the CallbackForward() function. The -// default template compiles out to be a no-op. -// -// In C++11, std::forward would replace all uses of this function. However, it -// is impossible to implement a general std::forward without C++11 due to a lack -// of rvalue references. -// -// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to -// simulate std::forward() and forward the result of one Callback as a -// parameter to another callback. This is to support Callbacks that return -// the movable-but-not-copyable types whitelisted above. -template <typename T> -typename std::enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward( - T& t) { - return t; -} - -template <typename T> -typename std::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward( - T& t) { - return std::move(t); -} - -} // namespace internal -} // namespace base - -#endif // BASE_CALLBACK_INTERNAL_H_ diff --git a/security/sandbox/chromium/base/compiler_specific.h b/security/sandbox/chromium/base/compiler_specific.h deleted file mode 100644 index 339e9b74e..000000000 --- a/security/sandbox/chromium/base/compiler_specific.h +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_COMPILER_SPECIFIC_H_ -#define BASE_COMPILER_SPECIFIC_H_ - -#include "build/build_config.h" - -#if defined(COMPILER_MSVC) - -// For _Printf_format_string_. -#include <sal.h> - -// Macros for suppressing and disabling warnings on MSVC. -// -// Warning numbers are enumerated at: -// http://msdn.microsoft.com/en-us/library/8x5x43k7(VS.80).aspx -// -// The warning pragma: -// http://msdn.microsoft.com/en-us/library/2c8f766e(VS.80).aspx -// -// Using __pragma instead of #pragma inside macros: -// http://msdn.microsoft.com/en-us/library/d9x1s805.aspx - -// MSVC_SUPPRESS_WARNING disables warning |n| for the remainder of the line and -// for the next line of the source file. -#define MSVC_SUPPRESS_WARNING(n) __pragma(warning(suppress:n)) - -// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled. -// The warning remains disabled until popped by MSVC_POP_WARNING. -#define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \ - __pragma(warning(disable:n)) - -// MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level. The level -// remains in effect until popped by MSVC_POP_WARNING(). Use 0 to disable all -// warnings. -#define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n)) - -// Pop effects of innermost MSVC_PUSH_* macro. -#define MSVC_POP_WARNING() __pragma(warning(pop)) - -#define MSVC_DISABLE_OPTIMIZE() __pragma(optimize("", off)) -#define MSVC_ENABLE_OPTIMIZE() __pragma(optimize("", on)) - -// Allows exporting a class that inherits from a non-exported base class. -// This uses suppress instead of push/pop because the delimiter after the -// declaration (either "," or "{") has to be placed before the pop macro. -// -// Example usage: -// class EXPORT_API Foo : NON_EXPORTED_BASE(public Bar) { -// -// MSVC Compiler warning C4275: -// non dll-interface class 'Bar' used as base for dll-interface class 'Foo'. -// Note that this is intended to be used only when no access to the base class' -// static data is done through derived classes or inline methods. For more info, -// see http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx -#define NON_EXPORTED_BASE(code) MSVC_SUPPRESS_WARNING(4275) \ - code - -#else // Not MSVC - -#define _Printf_format_string_ -#define MSVC_SUPPRESS_WARNING(n) -#define MSVC_PUSH_DISABLE_WARNING(n) -#define MSVC_PUSH_WARNING_LEVEL(n) -#define MSVC_POP_WARNING() -#define MSVC_DISABLE_OPTIMIZE() -#define MSVC_ENABLE_OPTIMIZE() -#define NON_EXPORTED_BASE(code) code - -#endif // COMPILER_MSVC - - -// Annotate a variable indicating it's ok if the variable is not used. -// (Typically used to silence a compiler warning when the assignment -// is important for some other reason.) -// Use like: -// int x = ...; -// ALLOW_UNUSED_LOCAL(x); -#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0 - -// Annotate a typedef or function indicating it's ok if it's not used. -// Use like: -// typedef Foo Bar ALLOW_UNUSED_TYPE; -#if defined(COMPILER_GCC) || defined(__clang__) -#define ALLOW_UNUSED_TYPE __attribute__((unused)) -#else -#define ALLOW_UNUSED_TYPE -#endif - -// Annotate a function indicating it should not be inlined. -// Use like: -// NOINLINE void DoStuff() { ... } -#if defined(COMPILER_GCC) -#define NOINLINE __attribute__((noinline)) -#elif defined(COMPILER_MSVC) -#define NOINLINE __declspec(noinline) -#else -#define NOINLINE -#endif - -// Specify memory alignment for structs, classes, etc. -// Use like: -// class ALIGNAS(16) MyClass { ... } -// ALIGNAS(16) int array[4]; -#if defined(COMPILER_MSVC) -#define ALIGNAS(byte_alignment) __declspec(align(byte_alignment)) -#elif defined(COMPILER_GCC) -#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) -#endif - -// Return the byte alignment of the given type (available at compile time). -// Use like: -// ALIGNOF(int32_t) // this would be 4 -#if defined(COMPILER_MSVC) -#define ALIGNOF(type) __alignof(type) -#elif defined(COMPILER_GCC) -#define ALIGNOF(type) __alignof__(type) -#endif - -// Annotate a function indicating the caller must examine the return value. -// Use like: -// int foo() WARN_UNUSED_RESULT; -// To explicitly ignore a result, see |ignore_result()| in base/macros.h. -#undef WARN_UNUSED_RESULT -#if defined(COMPILER_GCC) || defined(__clang__) -#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -#define WARN_UNUSED_RESULT -#endif - -// Tell the compiler a function is using a printf-style format string. -// |format_param| is the one-based index of the format string parameter; -// |dots_param| is the one-based index of the "..." parameter. -// For v*printf functions (which take a va_list), pass 0 for dots_param. -// (This is undocumented but matches what the system C headers do.) -#if defined(COMPILER_GCC) -#define PRINTF_FORMAT(format_param, dots_param) \ - __attribute__((format(printf, format_param, dots_param))) -#else -#define PRINTF_FORMAT(format_param, dots_param) -#endif - -// WPRINTF_FORMAT is the same, but for wide format strings. -// This doesn't appear to yet be implemented in any compiler. -// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38308 . -#define WPRINTF_FORMAT(format_param, dots_param) -// If available, it would look like: -// __attribute__((format(wprintf, format_param, dots_param))) - -// MemorySanitizer annotations. -#if defined(MEMORY_SANITIZER) && !defined(OS_NACL) -#include <sanitizer/msan_interface.h> - -// Mark a memory region fully initialized. -// Use this to annotate code that deliberately reads uninitialized data, for -// example a GC scavenging root set pointers from the stack. -#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size) - -// Check a memory region for initializedness, as if it was being used here. -// If any bits are uninitialized, crash with an MSan report. -// Use this to sanitize data which MSan won't be able to track, e.g. before -// passing data to another process via shared memory. -#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \ - __msan_check_mem_is_initialized(p, size) -#else // MEMORY_SANITIZER -#define MSAN_UNPOISON(p, size) -#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) -#endif // MEMORY_SANITIZER - -// Macro useful for writing cross-platform function pointers. -#if !defined(CDECL) -#if defined(OS_WIN) -#define CDECL __cdecl -#else // defined(OS_WIN) -#define CDECL -#endif // defined(OS_WIN) -#endif // !defined(CDECL) - -// Macro for hinting that an expression is likely to be false. -#if !defined(UNLIKELY) -#if defined(COMPILER_GCC) -#define UNLIKELY(x) __builtin_expect(!!(x), 0) -#else -#define UNLIKELY(x) (x) -#endif // defined(COMPILER_GCC) -#endif // !defined(UNLIKELY) - -#endif // BASE_COMPILER_SPECIFIC_H_ diff --git a/security/sandbox/chromium/base/containers/hash_tables.h b/security/sandbox/chromium/base/containers/hash_tables.h deleted file mode 100644 index c421dddf3..000000000 --- a/security/sandbox/chromium/base/containers/hash_tables.h +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// Deal with the differences between Microsoft and GNU implemenations -// of hash_map. Allows all platforms to use |base::hash_map| and -// |base::hash_set|. -// eg: -// base::hash_map<int> my_map; -// base::hash_set<int> my_set; -// -// NOTE: It is an explicit non-goal of this class to provide a generic hash -// function for pointers. If you want to hash a pointers to a particular class, -// please define the template specialization elsewhere (for example, in its -// header file) and keep it specific to just pointers to that class. This is -// because identity hashes are not desirable for all types that might show up -// in containers as pointers. - -#ifndef BASE_CONTAINERS_HASH_TABLES_H_ -#define BASE_CONTAINERS_HASH_TABLES_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <utility> - -#include "base/strings/string16.h" -#include "build/build_config.h" - -#if defined(COMPILER_MSVC) -#include <unordered_map> -#include <unordered_set> - -#define BASE_HASH_NAMESPACE std - -#elif defined(COMPILER_GCC) - -#define BASE_HASH_NAMESPACE base_hash - -// This is a hack to disable the gcc 4.4 warning about hash_map and hash_set -// being deprecated. We can get rid of this when we upgrade to VS2008 and we -// can use <tr1/unordered_map> and <tr1/unordered_set>. -#ifdef __DEPRECATED -#define CHROME_OLD__DEPRECATED __DEPRECATED -#undef __DEPRECATED -#endif - -#include <ext/hash_map> -#include <ext/hash_set> -#define BASE_HASH_IMPL_NAMESPACE __gnu_cxx - -#include <string> - -#ifdef CHROME_OLD__DEPRECATED -#define __DEPRECATED CHROME_OLD__DEPRECATED -#undef CHROME_OLD__DEPRECATED -#endif - -namespace BASE_HASH_NAMESPACE { - -// The pre-standard hash behaves like C++11's std::hash, except around pointers. -// const char* is specialized to hash the C string and hash functions for -// general T* are missing. Define a BASE_HASH_NAMESPACE::hash which aligns with -// the C++11 behavior. - -template<typename T> -struct hash { - std::size_t operator()(const T& value) const { - return BASE_HASH_IMPL_NAMESPACE::hash<T>()(value); - } -}; - -template<typename T> -struct hash<T*> { - std::size_t operator()(T* value) const { - return BASE_HASH_IMPL_NAMESPACE::hash<uintptr_t>()( - reinterpret_cast<uintptr_t>(value)); - } -}; - -// The GNU C++ library provides identity hash functions for many integral types, -// but not for |long long|. This hash function will truncate if |size_t| is -// narrower than |long long|. This is probably good enough for what we will -// use it for. - -#define DEFINE_TRIVIAL_HASH(integral_type) \ - template<> \ - struct hash<integral_type> { \ - std::size_t operator()(integral_type value) const { \ - return static_cast<std::size_t>(value); \ - } \ - } - -DEFINE_TRIVIAL_HASH(long long); -DEFINE_TRIVIAL_HASH(unsigned long long); - -#undef DEFINE_TRIVIAL_HASH - -// Implement string hash functions so that strings of various flavors can -// be used as keys in STL maps and sets. The hash algorithm comes from the -// GNU C++ library, in <tr1/functional>. It is duplicated here because GCC -// versions prior to 4.3.2 are unable to compile <tr1/functional> when RTTI -// is disabled, as it is in our build. - -#define DEFINE_STRING_HASH(string_type) \ - template<> \ - struct hash<string_type> { \ - std::size_t operator()(const string_type& s) const { \ - std::size_t result = 0; \ - for (string_type::const_iterator i = s.begin(); i != s.end(); ++i) \ - result = (result * 131) + *i; \ - return result; \ - } \ - } - -DEFINE_STRING_HASH(std::string); -DEFINE_STRING_HASH(base::string16); - -#undef DEFINE_STRING_HASH - -} // namespace BASE_HASH_NAMESPACE - -#else // COMPILER -#error define BASE_HASH_NAMESPACE for your compiler -#endif // COMPILER - -namespace base { - -// On MSVC, use the C++11 containers. -#if defined(COMPILER_MSVC) - -template<class Key, class T, - class Hash = std::hash<Key>, - class Pred = std::equal_to<Key>, - class Alloc = std::allocator<std::pair<const Key, T>>> -using hash_map = std::unordered_map<Key, T, Hash, Pred, Alloc>; - -template<class Key, class T, - class Hash = std::hash<Key>, - class Pred = std::equal_to<Key>, - class Alloc = std::allocator<std::pair<const Key, T>>> -using hash_multimap = std::unordered_multimap<Key, T, Hash, Pred, Alloc>; - -template<class Key, - class Hash = std::hash<Key>, - class Pred = std::equal_to<Key>, - class Alloc = std::allocator<Key>> -using hash_multiset = std::unordered_multiset<Key, Hash, Pred, Alloc>; - -template<class Key, - class Hash = std::hash<Key>, - class Pred = std::equal_to<Key>, - class Alloc = std::allocator<Key>> -using hash_set = std::unordered_set<Key, Hash, Pred, Alloc>; - -#else // !COMPILER_MSVC - -// Otherwise, use the pre-standard ones, but override the default hash to match -// C++11. -template<class Key, class T, - class Hash = BASE_HASH_NAMESPACE::hash<Key>, - class Pred = std::equal_to<Key>, - class Alloc = std::allocator<std::pair<const Key, T>>> -using hash_map = BASE_HASH_IMPL_NAMESPACE::hash_map<Key, T, Hash, Pred, Alloc>; - -template<class Key, class T, - class Hash = BASE_HASH_NAMESPACE::hash<Key>, - class Pred = std::equal_to<Key>, - class Alloc = std::allocator<std::pair<const Key, T>>> -using hash_multimap = - BASE_HASH_IMPL_NAMESPACE::hash_multimap<Key, T, Hash, Pred, Alloc>; - -template<class Key, - class Hash = BASE_HASH_NAMESPACE::hash<Key>, - class Pred = std::equal_to<Key>, - class Alloc = std::allocator<Key>> -using hash_multiset = - BASE_HASH_IMPL_NAMESPACE::hash_multiset<Key, Hash, Pred, Alloc>; - -template<class Key, - class Hash = BASE_HASH_NAMESPACE::hash<Key>, - class Pred = std::equal_to<Key>, - class Alloc = std::allocator<Key>> -using hash_set = BASE_HASH_IMPL_NAMESPACE::hash_set<Key, Hash, Pred, Alloc>; - -#undef BASE_HASH_IMPL_NAMESPACE - -#endif // COMPILER_MSVC - -// Implement hashing for pairs of at-most 32 bit integer values. -// When size_t is 32 bits, we turn the 64-bit hash code into 32 bits by using -// multiply-add hashing. This algorithm, as described in -// Theorem 4.3.3 of the thesis "Ãœber die Komplexität der Multiplikation in -// eingeschränkten Branchingprogrammmodellen" by Woelfel, is: -// -// h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32 -// -// Contact danakj@chromium.org for any questions. -inline std::size_t HashInts32(uint32_t value1, uint32_t value2) { - uint64_t value1_64 = value1; - uint64_t hash64 = (value1_64 << 32) | value2; - - if (sizeof(std::size_t) >= sizeof(uint64_t)) - return static_cast<std::size_t>(hash64); - - uint64_t odd_random = 481046412LL << 32 | 1025306955LL; - uint32_t shift_random = 10121U << 16; - - hash64 = hash64 * odd_random + shift_random; - std::size_t high_bits = static_cast<std::size_t>( - hash64 >> (8 * (sizeof(uint64_t) - sizeof(std::size_t)))); - return high_bits; -} - -// Implement hashing for pairs of up-to 64-bit integer values. -// We use the compound integer hash method to produce a 64-bit hash code, by -// breaking the two 64-bit inputs into 4 32-bit values: -// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000 -// Then we reduce our result to 32 bits if required, similar to above. -inline std::size_t HashInts64(uint64_t value1, uint64_t value2) { - uint32_t short_random1 = 842304669U; - uint32_t short_random2 = 619063811U; - uint32_t short_random3 = 937041849U; - uint32_t short_random4 = 3309708029U; - - uint32_t value1a = static_cast<uint32_t>(value1 & 0xffffffff); - uint32_t value1b = static_cast<uint32_t>((value1 >> 32) & 0xffffffff); - uint32_t value2a = static_cast<uint32_t>(value2 & 0xffffffff); - uint32_t value2b = static_cast<uint32_t>((value2 >> 32) & 0xffffffff); - - uint64_t product1 = static_cast<uint64_t>(value1a) * short_random1; - uint64_t product2 = static_cast<uint64_t>(value1b) * short_random2; - uint64_t product3 = static_cast<uint64_t>(value2a) * short_random3; - uint64_t product4 = static_cast<uint64_t>(value2b) * short_random4; - - uint64_t hash64 = product1 + product2 + product3 + product4; - - if (sizeof(std::size_t) >= sizeof(uint64_t)) - return static_cast<std::size_t>(hash64); - - uint64_t odd_random = 1578233944LL << 32 | 194370989LL; - uint32_t shift_random = 20591U << 16; - - hash64 = hash64 * odd_random + shift_random; - std::size_t high_bits = static_cast<std::size_t>( - hash64 >> (8 * (sizeof(uint64_t) - sizeof(std::size_t)))); - return high_bits; -} - -template<typename T1, typename T2> -inline std::size_t HashPair(T1 value1, T2 value2) { - // This condition is expected to be compile-time evaluated and optimised away - // in release builds. - if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t))) - return HashInts64(value1, value2); - - return HashInts32(value1, value2); -} - -} // namespace base - -namespace BASE_HASH_NAMESPACE { - -// Implement methods for hashing a pair of integers, so they can be used as -// keys in STL containers. - -template<typename Type1, typename Type2> -struct hash<std::pair<Type1, Type2> > { - std::size_t operator()(std::pair<Type1, Type2> value) const { - return base::HashPair(value.first, value.second); - } -}; - -} // namespace BASE_HASH_NAMESPACE - -#undef DEFINE_PAIR_HASH_FUNCTION_START -#undef DEFINE_PAIR_HASH_FUNCTION_END - -#endif // BASE_CONTAINERS_HASH_TABLES_H_ diff --git a/security/sandbox/chromium/base/cpu.cc b/security/sandbox/chromium/base/cpu.cc deleted file mode 100644 index 713544566..000000000 --- a/security/sandbox/chromium/base/cpu.cc +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/cpu.h" - -#include <limits.h> -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include <algorithm> - -#include "base/macros.h" -#include "base/strings/string_piece.h" -#include "build/build_config.h" - -#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) -#include "base/files/file_util.h" -#include "base/lazy_instance.h" -#endif - -#if defined(ARCH_CPU_X86_FAMILY) -#if defined(_MSC_VER) -#include <intrin.h> -#include <immintrin.h> // For _xgetbv() -#endif -#endif - -namespace base { - -CPU::CPU() - : signature_(0), - type_(0), - family_(0), - model_(0), - stepping_(0), - ext_model_(0), - ext_family_(0), - has_mmx_(false), - has_sse_(false), - has_sse2_(false), - has_sse3_(false), - has_ssse3_(false), - has_sse41_(false), - has_sse42_(false), - has_avx_(false), - has_avx2_(false), - has_aesni_(false), - has_non_stop_time_stamp_counter_(false), - has_broken_neon_(false), - cpu_vendor_("unknown") { - Initialize(); -} - -namespace { - -#if defined(ARCH_CPU_X86_FAMILY) -#ifndef _MSC_VER - -#if defined(__pic__) && defined(__i386__) - -void __cpuid(int cpu_info[4], int info_type) { - __asm__ volatile ( - "mov %%ebx, %%edi\n" - "cpuid\n" - "xchg %%edi, %%ebx\n" - : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type) - ); -} - -#else - -void __cpuid(int cpu_info[4], int info_type) { - __asm__ volatile ( - "cpuid\n" - : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) - : "a"(info_type) - ); -} - -#endif - -// _xgetbv returns the value of an Intel Extended Control Register (XCR). -// Currently only XCR0 is defined by Intel so |xcr| should always be zero. -uint64_t _xgetbv(uint32_t xcr) { - uint32_t eax, edx; - - __asm__ volatile ( - "xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr)); - return (static_cast<uint64_t>(edx) << 32) | eax; -} - -#endif // !_MSC_VER -#endif // ARCH_CPU_X86_FAMILY - -#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) -class LazyCpuInfoValue { - public: - LazyCpuInfoValue() : has_broken_neon_(false) { - // This function finds the value from /proc/cpuinfo under the key "model - // name" or "Processor". "model name" is used in Linux 3.8 and later (3.7 - // and later for arm64) and is shown once per CPU. "Processor" is used in - // earler versions and is shown only once at the top of /proc/cpuinfo - // regardless of the number CPUs. - const char kModelNamePrefix[] = "model name\t: "; - const char kProcessorPrefix[] = "Processor\t: "; - - // This function also calculates whether we believe that this CPU has a - // broken NEON unit based on these fields from cpuinfo: - unsigned implementer = 0, architecture = 0, variant = 0, part = 0, - revision = 0; - const struct { - const char key[17]; - unsigned int* result; - } kUnsignedValues[] = { - {"CPU implementer", &implementer}, - {"CPU architecture", &architecture}, - {"CPU variant", &variant}, - {"CPU part", &part}, - {"CPU revision", &revision}, - }; - - std::string contents; - ReadFileToString(FilePath("/proc/cpuinfo"), &contents); - DCHECK(!contents.empty()); - if (contents.empty()) { - return; - } - - std::istringstream iss(contents); - std::string line; - while (std::getline(iss, line)) { - if (brand_.empty() && - (line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0 || - line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0)) { - brand_.assign(line.substr(strlen(kModelNamePrefix))); - } - - for (size_t i = 0; i < arraysize(kUnsignedValues); i++) { - const char *key = kUnsignedValues[i].key; - const size_t len = strlen(key); - - if (line.compare(0, len, key) == 0 && - line.size() >= len + 1 && - (line[len] == '\t' || line[len] == ' ' || line[len] == ':')) { - size_t colon_pos = line.find(':', len); - if (colon_pos == std::string::npos) { - continue; - } - - const StringPiece line_sp(line); - StringPiece value_sp = line_sp.substr(colon_pos + 1); - while (!value_sp.empty() && - (value_sp[0] == ' ' || value_sp[0] == '\t')) { - value_sp = value_sp.substr(1); - } - - // The string may have leading "0x" or not, so we use strtoul to - // handle that. - char* endptr; - std::string value(value_sp.as_string()); - unsigned long int result = strtoul(value.c_str(), &endptr, 0); - if (*endptr == 0 && result <= UINT_MAX) { - *kUnsignedValues[i].result = result; - } - } - } - } - - has_broken_neon_ = - implementer == 0x51 && - architecture == 7 && - variant == 1 && - part == 0x4d && - revision == 0; - } - - const std::string& brand() const { return brand_; } - bool has_broken_neon() const { return has_broken_neon_; } - - private: - std::string brand_; - bool has_broken_neon_; - DISALLOW_COPY_AND_ASSIGN(LazyCpuInfoValue); -}; - -base::LazyInstance<LazyCpuInfoValue>::Leaky g_lazy_cpuinfo = - LAZY_INSTANCE_INITIALIZER; - -#endif // defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || - // defined(OS_LINUX)) - -} // anonymous namespace - -void CPU::Initialize() { -#if defined(ARCH_CPU_X86_FAMILY) - int cpu_info[4] = {-1}; - char cpu_string[48]; - - // __cpuid with an InfoType argument of 0 returns the number of - // valid Ids in CPUInfo[0] and the CPU identification string in - // the other three array elements. The CPU identification string is - // not in linear order. The code below arranges the information - // in a human readable form. The human readable order is CPUInfo[1] | - // CPUInfo[3] | CPUInfo[2]. CPUInfo[2] and CPUInfo[3] are swapped - // before using memcpy to copy these three array elements to cpu_string. - __cpuid(cpu_info, 0); - int num_ids = cpu_info[0]; - std::swap(cpu_info[2], cpu_info[3]); - memcpy(cpu_string, &cpu_info[1], 3 * sizeof(cpu_info[1])); - cpu_vendor_.assign(cpu_string, 3 * sizeof(cpu_info[1])); - - // Interpret CPU feature information. - if (num_ids > 0) { - int cpu_info7[4] = {0}; - __cpuid(cpu_info, 1); - if (num_ids >= 7) { - __cpuid(cpu_info7, 7); - } - signature_ = cpu_info[0]; - stepping_ = cpu_info[0] & 0xf; - model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0); - family_ = (cpu_info[0] >> 8) & 0xf; - type_ = (cpu_info[0] >> 12) & 0x3; - ext_model_ = (cpu_info[0] >> 16) & 0xf; - ext_family_ = (cpu_info[0] >> 20) & 0xff; - has_mmx_ = (cpu_info[3] & 0x00800000) != 0; - has_sse_ = (cpu_info[3] & 0x02000000) != 0; - has_sse2_ = (cpu_info[3] & 0x04000000) != 0; - has_sse3_ = (cpu_info[2] & 0x00000001) != 0; - has_ssse3_ = (cpu_info[2] & 0x00000200) != 0; - has_sse41_ = (cpu_info[2] & 0x00080000) != 0; - has_sse42_ = (cpu_info[2] & 0x00100000) != 0; - // AVX instructions will generate an illegal instruction exception unless - // a) they are supported by the CPU, - // b) XSAVE is supported by the CPU and - // c) XSAVE is enabled by the kernel. - // See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled - // - // In addition, we have observed some crashes with the xgetbv instruction - // even after following Intel's example code. (See crbug.com/375968.) - // Because of that, we also test the XSAVE bit because its description in - // the CPUID documentation suggests that it signals xgetbv support. - has_avx_ = - (cpu_info[2] & 0x10000000) != 0 && - (cpu_info[2] & 0x04000000) != 0 /* XSAVE */ && - (cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ && - (_xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */; - has_aesni_ = (cpu_info[2] & 0x02000000) != 0; - has_avx2_ = has_avx_ && (cpu_info7[1] & 0x00000020) != 0; - } - - // Get the brand string of the cpu. - __cpuid(cpu_info, 0x80000000); - const int parameter_end = 0x80000004; - int max_parameter = cpu_info[0]; - - if (cpu_info[0] >= parameter_end) { - char* cpu_string_ptr = cpu_string; - - for (int parameter = 0x80000002; parameter <= parameter_end && - cpu_string_ptr < &cpu_string[sizeof(cpu_string)]; parameter++) { - __cpuid(cpu_info, parameter); - memcpy(cpu_string_ptr, cpu_info, sizeof(cpu_info)); - cpu_string_ptr += sizeof(cpu_info); - } - cpu_brand_.assign(cpu_string, cpu_string_ptr - cpu_string); - } - - const int parameter_containing_non_stop_time_stamp_counter = 0x80000007; - if (max_parameter >= parameter_containing_non_stop_time_stamp_counter) { - __cpuid(cpu_info, parameter_containing_non_stop_time_stamp_counter); - has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0; - } -#elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) - cpu_brand_.assign(g_lazy_cpuinfo.Get().brand()); - has_broken_neon_ = g_lazy_cpuinfo.Get().has_broken_neon(); -#endif -} - -CPU::IntelMicroArchitecture CPU::GetIntelMicroArchitecture() const { - if (has_avx2()) return AVX2; - if (has_avx()) return AVX; - if (has_sse42()) return SSE42; - if (has_sse41()) return SSE41; - if (has_ssse3()) return SSSE3; - if (has_sse3()) return SSE3; - if (has_sse2()) return SSE2; - if (has_sse()) return SSE; - return PENTIUM; -} - -} // namespace base diff --git a/security/sandbox/chromium/base/cpu.h b/security/sandbox/chromium/base/cpu.h deleted file mode 100644 index 8c3c06c04..000000000 --- a/security/sandbox/chromium/base/cpu.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_CPU_H_ -#define BASE_CPU_H_ - -#include <string> - -#include "base/base_export.h" - -namespace base { - -// Query information about the processor. -class BASE_EXPORT CPU { - public: - // Constructor - CPU(); - - enum IntelMicroArchitecture { - PENTIUM, - SSE, - SSE2, - SSE3, - SSSE3, - SSE41, - SSE42, - AVX, - AVX2, - MAX_INTEL_MICRO_ARCHITECTURE - }; - - // Accessors for CPU information. - const std::string& vendor_name() const { return cpu_vendor_; } - int signature() const { return signature_; } - int stepping() const { return stepping_; } - int model() const { return model_; } - int family() const { return family_; } - int type() const { return type_; } - int extended_model() const { return ext_model_; } - int extended_family() const { return ext_family_; } - bool has_mmx() const { return has_mmx_; } - bool has_sse() const { return has_sse_; } - bool has_sse2() const { return has_sse2_; } - bool has_sse3() const { return has_sse3_; } - bool has_ssse3() const { return has_ssse3_; } - bool has_sse41() const { return has_sse41_; } - bool has_sse42() const { return has_sse42_; } - bool has_avx() const { return has_avx_; } - bool has_avx2() const { return has_avx2_; } - bool has_aesni() const { return has_aesni_; } - bool has_non_stop_time_stamp_counter() const { - return has_non_stop_time_stamp_counter_; - } - // has_broken_neon is only valid on ARM chips. If true, it indicates that we - // believe that the NEON unit on the current CPU is flawed and cannot execute - // some code. See https://code.google.com/p/chromium/issues/detail?id=341598 - bool has_broken_neon() const { return has_broken_neon_; } - - IntelMicroArchitecture GetIntelMicroArchitecture() const; - const std::string& cpu_brand() const { return cpu_brand_; } - - private: - // Query the processor for CPUID information. - void Initialize(); - - int signature_; // raw form of type, family, model, and stepping - int type_; // process type - int family_; // family of the processor - int model_; // model of processor - int stepping_; // processor revision number - int ext_model_; - int ext_family_; - bool has_mmx_; - bool has_sse_; - bool has_sse2_; - bool has_sse3_; - bool has_ssse3_; - bool has_sse41_; - bool has_sse42_; - bool has_avx_; - bool has_avx2_; - bool has_aesni_; - bool has_non_stop_time_stamp_counter_; - bool has_broken_neon_; - std::string cpu_vendor_; - std::string cpu_brand_; -}; - -} // namespace base - -#endif // BASE_CPU_H_ diff --git a/security/sandbox/chromium/base/debug/alias.cc b/security/sandbox/chromium/base/debug/alias.cc deleted file mode 100644 index 6b0caaa6d..000000000 --- a/security/sandbox/chromium/base/debug/alias.cc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/debug/alias.h" -#include "build/build_config.h" - -namespace base { -namespace debug { - -#if defined(COMPILER_MSVC) -#pragma optimize("", off) -#endif - -void Alias(const void* var) { -} - -#if defined(COMPILER_MSVC) -#pragma optimize("", on) -#endif - -} // namespace debug -} // namespace base diff --git a/security/sandbox/chromium/base/debug/alias.h b/security/sandbox/chromium/base/debug/alias.h deleted file mode 100644 index 3b2ab64f3..000000000 --- a/security/sandbox/chromium/base/debug/alias.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_DEBUG_ALIAS_H_ -#define BASE_DEBUG_ALIAS_H_ - -#include "base/base_export.h" - -namespace base { -namespace debug { - -// Make the optimizer think that var is aliased. This is to prevent it from -// optimizing out variables that that would not otherwise be live at the point -// of a potential crash. -void BASE_EXPORT Alias(const void* var); - -} // namespace debug -} // namespace base - -#endif // BASE_DEBUG_ALIAS_H_ diff --git a/security/sandbox/chromium/base/debug/debugger.h b/security/sandbox/chromium/base/debug/debugger.h deleted file mode 100644 index 8680e281e..000000000 --- a/security/sandbox/chromium/base/debug/debugger.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a cross platform interface for helper functions related to -// debuggers. You should use this to test if you're running under a debugger, -// and if you would like to yield (breakpoint) into the debugger. - -#ifndef BASE_DEBUG_DEBUGGER_H_ -#define BASE_DEBUG_DEBUGGER_H_ - -#include "base/base_export.h" - -namespace base { -namespace debug { - -// Waits wait_seconds seconds for a debugger to attach to the current process. -// When silent is false, an exception is thrown when a debugger is detected. -BASE_EXPORT bool WaitForDebugger(int wait_seconds, bool silent); - -// Returns true if the given process is being run under a debugger. -// -// On OS X, the underlying mechanism doesn't work when the sandbox is enabled. -// To get around this, this function caches its value. -// -// WARNING: Because of this, on OS X, a call MUST be made to this function -// BEFORE the sandbox is enabled. -BASE_EXPORT bool BeingDebugged(); - -// Break into the debugger, assumes a debugger is present. -BASE_EXPORT void BreakDebugger(); - -// Used in test code, this controls whether showing dialogs and breaking into -// the debugger is suppressed for debug errors, even in debug mode (normally -// release mode doesn't do this stuff -- this is controlled separately). -// Normally UI is not suppressed. This is normally used when running automated -// tests where we want a crash rather than a dialog or a debugger. -BASE_EXPORT void SetSuppressDebugUI(bool suppress); -BASE_EXPORT bool IsDebugUISuppressed(); - -} // namespace debug -} // namespace base - -#endif // BASE_DEBUG_DEBUGGER_H_ diff --git a/security/sandbox/chromium/base/debug/leak_annotations.h b/security/sandbox/chromium/base/debug/leak_annotations.h deleted file mode 100644 index dc502461d..000000000 --- a/security/sandbox/chromium/base/debug/leak_annotations.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_DEBUG_LEAK_ANNOTATIONS_H_ -#define BASE_DEBUG_LEAK_ANNOTATIONS_H_ - -#include "base/macros.h" -#include "build/build_config.h" - -// This file defines macros which can be used to annotate intentional memory -// leaks. Support for annotations is implemented in LeakSanitizer. Annotated -// objects will be treated as a source of live pointers, i.e. any heap objects -// reachable by following pointers from an annotated object will not be -// reported as leaks. -// -// ANNOTATE_SCOPED_MEMORY_LEAK: all allocations made in the current scope -// will be annotated as leaks. -// ANNOTATE_LEAKING_OBJECT_PTR(X): the heap object referenced by pointer X will -// be annotated as a leak. - -#if defined(LEAK_SANITIZER) && !defined(OS_NACL) - -#include <sanitizer/lsan_interface.h> - -class ScopedLeakSanitizerDisabler { - public: - ScopedLeakSanitizerDisabler() { __lsan_disable(); } - ~ScopedLeakSanitizerDisabler() { __lsan_enable(); } - private: - DISALLOW_COPY_AND_ASSIGN(ScopedLeakSanitizerDisabler); -}; - -#define ANNOTATE_SCOPED_MEMORY_LEAK \ - ScopedLeakSanitizerDisabler leak_sanitizer_disabler; static_cast<void>(0) - -#define ANNOTATE_LEAKING_OBJECT_PTR(X) __lsan_ignore_object(X); - -#else - -#define ANNOTATE_SCOPED_MEMORY_LEAK ((void)0) -#define ANNOTATE_LEAKING_OBJECT_PTR(X) ((void)0) - -#endif - -#endif // BASE_DEBUG_LEAK_ANNOTATIONS_H_ diff --git a/security/sandbox/chromium/base/debug/profiler.cc b/security/sandbox/chromium/base/debug/profiler.cc deleted file mode 100644 index 75e9aac0c..000000000 --- a/security/sandbox/chromium/base/debug/profiler.cc +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/debug/profiler.h" - -#include <string> - -#include "base/debug/debugging_flags.h" -#include "base/process/process_handle.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include "base/win/pe_image.h" -#endif // defined(OS_WIN) - -// TODO(peria): Enable profiling on Windows. -#if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN) -#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h" -#endif - -namespace base { -namespace debug { - -// TODO(peria): Enable profiling on Windows. -#if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN) - -static int profile_count = 0; - -void StartProfiling(const std::string& name) { - ++profile_count; - std::string full_name(name); - std::string pid = IntToString(GetCurrentProcId()); - std::string count = IntToString(profile_count); - ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid); - ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count); - ProfilerStart(full_name.c_str()); -} - -void StopProfiling() { - ProfilerFlush(); - ProfilerStop(); -} - -void FlushProfiling() { - ProfilerFlush(); -} - -bool BeingProfiled() { - return ProfilingIsEnabledForAllThreads(); -} - -void RestartProfilingAfterFork() { - ProfilerRegisterThread(); -} - -#else - -void StartProfiling(const std::string& name) { -} - -void StopProfiling() { -} - -void FlushProfiling() { -} - -bool BeingProfiled() { - return false; -} - -void RestartProfilingAfterFork() { -} - -#endif - -#if !defined(OS_WIN) - -bool IsBinaryInstrumented() { - return false; -} - -ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { - return NULL; -} - -DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() { - return NULL; -} - -AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() { - return NULL; -} - -MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { - return NULL; -} - -#else // defined(OS_WIN) - -// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx -extern "C" IMAGE_DOS_HEADER __ImageBase; - -bool IsBinaryInstrumented() { - enum InstrumentationCheckState { - UNINITIALIZED, - INSTRUMENTED_IMAGE, - NON_INSTRUMENTED_IMAGE, - }; - - static InstrumentationCheckState state = UNINITIALIZED; - - if (state == UNINITIALIZED) { - HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); - base::win::PEImage image(this_module); - - // Check to be sure our image is structured as we'd expect. - DCHECK(image.VerifyMagic()); - - // Syzygy-instrumented binaries contain a PE image section named ".thunks", - // and all Syzygy-modified binaries contain the ".syzygy" image section. - // This is a very fast check, as it only looks at the image header. - if ((image.GetImageSectionHeaderByName(".thunks") != NULL) && - (image.GetImageSectionHeaderByName(".syzygy") != NULL)) { - state = INSTRUMENTED_IMAGE; - } else { - state = NON_INSTRUMENTED_IMAGE; - } - } - DCHECK(state != UNINITIALIZED); - - return state == INSTRUMENTED_IMAGE; -} - -namespace { - -struct FunctionSearchContext { - const char* name; - FARPROC function; -}; - -// Callback function to PEImage::EnumImportChunks. -bool FindResolutionFunctionInImports( - const base::win::PEImage &image, const char* module_name, - PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table, - PVOID cookie) { - FunctionSearchContext* context = - reinterpret_cast<FunctionSearchContext*>(cookie); - - DCHECK_NE(static_cast<FunctionSearchContext*>(NULL), context); - DCHECK_EQ(static_cast<FARPROC>(NULL), context->function); - - // Our import address table contains pointers to the functions we import - // at this point. Let's retrieve the first such function and use it to - // find the module this import was resolved to by the loader. - const wchar_t* function_in_module = - reinterpret_cast<const wchar_t*>(import_address_table->u1.Function); - - // Retrieve the module by a function in the module. - const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; - HMODULE module = NULL; - if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) { - // This can happen if someone IAT patches us to a thunk. - return true; - } - - // See whether this module exports the function we're looking for. - FARPROC exported_func = ::GetProcAddress(module, context->name); - if (exported_func != NULL) { - // We found it, return the function and terminate the enumeration. - context->function = exported_func; - return false; - } - - // Keep going. - return true; -} - -template <typename FunctionType> -FunctionType FindFunctionInImports(const char* function_name) { - if (!IsBinaryInstrumented()) - return NULL; - - HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); - base::win::PEImage image(this_module); - - FunctionSearchContext ctx = { function_name, NULL }; - image.EnumImportChunks(FindResolutionFunctionInImports, &ctx); - - return reinterpret_cast<FunctionType>(ctx.function); -} - -} // namespace - -ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { - return FindFunctionInImports<ReturnAddressLocationResolver>( - "ResolveReturnAddressLocation"); -} - -DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() { - return FindFunctionInImports<DynamicFunctionEntryHook>( - "OnDynamicFunctionEntry"); -} - -AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() { - return FindFunctionInImports<AddDynamicSymbol>( - "AddDynamicSymbol"); -} - -MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { - return FindFunctionInImports<MoveDynamicSymbol>( - "MoveDynamicSymbol"); -} - -#endif // defined(OS_WIN) - -} // namespace debug -} // namespace base diff --git a/security/sandbox/chromium/base/debug/profiler.h b/security/sandbox/chromium/base/debug/profiler.h deleted file mode 100644 index 7cce7b08f..000000000 --- a/security/sandbox/chromium/base/debug/profiler.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_DEBUG_PROFILER_H_ -#define BASE_DEBUG_PROFILER_H_ - -#include <stddef.h> - -#include <string> - -#include "base/base_export.h" - -// The Profiler functions allow usage of the underlying sampling based -// profiler. If the application has not been built with the necessary -// flags (-DENABLE_PROFILING and not -DNO_TCMALLOC) then these functions -// are noops. -namespace base { -namespace debug { - -// Start profiling with the supplied name. -// {pid} will be replaced by the process' pid and {count} will be replaced -// by the count of the profile run (starts at 1 with each process). -BASE_EXPORT void StartProfiling(const std::string& name); - -// Stop profiling and write out data. -BASE_EXPORT void StopProfiling(); - -// Force data to be written to file. -BASE_EXPORT void FlushProfiling(); - -// Returns true if process is being profiled. -BASE_EXPORT bool BeingProfiled(); - -// Reset profiling after a fork, which disables timers. -BASE_EXPORT void RestartProfilingAfterFork(); - -// Returns true iff this executable is instrumented with the Syzygy profiler. -BASE_EXPORT bool IsBinaryInstrumented(); - -// There's a class of profilers that use "return address swizzling" to get a -// hook on function exits. This class of profilers uses some form of entry hook, -// like e.g. binary instrumentation, or a compiler flag, that calls a hook each -// time a function is invoked. The hook then switches the return address on the -// stack for the address of an exit hook function, and pushes the original -// return address to a shadow stack of some type. When in due course the CPU -// executes a return to the exit hook, the exit hook will do whatever work it -// does on function exit, then arrange to return to the original return address. -// This class of profiler does not play well with programs that look at the -// return address, as does e.g. V8. V8 uses the return address to certain -// runtime functions to find the JIT code that called it, and from there finds -// the V8 data structures associated to the JS function involved. -// A return address resolution function is used to fix this. It allows such -// programs to resolve a location on stack where a return address originally -// resided, to the shadow stack location where the profiler stashed it. -typedef uintptr_t (*ReturnAddressLocationResolver)( - uintptr_t return_addr_location); - -// This type declaration must match V8's FunctionEntryHook. -typedef void (*DynamicFunctionEntryHook)(uintptr_t function, - uintptr_t return_addr_location); - -// The functions below here are to support profiling V8-generated code. -// V8 has provisions for generating a call to an entry hook for newly generated -// JIT code, and it can push symbol information on code generation and advise -// when the garbage collector moves code. The functions declarations below here -// make glue between V8's facilities and a profiler. - -// This type declaration must match V8's FunctionEntryHook. -typedef void (*DynamicFunctionEntryHook)(uintptr_t function, - uintptr_t return_addr_location); - -typedef void (*AddDynamicSymbol)(const void* address, - size_t length, - const char* name, - size_t name_len); -typedef void (*MoveDynamicSymbol)(const void* address, const void* new_address); - - -// If this binary is instrumented and the instrumentation supplies a function -// for each of those purposes, find and return the function in question. -// Otherwise returns NULL. -BASE_EXPORT ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc(); -BASE_EXPORT DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc(); -BASE_EXPORT AddDynamicSymbol GetProfilerAddDynamicSymbolFunc(); -BASE_EXPORT MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc(); - -} // namespace debug -} // namespace base - -#endif // BASE_DEBUG_PROFILER_H_ diff --git a/security/sandbox/chromium/base/file_descriptor_posix.h b/security/sandbox/chromium/base/file_descriptor_posix.h deleted file mode 100644 index 2a366116a..000000000 --- a/security/sandbox/chromium/base/file_descriptor_posix.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_FILE_DESCRIPTOR_POSIX_H_ -#define BASE_FILE_DESCRIPTOR_POSIX_H_ - -#include "base/files/file.h" -#include "base/files/scoped_file.h" - -namespace base { - -// ----------------------------------------------------------------------------- -// We introduct a special structure for file descriptors in order that we are -// able to use template specialisation to special-case their handling. -// -// IMPORTANT: This is primarily intended for use when sending file descriptors -// over IPC. Even if |auto_close| is true, base::FileDescriptor does NOT close() -// |fd| when going out of scope. Instead, a consumer of a base::FileDescriptor -// must invoke close() on |fd| if |auto_close| is true. -// -// In the case of IPC, the the IPC subsystem knows to close() |fd| after sending -// a message that contains a base::FileDescriptor if auto_close == true. On the -// other end, the receiver must make sure to close() |fd| after it has finished -// processing the IPC message. See the IPC::ParamTraits<> specialization in -// ipc/ipc_message_utils.h for all the details. -// ----------------------------------------------------------------------------- -struct FileDescriptor { - FileDescriptor() : fd(-1), auto_close(false) {} - - FileDescriptor(int ifd, bool iauto_close) : fd(ifd), auto_close(iauto_close) { - } - - FileDescriptor(File file) : fd(file.TakePlatformFile()), auto_close(true) {} - explicit FileDescriptor(ScopedFD fd) : fd(fd.release()), auto_close(true) {} - - bool operator==(const FileDescriptor& other) const { - return (fd == other.fd && auto_close == other.auto_close); - } - - bool operator!=(const FileDescriptor& other) const { - return !operator==(other); - } - - // A comparison operator so that we can use these as keys in a std::map. - bool operator<(const FileDescriptor& other) const { - return other.fd < fd; - } - - int fd; - // If true, this file descriptor should be closed after it has been used. For - // example an IPC system might interpret this flag as indicating that the - // file descriptor it has been given should be closed after use. - bool auto_close; -}; - -} // namespace base - -#endif // BASE_FILE_DESCRIPTOR_POSIX_H_ diff --git a/security/sandbox/chromium/base/files/file_path.h b/security/sandbox/chromium/base/files/file_path.h deleted file mode 100644 index 89e9cbfb1..000000000 --- a/security/sandbox/chromium/base/files/file_path.h +++ /dev/null @@ -1,477 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// FilePath is a container for pathnames stored in a platform's native string -// type, providing containers for manipulation in according with the -// platform's conventions for pathnames. It supports the following path -// types: -// -// POSIX Windows -// --------------- ---------------------------------- -// Fundamental type char[] wchar_t[] -// Encoding unspecified* UTF-16 -// Separator / \, tolerant of / -// Drive letters no case-insensitive A-Z followed by : -// Alternate root // (surprise!) \\, for UNC paths -// -// * The encoding need not be specified on POSIX systems, although some -// POSIX-compliant systems do specify an encoding. Mac OS X uses UTF-8. -// Chrome OS also uses UTF-8. -// Linux does not specify an encoding, but in practice, the locale's -// character set may be used. -// -// For more arcane bits of path trivia, see below. -// -// FilePath objects are intended to be used anywhere paths are. An -// application may pass FilePath objects around internally, masking the -// underlying differences between systems, only differing in implementation -// where interfacing directly with the system. For example, a single -// OpenFile(const FilePath &) function may be made available, allowing all -// callers to operate without regard to the underlying implementation. On -// POSIX-like platforms, OpenFile might wrap fopen, and on Windows, it might -// wrap _wfopen_s, perhaps both by calling file_path.value().c_str(). This -// allows each platform to pass pathnames around without requiring conversions -// between encodings, which has an impact on performance, but more imporantly, -// has an impact on correctness on platforms that do not have well-defined -// encodings for pathnames. -// -// Several methods are available to perform common operations on a FilePath -// object, such as determining the parent directory (DirName), isolating the -// final path component (BaseName), and appending a relative pathname string -// to an existing FilePath object (Append). These methods are highly -// recommended over attempting to split and concatenate strings directly. -// These methods are based purely on string manipulation and knowledge of -// platform-specific pathname conventions, and do not consult the filesystem -// at all, making them safe to use without fear of blocking on I/O operations. -// These methods do not function as mutators but instead return distinct -// instances of FilePath objects, and are therefore safe to use on const -// objects. The objects themselves are safe to share between threads. -// -// To aid in initialization of FilePath objects from string literals, a -// FILE_PATH_LITERAL macro is provided, which accounts for the difference -// between char[]-based pathnames on POSIX systems and wchar_t[]-based -// pathnames on Windows. -// -// As a precaution against premature truncation, paths can't contain NULs. -// -// Because a FilePath object should not be instantiated at the global scope, -// instead, use a FilePath::CharType[] and initialize it with -// FILE_PATH_LITERAL. At runtime, a FilePath object can be created from the -// character array. Example: -// -// | const FilePath::CharType kLogFileName[] = FILE_PATH_LITERAL("log.txt"); -// | -// | void Function() { -// | FilePath log_file_path(kLogFileName); -// | [...] -// | } -// -// WARNING: FilePaths should ALWAYS be displayed with LTR directionality, even -// when the UI language is RTL. This means you always need to pass filepaths -// through base::i18n::WrapPathWithLTRFormatting() before displaying it in the -// RTL UI. -// -// This is a very common source of bugs, please try to keep this in mind. -// -// ARCANE BITS OF PATH TRIVIA -// -// - A double leading slash is actually part of the POSIX standard. Systems -// are allowed to treat // as an alternate root, as Windows does for UNC -// (network share) paths. Most POSIX systems don't do anything special -// with two leading slashes, but FilePath handles this case properly -// in case it ever comes across such a system. FilePath needs this support -// for Windows UNC paths, anyway. -// References: -// The Open Group Base Specifications Issue 7, sections 3.267 ("Pathname") -// and 4.12 ("Pathname Resolution"), available at: -// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_267 -// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12 -// -// - Windows treats c:\\ the same way it treats \\. This was intended to -// allow older applications that require drive letters to support UNC paths -// like \\server\share\path, by permitting c:\\server\share\path as an -// equivalent. Since the OS treats these paths specially, FilePath needs -// to do the same. Since Windows can use either / or \ as the separator, -// FilePath treats c://, c:\\, //, and \\ all equivalently. -// Reference: -// The Old New Thing, "Why is a drive letter permitted in front of UNC -// paths (sometimes)?", available at: -// http://blogs.msdn.com/oldnewthing/archive/2005/11/22/495740.aspx - -#ifndef BASE_FILES_FILE_PATH_H_ -#define BASE_FILES_FILE_PATH_H_ - -#include <stddef.h> - -#include <iosfwd> -#include <string> -#include <vector> - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/containers/hash_tables.h" -#include "base/macros.h" -#include "base/strings/string16.h" -#include "base/strings/string_piece.h" -#include "build/build_config.h" - -// Windows-style drive letter support and pathname separator characters can be -// enabled and disabled independently, to aid testing. These #defines are -// here so that the same setting can be used in both the implementation and -// in the unit test. -#if defined(OS_WIN) -#define FILE_PATH_USES_DRIVE_LETTERS -#define FILE_PATH_USES_WIN_SEPARATORS -#endif // OS_WIN - -// To print path names portably use PRIsFP (based on PRIuS and friends from -// C99 and format_macros.h) like this: -// base::StringPrintf("Path is %" PRIsFP ".\n", path.value().c_str()); -#if defined(OS_POSIX) -#define PRIsFP "s" -#elif defined(OS_WIN) -#define PRIsFP "ls" -#endif // OS_WIN - -namespace base { - -class Pickle; -class PickleIterator; - -// An abstraction to isolate users from the differences between native -// pathnames on different platforms. -class BASE_EXPORT FilePath { - public: -#if defined(OS_POSIX) - // On most platforms, native pathnames are char arrays, and the encoding - // may or may not be specified. On Mac OS X, native pathnames are encoded - // in UTF-8. - typedef std::string StringType; -#elif defined(OS_WIN) - // On Windows, for Unicode-aware applications, native pathnames are wchar_t - // arrays encoded in UTF-16. - typedef std::wstring StringType; -#endif // OS_WIN - - typedef BasicStringPiece<StringType> StringPieceType; - typedef StringType::value_type CharType; - - // Null-terminated array of separators used to separate components in - // hierarchical paths. Each character in this array is a valid separator, - // but kSeparators[0] is treated as the canonical separator and will be used - // when composing pathnames. - static const CharType kSeparators[]; - - // arraysize(kSeparators). - static const size_t kSeparatorsLength; - - // A special path component meaning "this directory." - static const CharType kCurrentDirectory[]; - - // A special path component meaning "the parent directory." - static const CharType kParentDirectory[]; - - // The character used to identify a file extension. - static const CharType kExtensionSeparator; - - FilePath(); - FilePath(const FilePath& that); - explicit FilePath(StringPieceType path); - ~FilePath(); - FilePath& operator=(const FilePath& that); - - bool operator==(const FilePath& that) const; - - bool operator!=(const FilePath& that) const; - - // Required for some STL containers and operations - bool operator<(const FilePath& that) const { - return path_ < that.path_; - } - - const StringType& value() const { return path_; } - - bool empty() const { return path_.empty(); } - - void clear() { path_.clear(); } - - // Returns true if |character| is in kSeparators. - static bool IsSeparator(CharType character); - - // Returns a vector of all of the components of the provided path. It is - // equivalent to calling DirName().value() on the path's root component, - // and BaseName().value() on each child component. - // - // To make sure this is lossless so we can differentiate absolute and - // relative paths, the root slash will be included even though no other - // slashes will be. The precise behavior is: - // - // Posix: "/foo/bar" -> [ "/", "foo", "bar" ] - // Windows: "C:\foo\bar" -> [ "C:", "\\", "foo", "bar" ] - void GetComponents(std::vector<FilePath::StringType>* components) const; - - // Returns true if this FilePath is a strict parent of the |child|. Absolute - // and relative paths are accepted i.e. is /foo parent to /foo/bar and - // is foo parent to foo/bar. Does not convert paths to absolute, follow - // symlinks or directory navigation (e.g. ".."). A path is *NOT* its own - // parent. - bool IsParent(const FilePath& child) const; - - // If IsParent(child) holds, appends to path (if non-NULL) the - // relative path to child and returns true. For example, if parent - // holds "/Users/johndoe/Library/Application Support", child holds - // "/Users/johndoe/Library/Application Support/Google/Chrome/Default", and - // *path holds "/Users/johndoe/Library/Caches", then after - // parent.AppendRelativePath(child, path) is called *path will hold - // "/Users/johndoe/Library/Caches/Google/Chrome/Default". Otherwise, - // returns false. - bool AppendRelativePath(const FilePath& child, FilePath* path) const; - - // Returns a FilePath corresponding to the directory containing the path - // named by this object, stripping away the file component. If this object - // only contains one component, returns a FilePath identifying - // kCurrentDirectory. If this object already refers to the root directory, - // returns a FilePath identifying the root directory. - FilePath DirName() const WARN_UNUSED_RESULT; - - // Returns a FilePath corresponding to the last path component of this - // object, either a file or a directory. If this object already refers to - // the root directory, returns a FilePath identifying the root directory; - // this is the only situation in which BaseName will return an absolute path. - FilePath BaseName() const WARN_UNUSED_RESULT; - - // Returns ".jpg" for path "C:\pics\jojo.jpg", or an empty string if - // the file has no extension. If non-empty, Extension() will always start - // with precisely one ".". The following code should always work regardless - // of the value of path. For common double-extensions like .tar.gz and - // .user.js, this method returns the combined extension. For a single - // component, use FinalExtension(). - // new_path = path.RemoveExtension().value().append(path.Extension()); - // ASSERT(new_path == path.value()); - // NOTE: this is different from the original file_util implementation which - // returned the extension without a leading "." ("jpg" instead of ".jpg") - StringType Extension() const WARN_UNUSED_RESULT; - - // Returns the path's file extension, as in Extension(), but will - // never return a double extension. - // - // TODO(davidben): Check all our extension-sensitive code to see if - // we can rename this to Extension() and the other to something like - // LongExtension(), defaulting to short extensions and leaving the - // long "extensions" to logic like base::GetUniquePathNumber(). - StringType FinalExtension() const WARN_UNUSED_RESULT; - - // Returns "C:\pics\jojo" for path "C:\pics\jojo.jpg" - // NOTE: this is slightly different from the similar file_util implementation - // which returned simply 'jojo'. - FilePath RemoveExtension() const WARN_UNUSED_RESULT; - - // Removes the path's file extension, as in RemoveExtension(), but - // ignores double extensions. - FilePath RemoveFinalExtension() const WARN_UNUSED_RESULT; - - // Inserts |suffix| after the file name portion of |path| but before the - // extension. Returns "" if BaseName() == "." or "..". - // Examples: - // path == "C:\pics\jojo.jpg" suffix == " (1)", returns "C:\pics\jojo (1).jpg" - // path == "jojo.jpg" suffix == " (1)", returns "jojo (1).jpg" - // path == "C:\pics\jojo" suffix == " (1)", returns "C:\pics\jojo (1)" - // path == "C:\pics.old\jojo" suffix == " (1)", returns "C:\pics.old\jojo (1)" - FilePath InsertBeforeExtension( - StringPieceType suffix) const WARN_UNUSED_RESULT; - FilePath InsertBeforeExtensionASCII( - StringPiece suffix) const WARN_UNUSED_RESULT; - - // Adds |extension| to |file_name|. Returns the current FilePath if - // |extension| is empty. Returns "" if BaseName() == "." or "..". - FilePath AddExtension(StringPieceType extension) const WARN_UNUSED_RESULT; - - // Replaces the extension of |file_name| with |extension|. If |file_name| - // does not have an extension, then |extension| is added. If |extension| is - // empty, then the extension is removed from |file_name|. - // Returns "" if BaseName() == "." or "..". - FilePath ReplaceExtension(StringPieceType extension) const WARN_UNUSED_RESULT; - - // Returns true if the file path matches the specified extension. The test is - // case insensitive. Don't forget the leading period if appropriate. - bool MatchesExtension(StringPieceType extension) const; - - // Returns a FilePath by appending a separator and the supplied path - // component to this object's path. Append takes care to avoid adding - // excessive separators if this object's path already ends with a separator. - // If this object's path is kCurrentDirectory, a new FilePath corresponding - // only to |component| is returned. |component| must be a relative path; - // it is an error to pass an absolute path. - FilePath Append(StringPieceType component) const WARN_UNUSED_RESULT; - FilePath Append(const FilePath& component) const WARN_UNUSED_RESULT; - - // Although Windows StringType is std::wstring, since the encoding it uses for - // paths is well defined, it can handle ASCII path components as well. - // Mac uses UTF8, and since ASCII is a subset of that, it works there as well. - // On Linux, although it can use any 8-bit encoding for paths, we assume that - // ASCII is a valid subset, regardless of the encoding, since many operating - // system paths will always be ASCII. - FilePath AppendASCII(StringPiece component) const WARN_UNUSED_RESULT; - - // Returns true if this FilePath contains an absolute path. On Windows, an - // absolute path begins with either a drive letter specification followed by - // a separator character, or with two separator characters. On POSIX - // platforms, an absolute path begins with a separator character. - bool IsAbsolute() const; - - // Returns true if the patch ends with a path separator character. - bool EndsWithSeparator() const WARN_UNUSED_RESULT; - - // Returns a copy of this FilePath that ends with a trailing separator. If - // the input path is empty, an empty FilePath will be returned. - FilePath AsEndingWithSeparator() const WARN_UNUSED_RESULT; - - // Returns a copy of this FilePath that does not end with a trailing - // separator. - FilePath StripTrailingSeparators() const WARN_UNUSED_RESULT; - - // Returns true if this FilePath contains an attempt to reference a parent - // directory (e.g. has a path component that is ".."). - bool ReferencesParent() const; - - // Return a Unicode human-readable version of this path. - // Warning: you can *not*, in general, go from a display name back to a real - // path. Only use this when displaying paths to users, not just when you - // want to stuff a string16 into some other API. - string16 LossyDisplayName() const; - - // Return the path as ASCII, or the empty string if the path is not ASCII. - // This should only be used for cases where the FilePath is representing a - // known-ASCII filename. - std::string MaybeAsASCII() const; - - // Return the path as UTF-8. - // - // This function is *unsafe* as there is no way to tell what encoding is - // used in file names on POSIX systems other than Mac and Chrome OS, - // although UTF-8 is practically used everywhere these days. To mitigate - // the encoding issue, this function internally calls - // SysNativeMBToWide() on POSIX systems other than Mac and Chrome OS, - // per assumption that the current locale's encoding is used in file - // names, but this isn't a perfect solution. - // - // Once it becomes safe to to stop caring about non-UTF-8 file names, - // the SysNativeMBToWide() hack will be removed from the code, along - // with "Unsafe" in the function name. - std::string AsUTF8Unsafe() const; - - // Similar to AsUTF8Unsafe, but returns UTF-16 instead. - string16 AsUTF16Unsafe() const; - - // Returns a FilePath object from a path name in UTF-8. This function - // should only be used for cases where you are sure that the input - // string is UTF-8. - // - // Like AsUTF8Unsafe(), this function is unsafe. This function - // internally calls SysWideToNativeMB() on POSIX systems other than Mac - // and Chrome OS, to mitigate the encoding issue. See the comment at - // AsUTF8Unsafe() for details. - static FilePath FromUTF8Unsafe(const std::string& utf8); - - // Similar to FromUTF8Unsafe, but accepts UTF-16 instead. - static FilePath FromUTF16Unsafe(const string16& utf16); - - void WriteToPickle(Pickle* pickle) const; - bool ReadFromPickle(PickleIterator* iter); - - // Normalize all path separators to backslash on Windows - // (if FILE_PATH_USES_WIN_SEPARATORS is true), or do nothing on POSIX systems. - FilePath NormalizePathSeparators() const; - - // Normalize all path separattors to given type on Windows - // (if FILE_PATH_USES_WIN_SEPARATORS is true), or do nothing on POSIX systems. - FilePath NormalizePathSeparatorsTo(CharType separator) const; - - // Compare two strings in the same way the file system does. - // Note that these always ignore case, even on file systems that are case- - // sensitive. If case-sensitive comparison is ever needed, add corresponding - // methods here. - // The methods are written as a static method so that they can also be used - // on parts of a file path, e.g., just the extension. - // CompareIgnoreCase() returns -1, 0 or 1 for less-than, equal-to and - // greater-than respectively. - static int CompareIgnoreCase(StringPieceType string1, - StringPieceType string2); - static bool CompareEqualIgnoreCase(StringPieceType string1, - StringPieceType string2) { - return CompareIgnoreCase(string1, string2) == 0; - } - static bool CompareLessIgnoreCase(StringPieceType string1, - StringPieceType string2) { - return CompareIgnoreCase(string1, string2) < 0; - } - -#if defined(OS_MACOSX) - // Returns the string in the special canonical decomposed form as defined for - // HFS, which is close to, but not quite, decomposition form D. See - // http://developer.apple.com/mac/library/technotes/tn/tn1150.html#UnicodeSubtleties - // for further comments. - // Returns the epmty string if the conversion failed. - static StringType GetHFSDecomposedForm(StringPieceType string); - - // Special UTF-8 version of FastUnicodeCompare. Cf: - // http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringComparisonAlgorithm - // IMPORTANT: The input strings must be in the special HFS decomposed form! - // (cf. above GetHFSDecomposedForm method) - static int HFSFastUnicodeCompare(StringPieceType string1, - StringPieceType string2); -#endif - -#if defined(OS_ANDROID) - // On android, file selection dialog can return a file with content uri - // scheme(starting with content://). Content uri needs to be opened with - // ContentResolver to guarantee that the app has appropriate permissions - // to access it. - // Returns true if the path is a content uri, or false otherwise. - bool IsContentUri() const; -#endif - - private: - // Remove trailing separators from this object. If the path is absolute, it - // will never be stripped any more than to refer to the absolute root - // directory, so "////" will become "/", not "". A leading pair of - // separators is never stripped, to support alternate roots. This is used to - // support UNC paths on Windows. - void StripTrailingSeparatorsInternal(); - - StringType path_; -}; - -// This is required by googletest to print a readable output on test failures. -// This is declared here for use in gtest-based unit tests but is defined in -// the test_support_base target. Depend on that to use this in your unit test. -// This should not be used in production code - call ToString() instead. -void PrintTo(const FilePath& path, std::ostream* out); - -} // namespace base - -// Macros for string literal initialization of FilePath::CharType[], and for -// using a FilePath::CharType[] in a printf-style format string. -#if defined(OS_POSIX) -#define FILE_PATH_LITERAL(x) x -#define PRFilePath "s" -#elif defined(OS_WIN) -#define FILE_PATH_LITERAL(x) L ## x -#define PRFilePath "ls" -#endif // OS_WIN - -// Provide a hash function so that hash_sets and maps can contain FilePath -// objects. -namespace BASE_HASH_NAMESPACE { - -template<> -struct hash<base::FilePath> { - size_t operator()(const base::FilePath& f) const { - return hash<base::FilePath::StringType>()(f.value()); - } -}; - -} // namespace BASE_HASH_NAMESPACE - -#endif // BASE_FILES_FILE_PATH_H_ diff --git a/security/sandbox/chromium/base/guid.h b/security/sandbox/chromium/base/guid.h deleted file mode 100644 index c0a06f885..000000000 --- a/security/sandbox/chromium/base/guid.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_GUID_H_ -#define BASE_GUID_H_ - -#include <stdint.h> - -#include <string> - -#include "base/base_export.h" -#include "build/build_config.h" - -namespace base { - -// Generate a 128-bit random GUID of the form: "%08X-%04X-%04X-%04X-%012llX". -// If GUID generation fails an empty string is returned. -// The POSIX implementation uses pseudo random number generation to create -// the GUID. The Windows implementation uses system services. -BASE_EXPORT std::string GenerateGUID(); - -// Returns true if the input string conforms to the GUID format. -BASE_EXPORT bool IsValidGUID(const std::string& guid); - -#if defined(OS_POSIX) -// For unit testing purposes only. Do not use outside of tests. -BASE_EXPORT std::string RandomDataToGUIDString(const uint64_t bytes[2]); -#endif - -} // namespace base - -#endif // BASE_GUID_H_ diff --git a/security/sandbox/chromium/base/hash.cc b/security/sandbox/chromium/base/hash.cc deleted file mode 100644 index d3206f6a6..000000000 --- a/security/sandbox/chromium/base/hash.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/hash.h" - -// Definition in base/third_party/superfasthash/superfasthash.c. (Third-party -// code did not come with its own header file, so declaring the function here.) -// Note: This algorithm is also in Blink under Source/wtf/StringHasher.h. -extern "C" uint32_t SuperFastHash(const char* data, int len); - -namespace base { - -uint32_t SuperFastHash(const char* data, int len) { - return ::SuperFastHash(data, len); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/hash.h b/security/sandbox/chromium/base/hash.h deleted file mode 100644 index ed8d9fd4c..000000000 --- a/security/sandbox/chromium/base/hash.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_HASH_H_ -#define BASE_HASH_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <limits> -#include <string> - -#include "base/base_export.h" -#include "base/logging.h" - -namespace base { - -// WARNING: This hash function should not be used for any cryptographic purpose. -BASE_EXPORT uint32_t SuperFastHash(const char* data, int len); - -// Computes a hash of a memory buffer |data| of a given |length|. -// WARNING: This hash function should not be used for any cryptographic purpose. -inline uint32_t Hash(const char* data, size_t length) { - if (length > static_cast<size_t>(std::numeric_limits<int>::max())) { - NOTREACHED(); - return 0; - } - return SuperFastHash(data, static_cast<int>(length)); -} - -// Computes a hash of a string |str|. -// WARNING: This hash function should not be used for any cryptographic purpose. -inline uint32_t Hash(const std::string& str) { - return Hash(str.data(), str.size()); -} - -} // namespace base - -#endif // BASE_HASH_H_ diff --git a/security/sandbox/chromium/base/lazy_instance.cc b/security/sandbox/chromium/base/lazy_instance.cc deleted file mode 100644 index 54680655a..000000000 --- a/security/sandbox/chromium/base/lazy_instance.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/lazy_instance.h" - -#include "base/at_exit.h" -#include "base/atomicops.h" -#include "base/threading/platform_thread.h" - -namespace base { -namespace internal { - -// TODO(joth): This function could be shared with Singleton, in place of its -// WaitForInstance() call. -bool NeedsLazyInstance(subtle::AtomicWord* state) { - // Try to create the instance, if we're the first, will go from 0 to - // kLazyInstanceStateCreating, otherwise we've already been beaten here. - // The memory access has no memory ordering as state 0 and - // kLazyInstanceStateCreating have no associated data (memory barriers are - // all about ordering of memory accesses to *associated* data). - if (subtle::NoBarrier_CompareAndSwap(state, 0, - kLazyInstanceStateCreating) == 0) - // Caller must create instance - return true; - - // It's either in the process of being created, or already created. Spin. - // The load has acquire memory ordering as a thread which sees - // state_ == STATE_CREATED needs to acquire visibility over - // the associated data (buf_). Pairing Release_Store is in - // CompleteLazyInstance(). - while (subtle::Acquire_Load(state) == kLazyInstanceStateCreating) { - PlatformThread::YieldCurrentThread(); - } - // Someone else created the instance. - return false; -} - -void CompleteLazyInstance(subtle::AtomicWord* state, - subtle::AtomicWord new_instance, - void* lazy_instance, - void (*dtor)(void*)) { - // Instance is created, go from CREATING to CREATED. - // Releases visibility over private_buf_ to readers. Pairing Acquire_Load's - // are in NeedsInstance() and Pointer(). - subtle::Release_Store(state, new_instance); - - // Make sure that the lazily instantiated object will get destroyed at exit. - if (dtor) - AtExitManager::RegisterCallback(dtor, lazy_instance); -} - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/lazy_instance.h b/security/sandbox/chromium/base/lazy_instance.h deleted file mode 100644 index fd0321017..000000000 --- a/security/sandbox/chromium/base/lazy_instance.h +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// The LazyInstance<Type, Traits> class manages a single instance of Type, -// which will be lazily created on the first time it's accessed. This class is -// useful for places you would normally use a function-level static, but you -// need to have guaranteed thread-safety. The Type constructor will only ever -// be called once, even if two threads are racing to create the object. Get() -// and Pointer() will always return the same, completely initialized instance. -// When the instance is constructed it is registered with AtExitManager. The -// destructor will be called on program exit. -// -// LazyInstance is completely thread safe, assuming that you create it safely. -// The class was designed to be POD initialized, so it shouldn't require a -// static constructor. It really only makes sense to declare a LazyInstance as -// a global variable using the LAZY_INSTANCE_INITIALIZER initializer. -// -// LazyInstance is similar to Singleton, except it does not have the singleton -// property. You can have multiple LazyInstance's of the same type, and each -// will manage a unique instance. It also preallocates the space for Type, as -// to avoid allocating the Type instance on the heap. This may help with the -// performance of creating the instance, and reducing heap fragmentation. This -// requires that Type be a complete type so we can determine the size. -// -// Example usage: -// static LazyInstance<MyClass> my_instance = LAZY_INSTANCE_INITIALIZER; -// void SomeMethod() { -// my_instance.Get().SomeMethod(); // MyClass::SomeMethod() -// -// MyClass* ptr = my_instance.Pointer(); -// ptr->DoDoDo(); // MyClass::DoDoDo -// } - -#ifndef BASE_LAZY_INSTANCE_H_ -#define BASE_LAZY_INSTANCE_H_ - -#include <new> // For placement new. - -#include "base/atomicops.h" -#include "base/base_export.h" -#include "base/debug/leak_annotations.h" -#include "base/logging.h" -#include "base/memory/aligned_memory.h" -#include "base/threading/thread_restrictions.h" - -// LazyInstance uses its own struct initializer-list style static -// initialization, as base's LINKER_INITIALIZED requires a constructor and on -// some compilers (notably gcc 4.4) this still ends up needing runtime -// initialization. -#define LAZY_INSTANCE_INITIALIZER {0} - -namespace base { - -template <typename Type> -struct DefaultLazyInstanceTraits { - static const bool kRegisterOnExit = true; -#ifndef NDEBUG - static const bool kAllowedToAccessOnNonjoinableThread = false; -#endif - - static Type* New(void* instance) { - DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) & (ALIGNOF(Type) - 1), 0u) - << ": Bad boy, the buffer passed to placement new is not aligned!\n" - "This may break some stuff like SSE-based optimizations assuming the " - "<Type> objects are word aligned."; - // Use placement new to initialize our instance in our preallocated space. - // The parenthesis is very important here to force POD type initialization. - return new (instance) Type(); - } - static void Delete(Type* instance) { - // Explicitly call the destructor. - instance->~Type(); - } -}; - -// We pull out some of the functionality into non-templated functions, so we -// can implement the more complicated pieces out of line in the .cc file. -namespace internal { - -// Use LazyInstance<T>::Leaky for a less-verbose call-site typedef; e.g.: -// base::LazyInstance<T>::Leaky my_leaky_lazy_instance; -// instead of: -// base::LazyInstance<T, base::internal::LeakyLazyInstanceTraits<T> > -// my_leaky_lazy_instance; -// (especially when T is MyLongTypeNameImplClientHolderFactory). -// Only use this internal::-qualified verbose form to extend this traits class -// (depending on its implementation details). -template <typename Type> -struct LeakyLazyInstanceTraits { - static const bool kRegisterOnExit = false; -#ifndef NDEBUG - static const bool kAllowedToAccessOnNonjoinableThread = true; -#endif - - static Type* New(void* instance) { - ANNOTATE_SCOPED_MEMORY_LEAK; - return DefaultLazyInstanceTraits<Type>::New(instance); - } - static void Delete(Type* instance) { - } -}; - -// Our AtomicWord doubles as a spinlock, where a value of -// kBeingCreatedMarker means the spinlock is being held for creation. -static const subtle::AtomicWord kLazyInstanceStateCreating = 1; - -// Check if instance needs to be created. If so return true otherwise -// if another thread has beat us, wait for instance to be created and -// return false. -BASE_EXPORT bool NeedsLazyInstance(subtle::AtomicWord* state); - -// After creating an instance, call this to register the dtor to be called -// at program exit and to update the atomic state to hold the |new_instance| -BASE_EXPORT void CompleteLazyInstance(subtle::AtomicWord* state, - subtle::AtomicWord new_instance, - void* lazy_instance, - void (*dtor)(void*)); - -} // namespace internal - -template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> > -class LazyInstance { - public: - // Do not define a destructor, as doing so makes LazyInstance a - // non-POD-struct. We don't want that because then a static initializer will - // be created to register the (empty) destructor with atexit() under MSVC, for - // example. We handle destruction of the contained Type class explicitly via - // the OnExit member function, where needed. - // ~LazyInstance() {} - - // Convenience typedef to avoid having to repeat Type for leaky lazy - // instances. - typedef LazyInstance<Type, internal::LeakyLazyInstanceTraits<Type> > Leaky; - - Type& Get() { - return *Pointer(); - } - - Type* Pointer() { -#ifndef NDEBUG - // Avoid making TLS lookup on release builds. - if (!Traits::kAllowedToAccessOnNonjoinableThread) - ThreadRestrictions::AssertSingletonAllowed(); -#endif - // If any bit in the created mask is true, the instance has already been - // fully constructed. - static const subtle::AtomicWord kLazyInstanceCreatedMask = - ~internal::kLazyInstanceStateCreating; - - // We will hopefully have fast access when the instance is already created. - // Since a thread sees private_instance_ == 0 or kLazyInstanceStateCreating - // at most once, the load is taken out of NeedsInstance() as a fast-path. - // The load has acquire memory ordering as a thread which sees - // private_instance_ > creating needs to acquire visibility over - // the associated data (private_buf_). Pairing Release_Store is in - // CompleteLazyInstance(). - subtle::AtomicWord value = subtle::Acquire_Load(&private_instance_); - if (!(value & kLazyInstanceCreatedMask) && - internal::NeedsLazyInstance(&private_instance_)) { - // Create the instance in the space provided by |private_buf_|. - value = reinterpret_cast<subtle::AtomicWord>( - Traits::New(private_buf_.void_data())); - internal::CompleteLazyInstance(&private_instance_, value, this, - Traits::kRegisterOnExit ? OnExit : NULL); - } - return instance(); - } - - bool operator==(Type* p) { - switch (subtle::NoBarrier_Load(&private_instance_)) { - case 0: - return p == NULL; - case internal::kLazyInstanceStateCreating: - return static_cast<void*>(p) == private_buf_.void_data(); - default: - return p == instance(); - } - } - - // Effectively private: member data is only public to allow the linker to - // statically initialize it and to maintain a POD class. DO NOT USE FROM - // OUTSIDE THIS CLASS. - - subtle::AtomicWord private_instance_; - // Preallocated space for the Type instance. - base::AlignedMemory<sizeof(Type), ALIGNOF(Type)> private_buf_; - - private: - Type* instance() { - return reinterpret_cast<Type*>(subtle::NoBarrier_Load(&private_instance_)); - } - - // Adapter function for use with AtExit. This should be called single - // threaded, so don't synchronize across threads. - // Calling OnExit while the instance is in use by other threads is a mistake. - static void OnExit(void* lazy_instance) { - LazyInstance<Type, Traits>* me = - reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance); - Traits::Delete(me->instance()); - subtle::NoBarrier_Store(&me->private_instance_, 0); - } -}; - -} // namespace base - -#endif // BASE_LAZY_INSTANCE_H_ diff --git a/security/sandbox/chromium/base/location.cc b/security/sandbox/chromium/base/location.cc deleted file mode 100644 index 1333e6ec4..000000000 --- a/security/sandbox/chromium/base/location.cc +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "build/build_config.h" - -#if defined(COMPILER_MSVC) -#include <intrin.h> -#endif - -#include "base/location.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" - -namespace tracked_objects { - -Location::Location(const char* function_name, - const char* file_name, - int line_number, - const void* program_counter) - : function_name_(function_name), - file_name_(file_name), - line_number_(line_number), - program_counter_(program_counter) { -} - -Location::Location() - : function_name_("Unknown"), - file_name_("Unknown"), - line_number_(-1), - program_counter_(NULL) { -} - -Location::Location(const Location& other) - : function_name_(other.function_name_), - file_name_(other.file_name_), - line_number_(other.line_number_), - program_counter_(other.program_counter_) { -} - -std::string Location::ToString() const { - return std::string(function_name_) + "@" + file_name_ + ":" + - base::IntToString(line_number_); -} - -void Location::Write(bool display_filename, bool display_function_name, - std::string* output) const { - base::StringAppendF(output, "%s[%d] ", - display_filename ? file_name_ : "line", - line_number_); - - if (display_function_name) { - WriteFunctionName(output); - output->push_back(' '); - } -} - -void Location::WriteFunctionName(std::string* output) const { - // Translate "<" to "<" for HTML safety. - // TODO(jar): Support ASCII or html for logging in ASCII. - for (const char *p = function_name_; *p; p++) { - switch (*p) { - case '<': - output->append("<"); - break; - - case '>': - output->append(">"); - break; - - default: - output->push_back(*p); - break; - } - } -} - -//------------------------------------------------------------------------------ -LocationSnapshot::LocationSnapshot() : line_number(-1) { -} - -LocationSnapshot::LocationSnapshot( - const tracked_objects::Location& location) - : file_name(location.file_name()), - function_name(location.function_name()), - line_number(location.line_number()) { -} - -LocationSnapshot::~LocationSnapshot() { -} - -//------------------------------------------------------------------------------ -#if defined(COMPILER_MSVC) -__declspec(noinline) -#endif -BASE_EXPORT const void* GetProgramCounter() { -#if defined(COMPILER_MSVC) - return _ReturnAddress(); -#elif defined(COMPILER_GCC) && !defined(OS_NACL) - return __builtin_extract_return_addr(__builtin_return_address(0)); -#else - return NULL; -#endif -} - -} // namespace tracked_objects diff --git a/security/sandbox/chromium/base/location.h b/security/sandbox/chromium/base/location.h deleted file mode 100644 index d3bb23c63..000000000 --- a/security/sandbox/chromium/base/location.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_LOCATION_H_ -#define BASE_LOCATION_H_ - -#include <stddef.h> - -#include <cassert> -#include <string> - -#include "base/base_export.h" -#include "base/containers/hash_tables.h" - -namespace tracked_objects { - -// Location provides basic info where of an object was constructed, or was -// significantly brought to life. -class BASE_EXPORT Location { - public: - // Constructor should be called with a long-lived char*, such as __FILE__. - // It assumes the provided value will persist as a global constant, and it - // will not make a copy of it. - Location(const char* function_name, - const char* file_name, - int line_number, - const void* program_counter); - - // Provide a default constructor for easy of debugging. - Location(); - - // Copy constructor. - Location(const Location& other); - - // Comparator for hash map insertion. - // No need to use |function_name_| since the other two fields uniquely - // identify this location. - bool operator==(const Location& other) const { - return line_number_ == other.line_number_ && - file_name_ == other.file_name_; - } - - const char* function_name() const { return function_name_; } - const char* file_name() const { return file_name_; } - int line_number() const { return line_number_; } - const void* program_counter() const { return program_counter_; } - - std::string ToString() const; - - // Hash operator for hash maps. - struct Hash { - size_t operator()(const Location& location) const { - // Compute the hash value using file name pointer and line number. - // No need to use |function_name_| since the other two fields uniquely - // identify this location. - - // The file name will always be uniquely identified by its pointer since - // it comes from __FILE__, so no need to check the contents of the string. - // See the definition of FROM_HERE in location.h, and how it is used - // elsewhere. - return base::HashPair(reinterpret_cast<uintptr_t>(location.file_name()), - location.line_number()); - } - }; - - // Translate the some of the state in this instance into a human readable - // string with HTML characters in the function names escaped, and append that - // string to |output|. Inclusion of the file_name_ and function_name_ are - // optional, and controlled by the boolean arguments. - void Write(bool display_filename, bool display_function_name, - std::string* output) const; - - // Write function_name_ in HTML with '<' and '>' properly encoded. - void WriteFunctionName(std::string* output) const; - - private: - const char* function_name_; - const char* file_name_; - int line_number_; - const void* program_counter_; -}; - -// A "snapshotted" representation of the Location class that can safely be -// passed across process boundaries. -struct BASE_EXPORT LocationSnapshot { - // The default constructor is exposed to support the IPC serialization macros. - LocationSnapshot(); - explicit LocationSnapshot(const tracked_objects::Location& location); - ~LocationSnapshot(); - - std::string file_name; - std::string function_name; - int line_number; -}; - -BASE_EXPORT const void* GetProgramCounter(); - -// Define a macro to record the current source location. -#define FROM_HERE FROM_HERE_WITH_EXPLICIT_FUNCTION(__FUNCTION__) - -#define FROM_HERE_WITH_EXPLICIT_FUNCTION(function_name) \ - ::tracked_objects::Location(function_name, \ - __FILE__, \ - __LINE__, \ - ::tracked_objects::GetProgramCounter()) - -} // namespace tracked_objects - -#endif // BASE_LOCATION_H_ diff --git a/security/sandbox/chromium/base/logging.h b/security/sandbox/chromium/base/logging.h deleted file mode 100644 index 300c9b526..000000000 --- a/security/sandbox/chromium/base/logging.h +++ /dev/null @@ -1,976 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_LOGGING_H_ -#define BASE_LOGGING_H_ - -#include <stddef.h> - -#include <cassert> -#include <cstring> -#include <sstream> -#include <string> - -#include "base/base_export.h" -#include "base/debug/debugger.h" -#include "base/macros.h" -#include "build/build_config.h" - -// -// Optional message capabilities -// ----------------------------- -// Assertion failed messages and fatal errors are displayed in a dialog box -// before the application exits. However, running this UI creates a message -// loop, which causes application messages to be processed and potentially -// dispatched to existing application windows. Since the application is in a -// bad state when this assertion dialog is displayed, these messages may not -// get processed and hang the dialog, or the application might go crazy. -// -// Therefore, it can be beneficial to display the error dialog in a separate -// process from the main application. When the logging system needs to display -// a fatal error dialog box, it will look for a program called -// "DebugMessage.exe" in the same directory as the application executable. It -// will run this application with the message as the command line, and will -// not include the name of the application as is traditional for easier -// parsing. -// -// The code for DebugMessage.exe is only one line. In WinMain, do: -// MessageBox(NULL, GetCommandLineW(), L"Fatal Error", 0); -// -// If DebugMessage.exe is not found, the logging code will use a normal -// MessageBox, potentially causing the problems discussed above. - - -// Instructions -// ------------ -// -// Make a bunch of macros for logging. The way to log things is to stream -// things to LOG(<a particular severity level>). E.g., -// -// LOG(INFO) << "Found " << num_cookies << " cookies"; -// -// You can also do conditional logging: -// -// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; -// -// The CHECK(condition) macro is active in both debug and release builds and -// effectively performs a LOG(FATAL) which terminates the process and -// generates a crashdump unless a debugger is attached. -// -// There are also "debug mode" logging macros like the ones above: -// -// DLOG(INFO) << "Found cookies"; -// -// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; -// -// All "debug mode" logging is compiled away to nothing for non-debug mode -// compiles. LOG_IF and development flags also work well together -// because the code can be compiled away sometimes. -// -// We also have -// -// LOG_ASSERT(assertion); -// DLOG_ASSERT(assertion); -// -// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion; -// -// There are "verbose level" logging macros. They look like -// -// VLOG(1) << "I'm printed when you run the program with --v=1 or more"; -// VLOG(2) << "I'm printed when you run the program with --v=2 or more"; -// -// These always log at the INFO log level (when they log at all). -// The verbose logging can also be turned on module-by-module. For instance, -// --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0 -// will cause: -// a. VLOG(2) and lower messages to be printed from profile.{h,cc} -// b. VLOG(1) and lower messages to be printed from icon_loader.{h,cc} -// c. VLOG(3) and lower messages to be printed from files prefixed with -// "browser" -// d. VLOG(4) and lower messages to be printed from files under a -// "chromeos" directory. -// e. VLOG(0) and lower messages to be printed from elsewhere -// -// The wildcarding functionality shown by (c) supports both '*' (match -// 0 or more characters) and '?' (match any single character) -// wildcards. Any pattern containing a forward or backward slash will -// be tested against the whole pathname and not just the module. -// E.g., "*/foo/bar/*=2" would change the logging level for all code -// in source files under a "foo/bar" directory. -// -// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as -// -// if (VLOG_IS_ON(2)) { -// // do some logging preparation and logging -// // that can't be accomplished with just VLOG(2) << ...; -// } -// -// There is also a VLOG_IF "verbose level" condition macro for sample -// cases, when some extra computation and preparation for logs is not -// needed. -// -// VLOG_IF(1, (size > 1024)) -// << "I'm printed when size is more than 1024 and when you run the " -// "program with --v=1 or more"; -// -// We also override the standard 'assert' to use 'DLOG_ASSERT'. -// -// Lastly, there is: -// -// PLOG(ERROR) << "Couldn't do foo"; -// DPLOG(ERROR) << "Couldn't do foo"; -// PLOG_IF(ERROR, cond) << "Couldn't do foo"; -// DPLOG_IF(ERROR, cond) << "Couldn't do foo"; -// PCHECK(condition) << "Couldn't do foo"; -// DPCHECK(condition) << "Couldn't do foo"; -// -// which append the last system error to the message in string form (taken from -// GetLastError() on Windows and errno on POSIX). -// -// The supported severity levels for macros that allow you to specify one -// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL. -// -// Very important: logging a message at the FATAL severity level causes -// the program to terminate (after the message is logged). -// -// There is the special severity of DFATAL, which logs FATAL in debug mode, -// ERROR in normal mode. - -namespace logging { - -// TODO(avi): do we want to do a unification of character types here? -#if defined(OS_WIN) -typedef wchar_t PathChar; -#else -typedef char PathChar; -#endif - -// Where to record logging output? A flat file and/or system debug log -// via OutputDebugString. -enum LoggingDestination { - LOG_NONE = 0, - LOG_TO_FILE = 1 << 0, - LOG_TO_SYSTEM_DEBUG_LOG = 1 << 1, - - LOG_TO_ALL = LOG_TO_FILE | LOG_TO_SYSTEM_DEBUG_LOG, - - // On Windows, use a file next to the exe; on POSIX platforms, where - // it may not even be possible to locate the executable on disk, use - // stderr. -#if defined(OS_WIN) - LOG_DEFAULT = LOG_TO_FILE, -#elif defined(OS_POSIX) - LOG_DEFAULT = LOG_TO_SYSTEM_DEBUG_LOG, -#endif -}; - -// Indicates that the log file should be locked when being written to. -// Unless there is only one single-threaded process that is logging to -// the log file, the file should be locked during writes to make each -// log output atomic. Other writers will block. -// -// All processes writing to the log file must have their locking set for it to -// work properly. Defaults to LOCK_LOG_FILE. -enum LogLockingState { LOCK_LOG_FILE, DONT_LOCK_LOG_FILE }; - -// On startup, should we delete or append to an existing log file (if any)? -// Defaults to APPEND_TO_OLD_LOG_FILE. -enum OldFileDeletionState { DELETE_OLD_LOG_FILE, APPEND_TO_OLD_LOG_FILE }; - -struct BASE_EXPORT LoggingSettings { - // The defaults values are: - // - // logging_dest: LOG_DEFAULT - // log_file: NULL - // lock_log: LOCK_LOG_FILE - // delete_old: APPEND_TO_OLD_LOG_FILE - LoggingSettings(); - - LoggingDestination logging_dest; - - // The three settings below have an effect only when LOG_TO_FILE is - // set in |logging_dest|. - const PathChar* log_file; - LogLockingState lock_log; - OldFileDeletionState delete_old; -}; - -// Define different names for the BaseInitLoggingImpl() function depending on -// whether NDEBUG is defined or not so that we'll fail to link if someone tries -// to compile logging.cc with NDEBUG but includes logging.h without defining it, -// or vice versa. -#if NDEBUG -#define BaseInitLoggingImpl BaseInitLoggingImpl_built_with_NDEBUG -#else -#define BaseInitLoggingImpl BaseInitLoggingImpl_built_without_NDEBUG -#endif - -// Implementation of the InitLogging() method declared below. We use a -// more-specific name so we can #define it above without affecting other code -// that has named stuff "InitLogging". -BASE_EXPORT bool BaseInitLoggingImpl(const LoggingSettings& settings); - -// Sets the log file name and other global logging state. Calling this function -// is recommended, and is normally done at the beginning of application init. -// If you don't call it, all the flags will be initialized to their default -// values, and there is a race condition that may leak a critical section -// object if two threads try to do the first log at the same time. -// See the definition of the enums above for descriptions and default values. -// -// The default log file is initialized to "debug.log" in the application -// directory. You probably don't want this, especially since the program -// directory may not be writable on an enduser's system. -// -// This function may be called a second time to re-direct logging (e.g after -// loging in to a user partition), however it should never be called more than -// twice. -inline bool InitLogging(const LoggingSettings& settings) { - return BaseInitLoggingImpl(settings); -} - -// Sets the log level. Anything at or above this level will be written to the -// log file/displayed to the user (if applicable). Anything below this level -// will be silently ignored. The log level defaults to 0 (everything is logged -// up to level INFO) if this function is not called. -// Note that log messages for VLOG(x) are logged at level -x, so setting -// the min log level to negative values enables verbose logging. -BASE_EXPORT void SetMinLogLevel(int level); - -// Gets the current log level. -BASE_EXPORT int GetMinLogLevel(); - -// Used by LOG_IS_ON to lazy-evaluate stream arguments. -BASE_EXPORT bool ShouldCreateLogMessage(int severity); - -// Gets the VLOG default verbosity level. -BASE_EXPORT int GetVlogVerbosity(); - -// Gets the current vlog level for the given file (usually taken from -// __FILE__). - -// Note that |N| is the size *with* the null terminator. -BASE_EXPORT int GetVlogLevelHelper(const char* file_start, size_t N); - -template <size_t N> -int GetVlogLevel(const char (&file)[N]) { - return GetVlogLevelHelper(file, N); -} - -// Sets the common items you want to be prepended to each log message. -// process and thread IDs default to off, the timestamp defaults to on. -// If this function is not called, logging defaults to writing the timestamp -// only. -BASE_EXPORT void SetLogItems(bool enable_process_id, bool enable_thread_id, - bool enable_timestamp, bool enable_tickcount); - -// Sets whether or not you'd like to see fatal debug messages popped up in -// a dialog box or not. -// Dialogs are not shown by default. -BASE_EXPORT void SetShowErrorDialogs(bool enable_dialogs); - -// Sets the Log Assert Handler that will be used to notify of check failures. -// The default handler shows a dialog box and then terminate the process, -// however clients can use this function to override with their own handling -// (e.g. a silent one for Unit Tests) -typedef void (*LogAssertHandlerFunction)(const std::string& str); -BASE_EXPORT void SetLogAssertHandler(LogAssertHandlerFunction handler); - -// Sets the Log Message Handler that gets passed every log message before -// it's sent to other log destinations (if any). -// Returns true to signal that it handled the message and the message -// should not be sent to other log destinations. -typedef bool (*LogMessageHandlerFunction)(int severity, - const char* file, int line, size_t message_start, const std::string& str); -BASE_EXPORT void SetLogMessageHandler(LogMessageHandlerFunction handler); -BASE_EXPORT LogMessageHandlerFunction GetLogMessageHandler(); - -typedef int LogSeverity; -const LogSeverity LOG_VERBOSE = -1; // This is level 1 verbosity -// Note: the log severities are used to index into the array of names, -// see log_severity_names. -const LogSeverity LOG_INFO = 0; -const LogSeverity LOG_WARNING = 1; -const LogSeverity LOG_ERROR = 2; -const LogSeverity LOG_FATAL = 3; -const LogSeverity LOG_NUM_SEVERITIES = 4; - -// LOG_DFATAL is LOG_FATAL in debug mode, ERROR in normal mode -#ifdef NDEBUG -const LogSeverity LOG_DFATAL = LOG_ERROR; -#else -const LogSeverity LOG_DFATAL = LOG_FATAL; -#endif - -// A few definitions of macros that don't generate much code. These are used -// by LOG() and LOG_IF, etc. Since these are used all over our code, it's -// better to have compact code for these operations. -#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_INFO , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_WARNING , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_ERROR , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_FATAL , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_DFATAL , ##__VA_ARGS__) - -#define COMPACT_GOOGLE_LOG_INFO \ - COMPACT_GOOGLE_LOG_EX_INFO(LogMessage) -#define COMPACT_GOOGLE_LOG_WARNING \ - COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage) -#define COMPACT_GOOGLE_LOG_ERROR \ - COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage) -#define COMPACT_GOOGLE_LOG_FATAL \ - COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage) -#define COMPACT_GOOGLE_LOG_DFATAL \ - COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage) - -#if defined(OS_WIN) -// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets -// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us -// to keep using this syntax, we define this macro to do the same thing -// as COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that -// the Windows SDK does for consistency. -#define ERROR 0 -#define COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \ - COMPACT_GOOGLE_LOG_EX_ERROR(ClassName , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR -// Needed for LOG_IS_ON(ERROR). -const LogSeverity LOG_0 = LOG_ERROR; -#endif - -// As special cases, we can assume that LOG_IS_ON(FATAL) always holds. Also, -// LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will -// always fire if they fail. -#define LOG_IS_ON(severity) \ - (::logging::ShouldCreateLogMessage(::logging::LOG_##severity)) - -// We can't do any caching tricks with VLOG_IS_ON() like the -// google-glog version since it requires GCC extensions. This means -// that using the v-logging functions in conjunction with --vmodule -// may be slow. -#define VLOG_IS_ON(verboselevel) \ - ((verboselevel) <= ::logging::GetVlogLevel(__FILE__)) - -// Helper macro which avoids evaluating the arguments to a stream if -// the condition doesn't hold. Condition is evaluated once and only once. -#define LAZY_STREAM(stream, condition) \ - !(condition) ? (void) 0 : ::logging::LogMessageVoidify() & (stream) - -// We use the preprocessor's merging operator, "##", so that, e.g., -// LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO. There's some funny -// subtle difference between ostream member streaming functions (e.g., -// ostream::operator<<(int) and ostream non-member streaming functions -// (e.g., ::operator<<(ostream&, string&): it turns out that it's -// impossible to stream something like a string directly to an unnamed -// ostream. We employ a neat hack by calling the stream() member -// function of LogMessage which seems to avoid the problem. -#define LOG_STREAM(severity) COMPACT_GOOGLE_LOG_ ## severity.stream() - -#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity)) -#define LOG_IF(severity, condition) \ - LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) - -#define SYSLOG(severity) LOG(severity) -#define SYSLOG_IF(severity, condition) LOG_IF(severity, condition) - -// The VLOG macros log with negative verbosities. -#define VLOG_STREAM(verbose_level) \ - logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream() - -#define VLOG(verbose_level) \ - LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) - -#define VLOG_IF(verbose_level, condition) \ - LAZY_STREAM(VLOG_STREAM(verbose_level), \ - VLOG_IS_ON(verbose_level) && (condition)) - -#if defined (OS_WIN) -#define VPLOG_STREAM(verbose_level) \ - logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \ - ::logging::GetLastSystemErrorCode()).stream() -#elif defined(OS_POSIX) -#define VPLOG_STREAM(verbose_level) \ - logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \ - ::logging::GetLastSystemErrorCode()).stream() -#endif - -#define VPLOG(verbose_level) \ - LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) - -#define VPLOG_IF(verbose_level, condition) \ - LAZY_STREAM(VPLOG_STREAM(verbose_level), \ - VLOG_IS_ON(verbose_level) && (condition)) - -// TODO(akalin): Add more VLOG variants, e.g. VPLOG. - -#define LOG_ASSERT(condition) \ - LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " -#define SYSLOG_ASSERT(condition) \ - SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " - -#if defined(OS_WIN) -#define PLOG_STREAM(severity) \ - COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \ - ::logging::GetLastSystemErrorCode()).stream() -#elif defined(OS_POSIX) -#define PLOG_STREAM(severity) \ - COMPACT_GOOGLE_LOG_EX_ ## severity(ErrnoLogMessage, \ - ::logging::GetLastSystemErrorCode()).stream() -#endif - -#define PLOG(severity) \ - LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity)) - -#define PLOG_IF(severity, condition) \ - LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) - -// The actual stream used isn't important. -#define EAT_STREAM_PARAMETERS \ - true ? (void) 0 : ::logging::LogMessageVoidify() & LOG_STREAM(FATAL) - -// Captures the result of a CHECK_EQ (for example) and facilitates testing as a -// boolean. -class CheckOpResult { - public: - // |message| must be null if and only if the check failed. - CheckOpResult(std::string* message) : message_(message) {} - // Returns true if the check succeeded. - operator bool() const { return !message_; } - // Returns the message. - std::string* message() { return message_; } - - private: - std::string* message_; -}; - -// CHECK dies with a fatal error if condition is not true. It is *not* -// controlled by NDEBUG, so the check will be executed regardless of -// compilation mode. -// -// We make sure CHECK et al. always evaluates their arguments, as -// doing CHECK(FunctionWithSideEffect()) is a common idiom. - -#if defined(OFFICIAL_BUILD) && defined(NDEBUG) && !defined(OS_ANDROID) - -// Make all CHECK functions discard their log strings to reduce code -// bloat for official release builds (except Android). - -// TODO(akalin): This would be more valuable if there were some way to -// remove BreakDebugger() from the backtrace, perhaps by turning it -// into a macro (like __debugbreak() on Windows). -#define CHECK(condition) \ - !(condition) ? ::base::debug::BreakDebugger() : EAT_STREAM_PARAMETERS - -#define PCHECK(condition) CHECK(condition) - -#define CHECK_OP(name, op, val1, val2) CHECK((val1) op (val2)) - -#else - -#if defined(_PREFAST_) && defined(OS_WIN) -// Use __analysis_assume to tell the VC++ static analysis engine that -// assert conditions are true, to suppress warnings. The LAZY_STREAM -// parameter doesn't reference 'condition' in /analyze builds because -// this evaluation confuses /analyze. The !! before condition is because -// __analysis_assume gets confused on some conditions: -// http://randomascii.wordpress.com/2011/09/13/analyze-for-visual-studio-the-ugly-part-5/ - -#define CHECK(condition) \ - __analysis_assume(!!(condition)), \ - LAZY_STREAM(LOG_STREAM(FATAL), false) \ - << "Check failed: " #condition ". " - -#define PCHECK(condition) \ - __analysis_assume(!!(condition)), \ - LAZY_STREAM(PLOG_STREAM(FATAL), false) \ - << "Check failed: " #condition ". " - -#else // _PREFAST_ - -// Do as much work as possible out of line to reduce inline code size. -#define CHECK(condition) \ - LAZY_STREAM(logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \ - !(condition)) - -#define PCHECK(condition) \ - LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \ - << "Check failed: " #condition ". " - -#endif // _PREFAST_ - -// Helper macro for binary operators. -// Don't use this macro directly in your code, use CHECK_EQ et al below. -// The 'switch' is used to prevent the 'else' from being ambiguous when the -// macro is used in an 'if' clause such as: -// if (a == 1) -// CHECK_EQ(2, a); -#define CHECK_OP(name, op, val1, val2) \ - switch (0) case 0: default: \ - if (logging::CheckOpResult true_if_passed = \ - logging::Check##name##Impl((val1), (val2), \ - #val1 " " #op " " #val2)) \ - ; \ - else \ - logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream() - -#endif - -// Build the error message string. This is separate from the "Impl" -// function template because it is not performance critical and so can -// be out of line, while the "Impl" code should be inline. Caller -// takes ownership of the returned string. -template<class t1, class t2> -std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { - std::ostringstream ss; - ss << names << " (" << v1 << " vs. " << v2 << ")"; - std::string* msg = new std::string(ss.str()); - return msg; -} - -// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated -// in logging.cc. -extern template BASE_EXPORT std::string* MakeCheckOpString<int, int>( - const int&, const int&, const char* names); -extern template BASE_EXPORT -std::string* MakeCheckOpString<unsigned long, unsigned long>( - const unsigned long&, const unsigned long&, const char* names); -extern template BASE_EXPORT -std::string* MakeCheckOpString<unsigned long, unsigned int>( - const unsigned long&, const unsigned int&, const char* names); -extern template BASE_EXPORT -std::string* MakeCheckOpString<unsigned int, unsigned long>( - const unsigned int&, const unsigned long&, const char* names); -extern template BASE_EXPORT -std::string* MakeCheckOpString<std::string, std::string>( - const std::string&, const std::string&, const char* name); - -// Helper functions for CHECK_OP macro. -// The (int, int) specialization works around the issue that the compiler -// will not instantiate the template version of the function on values of -// unnamed enum type - see comment below. -#define DEFINE_CHECK_OP_IMPL(name, op) \ - template <class t1, class t2> \ - inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ - const char* names) { \ - if (v1 op v2) return NULL; \ - else return MakeCheckOpString(v1, v2, names); \ - } \ - inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ - if (v1 op v2) return NULL; \ - else return MakeCheckOpString(v1, v2, names); \ - } -DEFINE_CHECK_OP_IMPL(EQ, ==) -DEFINE_CHECK_OP_IMPL(NE, !=) -DEFINE_CHECK_OP_IMPL(LE, <=) -DEFINE_CHECK_OP_IMPL(LT, < ) -DEFINE_CHECK_OP_IMPL(GE, >=) -DEFINE_CHECK_OP_IMPL(GT, > ) -#undef DEFINE_CHECK_OP_IMPL - -#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2) -#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2) -#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2) -#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2) -#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2) -#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2) - -#if defined(NDEBUG) -#define ENABLE_DLOG 0 -#else -#define ENABLE_DLOG 1 -#endif - -#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) -#define DCHECK_IS_ON() 0 -#else -#define DCHECK_IS_ON() 1 -#endif - -// Definitions for DLOG et al. - -#if ENABLE_DLOG - -#define DLOG_IS_ON(severity) LOG_IS_ON(severity) -#define DLOG_IF(severity, condition) LOG_IF(severity, condition) -#define DLOG_ASSERT(condition) LOG_ASSERT(condition) -#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition) -#define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition) -#define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition) - -#else // ENABLE_DLOG - -// If ENABLE_DLOG is off, we want to avoid emitting any references to -// |condition| (which may reference a variable defined only if NDEBUG -// is not defined). Contrast this with DCHECK et al., which has -// different behavior. - -#define DLOG_IS_ON(severity) false -#define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS -#define DLOG_ASSERT(condition) EAT_STREAM_PARAMETERS -#define DPLOG_IF(severity, condition) EAT_STREAM_PARAMETERS -#define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS -#define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS - -#endif // ENABLE_DLOG - -// DEBUG_MODE is for uses like -// if (DEBUG_MODE) foo.CheckThatFoo(); -// instead of -// #ifndef NDEBUG -// foo.CheckThatFoo(); -// #endif -// -// We tie its state to ENABLE_DLOG. -enum { DEBUG_MODE = ENABLE_DLOG }; - -#undef ENABLE_DLOG - -#define DLOG(severity) \ - LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity)) - -#define DPLOG(severity) \ - LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity)) - -#define DVLOG(verboselevel) DVLOG_IF(verboselevel, VLOG_IS_ON(verboselevel)) - -#define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, VLOG_IS_ON(verboselevel)) - -// Definitions for DCHECK et al. - -#if DCHECK_IS_ON() - -#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \ - COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL -const LogSeverity LOG_DCHECK = LOG_FATAL; - -#else // DCHECK_IS_ON() - -// These are just dummy values. -#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \ - COMPACT_GOOGLE_LOG_EX_INFO(ClassName , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_INFO -const LogSeverity LOG_DCHECK = LOG_INFO; - -#endif // DCHECK_IS_ON() - -// DCHECK et al. make sure to reference |condition| regardless of -// whether DCHECKs are enabled; this is so that we don't get unused -// variable warnings if the only use of a variable is in a DCHECK. -// This behavior is different from DLOG_IF et al. - -#if defined(_PREFAST_) && defined(OS_WIN) -// See comments on the previous use of __analysis_assume. - -#define DCHECK(condition) \ - __analysis_assume(!!(condition)), \ - LAZY_STREAM(LOG_STREAM(DCHECK), false) \ - << "Check failed: " #condition ". " - -#define DPCHECK(condition) \ - __analysis_assume(!!(condition)), \ - LAZY_STREAM(PLOG_STREAM(DCHECK), false) \ - << "Check failed: " #condition ". " - -#else // _PREFAST_ - -#define DCHECK(condition) \ - LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON() ? !(condition) : false) \ - << "Check failed: " #condition ". " - -#define DPCHECK(condition) \ - LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON() ? !(condition) : false) \ - << "Check failed: " #condition ". " - -#endif // _PREFAST_ - -// Helper macro for binary operators. -// Don't use this macro directly in your code, use DCHECK_EQ et al below. -// The 'switch' is used to prevent the 'else' from being ambiguous when the -// macro is used in an 'if' clause such as: -// if (a == 1) -// DCHECK_EQ(2, a); -#define DCHECK_OP(name, op, val1, val2) \ - switch (0) case 0: default: \ - if (logging::CheckOpResult true_if_passed = \ - DCHECK_IS_ON() ? \ - logging::Check##name##Impl((val1), (val2), \ - #val1 " " #op " " #val2) : nullptr) \ - ; \ - else \ - logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \ - true_if_passed.message()).stream() - -// Equality/Inequality checks - compare two values, and log a -// LOG_DCHECK message including the two values when the result is not -// as expected. The values must have operator<<(ostream, ...) -// defined. -// -// You may append to the error message like so: -// DCHECK_NE(1, 2) << ": The world must be ending!"; -// -// We are very careful to ensure that each argument is evaluated exactly -// once, and that anything which is legal to pass as a function argument is -// legal here. In particular, the arguments may be temporary expressions -// which will end up being destroyed at the end of the apparent statement, -// for example: -// DCHECK_EQ(string("abc")[1], 'b'); -// -// WARNING: These may not compile correctly if one of the arguments is a pointer -// and the other is NULL. To work around this, simply static_cast NULL to the -// type of the desired pointer. - -#define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2) -#define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2) -#define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2) -#define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2) -#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2) -#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2) - -#if !DCHECK_IS_ON() && defined(OS_CHROMEOS) -// Implement logging of NOTREACHED() as a dedicated function to get function -// call overhead down to a minimum. -void LogErrorNotReached(const char* file, int line); -#define NOTREACHED() \ - true ? ::logging::LogErrorNotReached(__FILE__, __LINE__) \ - : EAT_STREAM_PARAMETERS -#else -#define NOTREACHED() DCHECK(false) -#endif - -// Redefine the standard assert to use our nice log files -#undef assert -#define assert(x) DLOG_ASSERT(x) - -// This class more or less represents a particular log message. You -// create an instance of LogMessage and then stream stuff to it. -// When you finish streaming to it, ~LogMessage is called and the -// full message gets streamed to the appropriate destination. -// -// You shouldn't actually use LogMessage's constructor to log things, -// though. You should use the LOG() macro (and variants thereof) -// above. -class BASE_EXPORT LogMessage { - public: - // Used for LOG(severity). - LogMessage(const char* file, int line, LogSeverity severity); - - // Used for CHECK(). Implied severity = LOG_FATAL. - LogMessage(const char* file, int line, const char* condition); - - // Used for CHECK_EQ(), etc. Takes ownership of the given string. - // Implied severity = LOG_FATAL. - LogMessage(const char* file, int line, std::string* result); - - // Used for DCHECK_EQ(), etc. Takes ownership of the given string. - LogMessage(const char* file, int line, LogSeverity severity, - std::string* result); - - ~LogMessage(); - - std::ostream& stream() { return stream_; } - - private: - void Init(const char* file, int line); - - LogSeverity severity_; - std::ostringstream stream_; - size_t message_start_; // Offset of the start of the message (past prefix - // info). - // The file and line information passed in to the constructor. - const char* file_; - const int line_; - -#if defined(OS_WIN) - // Stores the current value of GetLastError in the constructor and restores - // it in the destructor by calling SetLastError. - // This is useful since the LogMessage class uses a lot of Win32 calls - // that will lose the value of GLE and the code that called the log function - // will have lost the thread error value when the log call returns. - class SaveLastError { - public: - SaveLastError(); - ~SaveLastError(); - - unsigned long get_error() const { return last_error_; } - - protected: - unsigned long last_error_; - }; - - SaveLastError last_error_; -#endif - - DISALLOW_COPY_AND_ASSIGN(LogMessage); -}; - -// A non-macro interface to the log facility; (useful -// when the logging level is not a compile-time constant). -inline void LogAtLevel(int log_level, const std::string& msg) { - LogMessage(__FILE__, __LINE__, log_level).stream() << msg; -} - -// This class is used to explicitly ignore values in the conditional -// logging macros. This avoids compiler warnings like "value computed -// is not used" and "statement has no effect". -class LogMessageVoidify { - public: - LogMessageVoidify() { } - // This has to be an operator with a precedence lower than << but - // higher than ?: - void operator&(std::ostream&) { } -}; - -#if defined(OS_WIN) -typedef unsigned long SystemErrorCode; -#elif defined(OS_POSIX) -typedef int SystemErrorCode; -#endif - -// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to -// pull in windows.h just for GetLastError() and DWORD. -BASE_EXPORT SystemErrorCode GetLastSystemErrorCode(); -BASE_EXPORT std::string SystemErrorCodeToString(SystemErrorCode error_code); - -#if defined(OS_WIN) -// Appends a formatted system message of the GetLastError() type. -class BASE_EXPORT Win32ErrorLogMessage { - public: - Win32ErrorLogMessage(const char* file, - int line, - LogSeverity severity, - SystemErrorCode err); - - // Appends the error message before destructing the encapsulated class. - ~Win32ErrorLogMessage(); - - std::ostream& stream() { return log_message_.stream(); } - - private: - SystemErrorCode err_; - LogMessage log_message_; - - DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage); -}; -#elif defined(OS_POSIX) -// Appends a formatted system message of the errno type -class BASE_EXPORT ErrnoLogMessage { - public: - ErrnoLogMessage(const char* file, - int line, - LogSeverity severity, - SystemErrorCode err); - - // Appends the error message before destructing the encapsulated class. - ~ErrnoLogMessage(); - - std::ostream& stream() { return log_message_.stream(); } - - private: - SystemErrorCode err_; - LogMessage log_message_; - - DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage); -}; -#endif // OS_WIN - -// Closes the log file explicitly if open. -// NOTE: Since the log file is opened as necessary by the action of logging -// statements, there's no guarantee that it will stay closed -// after this call. -BASE_EXPORT void CloseLogFile(); - -// Async signal safe logging mechanism. -BASE_EXPORT void RawLog(int level, const char* message); - -#define RAW_LOG(level, message) logging::RawLog(logging::LOG_ ## level, message) - -#define RAW_CHECK(condition) \ - do { \ - if (!(condition)) \ - logging::RawLog(logging::LOG_FATAL, "Check failed: " #condition "\n"); \ - } while (0) - -#if defined(OS_WIN) -// Returns true if logging to file is enabled. -BASE_EXPORT bool IsLoggingToFileEnabled(); - -// Returns the default log file path. -BASE_EXPORT std::wstring GetLogFileFullPath(); -#endif - -} // namespace logging - -// Note that "The behavior of a C++ program is undefined if it adds declarations -// or definitions to namespace std or to a namespace within namespace std unless -// otherwise specified." --C++11[namespace.std] -// -// We've checked that this particular definition has the intended behavior on -// our implementations, but it's prone to breaking in the future, and please -// don't imitate this in your own definitions without checking with some -// standard library experts. -namespace std { -// These functions are provided as a convenience for logging, which is where we -// use streams (it is against Google style to use streams in other places). It -// is designed to allow you to emit non-ASCII Unicode strings to the log file, -// which is normally ASCII. It is relatively slow, so try not to use it for -// common cases. Non-ASCII characters will be converted to UTF-8 by these -// operators. -BASE_EXPORT std::ostream& operator<<(std::ostream& out, const wchar_t* wstr); -inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) { - return out << wstr.c_str(); -} -} // namespace std - -// The NOTIMPLEMENTED() macro annotates codepaths which have -// not been implemented yet. -// -// The implementation of this macro is controlled by NOTIMPLEMENTED_POLICY: -// 0 -- Do nothing (stripped by compiler) -// 1 -- Warn at compile time -// 2 -- Fail at compile time -// 3 -- Fail at runtime (DCHECK) -// 4 -- [default] LOG(ERROR) at runtime -// 5 -- LOG(ERROR) at runtime, only once per call-site - -#ifndef NOTIMPLEMENTED_POLICY -#if defined(OS_ANDROID) && defined(OFFICIAL_BUILD) -#define NOTIMPLEMENTED_POLICY 0 -#else -// Select default policy: LOG(ERROR) -#define NOTIMPLEMENTED_POLICY 4 -#endif -#endif - -#if defined(COMPILER_GCC) -// On Linux, with GCC, we can use __PRETTY_FUNCTION__ to get the demangled name -// of the current function in the NOTIMPLEMENTED message. -#define NOTIMPLEMENTED_MSG "Not implemented reached in " << __PRETTY_FUNCTION__ -#else -#define NOTIMPLEMENTED_MSG "NOT IMPLEMENTED" -#endif - -#if NOTIMPLEMENTED_POLICY == 0 -#define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS -#elif NOTIMPLEMENTED_POLICY == 1 -// TODO, figure out how to generate a warning -#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED") -#elif NOTIMPLEMENTED_POLICY == 2 -#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED") -#elif NOTIMPLEMENTED_POLICY == 3 -#define NOTIMPLEMENTED() NOTREACHED() -#elif NOTIMPLEMENTED_POLICY == 4 -#define NOTIMPLEMENTED() LOG(ERROR) << NOTIMPLEMENTED_MSG -#elif NOTIMPLEMENTED_POLICY == 5 -#define NOTIMPLEMENTED() do {\ - static bool logged_once = false;\ - LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG;\ - logged_once = true;\ -} while(0);\ -EAT_STREAM_PARAMETERS -#endif - -#endif // BASE_LOGGING_H_ diff --git a/security/sandbox/chromium/base/macros.h b/security/sandbox/chromium/base/macros.h deleted file mode 100644 index 46ee1dadb..000000000 --- a/security/sandbox/chromium/base/macros.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains macros and macro-like constructs (e.g., templates) that -// are commonly used throughout Chromium source. (It may also contain things -// that are closely related to things that are commonly used that belong in this -// file.) - -#ifndef BASE_MACROS_H_ -#define BASE_MACROS_H_ - -#include <stddef.h> // For size_t. - -// Put this in the declarations for a class to be uncopyable. -#define DISALLOW_COPY(TypeName) \ - TypeName(const TypeName&) = delete - -// Put this in the declarations for a class to be unassignable. -#define DISALLOW_ASSIGN(TypeName) \ - void operator=(const TypeName&) = delete - -// A macro to disallow the copy constructor and operator= functions -// This should be used in the private: declarations for a class -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) - -// A macro to disallow all the implicit constructors, namely the -// default constructor, copy constructor and operator= functions. -// -// This should be used in the private: declarations for a class -// that wants to prevent anyone from instantiating it. This is -// especially useful for classes containing only static methods. -#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ - TypeName() = delete; \ - DISALLOW_COPY_AND_ASSIGN(TypeName) - -// The arraysize(arr) macro returns the # of elements in an array arr. The -// expression is a compile-time constant, and therefore can be used in defining -// new arrays, for example. If you use arraysize on a pointer by mistake, you -// will get a compile-time error. For the technical details, refer to -// http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx. - -// This template function declaration is used in defining arraysize. -// Note that the function doesn't need an implementation, as we only -// use its type. -template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N]; -#define arraysize(array) (sizeof(ArraySizeHelper(array))) - -// Used to explicitly mark the return value of a function as unused. If you are -// really sure you don't want to do anything with the return value of a function -// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example: -// -// scoped_ptr<MyType> my_var = ...; -// if (TakeOwnership(my_var.get()) == SUCCESS) -// ignore_result(my_var.release()); -// -template<typename T> -inline void ignore_result(const T&) { -} - -// The following enum should be used only as a constructor argument to indicate -// that the variable has static storage class, and that the constructor should -// do nothing to its state. It indicates to the reader that it is legal to -// declare a static instance of the class, provided the constructor is given -// the base::LINKER_INITIALIZED argument. Normally, it is unsafe to declare a -// static variable that has a constructor or a destructor because invocation -// order is undefined. However, IF the type can be initialized by filling with -// zeroes (which the loader does for static variables), AND the destructor also -// does nothing to the storage, AND there are no virtual methods, then a -// constructor declared as -// explicit MyClass(base::LinkerInitialized x) {} -// and invoked as -// static MyClass my_variable_name(base::LINKER_INITIALIZED); -namespace base { -enum LinkerInitialized { LINKER_INITIALIZED }; - -// Use these to declare and define a static local variable (static T;) so that -// it is leaked so that its destructors are not called at exit. If you need -// thread-safe initialization, use base/lazy_instance.h instead. -#define CR_DEFINE_STATIC_LOCAL(type, name, arguments) \ - static type& name = *new type arguments - -} // base - -#endif // BASE_MACROS_H_ diff --git a/security/sandbox/chromium/base/memory/aligned_memory.h b/security/sandbox/chromium/base/memory/aligned_memory.h deleted file mode 100644 index bb7bd872c..000000000 --- a/security/sandbox/chromium/base/memory/aligned_memory.h +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// AlignedMemory is a POD type that gives you a portable way to specify static -// or local stack data of a given alignment and size. For example, if you need -// static storage for a class, but you want manual control over when the object -// is constructed and destructed (you don't want static initialization and -// destruction), use AlignedMemory: -// -// static AlignedMemory<sizeof(MyClass), ALIGNOF(MyClass)> my_class; -// -// // ... at runtime: -// new(my_class.void_data()) MyClass(); -// -// // ... use it: -// MyClass* mc = my_class.data_as<MyClass>(); -// -// // ... later, to destruct my_class: -// my_class.data_as<MyClass>()->MyClass::~MyClass(); -// -// Alternatively, a runtime sized aligned allocation can be created: -// -// float* my_array = static_cast<float*>(AlignedAlloc(size, alignment)); -// -// // ... later, to release the memory: -// AlignedFree(my_array); -// -// Or using scoped_ptr: -// -// scoped_ptr<float, AlignedFreeDeleter> my_array( -// static_cast<float*>(AlignedAlloc(size, alignment))); - -#ifndef BASE_MEMORY_ALIGNED_MEMORY_H_ -#define BASE_MEMORY_ALIGNED_MEMORY_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/base_export.h" -#include "base/compiler_specific.h" - -#if defined(COMPILER_MSVC) -#include <malloc.h> -#else -#include <stdlib.h> -#endif - -namespace base { - -// AlignedMemory is specialized for all supported alignments. -// Make sure we get a compiler error if someone uses an unsupported alignment. -template <size_t Size, size_t ByteAlignment> -struct AlignedMemory {}; - -#define BASE_DECL_ALIGNED_MEMORY(byte_alignment) \ - template <size_t Size> \ - class AlignedMemory<Size, byte_alignment> { \ - public: \ - ALIGNAS(byte_alignment) uint8_t data_[Size]; \ - void* void_data() { return static_cast<void*>(data_); } \ - const void* void_data() const { return static_cast<const void*>(data_); } \ - template <typename Type> \ - Type* data_as() { \ - return static_cast<Type*>(void_data()); \ - } \ - template <typename Type> \ - const Type* data_as() const { \ - return static_cast<const Type*>(void_data()); \ - } \ - \ - private: \ - void* operator new(size_t); \ - void operator delete(void*); \ - } - -// Specialization for all alignments is required because MSVC (as of VS 2008) -// does not understand ALIGNAS(ALIGNOF(Type)) or ALIGNAS(template_param). -// Greater than 4096 alignment is not supported by some compilers, so 4096 is -// the maximum specified here. -BASE_DECL_ALIGNED_MEMORY(1); -BASE_DECL_ALIGNED_MEMORY(2); -BASE_DECL_ALIGNED_MEMORY(4); -BASE_DECL_ALIGNED_MEMORY(8); -BASE_DECL_ALIGNED_MEMORY(16); -BASE_DECL_ALIGNED_MEMORY(32); -BASE_DECL_ALIGNED_MEMORY(64); -BASE_DECL_ALIGNED_MEMORY(128); -BASE_DECL_ALIGNED_MEMORY(256); -BASE_DECL_ALIGNED_MEMORY(512); -BASE_DECL_ALIGNED_MEMORY(1024); -BASE_DECL_ALIGNED_MEMORY(2048); -BASE_DECL_ALIGNED_MEMORY(4096); - -#undef BASE_DECL_ALIGNED_MEMORY - -BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment); - -inline void AlignedFree(void* ptr) { -#if defined(COMPILER_MSVC) - _aligned_free(ptr); -#else - free(ptr); -#endif -} - -// Deleter for use with scoped_ptr. E.g., use as -// scoped_ptr<Foo, base::AlignedFreeDeleter> foo; -struct AlignedFreeDeleter { - inline void operator()(void* ptr) const { - AlignedFree(ptr); - } -}; - -} // namespace base - -#endif // BASE_MEMORY_ALIGNED_MEMORY_H_ diff --git a/security/sandbox/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h b/security/sandbox/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h deleted file mode 100644 index 09f982b12..000000000 --- a/security/sandbox/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ -#define BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ - -#include "base/memory/ref_counted.h" -#include "base/template_util.h" -#include "base/tuple.h" -#include "build/build_config.h" - -// It is dangerous to post a task with a T* argument where T is a subtype of -// RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the -// object may already have been deleted since it was not held with a -// scoped_refptr. Example: http://crbug.com/27191 -// The following set of traits are designed to generate a compile error -// whenever this antipattern is attempted. - -namespace base { - -// This is a base internal implementation file used by task.h and callback.h. -// Not for public consumption, so we wrap it in namespace internal. -namespace internal { - -template <typename T> -struct NeedsScopedRefptrButGetsRawPtr { -#if defined(OS_WIN) - enum { - value = base::false_type::value - }; -#else - enum { - // Human readable translation: you needed to be a scoped_refptr if you are a - // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) - // type. - value = (is_pointer<T>::value && - (is_convertible<T, subtle::RefCountedBase*>::value || - is_convertible<T, subtle::RefCountedThreadSafeBase*>::value)) - }; -#endif -}; - -template <typename Params> -struct ParamsUseScopedRefptrCorrectly { - enum { value = 0 }; -}; - -template <> -struct ParamsUseScopedRefptrCorrectly<Tuple<>> { - enum { value = 1 }; -}; - -template <typename Head, typename... Tail> -struct ParamsUseScopedRefptrCorrectly<Tuple<Head, Tail...>> { - enum { value = !NeedsScopedRefptrButGetsRawPtr<Head>::value && - ParamsUseScopedRefptrCorrectly<Tuple<Tail...>>::value }; -}; - -} // namespace internal - -} // namespace base - -#endif // BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ diff --git a/security/sandbox/chromium/base/memory/ref_counted.cc b/security/sandbox/chromium/base/memory/ref_counted.cc deleted file mode 100644 index f5924d0fe..000000000 --- a/security/sandbox/chromium/base/memory/ref_counted.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/ref_counted.h" -#include "base/threading/thread_collision_warner.h" - -namespace base { - -namespace subtle { - -bool RefCountedThreadSafeBase::HasOneRef() const { - return AtomicRefCountIsOne( - &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_); -} - -RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) { -#ifndef NDEBUG - in_dtor_ = false; -#endif -} - -RefCountedThreadSafeBase::~RefCountedThreadSafeBase() { -#ifndef NDEBUG - DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without " - "calling Release()"; -#endif -} - -void RefCountedThreadSafeBase::AddRef() const { -#ifndef NDEBUG - DCHECK(!in_dtor_); -#endif - AtomicRefCountInc(&ref_count_); -} - -bool RefCountedThreadSafeBase::Release() const { -#ifndef NDEBUG - DCHECK(!in_dtor_); - DCHECK(!AtomicRefCountIsZero(&ref_count_)); -#endif - if (!AtomicRefCountDec(&ref_count_)) { -#ifndef NDEBUG - in_dtor_ = true; -#endif - return true; - } - return false; -} - -} // namespace subtle - -} // namespace base diff --git a/security/sandbox/chromium/base/memory/ref_counted.h b/security/sandbox/chromium/base/memory/ref_counted.h deleted file mode 100644 index a1c126969..000000000 --- a/security/sandbox/chromium/base/memory/ref_counted.h +++ /dev/null @@ -1,446 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_REF_COUNTED_H_ -#define BASE_MEMORY_REF_COUNTED_H_ - -#include <cassert> -#include <iosfwd> - -#include "base/atomic_ref_count.h" -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/macros.h" -#ifndef NDEBUG -#include "base/logging.h" -#endif -#include "base/threading/thread_collision_warner.h" -#include "build/build_config.h" - -namespace base { - -namespace subtle { - -class BASE_EXPORT RefCountedBase { - public: - bool HasOneRef() const { return ref_count_ == 1; } - - protected: - RefCountedBase() - : ref_count_(0) - #ifndef NDEBUG - , in_dtor_(false) - #endif - { - } - - ~RefCountedBase() { - #ifndef NDEBUG - DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; - #endif - } - - - void AddRef() const { - // TODO(maruel): Add back once it doesn't assert 500 times/sec. - // Current thread books the critical section "AddRelease" - // without release it. - // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); - #ifndef NDEBUG - DCHECK(!in_dtor_); - #endif - ++ref_count_; - } - - // Returns true if the object should self-delete. - bool Release() const { - // TODO(maruel): Add back once it doesn't assert 500 times/sec. - // Current thread books the critical section "AddRelease" - // without release it. - // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); - #ifndef NDEBUG - DCHECK(!in_dtor_); - #endif - if (--ref_count_ == 0) { - #ifndef NDEBUG - in_dtor_ = true; - #endif - return true; - } - return false; - } - - private: - mutable int ref_count_; -#ifndef NDEBUG - mutable bool in_dtor_; -#endif - - DFAKE_MUTEX(add_release_); - - DISALLOW_COPY_AND_ASSIGN(RefCountedBase); -}; - -class BASE_EXPORT RefCountedThreadSafeBase { - public: - bool HasOneRef() const; - - protected: - RefCountedThreadSafeBase(); - ~RefCountedThreadSafeBase(); - - void AddRef() const; - - // Returns true if the object should self-delete. - bool Release() const; - - private: - mutable AtomicRefCount ref_count_; -#ifndef NDEBUG - mutable bool in_dtor_; -#endif - - DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); -}; - -} // namespace subtle - -// -// A base class for reference counted classes. Otherwise, known as a cheap -// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your -// class from it like so: -// -// class MyFoo : public base::RefCounted<MyFoo> { -// ... -// private: -// friend class base::RefCounted<MyFoo>; -// ~MyFoo(); -// }; -// -// You should always make your destructor non-public, to avoid any code deleting -// the object accidently while there are references to it. -template <class T> -class RefCounted : public subtle::RefCountedBase { - public: - RefCounted() {} - - void AddRef() const { - subtle::RefCountedBase::AddRef(); - } - - void Release() const { - if (subtle::RefCountedBase::Release()) { - delete static_cast<const T*>(this); - } - } - - protected: - ~RefCounted() {} - - private: - DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); -}; - -// Forward declaration. -template <class T, typename Traits> class RefCountedThreadSafe; - -// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref -// count reaches 0. Overload to delete it on a different thread etc. -template<typename T> -struct DefaultRefCountedThreadSafeTraits { - static void Destruct(const T* x) { - // Delete through RefCountedThreadSafe to make child classes only need to be - // friend with RefCountedThreadSafe instead of this struct, which is an - // implementation detail. - RefCountedThreadSafe<T, - DefaultRefCountedThreadSafeTraits>::DeleteInternal(x); - } -}; - -// -// A thread-safe variant of RefCounted<T> -// -// class MyFoo : public base::RefCountedThreadSafe<MyFoo> { -// ... -// }; -// -// If you're using the default trait, then you should add compile time -// asserts that no one else is deleting your object. i.e. -// private: -// friend class base::RefCountedThreadSafe<MyFoo>; -// ~MyFoo(); -template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > -class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { - public: - RefCountedThreadSafe() {} - - void AddRef() const { - subtle::RefCountedThreadSafeBase::AddRef(); - } - - void Release() const { - if (subtle::RefCountedThreadSafeBase::Release()) { - Traits::Destruct(static_cast<const T*>(this)); - } - } - - protected: - ~RefCountedThreadSafe() {} - - private: - friend struct DefaultRefCountedThreadSafeTraits<T>; - static void DeleteInternal(const T* x) { delete x; } - - DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); -}; - -// -// A thread-safe wrapper for some piece of data so we can place other -// things in scoped_refptrs<>. -// -template<typename T> -class RefCountedData - : public base::RefCountedThreadSafe< base::RefCountedData<T> > { - public: - RefCountedData() : data() {} - RefCountedData(const T& in_value) : data(in_value) {} - - T data; - - private: - friend class base::RefCountedThreadSafe<base::RefCountedData<T> >; - ~RefCountedData() {} -}; - -} // namespace base - -// -// A smart pointer class for reference counted objects. Use this class instead -// of calling AddRef and Release manually on a reference counted object to -// avoid common memory leaks caused by forgetting to Release an object -// reference. Sample usage: -// -// class MyFoo : public RefCounted<MyFoo> { -// ... -// }; -// -// void some_function() { -// scoped_refptr<MyFoo> foo = new MyFoo(); -// foo->Method(param); -// // |foo| is released when this function returns -// } -// -// void some_other_function() { -// scoped_refptr<MyFoo> foo = new MyFoo(); -// ... -// foo = NULL; // explicitly releases |foo| -// ... -// if (foo) -// foo->Method(param); -// } -// -// The above examples show how scoped_refptr<T> acts like a pointer to T. -// Given two scoped_refptr<T> classes, it is also possible to exchange -// references between the two objects, like so: -// -// { -// scoped_refptr<MyFoo> a = new MyFoo(); -// scoped_refptr<MyFoo> b; -// -// b.swap(a); -// // now, |b| references the MyFoo object, and |a| references NULL. -// } -// -// To make both |a| and |b| in the above example reference the same MyFoo -// object, simply use the assignment operator: -// -// { -// scoped_refptr<MyFoo> a = new MyFoo(); -// scoped_refptr<MyFoo> b; -// -// b = a; -// // now, |a| and |b| each own a reference to the same MyFoo object. -// } -// -template <class T> -class scoped_refptr { - public: - typedef T element_type; - - scoped_refptr() : ptr_(NULL) { - } - - scoped_refptr(T* p) : ptr_(p) { - if (ptr_) - AddRef(ptr_); - } - - // Copy constructor. - scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { - if (ptr_) - AddRef(ptr_); - } - - // Copy conversion constructor. - template <typename U> - scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { - if (ptr_) - AddRef(ptr_); - } - - // Move constructor. This is required in addition to the conversion - // constructor below in order for clang to warn about pessimizing moves. - scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } - - // Move conversion constructor. - template <typename U> - scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { - r.ptr_ = nullptr; - } - - ~scoped_refptr() { - if (ptr_) - Release(ptr_); - } - - T* get() const { return ptr_; } - - T& operator*() const { - assert(ptr_ != NULL); - return *ptr_; - } - - T* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - - scoped_refptr<T>& operator=(T* p) { - // AddRef first so that self assignment should work - if (p) - AddRef(p); - T* old_ptr = ptr_; - ptr_ = p; - if (old_ptr) - Release(old_ptr); - return *this; - } - - scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { - return *this = r.ptr_; - } - - template <typename U> - scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { - return *this = r.get(); - } - - scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { - scoped_refptr<T>(std::move(r)).swap(*this); - return *this; - } - - template <typename U> - scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { - scoped_refptr<T>(std::move(r)).swap(*this); - return *this; - } - - void swap(T** pp) { - T* p = ptr_; - ptr_ = *pp; - *pp = p; - } - - void swap(scoped_refptr<T>& r) { - swap(&r.ptr_); - } - - private: - template <typename U> friend class scoped_refptr; - - // Allow scoped_refptr<T> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - // - // Note that this trick is only safe when the == and != operators - // are declared explicitly, as otherwise "refptr1 == refptr2" - // will compile but do the wrong thing (i.e., convert to Testable - // and then do the comparison). - typedef T* scoped_refptr::*Testable; - - public: - operator Testable() const { return ptr_ ? &scoped_refptr::ptr_ : nullptr; } - - template <typename U> - bool operator==(const scoped_refptr<U>& rhs) const { - return ptr_ == rhs.get(); - } - - template <typename U> - bool operator!=(const scoped_refptr<U>& rhs) const { - return !operator==(rhs); - } - - template <typename U> - bool operator<(const scoped_refptr<U>& rhs) const { - return ptr_ < rhs.get(); - } - - protected: - T* ptr_; - - private: - // Non-inline helpers to allow: - // class Opaque; - // extern template class scoped_refptr<Opaque>; - // Otherwise the compiler will complain that Opaque is an incomplete type. - static void AddRef(T* ptr); - static void Release(T* ptr); -}; - -template <typename T> -void scoped_refptr<T>::AddRef(T* ptr) { - ptr->AddRef(); -} - -template <typename T> -void scoped_refptr<T>::Release(T* ptr) { - ptr->Release(); -} - -// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without -// having to retype all the template arguments -template <typename T> -scoped_refptr<T> make_scoped_refptr(T* t) { - return scoped_refptr<T>(t); -} - -// Temporary operator overloads to facilitate the transition. See -// https://crbug.com/110610. -template <typename T, typename U> -bool operator==(const scoped_refptr<T>& lhs, const U* rhs) { - return lhs.get() == rhs; -} - -template <typename T, typename U> -bool operator==(const T* lhs, const scoped_refptr<U>& rhs) { - return lhs == rhs.get(); -} - -template <typename T, typename U> -bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) { - return !operator==(lhs, rhs); -} - -template <typename T, typename U> -bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) { - return !operator==(lhs, rhs); -} - -template <typename T> -std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) { - return out << p.get(); -} - -#endif // BASE_MEMORY_REF_COUNTED_H_ diff --git a/security/sandbox/chromium/base/memory/scoped_ptr.h b/security/sandbox/chromium/base/memory/scoped_ptr.h deleted file mode 100644 index 282a01486..000000000 --- a/security/sandbox/chromium/base/memory/scoped_ptr.h +++ /dev/null @@ -1,607 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Scopers help you manage ownership of a pointer, helping you easily manage a -// pointer within a scope, and automatically destroying the pointer at the end -// of a scope. There are two main classes you will use, which correspond to the -// operators new/delete and new[]/delete[]. -// -// Example usage (scoped_ptr<T>): -// { -// scoped_ptr<Foo> foo(new Foo("wee")); -// } // foo goes out of scope, releasing the pointer with it. -// -// { -// scoped_ptr<Foo> foo; // No pointer managed. -// foo.reset(new Foo("wee")); // Now a pointer is managed. -// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. -// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. -// foo->Method(); // Foo::Method() called. -// foo.get()->Method(); // Foo::Method() called. -// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer -// // manages a pointer. -// foo.reset(new Foo("wee4")); // foo manages a pointer again. -// foo.reset(); // Foo("wee4") destroyed, foo no longer -// // manages a pointer. -// } // foo wasn't managing a pointer, so nothing was destroyed. -// -// Example usage (scoped_ptr<T[]>): -// { -// scoped_ptr<Foo[]> foo(new Foo[100]); -// foo.get()->Method(); // Foo::Method on the 0th element. -// foo[10].Method(); // Foo::Method on the 10th element. -// } -// -// These scopers also implement part of the functionality of C++11 unique_ptr -// in that they are "movable but not copyable." You can use the scopers in -// the parameter and return types of functions to signify ownership transfer -// in to and out of a function. When calling a function that has a scoper -// as the argument type, it must be called with an rvalue of a scoper, which -// can be created by using std::move(), or the result of another function that -// generates a temporary; passing by copy will NOT work. Here is an example -// using scoped_ptr: -// -// void TakesOwnership(scoped_ptr<Foo> arg) { -// // Do something with arg. -// } -// scoped_ptr<Foo> CreateFoo() { -// // No need for calling std::move() for returning a move-only value, or -// // when you already have an rvalue as we do here. -// return scoped_ptr<Foo>(new Foo("new")); -// } -// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) { -// return arg; -// } -// -// { -// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay"). -// TakesOwnership(std::move(ptr)); // ptr no longer owns Foo("yay"). -// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo. -// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2. -// PassThru(std::move(ptr2)); // ptr2 is correspondingly nullptr. -// } -// -// Notice that if you do not call std::move() when returning from PassThru(), or -// when invoking TakesOwnership(), the code will not compile because scopers -// are not copyable; they only implement move semantics which require calling -// the std::move() function to signify a destructive transfer of state. -// CreateFoo() is different though because we are constructing a temporary on -// the return line and thus can avoid needing to call std::move(). -// -// The conversion move-constructor properly handles upcast in initialization, -// i.e. you can use a scoped_ptr<Child> to initialize a scoped_ptr<Parent>: -// -// scoped_ptr<Foo> foo(new Foo()); -// scoped_ptr<FooParent> parent(std::move(foo)); - -#ifndef BASE_MEMORY_SCOPED_PTR_H_ -#define BASE_MEMORY_SCOPED_PTR_H_ - -// This is an implementation designed to match the anticipated future TR2 -// implementation of the scoped_ptr class. - -#include <assert.h> -#include <stddef.h> -#include <stdlib.h> - -#include <iosfwd> -#include <memory> -#include <type_traits> -#include <utility> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/move.h" -#include "base/template_util.h" - -namespace base { - -namespace subtle { -class RefCountedBase; -class RefCountedThreadSafeBase; -} // namespace subtle - -// Function object which invokes 'free' on its parameter, which must be -// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: -// -// scoped_ptr<int, base::FreeDeleter> foo_ptr( -// static_cast<int*>(malloc(sizeof(int)))); -struct FreeDeleter { - inline void operator()(void* ptr) const { - free(ptr); - } -}; - -namespace internal { - -template <typename T> struct IsNotRefCounted { - enum { - value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value && - !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>:: - value - }; -}; - -// Minimal implementation of the core logic of scoped_ptr, suitable for -// reuse in both scoped_ptr and its specializations. -template <class T, class D> -class scoped_ptr_impl { - public: - explicit scoped_ptr_impl(T* p) : data_(p) {} - - // Initializer for deleters that have data parameters. - scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} - - // Templated constructor that destructively takes the value from another - // scoped_ptr_impl. - template <typename U, typename V> - scoped_ptr_impl(scoped_ptr_impl<U, V>* other) - : data_(other->release(), other->get_deleter()) { - // We do not support move-only deleters. We could modify our move - // emulation to have base::subtle::move() and base::subtle::forward() - // functions that are imperfect emulations of their C++11 equivalents, - // but until there's a requirement, just assume deleters are copyable. - } - - template <typename U, typename V> - void TakeState(scoped_ptr_impl<U, V>* other) { - // See comment in templated constructor above regarding lack of support - // for move-only deleters. - reset(other->release()); - get_deleter() = other->get_deleter(); - } - - ~scoped_ptr_impl() { - // Match libc++, which calls reset() in its destructor. - // Use nullptr as the new value for three reasons: - // 1. libc++ does it. - // 2. Avoids infinitely recursing into destructors if two classes are owned - // in a reference cycle (see ScopedPtrTest.ReferenceCycle). - // 3. If |this| is accessed in the future, in a use-after-free bug, attempts - // to dereference |this|'s pointer should cause either a failure or a - // segfault closer to the problem. If |this| wasn't reset to nullptr, - // the access would cause the deleted memory to be read or written - // leading to other more subtle issues. - reset(nullptr); - } - - void reset(T* p) { - // Match C++11's definition of unique_ptr::reset(), which requires changing - // the pointer before invoking the deleter on the old pointer. This prevents - // |this| from being accessed after the deleter is run, which may destroy - // |this|. - T* old = data_.ptr; - data_.ptr = p; - if (old != nullptr) - static_cast<D&>(data_)(old); - } - - T* get() const { return data_.ptr; } - - D& get_deleter() { return data_; } - const D& get_deleter() const { return data_; } - - void swap(scoped_ptr_impl& p2) { - // Standard swap idiom: 'using std::swap' ensures that std::swap is - // present in the overload set, but we call swap unqualified so that - // any more-specific overloads can be used, if available. - using std::swap; - swap(static_cast<D&>(data_), static_cast<D&>(p2.data_)); - swap(data_.ptr, p2.data_.ptr); - } - - T* release() { - T* old_ptr = data_.ptr; - data_.ptr = nullptr; - return old_ptr; - } - - private: - // Needed to allow type-converting constructor. - template <typename U, typename V> friend class scoped_ptr_impl; - - // Use the empty base class optimization to allow us to have a D - // member, while avoiding any space overhead for it when D is an - // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good - // discussion of this technique. - struct Data : public D { - explicit Data(T* ptr_in) : ptr(ptr_in) {} - Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {} - T* ptr; - }; - - Data data_; - - DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl); -}; - -} // namespace internal - -} // namespace base - -// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> -// automatically deletes the pointer it holds (if any). -// That is, scoped_ptr<T> owns the T object that it points to. -// Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T -// object. Also like T*, scoped_ptr<T> is thread-compatible, and once you -// dereference it, you get the thread safety guarantees of T. -// -// The size of scoped_ptr is small. On most compilers, when using the -// std::default_delete, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters -// will increase the size proportional to whatever state they need to have. See -// comments inside scoped_ptr_impl<> for details. -// -// Current implementation targets having a strict subset of C++11's -// unique_ptr<> features. Known deficiencies include not supporting move-only -// deleteres, function pointers as deleters, and deleters with reference -// types. -template <class T, class D = std::default_delete<T>> -class scoped_ptr { - DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr) - - static_assert(!std::is_array<T>::value, - "scoped_ptr doesn't support array with size"); - static_assert(base::internal::IsNotRefCounted<T>::value, - "T is a refcounted type and needs a scoped_refptr"); - - public: - // The element and deleter types. - using element_type = T; - using deleter_type = D; - - // Constructor. Defaults to initializing with nullptr. - scoped_ptr() : impl_(nullptr) {} - - // Constructor. Takes ownership of p. - explicit scoped_ptr(element_type* p) : impl_(p) {} - - // Constructor. Allows initialization of a stateful deleter. - scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} - - // Constructor. Allows construction from a nullptr. - scoped_ptr(std::nullptr_t) : impl_(nullptr) {} - - // Move constructor. - // - // IMPLEMENTATION NOTE: Clang requires a move constructor to be defined (and - // not just the conversion constructor) in order to warn on pessimizing moves. - // The requirements for the move constructor are specified in C++11 - // 20.7.1.2.1.15-17, which has some subtleties around reference deleters. As - // we don't support reference (or move-only) deleters, the post conditions are - // trivially true: we always copy construct the deleter from other's deleter. - scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} - - // Conversion constructor. Allows construction from a scoped_ptr rvalue for a - // convertible type and deleter. - // - // IMPLEMENTATION NOTE: C++ 20.7.1.2.1.19 requires this constructor to only - // participate in overload resolution if all the following are true: - // - U is implicitly convertible to T: this is important for 2 reasons: - // 1. So type traits don't incorrectly return true, e.g. - // std::is_convertible<scoped_ptr<Base>, scoped_ptr<Derived>>::value - // should be false. - // 2. To make sure code like this compiles: - // void F(scoped_ptr<int>); - // void F(scoped_ptr<Base>); - // // Ambiguous since both conversion constructors match. - // F(scoped_ptr<Derived>()); - // - U is not an array type: to prevent conversions from scoped_ptr<T[]> to - // scoped_ptr<T>. - // - D is a reference type and E is the same type, or D is not a reference - // type and E is implicitly convertible to D: again, we don't support - // reference deleters, so we only worry about the latter requirement. - template <typename U, - typename E, - typename std::enable_if<!std::is_array<U>::value && - std::is_convertible<U*, T*>::value && - std::is_convertible<E, D>::value>::type* = - nullptr> - scoped_ptr(scoped_ptr<U, E>&& other) - : impl_(&other.impl_) {} - - // operator=. - // - // IMPLEMENTATION NOTE: Unlike the move constructor, Clang does not appear to - // require a move assignment operator to trigger the pessimizing move warning: - // in this case, the warning triggers when moving a temporary. For consistency - // with the move constructor, we define it anyway. C++11 20.7.1.2.3.1-3 - // defines several requirements around this: like the move constructor, the - // requirements are simplified by the fact that we don't support move-only or - // reference deleters. - scoped_ptr& operator=(scoped_ptr&& rhs) { - impl_.TakeState(&rhs.impl_); - return *this; - } - - // operator=. Allows assignment from a scoped_ptr rvalue for a convertible - // type and deleter. - // - // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from - // the normal move assignment operator. C++11 20.7.1.2.3.4-7 contains the - // requirement for this operator, but like the conversion constructor, the - // requirements are greatly simplified by not supporting move-only or - // reference deleters. - template <typename U, - typename E, - typename std::enable_if<!std::is_array<U>::value && - std::is_convertible<U*, T*>::value && - // Note that this really should be - // std::is_assignable, but <type_traits> - // appears to be missing this on some - // platforms. This is close enough (though - // it's not the same). - std::is_convertible<D, E>::value>::type* = - nullptr> - scoped_ptr& operator=(scoped_ptr<U, E>&& rhs) { - impl_.TakeState(&rhs.impl_); - return *this; - } - - // operator=. Allows assignment from a nullptr. Deletes the currently owned - // object, if any. - scoped_ptr& operator=(std::nullptr_t) { - reset(); - return *this; - } - - // Reset. Deletes the currently owned object, if any. - // Then takes ownership of a new object, if given. - void reset(element_type* p = nullptr) { impl_.reset(p); } - - // Accessors to get the owned object. - // operator* and operator-> will assert() if there is no current object. - element_type& operator*() const { - assert(impl_.get() != nullptr); - return *impl_.get(); - } - element_type* operator->() const { - assert(impl_.get() != nullptr); - return impl_.get(); - } - element_type* get() const { return impl_.get(); } - - // Access to the deleter. - deleter_type& get_deleter() { return impl_.get_deleter(); } - const deleter_type& get_deleter() const { return impl_.get_deleter(); } - - // Allow scoped_ptr<element_type> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - // - // Note that this trick is only safe when the == and != operators - // are declared explicitly, as otherwise "scoped_ptr1 == - // scoped_ptr2" will compile but do the wrong thing (i.e., convert - // to Testable and then do the comparison). - private: - typedef base::internal::scoped_ptr_impl<element_type, deleter_type> - scoped_ptr::*Testable; - - public: - operator Testable() const { - return impl_.get() ? &scoped_ptr::impl_ : nullptr; - } - - // Swap two scoped pointers. - void swap(scoped_ptr& p2) { - impl_.swap(p2.impl_); - } - - // Release a pointer. - // The return value is the current pointer held by this object. If this object - // holds a nullptr, the return value is nullptr. After this operation, this - // object will hold a nullptr, and will not own the object any more. - element_type* release() WARN_UNUSED_RESULT { - return impl_.release(); - } - - private: - // Needed to reach into |impl_| in the constructor. - template <typename U, typename V> friend class scoped_ptr; - base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; - - // Forbidden for API compatibility with std::unique_ptr. - explicit scoped_ptr(int disallow_construction_from_null); -}; - -template <class T, class D> -class scoped_ptr<T[], D> { - DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr) - - public: - // The element and deleter types. - using element_type = T; - using deleter_type = D; - - // Constructor. Defaults to initializing with nullptr. - scoped_ptr() : impl_(nullptr) {} - - // Constructor. Stores the given array. Note that the argument's type - // must exactly match T*. In particular: - // - it cannot be a pointer to a type derived from T, because it is - // inherently unsafe in the general case to access an array through a - // pointer whose dynamic type does not match its static type (eg., if - // T and the derived types had different sizes access would be - // incorrectly calculated). Deletion is also always undefined - // (C++98 [expr.delete]p3). If you're doing this, fix your code. - // - it cannot be const-qualified differently from T per unique_ptr spec - // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting - // to work around this may use const_cast<const T*>(). - explicit scoped_ptr(element_type* array) : impl_(array) {} - - // Constructor. Allows construction from a nullptr. - scoped_ptr(std::nullptr_t) : impl_(nullptr) {} - - // Constructor. Allows construction from a scoped_ptr rvalue. - scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} - - // operator=. Allows assignment from a scoped_ptr rvalue. - scoped_ptr& operator=(scoped_ptr&& rhs) { - impl_.TakeState(&rhs.impl_); - return *this; - } - - // operator=. Allows assignment from a nullptr. Deletes the currently owned - // array, if any. - scoped_ptr& operator=(std::nullptr_t) { - reset(); - return *this; - } - - // Reset. Deletes the currently owned array, if any. - // Then takes ownership of a new object, if given. - void reset(element_type* array = nullptr) { impl_.reset(array); } - - // Accessors to get the owned array. - element_type& operator[](size_t i) const { - assert(impl_.get() != nullptr); - return impl_.get()[i]; - } - element_type* get() const { return impl_.get(); } - - // Access to the deleter. - deleter_type& get_deleter() { return impl_.get_deleter(); } - const deleter_type& get_deleter() const { return impl_.get_deleter(); } - - // Allow scoped_ptr<element_type> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - private: - typedef base::internal::scoped_ptr_impl<element_type, deleter_type> - scoped_ptr::*Testable; - - public: - operator Testable() const { - return impl_.get() ? &scoped_ptr::impl_ : nullptr; - } - - // Swap two scoped pointers. - void swap(scoped_ptr& p2) { - impl_.swap(p2.impl_); - } - - // Release a pointer. - // The return value is the current pointer held by this object. If this object - // holds a nullptr, the return value is nullptr. After this operation, this - // object will hold a nullptr, and will not own the object any more. - element_type* release() WARN_UNUSED_RESULT { - return impl_.release(); - } - - private: - // Force element_type to be a complete type. - enum { type_must_be_complete = sizeof(element_type) }; - - // Actually hold the data. - base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; - - // Disable initialization from any type other than element_type*, by - // providing a constructor that matches such an initialization, but is - // private and has no definition. This is disabled because it is not safe to - // call delete[] on an array whose static type does not match its dynamic - // type. - template <typename U> explicit scoped_ptr(U* array); - explicit scoped_ptr(int disallow_construction_from_null); - - // Disable reset() from any type other than element_type*, for the same - // reasons as the constructor above. - template <typename U> void reset(U* array); - void reset(int disallow_reset_from_null); -}; - -// Free functions -template <class T, class D> -void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) { - p1.swap(p2); -} - -template <class T1, class D1, class T2, class D2> -bool operator==(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { - return p1.get() == p2.get(); -} -template <class T, class D> -bool operator==(const scoped_ptr<T, D>& p, std::nullptr_t) { - return p.get() == nullptr; -} -template <class T, class D> -bool operator==(std::nullptr_t, const scoped_ptr<T, D>& p) { - return p.get() == nullptr; -} - -template <class T1, class D1, class T2, class D2> -bool operator!=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { - return !(p1 == p2); -} -template <class T, class D> -bool operator!=(const scoped_ptr<T, D>& p, std::nullptr_t) { - return !(p == nullptr); -} -template <class T, class D> -bool operator!=(std::nullptr_t, const scoped_ptr<T, D>& p) { - return !(p == nullptr); -} - -template <class T1, class D1, class T2, class D2> -bool operator<(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { - return p1.get() < p2.get(); -} -template <class T, class D> -bool operator<(const scoped_ptr<T, D>& p, std::nullptr_t) { - return p.get() < nullptr; -} -template <class T, class D> -bool operator<(std::nullptr_t, const scoped_ptr<T, D>& p) { - return nullptr < p.get(); -} - -template <class T1, class D1, class T2, class D2> -bool operator>(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { - return p2 < p1; -} -template <class T, class D> -bool operator>(const scoped_ptr<T, D>& p, std::nullptr_t) { - return nullptr < p; -} -template <class T, class D> -bool operator>(std::nullptr_t, const scoped_ptr<T, D>& p) { - return p < nullptr; -} - -template <class T1, class D1, class T2, class D2> -bool operator<=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { - return !(p1 > p2); -} -template <class T, class D> -bool operator<=(const scoped_ptr<T, D>& p, std::nullptr_t) { - return !(p > nullptr); -} -template <class T, class D> -bool operator<=(std::nullptr_t, const scoped_ptr<T, D>& p) { - return !(nullptr > p); -} - -template <class T1, class D1, class T2, class D2> -bool operator>=(const scoped_ptr<T1, D1>& p1, const scoped_ptr<T2, D2>& p2) { - return !(p1 < p2); -} -template <class T, class D> -bool operator>=(const scoped_ptr<T, D>& p, std::nullptr_t) { - return !(p < nullptr); -} -template <class T, class D> -bool operator>=(std::nullptr_t, const scoped_ptr<T, D>& p) { - return !(nullptr < p); -} - -// A function to convert T* into scoped_ptr<T> -// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation -// for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) -template <typename T> -scoped_ptr<T> make_scoped_ptr(T* ptr) { - return scoped_ptr<T>(ptr); -} - -template <typename T> -std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { - return out << p.get(); -} - -#endif // BASE_MEMORY_SCOPED_PTR_H_ diff --git a/security/sandbox/chromium/base/memory/singleton.cc b/security/sandbox/chromium/base/memory/singleton.cc deleted file mode 100644 index f68ecaa8d..000000000 --- a/security/sandbox/chromium/base/memory/singleton.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/singleton.h" -#include "base/threading/platform_thread.h" - -namespace base { -namespace internal { - -subtle::AtomicWord WaitForInstance(subtle::AtomicWord* instance) { - // Handle the race. Another thread beat us and either: - // - Has the object in BeingCreated state - // - Already has the object created... - // We know value != NULL. It could be kBeingCreatedMarker, or a valid ptr. - // Unless your constructor can be very time consuming, it is very unlikely - // to hit this race. When it does, we just spin and yield the thread until - // the object has been created. - subtle::AtomicWord value; - while (true) { - // The load has acquire memory ordering as the thread which reads the - // instance pointer must acquire visibility over the associated data. - // The pairing Release_Store operation is in Singleton::get(). - value = subtle::Acquire_Load(instance); - if (value != kBeingCreatedMarker) - break; - PlatformThread::YieldCurrentThread(); - } - return value; -} - -} // namespace internal -} // namespace base - diff --git a/security/sandbox/chromium/base/memory/singleton.h b/security/sandbox/chromium/base/memory/singleton.h deleted file mode 100644 index 79e4441a8..000000000 --- a/security/sandbox/chromium/base/memory/singleton.h +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// PLEASE READ: Do you really need a singleton? -// -// Singletons make it hard to determine the lifetime of an object, which can -// lead to buggy code and spurious crashes. -// -// Instead of adding another singleton into the mix, try to identify either: -// a) An existing singleton that can manage your object's lifetime -// b) Locations where you can deterministically create the object and pass -// into other objects -// -// If you absolutely need a singleton, please keep them as trivial as possible -// and ideally a leaf dependency. Singletons get problematic when they attempt -// to do too much in their destructor or have circular dependencies. - -#ifndef BASE_MEMORY_SINGLETON_H_ -#define BASE_MEMORY_SINGLETON_H_ - -#include "base/at_exit.h" -#include "base/atomicops.h" -#include "base/base_export.h" -#include "base/macros.h" -#include "base/memory/aligned_memory.h" -#include "base/threading/thread_restrictions.h" - -namespace base { -namespace internal { - -// Our AtomicWord doubles as a spinlock, where a value of -// kBeingCreatedMarker means the spinlock is being held for creation. -static const subtle::AtomicWord kBeingCreatedMarker = 1; - -// We pull out some of the functionality into a non-templated function, so that -// we can implement the more complicated pieces out of line in the .cc file. -BASE_EXPORT subtle::AtomicWord WaitForInstance(subtle::AtomicWord* instance); - -class DeleteTraceLogForTesting; - -} // namespace internal - - -// Default traits for Singleton<Type>. Calls operator new and operator delete on -// the object. Registers automatic deletion at process exit. -// Overload if you need arguments or another memory allocation function. -template<typename Type> -struct DefaultSingletonTraits { - // Allocates the object. - static Type* New() { - // The parenthesis is very important here; it forces POD type - // initialization. - return new Type(); - } - - // Destroys the object. - static void Delete(Type* x) { - delete x; - } - - // Set to true to automatically register deletion of the object on process - // exit. See below for the required call that makes this happen. - static const bool kRegisterAtExit = true; - -#ifndef NDEBUG - // Set to false to disallow access on a non-joinable thread. This is - // different from kRegisterAtExit because StaticMemorySingletonTraits allows - // access on non-joinable threads, and gracefully handles this. - static const bool kAllowedToAccessOnNonjoinableThread = false; -#endif -}; - - -// Alternate traits for use with the Singleton<Type>. Identical to -// DefaultSingletonTraits except that the Singleton will not be cleaned up -// at exit. -template<typename Type> -struct LeakySingletonTraits : public DefaultSingletonTraits<Type> { - static const bool kRegisterAtExit = false; -#ifndef NDEBUG - static const bool kAllowedToAccessOnNonjoinableThread = true; -#endif -}; - - -// Alternate traits for use with the Singleton<Type>. Allocates memory -// for the singleton instance from a static buffer. The singleton will -// be cleaned up at exit, but can't be revived after destruction unless -// the Resurrect() method is called. -// -// This is useful for a certain category of things, notably logging and -// tracing, where the singleton instance is of a type carefully constructed to -// be safe to access post-destruction. -// In logging and tracing you'll typically get stray calls at odd times, like -// during static destruction, thread teardown and the like, and there's a -// termination race on the heap-based singleton - e.g. if one thread calls -// get(), but then another thread initiates AtExit processing, the first thread -// may call into an object residing in unallocated memory. If the instance is -// allocated from the data segment, then this is survivable. -// -// The destructor is to deallocate system resources, in this case to unregister -// a callback the system will invoke when logging levels change. Note that -// this is also used in e.g. Chrome Frame, where you have to allow for the -// possibility of loading briefly into someone else's process space, and -// so leaking is not an option, as that would sabotage the state of your host -// process once you've unloaded. -template <typename Type> -struct StaticMemorySingletonTraits { - // WARNING: User has to deal with get() in the singleton class - // this is traits for returning NULL. - static Type* New() { - // Only constructs once and returns pointer; otherwise returns NULL. - if (subtle::NoBarrier_AtomicExchange(&dead_, 1)) - return NULL; - - return new(buffer_.void_data()) Type(); - } - - static void Delete(Type* p) { - if (p != NULL) - p->Type::~Type(); - } - - static const bool kRegisterAtExit = true; - static const bool kAllowedToAccessOnNonjoinableThread = true; - - // Exposed for unittesting. - static void Resurrect() { subtle::NoBarrier_Store(&dead_, 0); } - - private: - static AlignedMemory<sizeof(Type), ALIGNOF(Type)> buffer_; - // Signal the object was already deleted, so it is not revived. - static subtle::Atomic32 dead_; -}; - -template <typename Type> -AlignedMemory<sizeof(Type), ALIGNOF(Type)> - StaticMemorySingletonTraits<Type>::buffer_; -template <typename Type> -subtle::Atomic32 StaticMemorySingletonTraits<Type>::dead_ = 0; - -// The Singleton<Type, Traits, DifferentiatingType> class manages a single -// instance of Type which will be created on first use and will be destroyed at -// normal process exit). The Trait::Delete function will not be called on -// abnormal process exit. -// -// DifferentiatingType is used as a key to differentiate two different -// singletons having the same memory allocation functions but serving a -// different purpose. This is mainly used for Locks serving different purposes. -// -// Example usage: -// -// In your header: -// template <typename T> struct DefaultSingletonTraits; -// class FooClass { -// public: -// static FooClass* GetInstance(); <-- See comment below on this. -// void Bar() { ... } -// private: -// FooClass() { ... } -// friend struct DefaultSingletonTraits<FooClass>; -// -// DISALLOW_COPY_AND_ASSIGN(FooClass); -// }; -// -// In your source file: -// #include "base/memory/singleton.h" -// FooClass* FooClass::GetInstance() { -// return Singleton<FooClass>::get(); -// } -// -// And to call methods on FooClass: -// FooClass::GetInstance()->Bar(); -// -// NOTE: The method accessing Singleton<T>::get() has to be named as GetInstance -// and it is important that FooClass::GetInstance() is not inlined in the -// header. This makes sure that when source files from multiple targets include -// this header they don't end up with different copies of the inlined code -// creating multiple copies of the singleton. -// -// Singleton<> has no non-static members and doesn't need to actually be -// instantiated. -// -// This class is itself thread-safe. The underlying Type must of course be -// thread-safe if you want to use it concurrently. Two parameters may be tuned -// depending on the user's requirements. -// -// Glossary: -// RAE = kRegisterAtExit -// -// On every platform, if Traits::RAE is true, the singleton will be destroyed at -// process exit. More precisely it uses AtExitManager which requires an -// object of this type to be instantiated. AtExitManager mimics the semantics -// of atexit() such as LIFO order but under Windows is safer to call. For more -// information see at_exit.h. -// -// If Traits::RAE is false, the singleton will not be freed at process exit, -// thus the singleton will be leaked if it is ever accessed. Traits::RAE -// shouldn't be false unless absolutely necessary. Remember that the heap where -// the object is allocated may be destroyed by the CRT anyway. -// -// Caveats: -// (a) Every call to get(), operator->() and operator*() incurs some overhead -// (16ns on my P4/2.8GHz) to check whether the object has already been -// initialized. You may wish to cache the result of get(); it will not -// change. -// -// (b) Your factory function must never throw an exception. This class is not -// exception-safe. -// - -template <typename Type, - typename Traits = DefaultSingletonTraits<Type>, - typename DifferentiatingType = Type> -class Singleton { - private: - // Classes using the Singleton<T> pattern should declare a GetInstance() - // method and call Singleton::get() from within that. - friend Type* Type::GetInstance(); - - // Allow TraceLog tests to test tracing after OnExit. - friend class internal::DeleteTraceLogForTesting; - - // This class is safe to be constructed and copy-constructed since it has no - // member. - - // Return a pointer to the one true instance of the class. - static Type* get() { -#ifndef NDEBUG - // Avoid making TLS lookup on release builds. - if (!Traits::kAllowedToAccessOnNonjoinableThread) - ThreadRestrictions::AssertSingletonAllowed(); -#endif - - // The load has acquire memory ordering as the thread which reads the - // instance_ pointer must acquire visibility over the singleton data. - subtle::AtomicWord value = subtle::Acquire_Load(&instance_); - if (value != 0 && value != internal::kBeingCreatedMarker) { - return reinterpret_cast<Type*>(value); - } - - // Object isn't created yet, maybe we will get to create it, let's try... - if (subtle::Acquire_CompareAndSwap(&instance_, 0, - internal::kBeingCreatedMarker) == 0) { - // instance_ was NULL and is now kBeingCreatedMarker. Only one thread - // will ever get here. Threads might be spinning on us, and they will - // stop right after we do this store. - Type* newval = Traits::New(); - - // Releases the visibility over instance_ to the readers. - subtle::Release_Store(&instance_, - reinterpret_cast<subtle::AtomicWord>(newval)); - - if (newval != NULL && Traits::kRegisterAtExit) - AtExitManager::RegisterCallback(OnExit, NULL); - - return newval; - } - - // We hit a race. Wait for the other thread to complete it. - value = internal::WaitForInstance(&instance_); - - return reinterpret_cast<Type*>(value); - } - - // Adapter function for use with AtExit(). This should be called single - // threaded, so don't use atomic operations. - // Calling OnExit while singleton is in use by other threads is a mistake. - static void OnExit(void* /*unused*/) { - // AtExit should only ever be register after the singleton instance was - // created. We should only ever get here with a valid instance_ pointer. - Traits::Delete(reinterpret_cast<Type*>(subtle::NoBarrier_Load(&instance_))); - instance_ = 0; - } - static subtle::AtomicWord instance_; -}; - -template <typename Type, typename Traits, typename DifferentiatingType> -subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::instance_ = 0; - -} // namespace base - -#endif // BASE_MEMORY_SINGLETON_H_ diff --git a/security/sandbox/chromium/base/memory/weak_ptr.h b/security/sandbox/chromium/base/memory/weak_ptr.h deleted file mode 100644 index 33d1e4736..000000000 --- a/security/sandbox/chromium/base/memory/weak_ptr.h +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Weak pointers are pointers to an object that do not affect its lifetime, -// and which may be invalidated (i.e. reset to NULL) by the object, or its -// owner, at any time, most commonly when the object is about to be deleted. - -// Weak pointers are useful when an object needs to be accessed safely by one -// or more objects other than its owner, and those callers can cope with the -// object vanishing and e.g. tasks posted to it being silently dropped. -// Reference-counting such an object would complicate the ownership graph and -// make it harder to reason about the object's lifetime. - -// EXAMPLE: -// -// class Controller { -// public: -// Controller() : weak_factory_(this) {} -// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } -// void WorkComplete(const Result& result) { ... } -// private: -// // Member variables should appear before the WeakPtrFactory, to ensure -// // that any WeakPtrs to Controller are invalidated before its members -// // variable's destructors are executed, rendering them invalid. -// WeakPtrFactory<Controller> weak_factory_; -// }; -// -// class Worker { -// public: -// static void StartNew(const WeakPtr<Controller>& controller) { -// Worker* worker = new Worker(controller); -// // Kick off asynchronous processing... -// } -// private: -// Worker(const WeakPtr<Controller>& controller) -// : controller_(controller) {} -// void DidCompleteAsynchronousProcessing(const Result& result) { -// if (controller_) -// controller_->WorkComplete(result); -// } -// WeakPtr<Controller> controller_; -// }; -// -// With this implementation a caller may use SpawnWorker() to dispatch multiple -// Workers and subsequently delete the Controller, without waiting for all -// Workers to have completed. - -// ------------------------- IMPORTANT: Thread-safety ------------------------- - -// Weak pointers may be passed safely between threads, but must always be -// dereferenced and invalidated on the same SequencedTaskRunner otherwise -// checking the pointer would be racey. -// -// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory -// is dereferenced, the factory and its WeakPtrs become bound to the calling -// thread or current SequencedWorkerPool token, and cannot be dereferenced or -// invalidated on any other task runner. Bound WeakPtrs can still be handed -// off to other task runners, e.g. to use to post tasks back to object on the -// bound sequence. -// -// If all WeakPtr objects are destroyed or invalidated then the factory is -// unbound from the SequencedTaskRunner/Thread. The WeakPtrFactory may then be -// destroyed, or new WeakPtr objects may be used, from a different sequence. -// -// Thus, at least one WeakPtr object must exist and have been dereferenced on -// the correct thread to enforce that other WeakPtr objects will enforce they -// are used on the desired thread. - -#ifndef BASE_MEMORY_WEAK_PTR_H_ -#define BASE_MEMORY_WEAK_PTR_H_ - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/sequence_checker.h" -#include "base/template_util.h" - -namespace base { - -template <typename T> class SupportsWeakPtr; -template <typename T> class WeakPtr; - -namespace internal { -// These classes are part of the WeakPtr implementation. -// DO NOT USE THESE CLASSES DIRECTLY YOURSELF. - -class BASE_EXPORT WeakReference { - public: - // Although Flag is bound to a specific SequencedTaskRunner, it may be - // deleted from another via base::WeakPtr::~WeakPtr(). - class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { - public: - Flag(); - - void Invalidate(); - bool IsValid() const; - - private: - friend class base::RefCountedThreadSafe<Flag>; - - ~Flag(); - - SequenceChecker sequence_checker_; - bool is_valid_; - }; - - WeakReference(); - explicit WeakReference(const Flag* flag); - ~WeakReference(); - - bool is_valid() const; - - private: - scoped_refptr<const Flag> flag_; -}; - -class BASE_EXPORT WeakReferenceOwner { - public: - WeakReferenceOwner(); - ~WeakReferenceOwner(); - - WeakReference GetRef() const; - - bool HasRefs() const { - return flag_.get() && !flag_->HasOneRef(); - } - - void Invalidate(); - - private: - mutable scoped_refptr<WeakReference::Flag> flag_; -}; - -// This class simplifies the implementation of WeakPtr's type conversion -// constructor by avoiding the need for a public accessor for ref_. A -// WeakPtr<T> cannot access the private members of WeakPtr<U>, so this -// base class gives us a way to access ref_ in a protected fashion. -class BASE_EXPORT WeakPtrBase { - public: - WeakPtrBase(); - ~WeakPtrBase(); - - protected: - explicit WeakPtrBase(const WeakReference& ref); - - WeakReference ref_; -}; - -// This class provides a common implementation of common functions that would -// otherwise get instantiated separately for each distinct instantiation of -// SupportsWeakPtr<>. -class SupportsWeakPtrBase { - public: - // A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This - // conversion will only compile if there is exists a Base which inherits - // from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper - // function that makes calling this easier. - template<typename Derived> - static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { - typedef - is_convertible<Derived, internal::SupportsWeakPtrBase&> convertible; - static_assert(convertible::value, - "AsWeakPtr argument must inherit from SupportsWeakPtr"); - return AsWeakPtrImpl<Derived>(t, *t); - } - - private: - // This template function uses type inference to find a Base of Derived - // which is an instance of SupportsWeakPtr<Base>. We can then safely - // static_cast the Base* to a Derived*. - template <typename Derived, typename Base> - static WeakPtr<Derived> AsWeakPtrImpl( - Derived* t, const SupportsWeakPtr<Base>&) { - WeakPtr<Base> ptr = t->Base::AsWeakPtr(); - return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_)); - } -}; - -} // namespace internal - -template <typename T> class WeakPtrFactory; - -// The WeakPtr class holds a weak reference to |T*|. -// -// This class is designed to be used like a normal pointer. You should always -// null-test an object of this class before using it or invoking a method that -// may result in the underlying object being destroyed. -// -// EXAMPLE: -// -// class Foo { ... }; -// WeakPtr<Foo> foo; -// if (foo) -// foo->method(); -// -template <typename T> -class WeakPtr : public internal::WeakPtrBase { - public: - WeakPtr() : ptr_(NULL) { - } - - // Allow conversion from U to T provided U "is a" T. Note that this - // is separate from the (implicit) copy constructor. - template <typename U> - WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) { - } - - T* get() const { return ref_.is_valid() ? ptr_ : NULL; } - - T& operator*() const { - DCHECK(get() != NULL); - return *get(); - } - T* operator->() const { - DCHECK(get() != NULL); - return get(); - } - - // Allow WeakPtr<element_type> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - // - // Note that this trick is only safe when the == and != operators - // are declared explicitly, as otherwise "weak_ptr1 == weak_ptr2" - // will compile but do the wrong thing (i.e., convert to Testable - // and then do the comparison). - private: - typedef T* WeakPtr::*Testable; - - public: - operator Testable() const { return get() ? &WeakPtr::ptr_ : NULL; } - - void reset() { - ref_ = internal::WeakReference(); - ptr_ = NULL; - } - - private: - // Explicitly declare comparison operators as required by the bool - // trick, but keep them private. - template <class U> bool operator==(WeakPtr<U> const&) const; - template <class U> bool operator!=(WeakPtr<U> const&) const; - - friend class internal::SupportsWeakPtrBase; - template <typename U> friend class WeakPtr; - friend class SupportsWeakPtr<T>; - friend class WeakPtrFactory<T>; - - WeakPtr(const internal::WeakReference& ref, T* ptr) - : WeakPtrBase(ref), - ptr_(ptr) { - } - - // This pointer is only valid when ref_.is_valid() is true. Otherwise, its - // value is undefined (as opposed to NULL). - T* ptr_; -}; - -// A class may be composed of a WeakPtrFactory and thereby -// control how it exposes weak pointers to itself. This is helpful if you only -// need weak pointers within the implementation of a class. This class is also -// useful when working with primitive types. For example, you could have a -// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool. -template <class T> -class WeakPtrFactory { - public: - explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { - } - - ~WeakPtrFactory() { - ptr_ = NULL; - } - - WeakPtr<T> GetWeakPtr() { - DCHECK(ptr_); - return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_); - } - - // Call this method to invalidate all existing weak pointers. - void InvalidateWeakPtrs() { - DCHECK(ptr_); - weak_reference_owner_.Invalidate(); - } - - // Call this method to determine if any weak pointers exist. - bool HasWeakPtrs() const { - DCHECK(ptr_); - return weak_reference_owner_.HasRefs(); - } - - private: - internal::WeakReferenceOwner weak_reference_owner_; - T* ptr_; - DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); -}; - -// A class may extend from SupportsWeakPtr to let others take weak pointers to -// it. This avoids the class itself implementing boilerplate to dispense weak -// pointers. However, since SupportsWeakPtr's destructor won't invalidate -// weak pointers to the class until after the derived class' members have been -// destroyed, its use can lead to subtle use-after-destroy issues. -template <class T> -class SupportsWeakPtr : public internal::SupportsWeakPtrBase { - public: - SupportsWeakPtr() {} - - WeakPtr<T> AsWeakPtr() { - return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this)); - } - - protected: - ~SupportsWeakPtr() {} - - private: - internal::WeakReferenceOwner weak_reference_owner_; - DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr); -}; - -// Helper function that uses type deduction to safely return a WeakPtr<Derived> -// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it -// extends a Base that extends SupportsWeakPtr<Base>. -// -// EXAMPLE: -// class Base : public base::SupportsWeakPtr<Producer> {}; -// class Derived : public Base {}; -// -// Derived derived; -// base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived); -// -// Note that the following doesn't work (invalid type conversion) since -// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(), -// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at -// the caller. -// -// base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. - -template <typename Derived> -WeakPtr<Derived> AsWeakPtr(Derived* t) { - return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); -} - -} // namespace base - -#endif // BASE_MEMORY_WEAK_PTR_H_ diff --git a/security/sandbox/chromium/base/move.h b/security/sandbox/chromium/base/move.h deleted file mode 100644 index 0af416e00..000000000 --- a/security/sandbox/chromium/base/move.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MOVE_H_ -#define BASE_MOVE_H_ - -#include <utility> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "build/build_config.h" - -// TODO(crbug.com/566182): DEPRECATED! -// Use DISALLOW_COPY_AND_ASSIGN instead, or if your type will be used in -// Callbacks, use DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND instead. -#define MOVE_ONLY_TYPE_FOR_CPP_03(type) \ - DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) - -// A macro to disallow the copy constructor and copy assignment functions. -// This should be used in the private: declarations for a class. -// -// Use this macro instead of DISALLOW_COPY_AND_ASSIGN if you want to pass -// ownership of the type through a base::Callback without heap-allocating it -// into a scoped_ptr. The class must define a move constructor and move -// assignment operator to make this work. -// -// This version of the macro adds a Pass() function and a cryptic -// MoveOnlyTypeForCPP03 typedef for the base::Callback implementation to use. -// See IsMoveOnlyType template and its usage in base/callback_internal.h -// for more details. -// TODO(crbug.com/566182): Remove this macro and use DISALLOW_COPY_AND_ASSIGN -// everywhere instead. -#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_MACOSX) -#define DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) \ - private: \ - type(const type&) = delete; \ - void operator=(const type&) = delete; \ - \ - public: \ - typedef void MoveOnlyTypeForCPP03; \ - \ - private: -#else -#define DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) \ - private: \ - type(const type&) = delete; \ - void operator=(const type&) = delete; \ - \ - public: \ - type&& Pass() WARN_UNUSED_RESULT { return std::move(*this); } \ - typedef void MoveOnlyTypeForCPP03; \ - \ - private: -#endif - -#endif // BASE_MOVE_H_ diff --git a/security/sandbox/chromium/base/numerics/safe_conversions.h b/security/sandbox/chromium/base/numerics/safe_conversions.h deleted file mode 100644 index baac188fd..000000000 --- a/security/sandbox/chromium/base/numerics/safe_conversions.h +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_ -#define BASE_NUMERICS_SAFE_CONVERSIONS_H_ - -#include <stddef.h> - -#include <limits> -#include <type_traits> - -#include "base/logging.h" -#include "base/numerics/safe_conversions_impl.h" - -namespace base { - -// Convenience function that returns true if the supplied value is in range -// for the destination type. -template <typename Dst, typename Src> -inline bool IsValueInRangeForNumericType(Src value) { - return internal::DstRangeRelationToSrcRange<Dst>(value) == - internal::RANGE_VALID; -} - -// Convenience function for determining if a numeric value is negative without -// throwing compiler warnings on: unsigned(value) < 0. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type -IsValueNegative(T value) { - static_assert(std::numeric_limits<T>::is_specialized, - "Argument must be numeric."); - return value < 0; -} - -template <typename T> -typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type - IsValueNegative(T) { - static_assert(std::numeric_limits<T>::is_specialized, - "Argument must be numeric."); - return false; -} - -// checked_cast<> is analogous to static_cast<> for numeric types, -// except that it CHECKs that the specified numeric conversion will not -// overflow or underflow. NaN source will always trigger a CHECK. -template <typename Dst, typename Src> -inline Dst checked_cast(Src value) { - CHECK(IsValueInRangeForNumericType<Dst>(value)); - return static_cast<Dst>(value); -} - -// HandleNaN will cause this class to CHECK(false). -struct SaturatedCastNaNBehaviorCheck { - template <typename T> - static T HandleNaN() { - CHECK(false); - return T(); - } -}; - -// HandleNaN will return 0 in this case. -struct SaturatedCastNaNBehaviorReturnZero { - template <typename T> - static T HandleNaN() { - return T(); - } -}; - -// saturated_cast<> is analogous to static_cast<> for numeric types, except -// that the specified numeric conversion will saturate rather than overflow or -// underflow. NaN assignment to an integral will defer the behavior to a -// specified class. By default, it will return 0. -template <typename Dst, - class NaNHandler = SaturatedCastNaNBehaviorReturnZero, - typename Src> -inline Dst saturated_cast(Src value) { - // Optimization for floating point values, which already saturate. - if (std::numeric_limits<Dst>::is_iec559) - return static_cast<Dst>(value); - - switch (internal::DstRangeRelationToSrcRange<Dst>(value)) { - case internal::RANGE_VALID: - return static_cast<Dst>(value); - - case internal::RANGE_UNDERFLOW: - return std::numeric_limits<Dst>::min(); - - case internal::RANGE_OVERFLOW: - return std::numeric_limits<Dst>::max(); - - // Should fail only on attempting to assign NaN to a saturated integer. - case internal::RANGE_INVALID: - return NaNHandler::template HandleNaN<Dst>(); - } - - NOTREACHED(); - return static_cast<Dst>(value); -} - -// strict_cast<> is analogous to static_cast<> for numeric types, except that -// it will cause a compile failure if the destination type is not large enough -// to contain any value in the source type. It performs no runtime checking. -template <typename Dst, typename Src> -inline Dst strict_cast(Src value) { - static_assert(std::numeric_limits<Src>::is_specialized, - "Argument must be numeric."); - static_assert(std::numeric_limits<Dst>::is_specialized, - "Result must be numeric."); - static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value == - internal::NUMERIC_RANGE_CONTAINED), - "The numeric conversion is out of range for this type. You " - "should probably use one of the following conversion " - "mechanisms on the value you want to pass:\n" - "- base::checked_cast\n" - "- base::saturated_cast\n" - "- base::CheckedNumeric"); - - return static_cast<Dst>(value); -} - -// StrictNumeric implements compile time range checking between numeric types by -// wrapping assignment operations in a strict_cast. This class is intended to be -// used for function arguments and return types, to ensure the destination type -// can always contain the source type. This is essentially the same as enforcing -// -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied -// incrementally at API boundaries, making it easier to convert code so that it -// compiles cleanly with truncation warnings enabled. -// This template should introduce no runtime overhead, but it also provides no -// runtime checking of any of the associated mathematical operations. Use -// CheckedNumeric for runtime range checks of tha actual value being assigned. -template <typename T> -class StrictNumeric { - public: - typedef T type; - - StrictNumeric() : value_(0) {} - - // Copy constructor. - template <typename Src> - StrictNumeric(const StrictNumeric<Src>& rhs) - : value_(strict_cast<T>(rhs.value_)) {} - - // This is not an explicit constructor because we implicitly upgrade regular - // numerics to StrictNumerics to make them easier to use. - template <typename Src> - StrictNumeric(Src value) - : value_(strict_cast<T>(value)) {} - - // The numeric cast operator basically handles all the magic. - template <typename Dst> - operator Dst() const { - return strict_cast<Dst>(value_); - } - - private: - T value_; -}; - -// Explicitly make a shorter size_t typedef for convenience. -typedef StrictNumeric<size_t> SizeT; - -} // namespace base - -#endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_ diff --git a/security/sandbox/chromium/base/numerics/safe_conversions_impl.h b/security/sandbox/chromium/base/numerics/safe_conversions_impl.h deleted file mode 100644 index 02e68e25d..000000000 --- a/security/sandbox/chromium/base/numerics/safe_conversions_impl.h +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ -#define BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ - -#include <limits.h> -#include <stdint.h> - -#include <limits> - -#include "base/template_util.h" - -namespace base { -namespace internal { - -// The std library doesn't provide a binary max_exponent for integers, however -// we can compute one by adding one to the number of non-sign bits. This allows -// for accurate range comparisons between floating point and integer types. -template <typename NumericType> -struct MaxExponent { - static const int value = std::numeric_limits<NumericType>::is_iec559 - ? std::numeric_limits<NumericType>::max_exponent - : (sizeof(NumericType) * 8 + 1 - - std::numeric_limits<NumericType>::is_signed); -}; - -enum IntegerRepresentation { - INTEGER_REPRESENTATION_UNSIGNED, - INTEGER_REPRESENTATION_SIGNED -}; - -// A range for a given nunmeric Src type is contained for a given numeric Dst -// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and -// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true. -// We implement this as template specializations rather than simple static -// comparisons to ensure type correctness in our comparisons. -enum NumericRangeRepresentation { - NUMERIC_RANGE_NOT_CONTAINED, - NUMERIC_RANGE_CONTAINED -}; - -// Helper templates to statically determine if our destination type can contain -// maximum and minimum values represented by the source type. - -template < - typename Dst, - typename Src, - IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed - ? INTEGER_REPRESENTATION_SIGNED - : INTEGER_REPRESENTATION_UNSIGNED, - IntegerRepresentation SrcSign = - std::numeric_limits<Src>::is_signed - ? INTEGER_REPRESENTATION_SIGNED - : INTEGER_REPRESENTATION_UNSIGNED > -struct StaticDstRangeRelationToSrcRange; - -// Same sign: Dst is guaranteed to contain Src only if its range is equal or -// larger. -template <typename Dst, typename Src, IntegerRepresentation Sign> -struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign> { - static const NumericRangeRepresentation value = - MaxExponent<Dst>::value >= MaxExponent<Src>::value - ? NUMERIC_RANGE_CONTAINED - : NUMERIC_RANGE_NOT_CONTAINED; -}; - -// Unsigned to signed: Dst is guaranteed to contain source only if its range is -// larger. -template <typename Dst, typename Src> -struct StaticDstRangeRelationToSrcRange<Dst, - Src, - INTEGER_REPRESENTATION_SIGNED, - INTEGER_REPRESENTATION_UNSIGNED> { - static const NumericRangeRepresentation value = - MaxExponent<Dst>::value > MaxExponent<Src>::value - ? NUMERIC_RANGE_CONTAINED - : NUMERIC_RANGE_NOT_CONTAINED; -}; - -// Signed to unsigned: Dst cannot be statically determined to contain Src. -template <typename Dst, typename Src> -struct StaticDstRangeRelationToSrcRange<Dst, - Src, - INTEGER_REPRESENTATION_UNSIGNED, - INTEGER_REPRESENTATION_SIGNED> { - static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED; -}; - -enum RangeConstraint { - RANGE_VALID = 0x0, // Value can be represented by the destination type. - RANGE_UNDERFLOW = 0x1, // Value would overflow. - RANGE_OVERFLOW = 0x2, // Value would underflow. - RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN). -}; - -// Helper function for coercing an int back to a RangeContraint. -inline RangeConstraint GetRangeConstraint(int integer_range_constraint) { - DCHECK(integer_range_constraint >= RANGE_VALID && - integer_range_constraint <= RANGE_INVALID); - return static_cast<RangeConstraint>(integer_range_constraint); -} - -// This function creates a RangeConstraint from an upper and lower bound -// check by taking advantage of the fact that only NaN can be out of range in -// both directions at once. -inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, - bool is_in_lower_bound) { - return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) | - (is_in_lower_bound ? 0 : RANGE_UNDERFLOW)); -} - -// The following helper template addresses a corner case in range checks for -// conversion from a floating-point type to an integral type of smaller range -// but larger precision (e.g. float -> unsigned). The problem is as follows: -// 1. Integral maximum is always one less than a power of two, so it must be -// truncated to fit the mantissa of the floating point. The direction of -// rounding is implementation defined, but by default it's always IEEE -// floats, which round to nearest and thus result in a value of larger -// magnitude than the integral value. -// Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX -// // is 4294967295u. -// 2. If the floating point value is equal to the promoted integral maximum -// value, a range check will erroneously pass. -// Example: (4294967296f <= 4294967295u) // This is true due to a precision -// // loss in rounding up to float. -// 3. When the floating point value is then converted to an integral, the -// resulting value is out of range for the target integral type and -// thus is implementation defined. -// Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0. -// To fix this bug we manually truncate the maximum value when the destination -// type is an integral of larger precision than the source floating-point type, -// such that the resulting maximum is represented exactly as a floating point. -template <typename Dst, typename Src> -struct NarrowingRange { - typedef typename std::numeric_limits<Src> SrcLimits; - typedef typename std::numeric_limits<Dst> DstLimits; - - static Dst max() { - // The following logic avoids warnings where the max function is - // instantiated with invalid values for a bit shift (even though - // such a function can never be called). - static const int shift = - (MaxExponent<Src>::value > MaxExponent<Dst>::value && - SrcLimits::digits < DstLimits::digits && SrcLimits::is_iec559 && - DstLimits::is_integer) - ? (DstLimits::digits - SrcLimits::digits) - : 0; - - // We use UINTMAX_C below to avoid compiler warnings about shifting floating - // points. Since it's a compile time calculation, it shouldn't have any - // performance impact. - return DstLimits::max() - static_cast<Dst>((UINTMAX_C(1) << shift) - 1); - } - - static Dst min() { - return std::numeric_limits<Dst>::is_iec559 ? -DstLimits::max() - : DstLimits::min(); - } -}; - -template < - typename Dst, - typename Src, - IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed - ? INTEGER_REPRESENTATION_SIGNED - : INTEGER_REPRESENTATION_UNSIGNED, - IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed - ? INTEGER_REPRESENTATION_SIGNED - : INTEGER_REPRESENTATION_UNSIGNED, - NumericRangeRepresentation DstRange = - StaticDstRangeRelationToSrcRange<Dst, Src>::value > -struct DstRangeRelationToSrcRangeImpl; - -// The following templates are for ranges that must be verified at runtime. We -// split it into checks based on signedness to avoid confusing casts and -// compiler warnings on signed an unsigned comparisons. - -// Dst range is statically determined to contain Src: Nothing to check. -template <typename Dst, - typename Src, - IntegerRepresentation DstSign, - IntegerRepresentation SrcSign> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - DstSign, - SrcSign, - NUMERIC_RANGE_CONTAINED> { - static RangeConstraint Check(Src value) { return RANGE_VALID; } -}; - -// Signed to signed narrowing: Both the upper and lower boundaries may be -// exceeded. -template <typename Dst, typename Src> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - INTEGER_REPRESENTATION_SIGNED, - INTEGER_REPRESENTATION_SIGNED, - NUMERIC_RANGE_NOT_CONTAINED> { - static RangeConstraint Check(Src value) { - return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()), - (value >= NarrowingRange<Dst, Src>::min())); - } -}; - -// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded. -template <typename Dst, typename Src> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - INTEGER_REPRESENTATION_UNSIGNED, - INTEGER_REPRESENTATION_UNSIGNED, - NUMERIC_RANGE_NOT_CONTAINED> { - static RangeConstraint Check(Src value) { - return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true); - } -}; - -// Unsigned to signed: The upper boundary may be exceeded. -template <typename Dst, typename Src> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - INTEGER_REPRESENTATION_SIGNED, - INTEGER_REPRESENTATION_UNSIGNED, - NUMERIC_RANGE_NOT_CONTAINED> { - static RangeConstraint Check(Src value) { - return sizeof(Dst) > sizeof(Src) - ? RANGE_VALID - : GetRangeConstraint( - value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()), - true); - } -}; - -// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst, -// and any negative value exceeds the lower boundary. -template <typename Dst, typename Src> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - INTEGER_REPRESENTATION_UNSIGNED, - INTEGER_REPRESENTATION_SIGNED, - NUMERIC_RANGE_NOT_CONTAINED> { - static RangeConstraint Check(Src value) { - return (MaxExponent<Dst>::value >= MaxExponent<Src>::value) - ? GetRangeConstraint(true, value >= static_cast<Src>(0)) - : GetRangeConstraint( - value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()), - value >= static_cast<Src>(0)); - } -}; - -template <typename Dst, typename Src> -inline RangeConstraint DstRangeRelationToSrcRange(Src value) { - static_assert(std::numeric_limits<Src>::is_specialized, - "Argument must be numeric."); - static_assert(std::numeric_limits<Dst>::is_specialized, - "Result must be numeric."); - return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value); -} - -} // namespace internal -} // namespace base - -#endif // BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ diff --git a/security/sandbox/chromium/base/numerics/safe_math.h b/security/sandbox/chromium/base/numerics/safe_math.h deleted file mode 100644 index d169690a8..000000000 --- a/security/sandbox/chromium/base/numerics/safe_math.h +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_NUMERICS_SAFE_MATH_H_ -#define BASE_NUMERICS_SAFE_MATH_H_ - -#include <stddef.h> - -#include "base/numerics/safe_math_impl.h" - -namespace base { - -namespace internal { - -// CheckedNumeric implements all the logic and operators for detecting integer -// boundary conditions such as overflow, underflow, and invalid conversions. -// The CheckedNumeric type implicitly converts from floating point and integer -// data types, and contains overloads for basic arithmetic operations (i.e.: +, -// -, *, /, %). -// -// The following methods convert from CheckedNumeric to standard numeric values: -// IsValid() - Returns true if the underlying numeric value is valid (i.e. has -// has not wrapped and is not the result of an invalid conversion). -// ValueOrDie() - Returns the underlying value. If the state is not valid this -// call will crash on a CHECK. -// ValueOrDefault() - Returns the current value, or the supplied default if the -// state is not valid. -// ValueFloating() - Returns the underlying floating point value (valid only -// only for floating point CheckedNumeric types). -// -// Bitwise operations are explicitly not supported, because correct -// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison -// operations are explicitly not supported because they could result in a crash -// on a CHECK condition. You should use patterns like the following for these -// operations: -// Bitwise operation: -// CheckedNumeric<int> checked_int = untrusted_input_value; -// int x = checked_int.ValueOrDefault(0) | kFlagValues; -// Comparison: -// CheckedNumeric<size_t> checked_size = untrusted_input_value; -// checked_size += HEADER LENGTH; -// if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) -// Do stuff... -template <typename T> -class CheckedNumeric { - public: - typedef T type; - - CheckedNumeric() {} - - // Copy constructor. - template <typename Src> - CheckedNumeric(const CheckedNumeric<Src>& rhs) - : state_(rhs.ValueUnsafe(), rhs.validity()) {} - - template <typename Src> - CheckedNumeric(Src value, RangeConstraint validity) - : state_(value, validity) {} - - // This is not an explicit constructor because we implicitly upgrade regular - // numerics to CheckedNumerics to make them easier to use. - template <typename Src> - CheckedNumeric(Src value) - : state_(value) { - static_assert(std::numeric_limits<Src>::is_specialized, - "Argument must be numeric."); - } - - // This is not an explicit constructor because we want a seamless conversion - // from StrictNumeric types. - template <typename Src> - CheckedNumeric(StrictNumeric<Src> value) - : state_(static_cast<Src>(value)) { - } - - // IsValid() is the public API to test if a CheckedNumeric is currently valid. - bool IsValid() const { return validity() == RANGE_VALID; } - - // ValueOrDie() The primary accessor for the underlying value. If the current - // state is not valid it will CHECK and crash. - T ValueOrDie() const { - CHECK(IsValid()); - return state_.value(); - } - - // ValueOrDefault(T default_value) A convenience method that returns the - // current value if the state is valid, and the supplied default_value for - // any other state. - T ValueOrDefault(T default_value) const { - return IsValid() ? state_.value() : default_value; - } - - // ValueFloating() - Since floating point values include their validity state, - // we provide an easy method for extracting them directly, without a risk of - // crashing on a CHECK. - T ValueFloating() const { - static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float."); - return CheckedNumeric<T>::cast(*this).ValueUnsafe(); - } - - // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for - // tests and to avoid a big matrix of friend operator overloads. But the - // values it returns are likely to change in the future. - // Returns: current validity state (i.e. valid, overflow, underflow, nan). - // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for - // saturation/wrapping so we can expose this state consistently and implement - // saturated arithmetic. - RangeConstraint validity() const { return state_.validity(); } - - // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now - // for tests and to avoid a big matrix of friend operator overloads. But the - // values it returns are likely to change in the future. - // Returns: the raw numeric value, regardless of the current state. - // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for - // saturation/wrapping so we can expose this state consistently and implement - // saturated arithmetic. - T ValueUnsafe() const { return state_.value(); } - - // Prototypes for the supported arithmetic operator overloads. - template <typename Src> CheckedNumeric& operator+=(Src rhs); - template <typename Src> CheckedNumeric& operator-=(Src rhs); - template <typename Src> CheckedNumeric& operator*=(Src rhs); - template <typename Src> CheckedNumeric& operator/=(Src rhs); - template <typename Src> CheckedNumeric& operator%=(Src rhs); - - CheckedNumeric operator-() const { - RangeConstraint validity; - T value = CheckedNeg(state_.value(), &validity); - // Negation is always valid for floating point. - if (std::numeric_limits<T>::is_iec559) - return CheckedNumeric<T>(value); - - validity = GetRangeConstraint(state_.validity() | validity); - return CheckedNumeric<T>(value, validity); - } - - CheckedNumeric Abs() const { - RangeConstraint validity; - T value = CheckedAbs(state_.value(), &validity); - // Absolute value is always valid for floating point. - if (std::numeric_limits<T>::is_iec559) - return CheckedNumeric<T>(value); - - validity = GetRangeConstraint(state_.validity() | validity); - return CheckedNumeric<T>(value, validity); - } - - // This function is available only for integral types. It returns an unsigned - // integer of the same width as the source type, containing the absolute value - // of the source, and properly handling signed min. - CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const { - return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( - CheckedUnsignedAbs(state_.value()), state_.validity()); - } - - CheckedNumeric& operator++() { - *this += 1; - return *this; - } - - CheckedNumeric operator++(int) { - CheckedNumeric value = *this; - *this += 1; - return value; - } - - CheckedNumeric& operator--() { - *this -= 1; - return *this; - } - - CheckedNumeric operator--(int) { - CheckedNumeric value = *this; - *this -= 1; - return value; - } - - // These static methods behave like a convenience cast operator targeting - // the desired CheckedNumeric type. As an optimization, a reference is - // returned when Src is the same type as T. - template <typename Src> - static CheckedNumeric<T> cast( - Src u, - typename std::enable_if<std::numeric_limits<Src>::is_specialized, - int>::type = 0) { - return u; - } - - template <typename Src> - static CheckedNumeric<T> cast( - const CheckedNumeric<Src>& u, - typename std::enable_if<!is_same<Src, T>::value, int>::type = 0) { - return u; - } - - static const CheckedNumeric<T>& cast(const CheckedNumeric<T>& u) { return u; } - - private: - template <typename NumericType> - struct UnderlyingType { - using type = NumericType; - }; - - template <typename NumericType> - struct UnderlyingType<CheckedNumeric<NumericType>> { - using type = NumericType; - }; - - CheckedNumericState<T> state_; -}; - -// This is the boilerplate for the standard arithmetic operator overloads. A -// macro isn't the prettiest solution, but it beats rewriting these five times. -// Some details worth noting are: -// * We apply the standard arithmetic promotions. -// * We skip range checks for floating points. -// * We skip range checks for destination integers with sufficient range. -// TODO(jschuh): extract these out into templates. -#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ - /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ - template <typename T> \ - CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \ - const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \ - typedef typename ArithmeticPromotion<T>::type Promotion; \ - /* Floating point always takes the fast path */ \ - if (std::numeric_limits<T>::is_iec559) \ - return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ - if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \ - return CheckedNumeric<Promotion>( \ - lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ - GetRangeConstraint(rhs.validity() | lhs.validity())); \ - RangeConstraint validity = RANGE_VALID; \ - T result = static_cast<T>(Checked##NAME( \ - static_cast<Promotion>(lhs.ValueUnsafe()), \ - static_cast<Promotion>(rhs.ValueUnsafe()), \ - &validity)); \ - return CheckedNumeric<Promotion>( \ - result, \ - GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \ - } \ - /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ - template <typename T> \ - template <typename Src> \ - CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \ - *this = CheckedNumeric<T>::cast(*this) \ - OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \ - return *this; \ - } \ - /* Binary arithmetic operator for CheckedNumeric of different type. */ \ - template <typename T, typename Src> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>( \ - lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ - GetRangeConstraint(rhs.validity() | lhs.validity())); \ - return CheckedNumeric<Promotion>::cast(lhs) \ - OP CheckedNumeric<Promotion>::cast(rhs); \ - } \ - /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ - template <typename T, typename Src> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - const CheckedNumeric<T>& lhs, Src rhs) { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, \ - lhs.validity()); \ - return CheckedNumeric<Promotion>::cast(lhs) \ - OP CheckedNumeric<Promotion>::cast(rhs); \ - } \ - /* Binary arithmetic operator for right numeric and left CheckedNumeric. */ \ - template <typename T, typename Src> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - Src lhs, const CheckedNumeric<T>& rhs) { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), \ - rhs.validity()); \ - return CheckedNumeric<Promotion>::cast(lhs) \ - OP CheckedNumeric<Promotion>::cast(rhs); \ - } - -BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, += ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %= ) - -#undef BASE_NUMERIC_ARITHMETIC_OPERATORS - -} // namespace internal - -using internal::CheckedNumeric; - -} // namespace base - -#endif // BASE_NUMERICS_SAFE_MATH_H_ diff --git a/security/sandbox/chromium/base/numerics/safe_math_impl.h b/security/sandbox/chromium/base/numerics/safe_math_impl.h deleted file mode 100644 index 4fbcc045b..000000000 --- a/security/sandbox/chromium/base/numerics/safe_math_impl.h +++ /dev/null @@ -1,545 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_ -#define BASE_NUMERICS_SAFE_MATH_IMPL_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <cmath> -#include <cstdlib> -#include <limits> -#include <type_traits> - -#include "base/numerics/safe_conversions.h" -#include "base/template_util.h" - -namespace base { -namespace internal { - -// Everything from here up to the floating point operations is portable C++, -// but it may not be fast. This code could be split based on -// platform/architecture and replaced with potentially faster implementations. - -// Integer promotion templates used by the portable checked integer arithmetic. -template <size_t Size, bool IsSigned> -struct IntegerForSizeAndSign; -template <> -struct IntegerForSizeAndSign<1, true> { - typedef int8_t type; -}; -template <> -struct IntegerForSizeAndSign<1, false> { - typedef uint8_t type; -}; -template <> -struct IntegerForSizeAndSign<2, true> { - typedef int16_t type; -}; -template <> -struct IntegerForSizeAndSign<2, false> { - typedef uint16_t type; -}; -template <> -struct IntegerForSizeAndSign<4, true> { - typedef int32_t type; -}; -template <> -struct IntegerForSizeAndSign<4, false> { - typedef uint32_t type; -}; -template <> -struct IntegerForSizeAndSign<8, true> { - typedef int64_t type; -}; -template <> -struct IntegerForSizeAndSign<8, false> { - typedef uint64_t type; -}; - -// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to -// support 128-bit math, then the ArithmeticPromotion template below will need -// to be updated (or more likely replaced with a decltype expression). - -template <typename Integer> -struct UnsignedIntegerForSize { - typedef typename std::enable_if< - std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type type; -}; - -template <typename Integer> -struct SignedIntegerForSize { - typedef typename std::enable_if< - std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type type; -}; - -template <typename Integer> -struct TwiceWiderInteger { - typedef typename std::enable_if< - std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign< - sizeof(Integer) * 2, - std::numeric_limits<Integer>::is_signed>::type>::type type; -}; - -template <typename Integer> -struct PositionOfSignBit { - static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, - size_t>::type value = - 8 * sizeof(Integer) - 1; -}; - -// This is used for UnsignedAbs, where we need to support floating-point -// template instantiations even though we don't actually support the operations. -// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs, -// so the float versions will not compile. -template <typename Numeric, - bool IsInteger = std::numeric_limits<Numeric>::is_integer, - bool IsFloat = std::numeric_limits<Numeric>::is_iec559> -struct UnsignedOrFloatForSize; - -template <typename Numeric> -struct UnsignedOrFloatForSize<Numeric, true, false> { - typedef typename UnsignedIntegerForSize<Numeric>::type type; -}; - -template <typename Numeric> -struct UnsignedOrFloatForSize<Numeric, false, true> { - typedef Numeric type; -}; - -// Helper templates for integer manipulations. - -template <typename T> -bool HasSignBit(T x) { - // Cast to unsigned since right shift on signed is undefined. - return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >> - PositionOfSignBit<T>::value); -} - -// This wrapper undoes the standard integer promotions. -template <typename T> -T BinaryComplement(T x) { - return ~x; -} - -// Here are the actual portable checked integer math implementations. -// TODO(jschuh): Break this code out from the enable_if pattern and find a clean -// way to coalesce things into the CheckedNumericState specializations below. - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type -CheckedAdd(T x, T y, RangeConstraint* validity) { - // Since the value of x+y is undefined if we have a signed type, we compute - // it using the unsigned type of the same size. - typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; - UnsignedDst ux = static_cast<UnsignedDst>(x); - UnsignedDst uy = static_cast<UnsignedDst>(y); - UnsignedDst uresult = ux + uy; - // Addition is valid if the sign of (x + y) is equal to either that of x or - // that of y. - if (std::numeric_limits<T>::is_signed) { - if (HasSignBit(BinaryComplement((uresult ^ ux) & (uresult ^ uy)))) - *validity = RANGE_VALID; - else // Direction of wrap is inverse of result sign. - *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; - - } else { // Unsigned is either valid or overflow. - *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW; - } - return static_cast<T>(uresult); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type -CheckedSub(T x, T y, RangeConstraint* validity) { - // Since the value of x+y is undefined if we have a signed type, we compute - // it using the unsigned type of the same size. - typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; - UnsignedDst ux = static_cast<UnsignedDst>(x); - UnsignedDst uy = static_cast<UnsignedDst>(y); - UnsignedDst uresult = ux - uy; - // Subtraction is valid if either x and y have same sign, or (x-y) and x have - // the same sign. - if (std::numeric_limits<T>::is_signed) { - if (HasSignBit(BinaryComplement((uresult ^ ux) & (ux ^ uy)))) - *validity = RANGE_VALID; - else // Direction of wrap is inverse of result sign. - *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; - - } else { // Unsigned is either valid or underflow. - *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW; - } - return static_cast<T>(uresult); -} - -// Integer multiplication is a bit complicated. In the fast case we just -// we just promote to a twice wider type, and range check the result. In the -// slow case we need to manually check that the result won't be truncated by -// checking with division against the appropriate bound. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - sizeof(T) * 2 <= sizeof(uintmax_t), - T>::type -CheckedMul(T x, T y, RangeConstraint* validity) { - typedef typename TwiceWiderInteger<T>::type IntermediateType; - IntermediateType tmp = - static_cast<IntermediateType>(x) * static_cast<IntermediateType>(y); - *validity = DstRangeRelationToSrcRange<T>(tmp); - return static_cast<T>(tmp); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed && - (sizeof(T) * 2 > sizeof(uintmax_t)), - T>::type -CheckedMul(T x, T y, RangeConstraint* validity) { - // If either side is zero then the result will be zero. - if (!x || !y) { - return RANGE_VALID; - - } else if (x > 0) { - if (y > 0) - *validity = - x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW; - else - *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID - : RANGE_UNDERFLOW; - - } else { - if (y > 0) - *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID - : RANGE_UNDERFLOW; - else - *validity = - y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW; - } - - return x * y; -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed && - (sizeof(T) * 2 > sizeof(uintmax_t)), - T>::type -CheckedMul(T x, T y, RangeConstraint* validity) { - *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) - ? RANGE_VALID - : RANGE_OVERFLOW; - return x * y; -} - -// Division just requires a check for an invalid negation on signed min/-1. -template <typename T> -T CheckedDiv(T x, - T y, - RangeConstraint* validity, - typename std::enable_if<std::numeric_limits<T>::is_integer, - int>::type = 0) { - if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && - y == static_cast<T>(-1)) { - *validity = RANGE_OVERFLOW; - return std::numeric_limits<T>::min(); - } - - *validity = RANGE_VALID; - return x / y; -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, - T>::type -CheckedMod(T x, T y, RangeConstraint* validity) { - *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; - return x % y; -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, - T>::type -CheckedMod(T x, T y, RangeConstraint* validity) { - *validity = RANGE_VALID; - return x % y; -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, - T>::type -CheckedNeg(T value, RangeConstraint* validity) { - *validity = - value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; - // The negation of signed min is min, so catch that one. - return -value; -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, - T>::type -CheckedNeg(T value, RangeConstraint* validity) { - // The only legal unsigned negation is zero. - *validity = value ? RANGE_UNDERFLOW : RANGE_VALID; - return static_cast<T>( - -static_cast<typename SignedIntegerForSize<T>::type>(value)); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, - T>::type -CheckedAbs(T value, RangeConstraint* validity) { - *validity = - value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; - return static_cast<T>(std::abs(value)); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, - T>::type -CheckedAbs(T value, RangeConstraint* validity) { - // T is unsigned, so |value| must already be positive. - *validity = RANGE_VALID; - return value; -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, - typename UnsignedIntegerForSize<T>::type>::type -CheckedUnsignedAbs(T value) { - typedef typename UnsignedIntegerForSize<T>::type UnsignedT; - return value == std::numeric_limits<T>::min() - ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1 - : static_cast<UnsignedT>(std::abs(value)); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, - T>::type -CheckedUnsignedAbs(T value) { - // T is unsigned, so |value| must already be positive. - return value; -} - -// These are the floating point stubs that the compiler needs to see. Only the -// negation operation is ever called. -#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ - template <typename T> \ - typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type \ - Checked##NAME(T, T, RangeConstraint*) { \ - NOTREACHED(); \ - return 0; \ - } - -BASE_FLOAT_ARITHMETIC_STUBS(Add) -BASE_FLOAT_ARITHMETIC_STUBS(Sub) -BASE_FLOAT_ARITHMETIC_STUBS(Mul) -BASE_FLOAT_ARITHMETIC_STUBS(Div) -BASE_FLOAT_ARITHMETIC_STUBS(Mod) - -#undef BASE_FLOAT_ARITHMETIC_STUBS - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedNeg( - T value, - RangeConstraint*) { - return -value; -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedAbs( - T value, - RangeConstraint*) { - return std::abs(value); -} - -// Floats carry around their validity state with them, but integers do not. So, -// we wrap the underlying value in a specialization in order to hide that detail -// and expose an interface via accessors. -enum NumericRepresentation { - NUMERIC_INTEGER, - NUMERIC_FLOATING, - NUMERIC_UNKNOWN -}; - -template <typename NumericType> -struct GetNumericRepresentation { - static const NumericRepresentation value = - std::numeric_limits<NumericType>::is_integer - ? NUMERIC_INTEGER - : (std::numeric_limits<NumericType>::is_iec559 ? NUMERIC_FLOATING - : NUMERIC_UNKNOWN); -}; - -template <typename T, NumericRepresentation type = - GetNumericRepresentation<T>::value> -class CheckedNumericState {}; - -// Integrals require quite a bit of additional housekeeping to manage state. -template <typename T> -class CheckedNumericState<T, NUMERIC_INTEGER> { - private: - T value_; - RangeConstraint validity_; - - public: - template <typename Src, NumericRepresentation type> - friend class CheckedNumericState; - - CheckedNumericState() : value_(0), validity_(RANGE_VALID) {} - - template <typename Src> - CheckedNumericState(Src value, RangeConstraint validity) - : value_(static_cast<T>(value)), - validity_(GetRangeConstraint(validity | - DstRangeRelationToSrcRange<T>(value))) { - static_assert(std::numeric_limits<Src>::is_specialized, - "Argument must be numeric."); - } - - // Copy constructor. - template <typename Src> - CheckedNumericState(const CheckedNumericState<Src>& rhs) - : value_(static_cast<T>(rhs.value())), - validity_(GetRangeConstraint( - rhs.validity() | DstRangeRelationToSrcRange<T>(rhs.value()))) {} - - template <typename Src> - explicit CheckedNumericState( - Src value, - typename std::enable_if<std::numeric_limits<Src>::is_specialized, - int>::type = 0) - : value_(static_cast<T>(value)), - validity_(DstRangeRelationToSrcRange<T>(value)) {} - - RangeConstraint validity() const { return validity_; } - T value() const { return value_; } -}; - -// Floating points maintain their own validity, but need translation wrappers. -template <typename T> -class CheckedNumericState<T, NUMERIC_FLOATING> { - private: - T value_; - - public: - template <typename Src, NumericRepresentation type> - friend class CheckedNumericState; - - CheckedNumericState() : value_(0.0) {} - - template <typename Src> - CheckedNumericState( - Src value, - RangeConstraint validity, - typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = - 0) { - switch (DstRangeRelationToSrcRange<T>(value)) { - case RANGE_VALID: - value_ = static_cast<T>(value); - break; - - case RANGE_UNDERFLOW: - value_ = -std::numeric_limits<T>::infinity(); - break; - - case RANGE_OVERFLOW: - value_ = std::numeric_limits<T>::infinity(); - break; - - case RANGE_INVALID: - value_ = std::numeric_limits<T>::quiet_NaN(); - break; - - default: - NOTREACHED(); - } - } - - template <typename Src> - explicit CheckedNumericState( - Src value, - typename std::enable_if<std::numeric_limits<Src>::is_specialized, - int>::type = 0) - : value_(static_cast<T>(value)) {} - - // Copy constructor. - template <typename Src> - CheckedNumericState(const CheckedNumericState<Src>& rhs) - : value_(static_cast<T>(rhs.value())) {} - - RangeConstraint validity() const { - return GetRangeConstraint(value_ <= std::numeric_limits<T>::max(), - value_ >= -std::numeric_limits<T>::max()); - } - T value() const { return value_; } -}; - -// For integers less than 128-bit and floats 32-bit or larger, we can distil -// C/C++ arithmetic promotions down to two simple rules: -// 1. The type with the larger maximum exponent always takes precedence. -// 2. The resulting type must be promoted to at least an int. -// The following template specializations implement that promotion logic. -enum ArithmeticPromotionCategory { - LEFT_PROMOTION, - RIGHT_PROMOTION, - DEFAULT_PROMOTION -}; - -template <typename Lhs, - typename Rhs = Lhs, - ArithmeticPromotionCategory Promotion = - (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) - ? (MaxExponent<Lhs>::value > MaxExponent<int>::value - ? LEFT_PROMOTION - : DEFAULT_PROMOTION) - : (MaxExponent<Rhs>::value > MaxExponent<int>::value - ? RIGHT_PROMOTION - : DEFAULT_PROMOTION) > -struct ArithmeticPromotion; - -template <typename Lhs, typename Rhs> -struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION> { - typedef Lhs type; -}; - -template <typename Lhs, typename Rhs> -struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION> { - typedef Rhs type; -}; - -template <typename Lhs, typename Rhs> -struct ArithmeticPromotion<Lhs, Rhs, DEFAULT_PROMOTION> { - typedef int type; -}; - -// We can statically check if operations on the provided types can wrap, so we -// can skip the checked operations if they're not needed. So, for an integer we -// care if the destination type preserves the sign and is twice the width of -// the source. -template <typename T, typename Lhs, typename Rhs> -struct IsIntegerArithmeticSafe { - static const bool value = !std::numeric_limits<T>::is_iec559 && - StaticDstRangeRelationToSrcRange<T, Lhs>::value == - NUMERIC_RANGE_CONTAINED && - sizeof(T) >= (2 * sizeof(Lhs)) && - StaticDstRangeRelationToSrcRange<T, Rhs>::value != - NUMERIC_RANGE_CONTAINED && - sizeof(T) >= (2 * sizeof(Rhs)); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_ diff --git a/security/sandbox/chromium/base/os_compat_android.h b/security/sandbox/chromium/base/os_compat_android.h deleted file mode 100644 index 0f2544496..000000000 --- a/security/sandbox/chromium/base/os_compat_android.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_OS_COMPAT_ANDROID_H_ -#define BASE_OS_COMPAT_ANDROID_H_ - -#include <fcntl.h> -#include <sys/types.h> -#include <utime.h> - -// Not implemented in Bionic. -extern "C" int futimes(int fd, const struct timeval tv[2]); - -// Not exposed or implemented in Bionic. -extern "C" char* mkdtemp(char* path); - -// Android has no timegm(). -extern "C" time_t timegm(struct tm* const t); - -// The lockf() function is not available on Android; we translate to flock(). -#define F_LOCK LOCK_EX -#define F_ULOCK LOCK_UN -inline int lockf(int fd, int cmd, off_t ignored_len) { - return flock(fd, cmd); -} - -#endif // BASE_OS_COMPAT_ANDROID_H_ diff --git a/security/sandbox/chromium/base/path_service.h b/security/sandbox/chromium/base/path_service.h deleted file mode 100644 index c7f1abe71..000000000 --- a/security/sandbox/chromium/base/path_service.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_PATH_SERVICE_H_ -#define BASE_PATH_SERVICE_H_ - -#include <string> - -#include "base/base_export.h" -#include "base/base_paths.h" -#include "base/gtest_prod_util.h" -#include "build/build_config.h" - -namespace base { - -class FilePath; -class ScopedPathOverride; - -// The path service is a global table mapping keys to file system paths. It is -// OK to use this service from multiple threads. -// -class BASE_EXPORT PathService { - public: - // Retrieves a path to a special directory or file and places it into the - // string pointed to by 'path'. If you ask for a directory it is guaranteed - // to NOT have a path separator at the end. For example, "c:\windows\temp" - // Directories are also guaranteed to exist when this function succeeds. - // - // Returns true if the directory or file was successfully retrieved. On - // failure, 'path' will not be changed. - static bool Get(int key, FilePath* path); - - // Overrides the path to a special directory or file. This cannot be used to - // change the value of DIR_CURRENT, but that should be obvious. Also, if the - // path specifies a directory that does not exist, the directory will be - // created by this method. This method returns true if successful. - // - // If the given path is relative, then it will be resolved against - // DIR_CURRENT. - // - // WARNING: Consumers of PathService::Get may expect paths to be constant - // over the lifetime of the app, so this method should be used with caution. - // - // Unit tests generally should use ScopedPathOverride instead. Overrides from - // one test should not carry over to another. - static bool Override(int key, const FilePath& path); - - // This function does the same as PathService::Override but it takes extra - // parameters: - // - |is_absolute| indicates that |path| has already been expanded into an - // absolute path, otherwise MakeAbsoluteFilePath() will be used. This is - // useful to override paths that may not exist yet, since MakeAbsoluteFilePath - // fails for those. Note that MakeAbsoluteFilePath also expands symbolic - // links, even if path.IsAbsolute() is already true. - // - |create| guides whether the directory to be overriden must - // be created in case it doesn't exist already. - static bool OverrideAndCreateIfNeeded(int key, - const FilePath& path, - bool is_absolute, - bool create); - - // To extend the set of supported keys, you can register a path provider, - // which is just a function mirroring PathService::Get. The ProviderFunc - // returns false if it cannot provide a non-empty path for the given key. - // Otherwise, true is returned. - // - // WARNING: This function could be called on any thread from which the - // PathService is used, so a the ProviderFunc MUST BE THREADSAFE. - // - typedef bool (*ProviderFunc)(int, FilePath*); - - // Call to register a path provider. You must specify the range "[key_start, - // key_end)" of supported path keys. - static void RegisterProvider(ProviderFunc provider, - int key_start, - int key_end); - - // Disable internal cache. - static void DisableCache(); - - private: - friend class ScopedPathOverride; - FRIEND_TEST_ALL_PREFIXES(PathServiceTest, RemoveOverride); - - // Removes an override for a special directory or file. Returns true if there - // was an override to remove or false if none was present. - // NOTE: This function is intended to be used by tests only! - static bool RemoveOverride(int key); -}; - -} // namespace base - -// TODO(brettw) Convert all callers to using the base namespace and remove this. -using base::PathService; - -#endif // BASE_PATH_SERVICE_H_ diff --git a/security/sandbox/chromium/base/posix/eintr_wrapper.h b/security/sandbox/chromium/base/posix/eintr_wrapper.h deleted file mode 100644 index 5a5dc758a..000000000 --- a/security/sandbox/chromium/base/posix/eintr_wrapper.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This provides a wrapper around system calls which may be interrupted by a -// signal and return EINTR. See man 7 signal. -// To prevent long-lasting loops (which would likely be a bug, such as a signal -// that should be masked) to go unnoticed, there is a limit after which the -// caller will nonetheless see an EINTR in Debug builds. -// -// On Windows, this wrapper macro does nothing. -// -// Don't wrap close calls in HANDLE_EINTR. Use IGNORE_EINTR if the return -// value of close is significant. See http://crbug.com/269623. - -#ifndef BASE_POSIX_EINTR_WRAPPER_H_ -#define BASE_POSIX_EINTR_WRAPPER_H_ - -#include "build/build_config.h" - -#if defined(OS_POSIX) - -#include <errno.h> - -#if defined(NDEBUG) - -#define HANDLE_EINTR(x) ({ \ - decltype(x) eintr_wrapper_result; \ - do { \ - eintr_wrapper_result = (x); \ - } while (eintr_wrapper_result == -1 && errno == EINTR); \ - eintr_wrapper_result; \ -}) - -#else - -#define HANDLE_EINTR(x) ({ \ - int eintr_wrapper_counter = 0; \ - decltype(x) eintr_wrapper_result; \ - do { \ - eintr_wrapper_result = (x); \ - } while (eintr_wrapper_result == -1 && errno == EINTR && \ - eintr_wrapper_counter++ < 100); \ - eintr_wrapper_result; \ -}) - -#endif // NDEBUG - -#define IGNORE_EINTR(x) ({ \ - decltype(x) eintr_wrapper_result; \ - do { \ - eintr_wrapper_result = (x); \ - if (eintr_wrapper_result == -1 && errno == EINTR) { \ - eintr_wrapper_result = 0; \ - } \ - } while (0); \ - eintr_wrapper_result; \ -}) - -#else - -#define HANDLE_EINTR(x) (x) -#define IGNORE_EINTR(x) (x) - -#endif // OS_POSIX - -#endif // BASE_POSIX_EINTR_WRAPPER_H_ diff --git a/security/sandbox/chromium/base/process/process_handle.h b/security/sandbox/chromium/base/process/process_handle.h deleted file mode 100644 index ef7a60255..000000000 --- a/security/sandbox/chromium/base/process/process_handle.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_PROCESS_PROCESS_HANDLE_H_ -#define BASE_PROCESS_PROCESS_HANDLE_H_ - -#include <stdint.h> -#include <sys/types.h> - -#include "base/base_export.h" -#include "base/files/file_path.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#endif - -namespace base { - -// ProcessHandle is a platform specific type which represents the underlying OS -// handle to a process. -// ProcessId is a number which identifies the process in the OS. -#if defined(OS_WIN) -typedef HANDLE ProcessHandle; -typedef DWORD ProcessId; -typedef HANDLE UserTokenHandle; -const ProcessHandle kNullProcessHandle = NULL; -const ProcessId kNullProcessId = 0; -#elif defined(OS_POSIX) -// On POSIX, our ProcessHandle will just be the PID. -typedef pid_t ProcessHandle; -typedef pid_t ProcessId; -const ProcessHandle kNullProcessHandle = 0; -const ProcessId kNullProcessId = 0; -#endif // defined(OS_WIN) - -// Returns the id of the current process. -// Note that on some platforms, this is not guaranteed to be unique across -// processes (use GetUniqueIdForProcess if uniqueness is required). -BASE_EXPORT ProcessId GetCurrentProcId(); - -// Returns a unique ID for the current process. The ID will be unique across all -// currently running processes within the chrome session, but IDs of terminated -// processes may be reused. This returns an opaque value that is different from -// a process's PID. -BASE_EXPORT uint32_t GetUniqueIdForProcess(); - -#if defined(OS_LINUX) -// When a process is started in a different PID namespace from the browser -// process, this function must be called with the process's PID in the browser's -// PID namespace in order to initialize its unique ID. Not thread safe. -// WARNING: To avoid inconsistent results from GetUniqueIdForProcess, this -// should only be called very early after process startup - ideally as soon -// after process creation as possible. -BASE_EXPORT void InitUniqueIdForProcessInPidNamespace( - ProcessId pid_outside_of_namespace); -#endif - -// Returns the ProcessHandle of the current process. -BASE_EXPORT ProcessHandle GetCurrentProcessHandle(); - -// Returns the process ID for the specified process. This is functionally the -// same as Windows' GetProcessId(), but works on versions of Windows before Win -// XP SP1 as well. -// DEPRECATED. New code should be using Process::Pid() instead. -// Note that on some platforms, this is not guaranteed to be unique across -// processes. -BASE_EXPORT ProcessId GetProcId(ProcessHandle process); - -// Returns the ID for the parent of the given process. -BASE_EXPORT ProcessId GetParentProcessId(ProcessHandle process); - -#if defined(OS_POSIX) -// Returns the path to the executable of the given process. -BASE_EXPORT FilePath GetProcessExecutablePath(ProcessHandle process); -#endif - -} // namespace base - -#endif // BASE_PROCESS_PROCESS_HANDLE_H_ diff --git a/security/sandbox/chromium/base/rand_util.h b/security/sandbox/chromium/base/rand_util.h deleted file mode 100644 index 881dbd50b..000000000 --- a/security/sandbox/chromium/base/rand_util.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_RAND_UTIL_H_ -#define BASE_RAND_UTIL_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <string> - -#include "base/base_export.h" -#include "build/build_config.h" - -namespace base { - -// Returns a random number in range [0, UINT64_MAX]. Thread-safe. -BASE_EXPORT uint64_t RandUint64(); - -// Returns a random number between min and max (inclusive). Thread-safe. -BASE_EXPORT int RandInt(int min, int max); - -// Returns a random number in range [0, range). Thread-safe. -// -// Note that this can be used as an adapter for std::random_shuffle(): -// Given a pre-populated |std::vector<int> myvector|, shuffle it as -// std::random_shuffle(myvector.begin(), myvector.end(), base::RandGenerator); -BASE_EXPORT uint64_t RandGenerator(uint64_t range); - -// Returns a random double in range [0, 1). Thread-safe. -BASE_EXPORT double RandDouble(); - -// Given input |bits|, convert with maximum precision to a double in -// the range [0, 1). Thread-safe. -BASE_EXPORT double BitsToOpenEndedUnitInterval(uint64_t bits); - -// Fills |output_length| bytes of |output| with random data. -// -// WARNING: -// Do not use for security-sensitive purposes. -// See crypto/ for cryptographically secure random number generation APIs. -BASE_EXPORT void RandBytes(void* output, size_t output_length); - -// Fills a string of length |length| with random data and returns it. -// |length| should be nonzero. -// -// Note that this is a variation of |RandBytes| with a different return type. -// The returned string is likely not ASCII/UTF-8. Use with care. -// -// WARNING: -// Do not use for security-sensitive purposes. -// See crypto/ for cryptographically secure random number generation APIs. -BASE_EXPORT std::string RandBytesAsString(size_t length); - -#if defined(OS_POSIX) -BASE_EXPORT int GetUrandomFD(); -#endif - -} // namespace base - -#endif // BASE_RAND_UTIL_H_ diff --git a/security/sandbox/chromium/base/scoped_clear_errno.h b/security/sandbox/chromium/base/scoped_clear_errno.h deleted file mode 100644 index 585f6f768..000000000 --- a/security/sandbox/chromium/base/scoped_clear_errno.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SCOPED_CLEAR_ERRNO_H_ -#define BASE_SCOPED_CLEAR_ERRNO_H_ - -#include <errno.h> - -#include "base/macros.h" - -namespace base { - -// Simple scoper that saves the current value of errno, resets it to 0, and on -// destruction puts the old value back. -class ScopedClearErrno { - public: - ScopedClearErrno() : old_errno_(errno) { - errno = 0; - } - ~ScopedClearErrno() { - if (errno == 0) - errno = old_errno_; - } - - private: - const int old_errno_; - - DISALLOW_COPY_AND_ASSIGN(ScopedClearErrno); -}; - -} // namespace base - -#endif // BASE_SCOPED_CLEAR_ERRNO_H_ diff --git a/security/sandbox/chromium/base/sequence_checker.h b/security/sandbox/chromium/base/sequence_checker.h deleted file mode 100644 index ad0182825..000000000 --- a/security/sandbox/chromium/base/sequence_checker.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SEQUENCE_CHECKER_H_ -#define BASE_SEQUENCE_CHECKER_H_ - -// See comments for the similar block in thread_checker.h. -#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) -#define ENABLE_SEQUENCE_CHECKER 1 -#else -#define ENABLE_SEQUENCE_CHECKER 0 -#endif - -#include "base/sequence_checker_impl.h" - -namespace base { - -// Do nothing implementation, for use in release mode. -// -// Note: You should almost always use the SequenceChecker class to get -// the right version for your build configuration. -class SequenceCheckerDoNothing { - public: - bool CalledOnValidSequencedThread() const { - return true; - } - - void DetachFromSequence() {} -}; - -// SequenceChecker is a helper class used to help verify that some -// methods of a class are called in sequence -- that is, called from -// the same SequencedTaskRunner. It is a generalization of -// ThreadChecker; see comments in sequence_checker_impl.h for details. -// -// Example: -// class MyClass { -// public: -// void Foo() { -// DCHECK(sequence_checker_.CalledOnValidSequencedThread()); -// ... (do stuff) ... -// } -// -// private: -// SequenceChecker sequence_checker_; -// } -// -// In Release mode, CalledOnValidSequencedThread() will always return true. -#if ENABLE_SEQUENCE_CHECKER -class SequenceChecker : public SequenceCheckerImpl { -}; -#else -class SequenceChecker : public SequenceCheckerDoNothing { -}; -#endif // ENABLE_SEQUENCE_CHECKER - -#undef ENABLE_SEQUENCE_CHECKER - -} // namespace base - -#endif // BASE_SEQUENCE_CHECKER_H_ diff --git a/security/sandbox/chromium/base/sequence_checker_impl.h b/security/sandbox/chromium/base/sequence_checker_impl.h deleted file mode 100644 index e3c5fed50..000000000 --- a/security/sandbox/chromium/base/sequence_checker_impl.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SEQUENCE_CHECKER_IMPL_H_ -#define BASE_SEQUENCE_CHECKER_IMPL_H_ - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "base/threading/sequenced_worker_pool.h" -#include "base/threading/thread_checker_impl.h" - -namespace base { - -// SequenceCheckerImpl is used to help verify that some methods of a -// class are called in sequence -- that is, called from the same -// SequencedTaskRunner. It is a generalization of ThreadChecker; in -// particular, it behaves exactly like ThreadChecker if constructed -// on a thread that is not part of a SequencedWorkerPool. -class BASE_EXPORT SequenceCheckerImpl { - public: - SequenceCheckerImpl(); - ~SequenceCheckerImpl(); - - // Returns whether the we are being called on the same sequence token - // as previous calls. If there is no associated sequence, then returns - // whether we are being called on the underlying ThreadChecker's thread. - bool CalledOnValidSequencedThread() const; - - // Unbinds the checker from the currently associated sequence. The - // checker will be re-bound on the next call to CalledOnValidSequence(). - void DetachFromSequence(); - - private: - void EnsureSequenceTokenAssigned() const; - - // Guards all variables below. - mutable Lock lock_; - - // Used if |sequence_token_| is not valid. - ThreadCheckerImpl thread_checker_; - mutable bool sequence_token_assigned_; - - mutable SequencedWorkerPool::SequenceToken sequence_token_; - - DISALLOW_COPY_AND_ASSIGN(SequenceCheckerImpl); -}; - -} // namespace base - -#endif // BASE_SEQUENCE_CHECKER_IMPL_H_ diff --git a/security/sandbox/chromium/base/sequenced_task_runner.h b/security/sandbox/chromium/base/sequenced_task_runner.h deleted file mode 100644 index 6bb3f2b87..000000000 --- a/security/sandbox/chromium/base/sequenced_task_runner.h +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SEQUENCED_TASK_RUNNER_H_ -#define BASE_SEQUENCED_TASK_RUNNER_H_ - -#include "base/base_export.h" -#include "base/sequenced_task_runner_helpers.h" -#include "base/task_runner.h" - -namespace base { - -// A SequencedTaskRunner is a subclass of TaskRunner that provides -// additional guarantees on the order that tasks are started, as well -// as guarantees on when tasks are in sequence, i.e. one task finishes -// before the other one starts. -// -// Summary -// ------- -// Non-nested tasks with the same delay will run one by one in FIFO -// order. -// -// Detailed guarantees -// ------------------- -// -// SequencedTaskRunner also adds additional methods for posting -// non-nestable tasks. In general, an implementation of TaskRunner -// may expose task-running methods which are themselves callable from -// within tasks. A non-nestable task is one that is guaranteed to not -// be run from within an already-running task. Conversely, a nestable -// task (the default) is a task that can be run from within an -// already-running task. -// -// The guarantees of SequencedTaskRunner are as follows: -// -// - Given two tasks T2 and T1, T2 will start after T1 starts if: -// -// * T2 is posted after T1; and -// * T2 has equal or higher delay than T1; and -// * T2 is non-nestable or T1 is nestable. -// -// - If T2 will start after T1 starts by the above guarantee, then -// T2 will start after T1 finishes and is destroyed if: -// -// * T2 is non-nestable, or -// * T1 doesn't call any task-running methods. -// -// - If T2 will start after T1 finishes by the above guarantee, then -// all memory changes in T1 and T1's destruction will be visible -// to T2. -// -// - If T2 runs nested within T1 via a call to the task-running -// method M, then all memory changes in T1 up to the call to M -// will be visible to T2, and all memory changes in T2 will be -// visible to T1 from the return from M. -// -// Note that SequencedTaskRunner does not guarantee that tasks are run -// on a single dedicated thread, although the above guarantees provide -// most (but not all) of the same guarantees. If you do need to -// guarantee that tasks are run on a single dedicated thread, see -// SingleThreadTaskRunner (in single_thread_task_runner.h). -// -// Some corollaries to the above guarantees, assuming the tasks in -// question don't call any task-running methods: -// -// - Tasks posted via PostTask are run in FIFO order. -// -// - Tasks posted via PostNonNestableTask are run in FIFO order. -// -// - Tasks posted with the same delay and the same nestable state -// are run in FIFO order. -// -// - A list of tasks with the same nestable state posted in order of -// non-decreasing delay is run in FIFO order. -// -// - A list of tasks posted in order of non-decreasing delay with at -// most a single change in nestable state from nestable to -// non-nestable is run in FIFO order. (This is equivalent to the -// statement of the first guarantee above.) -// -// Some theoretical implementations of SequencedTaskRunner: -// -// - A SequencedTaskRunner that wraps a regular TaskRunner but makes -// sure that only one task at a time is posted to the TaskRunner, -// with appropriate memory barriers in between tasks. -// -// - A SequencedTaskRunner that, for each task, spawns a joinable -// thread to run that task and immediately quit, and then -// immediately joins that thread. -// -// - A SequencedTaskRunner that stores the list of posted tasks and -// has a method Run() that runs each runnable task in FIFO order -// that can be called from any thread, but only if another -// (non-nested) Run() call isn't already happening. -class BASE_EXPORT SequencedTaskRunner : public TaskRunner { - public: - // The two PostNonNestable*Task methods below are like their - // nestable equivalents in TaskRunner, but they guarantee that the - // posted task will not run nested within an already-running task. - // - // A simple corollary is that posting a task as non-nestable can - // only delay when the task gets run. That is, posting a task as - // non-nestable may not affect when the task gets run, or it could - // make it run later than it normally would, but it won't make it - // run earlier than it normally would. - - // TODO(akalin): Get rid of the boolean return value for the methods - // below. - - bool PostNonNestableTask(const tracked_objects::Location& from_here, - const Closure& task); - - virtual bool PostNonNestableDelayedTask( - const tracked_objects::Location& from_here, - const Closure& task, - base::TimeDelta delay) = 0; - - // Submits a non-nestable task to delete the given object. Returns - // true if the object may be deleted at some point in the future, - // and false if the object definitely will not be deleted. - template <class T> - bool DeleteSoon(const tracked_objects::Location& from_here, - const T* object) { - return - subtle::DeleteHelperInternal<T, bool>::DeleteViaSequencedTaskRunner( - this, from_here, object); - } - - // Submits a non-nestable task to release the given object. Returns - // true if the object may be released at some point in the future, - // and false if the object definitely will not be released. - template <class T> - bool ReleaseSoon(const tracked_objects::Location& from_here, - T* object) { - return - subtle::ReleaseHelperInternal<T, bool>::ReleaseViaSequencedTaskRunner( - this, from_here, object); - } - - protected: - ~SequencedTaskRunner() override {} - - private: - template <class T, class R> friend class subtle::DeleteHelperInternal; - template <class T, class R> friend class subtle::ReleaseHelperInternal; - - bool DeleteSoonInternal(const tracked_objects::Location& from_here, - void(*deleter)(const void*), - const void* object); - - bool ReleaseSoonInternal(const tracked_objects::Location& from_here, - void(*releaser)(const void*), - const void* object); -}; - -} // namespace base - -#endif // BASE_SEQUENCED_TASK_RUNNER_H_ diff --git a/security/sandbox/chromium/base/sequenced_task_runner_helpers.h b/security/sandbox/chromium/base/sequenced_task_runner_helpers.h deleted file mode 100644 index 7980b46b6..000000000 --- a/security/sandbox/chromium/base/sequenced_task_runner_helpers.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ -#define BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ - -#include "base/debug/alias.h" -#include "base/macros.h" - -// TODO(akalin): Investigate whether it's possible to just have -// SequencedTaskRunner use these helpers (instead of MessageLoop). -// Then we can just move these to sequenced_task_runner.h. - -namespace tracked_objects { -class Location; -} - -namespace base { - -namespace subtle { -template <class T, class R> class DeleteHelperInternal; -template <class T, class R> class ReleaseHelperInternal; -} - -// Template helpers which use function indirection to erase T from the -// function signature while still remembering it so we can call the -// correct destructor/release function. -// -// We use this trick so we don't need to include bind.h in a header -// file like sequenced_task_runner.h. We also wrap the helpers in a -// templated class to make it easier for users of DeleteSoon to -// declare the helper as a friend. -template <class T> -class DeleteHelper { - private: - template <class T2, class R> friend class subtle::DeleteHelperInternal; - - static void DoDelete(const void* object) { - delete reinterpret_cast<const T*>(object); - } - - DISALLOW_COPY_AND_ASSIGN(DeleteHelper); -}; - -template <class T> -class ReleaseHelper { - private: - template <class T2, class R> friend class subtle::ReleaseHelperInternal; - - static void DoRelease(const void* object) { - reinterpret_cast<const T*>(object)->Release(); - } - - DISALLOW_COPY_AND_ASSIGN(ReleaseHelper); -}; - -namespace subtle { - -// An internal SequencedTaskRunner-like class helper for DeleteHelper -// and ReleaseHelper. We don't want to expose the Do*() functions -// directly directly since the void* argument makes it possible to -// pass/ an object of the wrong type to delete. Instead, we force -// callers to go through these internal helpers for type -// safety. SequencedTaskRunner-like classes which expose DeleteSoon or -// ReleaseSoon methods should friend the appropriate helper and -// implement a corresponding *Internal method with the following -// signature: -// -// bool(const tracked_objects::Location&, -// void(*function)(const void*), -// void* object) -// -// An implementation of this function should simply create a -// base::Closure from (function, object) and return the result of -// posting the task. -template <class T, class ReturnType> -class DeleteHelperInternal { - public: - template <class SequencedTaskRunnerType> - static ReturnType DeleteViaSequencedTaskRunner( - SequencedTaskRunnerType* sequenced_task_runner, - const tracked_objects::Location& from_here, - const T* object) { - return sequenced_task_runner->DeleteSoonInternal( - from_here, &DeleteHelper<T>::DoDelete, object); - } - - private: - DISALLOW_COPY_AND_ASSIGN(DeleteHelperInternal); -}; - -template <class T, class ReturnType> -class ReleaseHelperInternal { - public: - template <class SequencedTaskRunnerType> - static ReturnType ReleaseViaSequencedTaskRunner( - SequencedTaskRunnerType* sequenced_task_runner, - const tracked_objects::Location& from_here, - const T* object) { - return sequenced_task_runner->ReleaseSoonInternal( - from_here, &ReleaseHelper<T>::DoRelease, object); - } - - private: - DISALLOW_COPY_AND_ASSIGN(ReleaseHelperInternal); -}; - -} // namespace subtle - -} // namespace base - -#endif // BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ diff --git a/security/sandbox/chromium/base/single_thread_task_runner.h b/security/sandbox/chromium/base/single_thread_task_runner.h deleted file mode 100644 index 6e9319314..000000000 --- a/security/sandbox/chromium/base/single_thread_task_runner.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SINGLE_THREAD_TASK_RUNNER_H_ -#define BASE_SINGLE_THREAD_TASK_RUNNER_H_ - -#include "base/base_export.h" -#include "base/sequenced_task_runner.h" - -namespace base { - -// A SingleThreadTaskRunner is a SequencedTaskRunner with one more -// guarantee; namely, that all tasks are run on a single dedicated -// thread. Most use cases require only a SequencedTaskRunner, unless -// there is a specific need to run tasks on only a single thread. -// -// SingleThreadTaskRunner implementations might: -// - Post tasks to an existing thread's MessageLoop (see -// MessageLoop::task_runner()). -// - Create their own worker thread and MessageLoop to post tasks to. -// - Add tasks to a FIFO and signal to a non-MessageLoop thread for them to -// be processed. This allows TaskRunner-oriented code run on threads -// running other kinds of message loop, e.g. Jingle threads. -class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner { - public: - // A more explicit alias to RunsTasksOnCurrentThread(). - bool BelongsToCurrentThread() const { - return RunsTasksOnCurrentThread(); - } - - protected: - ~SingleThreadTaskRunner() override {} -}; - -} // namespace base - -#endif // BASE_SINGLE_THREAD_TASK_RUNNER_H_ diff --git a/security/sandbox/chromium/base/stl_util.h b/security/sandbox/chromium/base/stl_util.h deleted file mode 100644 index 12e226a9d..000000000 --- a/security/sandbox/chromium/base/stl_util.h +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Derived from google3/util/gtl/stl_util.h - -#ifndef BASE_STL_UTIL_H_ -#define BASE_STL_UTIL_H_ - -#include <algorithm> -#include <functional> -#include <iterator> -#include <string> -#include <vector> - -#include "base/logging.h" - -// Clears internal memory of an STL object. -// STL clear()/reserve(0) does not always free internal memory allocated -// This function uses swap/destructor to ensure the internal memory is freed. -template<class T> -void STLClearObject(T* obj) { - T tmp; - tmp.swap(*obj); - // Sometimes "T tmp" allocates objects with memory (arena implementation?). - // Hence using additional reserve(0) even if it doesn't always work. - obj->reserve(0); -} - -// For a range within a container of pointers, calls delete (non-array version) -// on these pointers. -// NOTE: for these three functions, we could just implement a DeleteObject -// functor and then call for_each() on the range and functor, but this -// requires us to pull in all of algorithm.h, which seems expensive. -// For hash_[multi]set, it is important that this deletes behind the iterator -// because the hash_set may call the hash function on the iterator when it is -// advanced, which could result in the hash function trying to deference a -// stale pointer. -template <class ForwardIterator> -void STLDeleteContainerPointers(ForwardIterator begin, ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete *temp; - } -} - -// For a range within a container of pairs, calls delete (non-array version) on -// BOTH items in the pairs. -// NOTE: Like STLDeleteContainerPointers, it is important that this deletes -// behind the iterator because if both the key and value are deleted, the -// container may call the hash function on the iterator when it is advanced, -// which could result in the hash function trying to dereference a stale -// pointer. -template <class ForwardIterator> -void STLDeleteContainerPairPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->first; - delete temp->second; - } -} - -// For a range within a container of pairs, calls delete (non-array version) on -// the FIRST item in the pairs. -// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator. -template <class ForwardIterator> -void STLDeleteContainerPairFirstPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->first; - } -} - -// For a range within a container of pairs, calls delete. -// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator. -// Deleting the value does not always invalidate the iterator, but it may -// do so if the key is a pointer into the value object. -template <class ForwardIterator> -void STLDeleteContainerPairSecondPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->second; - } -} - -// Counts the number of instances of val in a container. -template <typename Container, typename T> -typename std::iterator_traits< - typename Container::const_iterator>::difference_type -STLCount(const Container& container, const T& val) { - return std::count(container.begin(), container.end(), val); -} - -// Return a mutable char* pointing to a string's internal buffer, -// which may not be null-terminated. Writing through this pointer will -// modify the string. -// -// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the -// next call to a string method that invalidates iterators. -// -// As of 2006-04, there is no standard-blessed way of getting a -// mutable reference to a string's internal buffer. However, issue 530 -// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) -// proposes this as the method. According to Matt Austern, this should -// already work on all current implementations. -inline char* string_as_array(std::string* str) { - // DO NOT USE const_cast<char*>(str->data()) - return str->empty() ? NULL : &*str->begin(); -} - -// The following functions are useful for cleaning up STL containers whose -// elements point to allocated memory. - -// STLDeleteElements() deletes all the elements in an STL container and clears -// the container. This function is suitable for use with a vector, set, -// hash_set, or any other STL container which defines sensible begin(), end(), -// and clear() methods. -// -// If container is NULL, this function is a no-op. -// -// As an alternative to calling STLDeleteElements() directly, consider -// STLElementDeleter (defined below), which ensures that your container's -// elements are deleted when the STLElementDeleter goes out of scope. -template <class T> -void STLDeleteElements(T* container) { - if (!container) - return; - STLDeleteContainerPointers(container->begin(), container->end()); - container->clear(); -} - -// Given an STL container consisting of (key, value) pairs, STLDeleteValues -// deletes all the "value" components and clears the container. Does nothing -// in the case it's given a NULL pointer. -template <class T> -void STLDeleteValues(T* container) { - if (!container) - return; - STLDeleteContainerPairSecondPointers(container->begin(), container->end()); - container->clear(); -} - - -// The following classes provide a convenient way to delete all elements or -// values from STL containers when they goes out of scope. This greatly -// simplifies code that creates temporary objects and has multiple return -// statements. Example: -// -// vector<MyProto *> tmp_proto; -// STLElementDeleter<vector<MyProto *> > d(&tmp_proto); -// if (...) return false; -// ... -// return success; - -// Given a pointer to an STL container this class will delete all the element -// pointers when it goes out of scope. -template<class T> -class STLElementDeleter { - public: - STLElementDeleter<T>(T* container) : container_(container) {} - ~STLElementDeleter<T>() { STLDeleteElements(container_); } - - private: - T* container_; -}; - -// Given a pointer to an STL container this class will delete all the value -// pointers when it goes out of scope. -template<class T> -class STLValueDeleter { - public: - STLValueDeleter<T>(T* container) : container_(container) {} - ~STLValueDeleter<T>() { STLDeleteValues(container_); } - - private: - T* container_; -}; - -// Test to see if a set, map, hash_set or hash_map contains a particular key. -// Returns true if the key is in the collection. -template <typename Collection, typename Key> -bool ContainsKey(const Collection& collection, const Key& key) { - return collection.find(key) != collection.end(); -} - -// Test to see if a collection like a vector contains a particular value. -// Returns true if the value is in the collection. -template <typename Collection, typename Value> -bool ContainsValue(const Collection& collection, const Value& value) { - return std::find(collection.begin(), collection.end(), value) != - collection.end(); -} - -namespace base { - -// Returns true if the container is sorted. -template <typename Container> -bool STLIsSorted(const Container& cont) { - // Note: Use reverse iterator on container to ensure we only require - // value_type to implement operator<. - return std::adjacent_find(cont.rbegin(), cont.rend(), - std::less<typename Container::value_type>()) - == cont.rend(); -} - -// Returns a new ResultType containing the difference of two sorted containers. -template <typename ResultType, typename Arg1, typename Arg2> -ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) { - DCHECK(STLIsSorted(a1)); - DCHECK(STLIsSorted(a2)); - ResultType difference; - std::set_difference(a1.begin(), a1.end(), - a2.begin(), a2.end(), - std::inserter(difference, difference.end())); - return difference; -} - -// Returns a new ResultType containing the union of two sorted containers. -template <typename ResultType, typename Arg1, typename Arg2> -ResultType STLSetUnion(const Arg1& a1, const Arg2& a2) { - DCHECK(STLIsSorted(a1)); - DCHECK(STLIsSorted(a2)); - ResultType result; - std::set_union(a1.begin(), a1.end(), - a2.begin(), a2.end(), - std::inserter(result, result.end())); - return result; -} - -// Returns a new ResultType containing the intersection of two sorted -// containers. -template <typename ResultType, typename Arg1, typename Arg2> -ResultType STLSetIntersection(const Arg1& a1, const Arg2& a2) { - DCHECK(STLIsSorted(a1)); - DCHECK(STLIsSorted(a2)); - ResultType result; - std::set_intersection(a1.begin(), a1.end(), - a2.begin(), a2.end(), - std::inserter(result, result.end())); - return result; -} - -// Returns true if the sorted container |a1| contains all elements of the sorted -// container |a2|. -template <typename Arg1, typename Arg2> -bool STLIncludes(const Arg1& a1, const Arg2& a2) { - DCHECK(STLIsSorted(a1)); - DCHECK(STLIsSorted(a2)); - return std::includes(a1.begin(), a1.end(), - a2.begin(), a2.end()); -} - -} // namespace base - -#endif // BASE_STL_UTIL_H_ diff --git a/security/sandbox/chromium/base/strings/nullable_string16.cc b/security/sandbox/chromium/base/strings/nullable_string16.cc deleted file mode 100644 index 07f81d433..000000000 --- a/security/sandbox/chromium/base/strings/nullable_string16.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/nullable_string16.h" - -#include <ostream> - -#include "base/strings/utf_string_conversions.h" - -namespace base { - -std::ostream& operator<<(std::ostream& out, const NullableString16& value) { - return value.is_null() ? out << "(null)" : out << UTF16ToUTF8(value.string()); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/strings/nullable_string16.h b/security/sandbox/chromium/base/strings/nullable_string16.h deleted file mode 100644 index 016c25c25..000000000 --- a/security/sandbox/chromium/base/strings/nullable_string16.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_NULLABLE_STRING16_H_ -#define BASE_STRINGS_NULLABLE_STRING16_H_ - -#include <iosfwd> - -#include "base/base_export.h" -#include "base/strings/string16.h" - -namespace base { - -// This class is a simple wrapper for string16 which also contains a null -// state. This should be used only where the difference between null and -// empty is meaningful. -class NullableString16 { - public: - NullableString16() : is_null_(true) { } - NullableString16(const string16& string, bool is_null) - : string_(string), is_null_(is_null) { - } - - const string16& string() const { return string_; } - bool is_null() const { return is_null_; } - - private: - string16 string_; - bool is_null_; -}; - -inline bool operator==(const NullableString16& a, const NullableString16& b) { - return a.is_null() == b.is_null() && a.string() == b.string(); -} - -inline bool operator!=(const NullableString16& a, const NullableString16& b) { - return !(a == b); -} - -BASE_EXPORT std::ostream& operator<<(std::ostream& out, - const NullableString16& value); - -} // namespace base - -#endif // BASE_STRINGS_NULLABLE_STRING16_H_ diff --git a/security/sandbox/chromium/base/strings/safe_sprintf.cc b/security/sandbox/chromium/base/strings/safe_sprintf.cc deleted file mode 100644 index a51c77827..000000000 --- a/security/sandbox/chromium/base/strings/safe_sprintf.cc +++ /dev/null @@ -1,686 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/safe_sprintf.h" - -#include <errno.h> -#include <string.h> - -#include <limits> - -#include "base/macros.h" -#include "build/build_config.h" - -#if !defined(NDEBUG) -// In debug builds, we use RAW_CHECK() to print useful error messages, if -// SafeSPrintf() is called with broken arguments. -// As our contract promises that SafeSPrintf() can be called from any -// restricted run-time context, it is not actually safe to call logging -// functions from it; and we only ever do so for debug builds and hope for the -// best. We should _never_ call any logging function other than RAW_CHECK(), -// and we should _never_ include any logging code that is active in production -// builds. Most notably, we should not include these logging functions in -// unofficial release builds, even though those builds would otherwise have -// DCHECKS() enabled. -// In other words; please do not remove the #ifdef around this #include. -// Instead, in production builds we opt for returning a degraded result, -// whenever an error is encountered. -// E.g. The broken function call -// SafeSPrintf("errno = %d (%x)", errno, strerror(errno)) -// will print something like -// errno = 13, (%x) -// instead of -// errno = 13 (Access denied) -// In most of the anticipated use cases, that's probably the preferred -// behavior. -#include "base/logging.h" -#define DEBUG_CHECK RAW_CHECK -#else -#define DEBUG_CHECK(x) do { if (x) { } } while (0) -#endif - -namespace base { -namespace strings { - -// The code in this file is extremely careful to be async-signal-safe. -// -// Most obviously, we avoid calling any code that could dynamically allocate -// memory. Doing so would almost certainly result in bugs and dead-locks. -// We also avoid calling any other STL functions that could have unintended -// side-effects involving memory allocation or access to other shared -// resources. -// -// But on top of that, we also avoid calling other library functions, as many -// of them have the side-effect of calling getenv() (in order to deal with -// localization) or accessing errno. The latter sounds benign, but there are -// several execution contexts where it isn't even possible to safely read let -// alone write errno. -// -// The stated design goal of the SafeSPrintf() function is that it can be -// called from any context that can safely call C or C++ code (i.e. anything -// that doesn't require assembly code). -// -// For a brief overview of some but not all of the issues with async-signal- -// safety, refer to: -// http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html - -namespace { -const size_t kSSizeMaxConst = ((size_t)(ssize_t)-1) >> 1; - -const char kUpCaseHexDigits[] = "0123456789ABCDEF"; -const char kDownCaseHexDigits[] = "0123456789abcdef"; -} - -#if defined(NDEBUG) -// We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(), -// but C++ doesn't allow us to do that for constants. Instead, we have to -// use careful casting and shifting. We later use a static_assert to -// verify that this worked correctly. -namespace { -const size_t kSSizeMax = kSSizeMaxConst; -} -#else // defined(NDEBUG) -// For efficiency, we really need kSSizeMax to be a constant. But for unit -// tests, it should be adjustable. This allows us to verify edge cases without -// having to fill the entire available address space. As a compromise, we make -// kSSizeMax adjustable in debug builds, and then only compile that particular -// part of the unit test in debug builds. -namespace { -static size_t kSSizeMax = kSSizeMaxConst; -} - -namespace internal { -void SetSafeSPrintfSSizeMaxForTest(size_t max) { - kSSizeMax = max; -} - -size_t GetSafeSPrintfSSizeMaxForTest() { - return kSSizeMax; -} -} -#endif // defined(NDEBUG) - -namespace { -class Buffer { - public: - // |buffer| is caller-allocated storage that SafeSPrintf() writes to. It - // has |size| bytes of writable storage. It is the caller's responsibility - // to ensure that the buffer is at least one byte in size, so that it fits - // the trailing NUL that will be added by the destructor. The buffer also - // must be smaller or equal to kSSizeMax in size. - Buffer(char* buffer, size_t size) - : buffer_(buffer), - size_(size - 1), // Account for trailing NUL byte - count_(0) { -// MSVS2013's standard library doesn't mark max() as constexpr yet. cl.exe -// supports static_cast but doesn't really implement constexpr yet so it doesn't -// complain, but clang does. -#if __cplusplus >= 201103 && !(defined(__clang__) && defined(OS_WIN)) - static_assert(kSSizeMaxConst == - static_cast<size_t>(std::numeric_limits<ssize_t>::max()), - "kSSizeMaxConst should be the max value of an ssize_t"); -#endif - DEBUG_CHECK(size > 0); - DEBUG_CHECK(size <= kSSizeMax); - } - - ~Buffer() { - // The code calling the constructor guaranteed that there was enough space - // to store a trailing NUL -- and in debug builds, we are actually - // verifying this with DEBUG_CHECK()s in the constructor. So, we can - // always unconditionally write the NUL byte in the destructor. We do not - // need to adjust the count_, as SafeSPrintf() copies snprintf() in not - // including the NUL byte in its return code. - *GetInsertionPoint() = '\000'; - } - - // Returns true, iff the buffer is filled all the way to |kSSizeMax-1|. The - // caller can now stop adding more data, as GetCount() has reached its - // maximum possible value. - inline bool OutOfAddressableSpace() const { - return count_ == static_cast<size_t>(kSSizeMax - 1); - } - - // Returns the number of bytes that would have been emitted to |buffer_| - // if it was sized sufficiently large. This number can be larger than - // |size_|, if the caller provided an insufficiently large output buffer. - // But it will never be bigger than |kSSizeMax-1|. - inline ssize_t GetCount() const { - DEBUG_CHECK(count_ < kSSizeMax); - return static_cast<ssize_t>(count_); - } - - // Emits one |ch| character into the |buffer_| and updates the |count_| of - // characters that are currently supposed to be in the buffer. - // Returns "false", iff the buffer was already full. - // N.B. |count_| increases even if no characters have been written. This is - // needed so that GetCount() can return the number of bytes that should - // have been allocated for the |buffer_|. - inline bool Out(char ch) { - if (size_ >= 1 && count_ < size_) { - buffer_[count_] = ch; - return IncrementCountByOne(); - } - // |count_| still needs to be updated, even if the buffer has been - // filled completely. This allows SafeSPrintf() to return the number of - // bytes that should have been emitted. - IncrementCountByOne(); - return false; - } - - // Inserts |padding|-|len| bytes worth of padding into the |buffer_|. - // |count_| will also be incremented by the number of bytes that were meant - // to be emitted. The |pad| character is typically either a ' ' space - // or a '0' zero, but other non-NUL values are legal. - // Returns "false", iff the the |buffer_| filled up (i.e. |count_| - // overflowed |size_|) at any time during padding. - inline bool Pad(char pad, size_t padding, size_t len) { - DEBUG_CHECK(pad); - DEBUG_CHECK(padding <= kSSizeMax); - for (; padding > len; --padding) { - if (!Out(pad)) { - if (--padding) { - IncrementCount(padding-len); - } - return false; - } - } - return true; - } - - // POSIX doesn't define any async-signal-safe function for converting - // an integer to ASCII. Define our own version. - // - // This also gives us the ability to make the function a little more - // powerful and have it deal with |padding|, with truncation, and with - // predicting the length of the untruncated output. - // - // IToASCII() converts an integer |i| to ASCII. - // - // Unlike similar functions in the standard C library, it never appends a - // NUL character. This is left for the caller to do. - // - // While the function signature takes a signed int64_t, the code decides at - // run-time whether to treat the argument as signed (int64_t) or as unsigned - // (uint64_t) based on the value of |sign|. - // - // It supports |base|s 2 through 16. Only a |base| of 10 is allowed to have - // a |sign|. Otherwise, |i| is treated as unsigned. - // - // For bases larger than 10, |upcase| decides whether lower-case or upper- - // case letters should be used to designate digits greater than 10. - // - // Padding can be done with either '0' zeros or ' ' spaces. Padding has to - // be positive and will always be applied to the left of the output. - // - // Prepends a |prefix| to the number (e.g. "0x"). This prefix goes to - // the left of |padding|, if |pad| is '0'; and to the right of |padding| - // if |pad| is ' '. - // - // Returns "false", if the |buffer_| overflowed at any time. - bool IToASCII(bool sign, bool upcase, int64_t i, int base, - char pad, size_t padding, const char* prefix); - - private: - // Increments |count_| by |inc| unless this would cause |count_| to - // overflow |kSSizeMax-1|. Returns "false", iff an overflow was detected; - // it then clamps |count_| to |kSSizeMax-1|. - inline bool IncrementCount(size_t inc) { - // "inc" is either 1 or a "padding" value. Padding is clamped at - // run-time to at most kSSizeMax-1. So, we know that "inc" is always in - // the range 1..kSSizeMax-1. - // This allows us to compute "kSSizeMax - 1 - inc" without incurring any - // integer overflows. - DEBUG_CHECK(inc <= kSSizeMax - 1); - if (count_ > kSSizeMax - 1 - inc) { - count_ = kSSizeMax - 1; - return false; - } else { - count_ += inc; - return true; - } - } - - // Convenience method for the common case of incrementing |count_| by one. - inline bool IncrementCountByOne() { - return IncrementCount(1); - } - - // Return the current insertion point into the buffer. This is typically - // at |buffer_| + |count_|, but could be before that if truncation - // happened. It always points to one byte past the last byte that was - // successfully placed into the |buffer_|. - inline char* GetInsertionPoint() const { - size_t idx = count_; - if (idx > size_) { - idx = size_; - } - return buffer_ + idx; - } - - // User-provided buffer that will receive the fully formatted output string. - char* buffer_; - - // Number of bytes that are available in the buffer excluding the trailing - // NUL byte that will be added by the destructor. - const size_t size_; - - // Number of bytes that would have been emitted to the buffer, if the buffer - // was sufficiently big. This number always excludes the trailing NUL byte - // and it is guaranteed to never grow bigger than kSSizeMax-1. - size_t count_; - - DISALLOW_COPY_AND_ASSIGN(Buffer); -}; - - -bool Buffer::IToASCII(bool sign, bool upcase, int64_t i, int base, - char pad, size_t padding, const char* prefix) { - // Sanity check for parameters. None of these should ever fail, but see - // above for the rationale why we can't call CHECK(). - DEBUG_CHECK(base >= 2); - DEBUG_CHECK(base <= 16); - DEBUG_CHECK(!sign || base == 10); - DEBUG_CHECK(pad == '0' || pad == ' '); - DEBUG_CHECK(padding <= kSSizeMax); - DEBUG_CHECK(!(sign && prefix && *prefix)); - - // Handle negative numbers, if the caller indicated that |i| should be - // treated as a signed number; otherwise treat |i| as unsigned (even if the - // MSB is set!) - // Details are tricky, because of limited data-types, but equivalent pseudo- - // code would look like: - // if (sign && i < 0) - // prefix = "-"; - // num = abs(i); - int minint = 0; - uint64_t num; - if (sign && i < 0) { - prefix = "-"; - - // Turn our number positive. - if (i == std::numeric_limits<int64_t>::min()) { - // The most negative integer needs special treatment. - minint = 1; - num = static_cast<uint64_t>(-(i + 1)); - } else { - // "Normal" negative numbers are easy. - num = static_cast<uint64_t>(-i); - } - } else { - num = static_cast<uint64_t>(i); - } - - // If padding with '0' zero, emit the prefix or '-' character now. Otherwise, - // make the prefix accessible in reverse order, so that we can later output - // it right between padding and the number. - // We cannot choose the easier approach of just reversing the number, as that - // fails in situations where we need to truncate numbers that have padding - // and/or prefixes. - const char* reverse_prefix = NULL; - if (prefix && *prefix) { - if (pad == '0') { - while (*prefix) { - if (padding) { - --padding; - } - Out(*prefix++); - } - prefix = NULL; - } else { - for (reverse_prefix = prefix; *reverse_prefix; ++reverse_prefix) { - } - } - } else - prefix = NULL; - const size_t prefix_length = reverse_prefix - prefix; - - // Loop until we have converted the entire number. Output at least one - // character (i.e. '0'). - size_t start = count_; - size_t discarded = 0; - bool started = false; - do { - // Make sure there is still enough space left in our output buffer. - if (count_ >= size_) { - if (start < size_) { - // It is rare that we need to output a partial number. But if asked - // to do so, we will still make sure we output the correct number of - // leading digits. - // Since we are generating the digits in reverse order, we actually - // have to discard digits in the order that we have already emitted - // them. This is essentially equivalent to: - // memmove(buffer_ + start, buffer_ + start + 1, size_ - start - 1) - for (char* move = buffer_ + start, *end = buffer_ + size_ - 1; - move < end; - ++move) { - *move = move[1]; - } - ++discarded; - --count_; - } else if (count_ - size_ > 1) { - // Need to increment either |count_| or |discarded| to make progress. - // The latter is more efficient, as it eventually triggers fast - // handling of padding. But we have to ensure we don't accidentally - // change the overall state (i.e. switch the state-machine from - // discarding to non-discarding). |count_| needs to always stay - // bigger than |size_|. - --count_; - ++discarded; - } - } - - // Output the next digit and (if necessary) compensate for the most - // negative integer needing special treatment. This works because, - // no matter the bit width of the integer, the lowest-most decimal - // integer always ends in 2, 4, 6, or 8. - if (!num && started) { - if (reverse_prefix > prefix) { - Out(*--reverse_prefix); - } else { - Out(pad); - } - } else { - started = true; - Out((upcase ? kUpCaseHexDigits : kDownCaseHexDigits)[num%base + minint]); - } - - minint = 0; - num /= base; - - // Add padding, if requested. - if (padding > 0) { - --padding; - - // Performance optimization for when we are asked to output excessive - // padding, but our output buffer is limited in size. Even if we output - // a 64bit number in binary, we would never write more than 64 plus - // prefix non-padding characters. So, once this limit has been passed, - // any further state change can be computed arithmetically; we know that - // by this time, our entire final output consists of padding characters - // that have all already been output. - if (discarded > 8*sizeof(num) + prefix_length) { - IncrementCount(padding); - padding = 0; - } - } - } while (num || padding || (reverse_prefix > prefix)); - - // Conversion to ASCII actually resulted in the digits being in reverse - // order. We can't easily generate them in forward order, as we can't tell - // the number of characters needed until we are done converting. - // So, now, we reverse the string (except for the possible '-' sign). - char* front = buffer_ + start; - char* back = GetInsertionPoint(); - while (--back > front) { - char ch = *back; - *back = *front; - *front++ = ch; - } - - IncrementCount(discarded); - return !discarded; -} - -} // anonymous namespace - -namespace internal { - -ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args, - const size_t max_args) { - // Make sure that at least one NUL byte can be written, and that the buffer - // never overflows kSSizeMax. Not only does that use up most or all of the - // address space, it also would result in a return code that cannot be - // represented. - if (static_cast<ssize_t>(sz) < 1) { - return -1; - } else if (sz > kSSizeMax) { - sz = kSSizeMax; - } - - // Iterate over format string and interpret '%' arguments as they are - // encountered. - Buffer buffer(buf, sz); - size_t padding; - char pad; - for (unsigned int cur_arg = 0; *fmt && !buffer.OutOfAddressableSpace(); ) { - if (*fmt++ == '%') { - padding = 0; - pad = ' '; - char ch = *fmt++; - format_character_found: - switch (ch) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - // Found a width parameter. Convert to an integer value and store in - // "padding". If the leading digit is a zero, change the padding - // character from a space ' ' to a zero '0'. - pad = ch == '0' ? '0' : ' '; - for (;;) { - // The maximum allowed padding fills all the available address - // space and leaves just enough space to insert the trailing NUL. - const size_t max_padding = kSSizeMax - 1; - if (padding > max_padding/10 || - 10*padding > max_padding - (ch - '0')) { - DEBUG_CHECK(padding <= max_padding/10 && - 10*padding <= max_padding - (ch - '0')); - // Integer overflow detected. Skip the rest of the width until - // we find the format character, then do the normal error handling. - padding_overflow: - padding = max_padding; - while ((ch = *fmt++) >= '0' && ch <= '9') { - } - if (cur_arg < max_args) { - ++cur_arg; - } - goto fail_to_expand; - } - padding = 10*padding + ch - '0'; - if (padding > max_padding) { - // This doesn't happen for "sane" values of kSSizeMax. But once - // kSSizeMax gets smaller than about 10, our earlier range checks - // are incomplete. Unittests do trigger this artificial corner - // case. - DEBUG_CHECK(padding <= max_padding); - goto padding_overflow; - } - ch = *fmt++; - if (ch < '0' || ch > '9') { - // Reached the end of the width parameter. This is where the format - // character is found. - goto format_character_found; - } - } - break; - case 'c': { // Output an ASCII character. - // Check that there are arguments left to be inserted. - if (cur_arg >= max_args) { - DEBUG_CHECK(cur_arg < max_args); - goto fail_to_expand; - } - - // Check that the argument has the expected type. - const Arg& arg = args[cur_arg++]; - if (arg.type != Arg::INT && arg.type != Arg::UINT) { - DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT); - goto fail_to_expand; - } - - // Apply padding, if needed. - buffer.Pad(' ', padding, 1); - - // Convert the argument to an ASCII character and output it. - char as_char = static_cast<char>(arg.integer.i); - if (!as_char) { - goto end_of_output_buffer; - } - buffer.Out(as_char); - break; } - case 'd': // Output a possibly signed decimal value. - case 'o': // Output an unsigned octal value. - case 'x': // Output an unsigned hexadecimal value. - case 'X': - case 'p': { // Output a pointer value. - // Check that there are arguments left to be inserted. - if (cur_arg >= max_args) { - DEBUG_CHECK(cur_arg < max_args); - goto fail_to_expand; - } - - const Arg& arg = args[cur_arg++]; - int64_t i; - const char* prefix = NULL; - if (ch != 'p') { - // Check that the argument has the expected type. - if (arg.type != Arg::INT && arg.type != Arg::UINT) { - DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT); - goto fail_to_expand; - } - i = arg.integer.i; - - if (ch != 'd') { - // The Arg() constructor automatically performed sign expansion on - // signed parameters. This is great when outputting a %d decimal - // number, but can result in unexpected leading 0xFF bytes when - // outputting a %x hexadecimal number. Mask bits, if necessary. - // We have to do this here, instead of in the Arg() constructor, as - // the Arg() constructor cannot tell whether we will output a %d - // or a %x. Only the latter should experience masking. - if (arg.integer.width < sizeof(int64_t)) { - i &= (1LL << (8*arg.integer.width)) - 1; - } - } - } else { - // Pointer values require an actual pointer or a string. - if (arg.type == Arg::POINTER) { - i = reinterpret_cast<uintptr_t>(arg.ptr); - } else if (arg.type == Arg::STRING) { - i = reinterpret_cast<uintptr_t>(arg.str); - } else if (arg.type == Arg::INT && - arg.integer.width == sizeof(NULL) && - arg.integer.i == 0) { // Allow C++'s version of NULL - i = 0; - } else { - DEBUG_CHECK(arg.type == Arg::POINTER || arg.type == Arg::STRING); - goto fail_to_expand; - } - - // Pointers always include the "0x" prefix. - prefix = "0x"; - } - - // Use IToASCII() to convert to ASCII representation. For decimal - // numbers, optionally print a sign. For hexadecimal numbers, - // distinguish between upper and lower case. %p addresses are always - // printed as upcase. Supports base 8, 10, and 16. Prints padding - // and/or prefixes, if so requested. - buffer.IToASCII(ch == 'd' && arg.type == Arg::INT, - ch != 'x', i, - ch == 'o' ? 8 : ch == 'd' ? 10 : 16, - pad, padding, prefix); - break; } - case 's': { - // Check that there are arguments left to be inserted. - if (cur_arg >= max_args) { - DEBUG_CHECK(cur_arg < max_args); - goto fail_to_expand; - } - - // Check that the argument has the expected type. - const Arg& arg = args[cur_arg++]; - const char *s; - if (arg.type == Arg::STRING) { - s = arg.str ? arg.str : "<NULL>"; - } else if (arg.type == Arg::INT && arg.integer.width == sizeof(NULL) && - arg.integer.i == 0) { // Allow C++'s version of NULL - s = "<NULL>"; - } else { - DEBUG_CHECK(arg.type == Arg::STRING); - goto fail_to_expand; - } - - // Apply padding, if needed. This requires us to first check the - // length of the string that we are outputting. - if (padding) { - size_t len = 0; - for (const char* src = s; *src++; ) { - ++len; - } - buffer.Pad(' ', padding, len); - } - - // Printing a string involves nothing more than copying it into the - // output buffer and making sure we don't output more bytes than - // available space; Out() takes care of doing that. - for (const char* src = s; *src; ) { - buffer.Out(*src++); - } - break; } - case '%': - // Quoted percent '%' character. - goto copy_verbatim; - fail_to_expand: - // C++ gives us tools to do type checking -- something that snprintf() - // could never really do. So, whenever we see arguments that don't - // match up with the format string, we refuse to output them. But - // since we have to be extremely conservative about being async- - // signal-safe, we are limited in the type of error handling that we - // can do in production builds (in debug builds we can use - // DEBUG_CHECK() and hope for the best). So, all we do is pass the - // format string unchanged. That should eventually get the user's - // attention; and in the meantime, it hopefully doesn't lose too much - // data. - default: - // Unknown or unsupported format character. Just copy verbatim to - // output. - buffer.Out('%'); - DEBUG_CHECK(ch); - if (!ch) { - goto end_of_format_string; - } - buffer.Out(ch); - break; - } - } else { - copy_verbatim: - buffer.Out(fmt[-1]); - } - } - end_of_format_string: - end_of_output_buffer: - return buffer.GetCount(); -} - -} // namespace internal - -ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt) { - // Make sure that at least one NUL byte can be written, and that the buffer - // never overflows kSSizeMax. Not only does that use up most or all of the - // address space, it also would result in a return code that cannot be - // represented. - if (static_cast<ssize_t>(sz) < 1) { - return -1; - } else if (sz > kSSizeMax) { - sz = kSSizeMax; - } - - Buffer buffer(buf, sz); - - // In the slow-path, we deal with errors by copying the contents of - // "fmt" unexpanded. This means, if there are no arguments passed, the - // SafeSPrintf() function always degenerates to a version of strncpy() that - // de-duplicates '%' characters. - const char* src = fmt; - for (; *src; ++src) { - buffer.Out(*src); - DEBUG_CHECK(src[0] != '%' || src[1] == '%'); - if (src[0] == '%' && src[1] == '%') { - ++src; - } - } - return buffer.GetCount(); -} - -} // namespace strings -} // namespace base diff --git a/security/sandbox/chromium/base/strings/safe_sprintf.h b/security/sandbox/chromium/base/strings/safe_sprintf.h deleted file mode 100644 index 65524a50c..000000000 --- a/security/sandbox/chromium/base/strings/safe_sprintf.h +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_SAFE_SPRINTF_H_ -#define BASE_STRINGS_SAFE_SPRINTF_H_ - -#include "build/build_config.h" - -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> - -#if defined(OS_POSIX) -// For ssize_t -#include <unistd.h> -#endif - -#include "base/base_export.h" - -namespace base { -namespace strings { - -#if defined(_MSC_VER) -// Define ssize_t inside of our namespace. -#if defined(_WIN64) -typedef __int64 ssize_t; -#else -typedef long ssize_t; -#endif -#endif - -// SafeSPrintf() is a type-safe and completely self-contained version of -// snprintf(). -// -// SafeSNPrintf() is an alternative function signature that can be used when -// not dealing with fixed-sized buffers. When possible, SafeSPrintf() should -// always be used instead of SafeSNPrintf() -// -// These functions allow for formatting complicated messages from contexts that -// require strict async-signal-safety. In fact, it is safe to call them from -// any low-level execution context, as they are guaranteed to make no library -// or system calls. It deliberately never touches "errno", either. -// -// The only exception to this rule is that in debug builds the code calls -// RAW_CHECK() to help diagnose problems when the format string does not -// match the rest of the arguments. In release builds, no CHECK()s are used, -// and SafeSPrintf() instead returns an output string that expands only -// those arguments that match their format characters. Mismatched arguments -// are ignored. -// -// The code currently only supports a subset of format characters: -// %c, %o, %d, %x, %X, %p, and %s. -// -// SafeSPrintf() aims to be as liberal as reasonably possible. Integer-like -// values of arbitrary width can be passed to all of the format characters -// that expect integers. Thus, it is explicitly legal to pass an "int" to -// "%c", and output will automatically look at the LSB only. It is also -// explicitly legal to pass either signed or unsigned values, and the format -// characters will automatically interpret the arguments accordingly. -// -// It is still not legal to mix-and-match integer-like values with pointer -// values. For instance, you cannot pass a pointer to %x, nor can you pass an -// integer to %p. -// -// The one exception is "0" zero being accepted by "%p". This works-around -// the problem of C++ defining NULL as an integer-like value. -// -// All format characters take an optional width parameter. This must be a -// positive integer. For %d, %o, %x, %X and %p, if the width starts with -// a leading '0', padding is done with '0' instead of ' ' characters. -// -// There are a few features of snprintf()-style format strings, that -// SafeSPrintf() does not support at this time. -// -// If an actual user showed up, there is no particularly strong reason they -// couldn't be added. But that assumes that the trade-offs between complexity -// and utility are favorable. -// -// For example, adding support for negative padding widths, and for %n are all -// likely to be viewed positively. They are all clearly useful, low-risk, easy -// to test, don't jeopardize the async-signal-safety of the code, and overall -// have little impact on other parts of SafeSPrintf() function. -// -// On the other hands, adding support for alternate forms, positional -// arguments, grouping, wide characters, localization or floating point numbers -// are all unlikely to ever be added. -// -// SafeSPrintf() and SafeSNPrintf() mimic the behavior of snprintf() and they -// return the number of bytes needed to store the untruncated output. This -// does *not* include the terminating NUL byte. -// -// They return -1, iff a fatal error happened. This typically can only happen, -// if the buffer size is a) negative, or b) zero (i.e. not even the NUL byte -// can be written). The return value can never be larger than SSIZE_MAX-1. -// This ensures that the caller can always add one to the signed return code -// in order to determine the amount of storage that needs to be allocated. -// -// While the code supports type checking and while it is generally very careful -// to avoid printing incorrect values, it tends to be conservative in printing -// as much as possible, even when given incorrect parameters. Typically, in -// case of an error, the format string will not be expanded. (i.e. something -// like SafeSPrintf(buf, "%p %d", 1, 2) results in "%p 2"). See above for -// the use of RAW_CHECK() in debug builds, though. -// -// Basic example: -// char buf[20]; -// base::strings::SafeSPrintf(buf, "The answer: %2d", 42); -// -// Example with dynamically sized buffer (async-signal-safe). This code won't -// work on Visual studio, as it requires dynamically allocating arrays on the -// stack. Consider picking a smaller value for |kMaxSize| if stack size is -// limited and known. On the other hand, if the parameters to SafeSNPrintf() -// are trusted and not controllable by the user, you can consider eliminating -// the check for |kMaxSize| altogether. The current value of SSIZE_MAX is -// essentially a no-op that just illustrates how to implement an upper bound: -// const size_t kInitialSize = 128; -// const size_t kMaxSize = std::numeric_limits<ssize_t>::max(); -// size_t size = kInitialSize; -// for (;;) { -// char buf[size]; -// size = SafeSNPrintf(buf, size, "Error message \"%s\"\n", err) + 1; -// if (sizeof(buf) < kMaxSize && size > kMaxSize) { -// size = kMaxSize; -// continue; -// } else if (size > sizeof(buf)) -// continue; -// write(2, buf, size-1); -// break; -// } - -namespace internal { -// Helpers that use C++ overloading, templates, and specializations to deduce -// and record type information from function arguments. This allows us to -// later write a type-safe version of snprintf(). - -struct Arg { - enum Type { INT, UINT, STRING, POINTER }; - - // Any integer-like value. - Arg(signed char c) : type(INT) { - integer.i = c; - integer.width = sizeof(char); - } - Arg(unsigned char c) : type(UINT) { - integer.i = c; - integer.width = sizeof(char); - } - Arg(signed short j) : type(INT) { - integer.i = j; - integer.width = sizeof(short); - } - Arg(unsigned short j) : type(UINT) { - integer.i = j; - integer.width = sizeof(short); - } - Arg(signed int j) : type(INT) { - integer.i = j; - integer.width = sizeof(int); - } - Arg(unsigned int j) : type(UINT) { - integer.i = j; - integer.width = sizeof(int); - } - Arg(signed long j) : type(INT) { - integer.i = j; - integer.width = sizeof(long); - } - Arg(unsigned long j) : type(UINT) { - integer.i = j; - integer.width = sizeof(long); - } - Arg(signed long long j) : type(INT) { - integer.i = j; - integer.width = sizeof(long long); - } - Arg(unsigned long long j) : type(UINT) { - integer.i = j; - integer.width = sizeof(long long); - } - - // A C-style text string. - Arg(const char* s) : str(s), type(STRING) { } - Arg(char* s) : str(s), type(STRING) { } - - // Any pointer value that can be cast to a "void*". - template<class T> Arg(T* p) : ptr((void*)p), type(POINTER) { } - - union { - // An integer-like value. - struct { - int64_t i; - unsigned char width; - } integer; - - // A C-style text string. - const char* str; - - // A pointer to an arbitrary object. - const void* ptr; - }; - const enum Type type; -}; - -// This is the internal function that performs the actual formatting of -// an snprintf()-style format string. -BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, - const Arg* args, size_t max_args); - -#if !defined(NDEBUG) -// In debug builds, allow unit tests to artificially lower the kSSizeMax -// constant that is used as a hard upper-bound for all buffers. In normal -// use, this constant should always be std::numeric_limits<ssize_t>::max(). -BASE_EXPORT void SetSafeSPrintfSSizeMaxForTest(size_t max); -BASE_EXPORT size_t GetSafeSPrintfSSizeMaxForTest(); -#endif - -} // namespace internal - -template<typename... Args> -ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, Args... args) { - // Use Arg() object to record type information and then copy arguments to an - // array to make it easier to iterate over them. - const internal::Arg arg_array[] = { args... }; - return internal::SafeSNPrintf(buf, N, fmt, arg_array, sizeof...(args)); -} - -template<size_t N, typename... Args> -ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, Args... args) { - // Use Arg() object to record type information and then copy arguments to an - // array to make it easier to iterate over them. - const internal::Arg arg_array[] = { args... }; - return internal::SafeSNPrintf(buf, N, fmt, arg_array, sizeof...(args)); -} - -// Fast-path when we don't actually need to substitute any arguments. -BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt); -template<size_t N> -inline ssize_t SafeSPrintf(char (&buf)[N], const char* fmt) { - return SafeSNPrintf(buf, N, fmt); -} - -} // namespace strings -} // namespace base - -#endif // BASE_STRINGS_SAFE_SPRINTF_H_ diff --git a/security/sandbox/chromium/base/strings/safe_sprintf_unittest.cc b/security/sandbox/chromium/base/strings/safe_sprintf_unittest.cc deleted file mode 100644 index 931ace8b1..000000000 --- a/security/sandbox/chromium/base/strings/safe_sprintf_unittest.cc +++ /dev/null @@ -1,763 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/safe_sprintf.h" - -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include <limits> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" - -// Death tests on Android are currently very flaky. No need to add more flaky -// tests, as they just make it hard to spot real problems. -// TODO(markus): See if the restrictions on Android can eventually be lifted. -#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) -#define ALLOW_DEATH_TEST -#endif - -namespace base { -namespace strings { - -TEST(SafeSPrintfTest, Empty) { - char buf[2] = { 'X', 'X' }; - - // Negative buffer size should always result in an error. - EXPECT_EQ(-1, SafeSNPrintf(buf, static_cast<size_t>(-1), "")); - EXPECT_EQ('X', buf[0]); - EXPECT_EQ('X', buf[1]); - - // Zero buffer size should always result in an error. - EXPECT_EQ(-1, SafeSNPrintf(buf, 0, "")); - EXPECT_EQ('X', buf[0]); - EXPECT_EQ('X', buf[1]); - - // A one-byte buffer should always print a single NUL byte. - EXPECT_EQ(0, SafeSNPrintf(buf, 1, "")); - EXPECT_EQ(0, buf[0]); - EXPECT_EQ('X', buf[1]); - buf[0] = 'X'; - - // A larger buffer should leave the trailing bytes unchanged. - EXPECT_EQ(0, SafeSNPrintf(buf, 2, "")); - EXPECT_EQ(0, buf[0]); - EXPECT_EQ('X', buf[1]); - buf[0] = 'X'; - - // The same test using SafeSPrintf() instead of SafeSNPrintf(). - EXPECT_EQ(0, SafeSPrintf(buf, "")); - EXPECT_EQ(0, buf[0]); - EXPECT_EQ('X', buf[1]); - buf[0] = 'X'; -} - -TEST(SafeSPrintfTest, NoArguments) { - // Output a text message that doesn't require any substitutions. This - // is roughly equivalent to calling strncpy() (but unlike strncpy(), it does - // always add a trailing NUL; it always deduplicates '%' characters). - static const char text[] = "hello world"; - char ref[20], buf[20]; - memset(ref, 'X', sizeof(ref)); - memcpy(buf, ref, sizeof(buf)); - - // A negative buffer size should always result in an error. - EXPECT_EQ(-1, SafeSNPrintf(buf, static_cast<size_t>(-1), text)); - EXPECT_TRUE(!memcmp(buf, ref, sizeof(buf))); - - // Zero buffer size should always result in an error. - EXPECT_EQ(-1, SafeSNPrintf(buf, 0, text)); - EXPECT_TRUE(!memcmp(buf, ref, sizeof(buf))); - - // A one-byte buffer should always print a single NUL byte. - EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, SafeSNPrintf(buf, 1, text)); - EXPECT_EQ(0, buf[0]); - EXPECT_TRUE(!memcmp(buf+1, ref+1, sizeof(buf)-1)); - memcpy(buf, ref, sizeof(buf)); - - // A larger (but limited) buffer should always leave the trailing bytes - // unchanged. - EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, SafeSNPrintf(buf, 2, text)); - EXPECT_EQ(text[0], buf[0]); - EXPECT_EQ(0, buf[1]); - EXPECT_TRUE(!memcmp(buf+2, ref+2, sizeof(buf)-2)); - memcpy(buf, ref, sizeof(buf)); - - // A unrestricted buffer length should always leave the trailing bytes - // unchanged. - EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, - SafeSNPrintf(buf, sizeof(buf), text)); - EXPECT_EQ(std::string(text), std::string(buf)); - EXPECT_TRUE(!memcmp(buf + sizeof(text), ref + sizeof(text), - sizeof(buf) - sizeof(text))); - memcpy(buf, ref, sizeof(buf)); - - // The same test using SafeSPrintf() instead of SafeSNPrintf(). - EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, SafeSPrintf(buf, text)); - EXPECT_EQ(std::string(text), std::string(buf)); - EXPECT_TRUE(!memcmp(buf + sizeof(text), ref + sizeof(text), - sizeof(buf) - sizeof(text))); - memcpy(buf, ref, sizeof(buf)); - - // Check for deduplication of '%' percent characters. - EXPECT_EQ(1, SafeSPrintf(buf, "%%")); - EXPECT_EQ(2, SafeSPrintf(buf, "%%%%")); - EXPECT_EQ(2, SafeSPrintf(buf, "%%X")); - EXPECT_EQ(3, SafeSPrintf(buf, "%%%%X")); -#if defined(NDEBUG) - EXPECT_EQ(1, SafeSPrintf(buf, "%")); - EXPECT_EQ(2, SafeSPrintf(buf, "%%%")); - EXPECT_EQ(2, SafeSPrintf(buf, "%X")); - EXPECT_EQ(3, SafeSPrintf(buf, "%%%X")); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, "%"), "src.1. == '%'"); - EXPECT_DEATH(SafeSPrintf(buf, "%%%"), "src.1. == '%'"); - EXPECT_DEATH(SafeSPrintf(buf, "%X"), "src.1. == '%'"); - EXPECT_DEATH(SafeSPrintf(buf, "%%%X"), "src.1. == '%'"); -#endif -} - -TEST(SafeSPrintfTest, OneArgument) { - // Test basic single-argument single-character substitution. - const char text[] = "hello world"; - const char fmt[] = "hello%cworld"; - char ref[20], buf[20]; - memset(ref, 'X', sizeof(buf)); - memcpy(buf, ref, sizeof(buf)); - - // A negative buffer size should always result in an error. - EXPECT_EQ(-1, SafeSNPrintf(buf, static_cast<size_t>(-1), fmt, ' ')); - EXPECT_TRUE(!memcmp(buf, ref, sizeof(buf))); - - // Zero buffer size should always result in an error. - EXPECT_EQ(-1, SafeSNPrintf(buf, 0, fmt, ' ')); - EXPECT_TRUE(!memcmp(buf, ref, sizeof(buf))); - - // A one-byte buffer should always print a single NUL byte. - EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, - SafeSNPrintf(buf, 1, fmt, ' ')); - EXPECT_EQ(0, buf[0]); - EXPECT_TRUE(!memcmp(buf+1, ref+1, sizeof(buf)-1)); - memcpy(buf, ref, sizeof(buf)); - - // A larger (but limited) buffer should always leave the trailing bytes - // unchanged. - EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, - SafeSNPrintf(buf, 2, fmt, ' ')); - EXPECT_EQ(text[0], buf[0]); - EXPECT_EQ(0, buf[1]); - EXPECT_TRUE(!memcmp(buf+2, ref+2, sizeof(buf)-2)); - memcpy(buf, ref, sizeof(buf)); - - // A unrestricted buffer length should always leave the trailing bytes - // unchanged. - EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, - SafeSNPrintf(buf, sizeof(buf), fmt, ' ')); - EXPECT_EQ(std::string(text), std::string(buf)); - EXPECT_TRUE(!memcmp(buf + sizeof(text), ref + sizeof(text), - sizeof(buf) - sizeof(text))); - memcpy(buf, ref, sizeof(buf)); - - // The same test using SafeSPrintf() instead of SafeSNPrintf(). - EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, SafeSPrintf(buf, fmt, ' ')); - EXPECT_EQ(std::string(text), std::string(buf)); - EXPECT_TRUE(!memcmp(buf + sizeof(text), ref + sizeof(text), - sizeof(buf) - sizeof(text))); - memcpy(buf, ref, sizeof(buf)); - - // Check for deduplication of '%' percent characters. - EXPECT_EQ(1, SafeSPrintf(buf, "%%", 0)); - EXPECT_EQ(2, SafeSPrintf(buf, "%%%%", 0)); - EXPECT_EQ(2, SafeSPrintf(buf, "%Y", 0)); - EXPECT_EQ(2, SafeSPrintf(buf, "%%Y", 0)); - EXPECT_EQ(3, SafeSPrintf(buf, "%%%Y", 0)); - EXPECT_EQ(3, SafeSPrintf(buf, "%%%%Y", 0)); -#if defined(NDEBUG) - EXPECT_EQ(1, SafeSPrintf(buf, "%", 0)); - EXPECT_EQ(2, SafeSPrintf(buf, "%%%", 0)); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, "%", 0), "ch"); - EXPECT_DEATH(SafeSPrintf(buf, "%%%", 0), "ch"); -#endif -} - -TEST(SafeSPrintfTest, MissingArg) { -#if defined(NDEBUG) - char buf[20]; - EXPECT_EQ(3, SafeSPrintf(buf, "%c%c", 'A')); - EXPECT_EQ("A%c", std::string(buf)); -#elif defined(ALLOW_DEATH_TEST) - char buf[20]; - EXPECT_DEATH(SafeSPrintf(buf, "%c%c", 'A'), "cur_arg < max_args"); -#endif -} - -TEST(SafeSPrintfTest, ASANFriendlyBufferTest) { - // Print into a buffer that is sized exactly to size. ASAN can verify that - // nobody attempts to write past the end of the buffer. - // There is a more complicated test in PrintLongString() that covers a lot - // more edge case, but it is also harder to debug in case of a failure. - const char kTestString[] = "This is a test"; - scoped_ptr<char[]> buf(new char[sizeof(kTestString)]); - EXPECT_EQ(static_cast<ssize_t>(sizeof(kTestString) - 1), - SafeSNPrintf(buf.get(), sizeof(kTestString), kTestString)); - EXPECT_EQ(std::string(kTestString), std::string(buf.get())); - EXPECT_EQ(static_cast<ssize_t>(sizeof(kTestString) - 1), - SafeSNPrintf(buf.get(), sizeof(kTestString), "%s", kTestString)); - EXPECT_EQ(std::string(kTestString), std::string(buf.get())); -} - -TEST(SafeSPrintfTest, NArgs) { - // Pre-C++11 compilers have a different code path, that can only print - // up to ten distinct arguments. - // We test both SafeSPrintf() and SafeSNPrintf(). This makes sure we don't - // have typos in the copy-n-pasted code that is needed to deal with various - // numbers of arguments. - char buf[12]; - EXPECT_EQ(1, SafeSPrintf(buf, "%c", 1)); - EXPECT_EQ("\1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%c%c", 1, 2)); - EXPECT_EQ("\1\2", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%c%c%c", 1, 2, 3)); - EXPECT_EQ("\1\2\3", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%c%c%c%c", 1, 2, 3, 4)); - EXPECT_EQ("\1\2\3\4", std::string(buf)); - EXPECT_EQ(5, SafeSPrintf(buf, "%c%c%c%c%c", 1, 2, 3, 4, 5)); - EXPECT_EQ("\1\2\3\4\5", std::string(buf)); - EXPECT_EQ(6, SafeSPrintf(buf, "%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6)); - EXPECT_EQ("\1\2\3\4\5\6", std::string(buf)); - EXPECT_EQ(7, SafeSPrintf(buf, "%c%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6, 7)); - EXPECT_EQ("\1\2\3\4\5\6\7", std::string(buf)); - EXPECT_EQ(8, SafeSPrintf(buf, "%c%c%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6, 7, 8)); - EXPECT_EQ("\1\2\3\4\5\6\7\10", std::string(buf)); - EXPECT_EQ(9, SafeSPrintf(buf, "%c%c%c%c%c%c%c%c%c", - 1, 2, 3, 4, 5, 6, 7, 8, 9)); - EXPECT_EQ("\1\2\3\4\5\6\7\10\11", std::string(buf)); - EXPECT_EQ(10, SafeSPrintf(buf, "%c%c%c%c%c%c%c%c%c%c", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); - - // Repeat all the tests with SafeSNPrintf() instead of SafeSPrintf(). - EXPECT_EQ("\1\2\3\4\5\6\7\10\11\12", std::string(buf)); - EXPECT_EQ(1, SafeSNPrintf(buf, 11, "%c", 1)); - EXPECT_EQ("\1", std::string(buf)); - EXPECT_EQ(2, SafeSNPrintf(buf, 11, "%c%c", 1, 2)); - EXPECT_EQ("\1\2", std::string(buf)); - EXPECT_EQ(3, SafeSNPrintf(buf, 11, "%c%c%c", 1, 2, 3)); - EXPECT_EQ("\1\2\3", std::string(buf)); - EXPECT_EQ(4, SafeSNPrintf(buf, 11, "%c%c%c%c", 1, 2, 3, 4)); - EXPECT_EQ("\1\2\3\4", std::string(buf)); - EXPECT_EQ(5, SafeSNPrintf(buf, 11, "%c%c%c%c%c", 1, 2, 3, 4, 5)); - EXPECT_EQ("\1\2\3\4\5", std::string(buf)); - EXPECT_EQ(6, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6)); - EXPECT_EQ("\1\2\3\4\5\6", std::string(buf)); - EXPECT_EQ(7, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6, 7)); - EXPECT_EQ("\1\2\3\4\5\6\7", std::string(buf)); - EXPECT_EQ(8, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c%c%c", - 1, 2, 3, 4, 5, 6, 7, 8)); - EXPECT_EQ("\1\2\3\4\5\6\7\10", std::string(buf)); - EXPECT_EQ(9, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c%c%c%c", - 1, 2, 3, 4, 5, 6, 7, 8, 9)); - EXPECT_EQ("\1\2\3\4\5\6\7\10\11", std::string(buf)); - EXPECT_EQ(10, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c%c%c%c%c", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); - EXPECT_EQ("\1\2\3\4\5\6\7\10\11\12", std::string(buf)); - - EXPECT_EQ(11, SafeSPrintf(buf, "%c%c%c%c%c%c%c%c%c%c%c", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); - EXPECT_EQ("\1\2\3\4\5\6\7\10\11\12\13", std::string(buf)); - EXPECT_EQ(11, SafeSNPrintf(buf, 12, "%c%c%c%c%c%c%c%c%c%c%c", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); - EXPECT_EQ("\1\2\3\4\5\6\7\10\11\12\13", std::string(buf)); -} - -TEST(SafeSPrintfTest, DataTypes) { - char buf[40]; - - // Bytes - EXPECT_EQ(1, SafeSPrintf(buf, "%d", (uint8_t)1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%d", (uint8_t)-1)); - EXPECT_EQ("255", std::string(buf)); - EXPECT_EQ(1, SafeSPrintf(buf, "%d", (int8_t)1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%d", (int8_t)-1)); - EXPECT_EQ("-1", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%d", (int8_t)-128)); - EXPECT_EQ("-128", std::string(buf)); - - // Half-words - EXPECT_EQ(1, SafeSPrintf(buf, "%d", (uint16_t)1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(5, SafeSPrintf(buf, "%d", (uint16_t)-1)); - EXPECT_EQ("65535", std::string(buf)); - EXPECT_EQ(1, SafeSPrintf(buf, "%d", (int16_t)1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%d", (int16_t)-1)); - EXPECT_EQ("-1", std::string(buf)); - EXPECT_EQ(6, SafeSPrintf(buf, "%d", (int16_t)-32768)); - EXPECT_EQ("-32768", std::string(buf)); - - // Words - EXPECT_EQ(1, SafeSPrintf(buf, "%d", (uint32_t)1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(10, SafeSPrintf(buf, "%d", (uint32_t)-1)); - EXPECT_EQ("4294967295", std::string(buf)); - EXPECT_EQ(1, SafeSPrintf(buf, "%d", (int32_t)1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%d", (int32_t)-1)); - EXPECT_EQ("-1", std::string(buf)); - // Work-around for an limitation of C90 - EXPECT_EQ(11, SafeSPrintf(buf, "%d", (int32_t)-2147483647-1)); - EXPECT_EQ("-2147483648", std::string(buf)); - - // Quads - EXPECT_EQ(1, SafeSPrintf(buf, "%d", (uint64_t)1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(20, SafeSPrintf(buf, "%d", (uint64_t)-1)); - EXPECT_EQ("18446744073709551615", std::string(buf)); - EXPECT_EQ(1, SafeSPrintf(buf, "%d", (int64_t)1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%d", (int64_t)-1)); - EXPECT_EQ("-1", std::string(buf)); - // Work-around for an limitation of C90 - EXPECT_EQ(20, SafeSPrintf(buf, "%d", (int64_t)-9223372036854775807LL-1)); - EXPECT_EQ("-9223372036854775808", std::string(buf)); - - // Strings (both const and mutable). - EXPECT_EQ(4, SafeSPrintf(buf, "test")); - EXPECT_EQ("test", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, buf)); - EXPECT_EQ("test", std::string(buf)); - - // Pointer - char addr[20]; - sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)buf); - SafeSPrintf(buf, "%p", buf); - EXPECT_EQ(std::string(addr), std::string(buf)); - SafeSPrintf(buf, "%p", (const char *)buf); - EXPECT_EQ(std::string(addr), std::string(buf)); - sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)sprintf); - SafeSPrintf(buf, "%p", sprintf); - EXPECT_EQ(std::string(addr), std::string(buf)); - - // Padding for pointers is a little more complicated because of the "0x" - // prefix. Padding with '0' zeros is relatively straight-forward, but - // padding with ' ' spaces requires more effort. - sprintf(addr, "0x%017llX", (unsigned long long)(uintptr_t)buf); - SafeSPrintf(buf, "%019p", buf); - EXPECT_EQ(std::string(addr), std::string(buf)); - sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)buf); - memset(addr, ' ', - (char*)memmove(addr + sizeof(addr) - strlen(addr) - 1, - addr, strlen(addr)+1) - addr); - SafeSPrintf(buf, "%19p", buf); - EXPECT_EQ(std::string(addr), std::string(buf)); -} - -namespace { -void PrintLongString(char* buf, size_t sz) { - // Output a reasonably complex expression into a limited-size buffer. - // At least one byte is available for writing the NUL character. - CHECK_GT(sz, static_cast<size_t>(0)); - - // Allocate slightly more space, so that we can verify that SafeSPrintf() - // never writes past the end of the buffer. - scoped_ptr<char[]> tmp(new char[sz+2]); - memset(tmp.get(), 'X', sz+2); - - // Use SafeSPrintf() to output a complex list of arguments: - // - test padding and truncating %c single characters. - // - test truncating %s simple strings. - // - test mismatching arguments and truncating (for %d != %s). - // - test zero-padding and truncating %x hexadecimal numbers. - // - test outputting and truncating %d MININT. - // - test outputting and truncating %p arbitrary pointer values. - // - test outputting, padding and truncating NULL-pointer %s strings. - char* out = tmp.get(); - size_t out_sz = sz; - size_t len; - for (scoped_ptr<char[]> perfect_buf;;) { - size_t needed = SafeSNPrintf(out, out_sz, -#if defined(NDEBUG) - "A%2cong %s: %d %010X %d %p%7s", 'l', "string", "", -#else - "A%2cong %s: %%d %010X %d %p%7s", 'l', "string", -#endif - 0xDEADBEEF, std::numeric_limits<intptr_t>::min(), - PrintLongString, static_cast<char*>(NULL)) + 1; - - // Various sanity checks: - // The numbered of characters needed to print the full string should always - // be bigger or equal to the bytes that have actually been output. - len = strlen(tmp.get()); - CHECK_GE(needed, len+1); - - // The number of characters output should always fit into the buffer that - // was passed into SafeSPrintf(). - CHECK_LT(len, out_sz); - - // The output is always terminated with a NUL byte (actually, this test is - // always going to pass, as strlen() already verified this) - EXPECT_FALSE(tmp[len]); - - // ASAN can check that we are not overwriting buffers, iff we make sure the - // buffer is exactly the size that we are expecting to be written. After - // running SafeSNPrintf() the first time, it is possible to compute the - // correct buffer size for this test. So, allocate a second buffer and run - // the exact same SafeSNPrintf() command again. - if (!perfect_buf.get()) { - out_sz = std::min(needed, sz); - out = new char[out_sz]; - perfect_buf.reset(out); - } else { - break; - } - } - - // All trailing bytes are unchanged. - for (size_t i = len+1; i < sz+2; ++i) - EXPECT_EQ('X', tmp[i]); - - // The text that was generated by SafeSPrintf() should always match the - // equivalent text generated by sprintf(). Please note that the format - // string for sprintf() is not complicated, as it does not have the - // benefit of getting type information from the C++ compiler. - // - // N.B.: It would be so much cleaner to use snprintf(). But unfortunately, - // Visual Studio doesn't support this function, and the work-arounds - // are all really awkward. - char ref[256]; - CHECK_LE(sz, sizeof(ref)); - sprintf(ref, "A long string: %%d 00DEADBEEF %lld 0x%llX <NULL>", - static_cast<long long>(std::numeric_limits<intptr_t>::min()), - static_cast<unsigned long long>( - reinterpret_cast<uintptr_t>(PrintLongString))); - ref[sz-1] = '\000'; - -#if defined(NDEBUG) - const size_t kSSizeMax = std::numeric_limits<ssize_t>::max(); -#else - const size_t kSSizeMax = internal::GetSafeSPrintfSSizeMaxForTest(); -#endif - - // Compare the output from SafeSPrintf() to the one from sprintf(). - EXPECT_EQ(std::string(ref).substr(0, kSSizeMax-1), std::string(tmp.get())); - - // We allocated a slightly larger buffer, so that we could perform some - // extra sanity checks. Now that the tests have all passed, we copy the - // data to the output buffer that the caller provided. - memcpy(buf, tmp.get(), len+1); -} - -#if !defined(NDEBUG) -class ScopedSafeSPrintfSSizeMaxSetter { - public: - ScopedSafeSPrintfSSizeMaxSetter(size_t sz) { - old_ssize_max_ = internal::GetSafeSPrintfSSizeMaxForTest(); - internal::SetSafeSPrintfSSizeMaxForTest(sz); - } - - ~ScopedSafeSPrintfSSizeMaxSetter() { - internal::SetSafeSPrintfSSizeMaxForTest(old_ssize_max_); - } - - private: - size_t old_ssize_max_; - - DISALLOW_COPY_AND_ASSIGN(ScopedSafeSPrintfSSizeMaxSetter); -}; -#endif - -} // anonymous namespace - -TEST(SafeSPrintfTest, Truncation) { - // We use PrintLongString() to print a complex long string and then - // truncate to all possible lengths. This ends up exercising a lot of - // different code paths in SafeSPrintf() and IToASCII(), as truncation can - // happen in a lot of different states. - char ref[256]; - PrintLongString(ref, sizeof(ref)); - for (size_t i = strlen(ref)+1; i; --i) { - char buf[sizeof(ref)]; - PrintLongString(buf, i); - EXPECT_EQ(std::string(ref, i - 1), std::string(buf)); - } - - // When compiling in debug mode, we have the ability to fake a small - // upper limit for the maximum value that can be stored in an ssize_t. - // SafeSPrintf() uses this upper limit to determine how many bytes it will - // write to the buffer, even if the caller claimed a bigger buffer size. - // Repeat the truncation test and verify that this other code path in - // SafeSPrintf() works correctly, too. -#if !defined(NDEBUG) - for (size_t i = strlen(ref)+1; i > 1; --i) { - ScopedSafeSPrintfSSizeMaxSetter ssize_max_setter(i); - char buf[sizeof(ref)]; - PrintLongString(buf, sizeof(buf)); - EXPECT_EQ(std::string(ref, i - 1), std::string(buf)); - } - - // kSSizeMax is also used to constrain the maximum amount of padding, before - // SafeSPrintf() detects an error in the format string. - ScopedSafeSPrintfSSizeMaxSetter ssize_max_setter(100); - char buf[256]; - EXPECT_EQ(99, SafeSPrintf(buf, "%99c", ' ')); - EXPECT_EQ(std::string(99, ' '), std::string(buf)); - *buf = '\000'; -#if defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, "%100c", ' '), "padding <= max_padding"); -#endif - EXPECT_EQ(0, *buf); -#endif -} - -TEST(SafeSPrintfTest, Padding) { - char buf[40], fmt[40]; - - // Chars %c - EXPECT_EQ(1, SafeSPrintf(buf, "%c", 'A')); - EXPECT_EQ("A", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%2c", 'A')); - EXPECT_EQ(" A", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%02c", 'A')); - EXPECT_EQ(" A", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%-2c", 'A')); - EXPECT_EQ("%-2c", std::string(buf)); - SafeSPrintf(fmt, "%%%dc", std::numeric_limits<ssize_t>::max() - 1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, SafeSPrintf(buf, fmt, 'A')); - SafeSPrintf(fmt, "%%%dc", - static_cast<size_t>(std::numeric_limits<ssize_t>::max())); -#if defined(NDEBUG) - EXPECT_EQ(2, SafeSPrintf(buf, fmt, 'A')); - EXPECT_EQ("%c", std::string(buf)); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, fmt, 'A'), "padding <= max_padding"); -#endif - - // Octal %o - EXPECT_EQ(1, SafeSPrintf(buf, "%o", 1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%2o", 1)); - EXPECT_EQ(" 1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%02o", 1)); - EXPECT_EQ("01", std::string(buf)); - EXPECT_EQ(12, SafeSPrintf(buf, "%12o", -1)); - EXPECT_EQ(" 37777777777", std::string(buf)); - EXPECT_EQ(12, SafeSPrintf(buf, "%012o", -1)); - EXPECT_EQ("037777777777", std::string(buf)); - EXPECT_EQ(23, SafeSPrintf(buf, "%23o", -1LL)); - EXPECT_EQ(" 1777777777777777777777", std::string(buf)); - EXPECT_EQ(23, SafeSPrintf(buf, "%023o", -1LL)); - EXPECT_EQ("01777777777777777777777", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%2o", 0111)); - EXPECT_EQ("111", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%-2o", 1)); - EXPECT_EQ("%-2o", std::string(buf)); - SafeSPrintf(fmt, "%%%do", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, 1)); - EXPECT_EQ(" ", std::string(buf)); - SafeSPrintf(fmt, "%%0%do", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, 1)); - EXPECT_EQ("000", std::string(buf)); - SafeSPrintf(fmt, "%%%do", - static_cast<size_t>(std::numeric_limits<ssize_t>::max())); -#if defined(NDEBUG) - EXPECT_EQ(2, SafeSPrintf(buf, fmt, 1)); - EXPECT_EQ("%o", std::string(buf)); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, fmt, 1), "padding <= max_padding"); -#endif - - // Decimals %d - EXPECT_EQ(1, SafeSPrintf(buf, "%d", 1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%2d", 1)); - EXPECT_EQ(" 1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%02d", 1)); - EXPECT_EQ("01", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%3d", -1)); - EXPECT_EQ(" -1", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%03d", -1)); - EXPECT_EQ("-01", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%2d", 111)); - EXPECT_EQ("111", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%2d", -111)); - EXPECT_EQ("-111", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%-2d", 1)); - EXPECT_EQ("%-2d", std::string(buf)); - SafeSPrintf(fmt, "%%%dd", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, 1)); - EXPECT_EQ(" ", std::string(buf)); - SafeSPrintf(fmt, "%%0%dd", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, 1)); - EXPECT_EQ("000", std::string(buf)); - SafeSPrintf(fmt, "%%%dd", - static_cast<size_t>(std::numeric_limits<ssize_t>::max())); -#if defined(NDEBUG) - EXPECT_EQ(2, SafeSPrintf(buf, fmt, 1)); - EXPECT_EQ("%d", std::string(buf)); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, fmt, 1), "padding <= max_padding"); -#endif - - // Hex %X - EXPECT_EQ(1, SafeSPrintf(buf, "%X", 1)); - EXPECT_EQ("1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%2X", 1)); - EXPECT_EQ(" 1", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%02X", 1)); - EXPECT_EQ("01", std::string(buf)); - EXPECT_EQ(9, SafeSPrintf(buf, "%9X", -1)); - EXPECT_EQ(" FFFFFFFF", std::string(buf)); - EXPECT_EQ(9, SafeSPrintf(buf, "%09X", -1)); - EXPECT_EQ("0FFFFFFFF", std::string(buf)); - EXPECT_EQ(17, SafeSPrintf(buf, "%17X", -1LL)); - EXPECT_EQ(" FFFFFFFFFFFFFFFF", std::string(buf)); - EXPECT_EQ(17, SafeSPrintf(buf, "%017X", -1LL)); - EXPECT_EQ("0FFFFFFFFFFFFFFFF", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%2X", 0x111)); - EXPECT_EQ("111", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%-2X", 1)); - EXPECT_EQ("%-2X", std::string(buf)); - SafeSPrintf(fmt, "%%%dX", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, 1)); - EXPECT_EQ(" ", std::string(buf)); - SafeSPrintf(fmt, "%%0%dX", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, 1)); - EXPECT_EQ("000", std::string(buf)); - SafeSPrintf(fmt, "%%%dX", - static_cast<size_t>(std::numeric_limits<ssize_t>::max())); -#if defined(NDEBUG) - EXPECT_EQ(2, SafeSPrintf(buf, fmt, 1)); - EXPECT_EQ("%X", std::string(buf)); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, fmt, 1), "padding <= max_padding"); -#endif - - // Pointer %p - EXPECT_EQ(3, SafeSPrintf(buf, "%p", (void*)1)); - EXPECT_EQ("0x1", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%4p", (void*)1)); - EXPECT_EQ(" 0x1", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%04p", (void*)1)); - EXPECT_EQ("0x01", std::string(buf)); - EXPECT_EQ(5, SafeSPrintf(buf, "%4p", (void*)0x111)); - EXPECT_EQ("0x111", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%-2p", (void*)1)); - EXPECT_EQ("%-2p", std::string(buf)); - SafeSPrintf(fmt, "%%%dp", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, (void*)1)); - EXPECT_EQ(" ", std::string(buf)); - SafeSPrintf(fmt, "%%0%dp", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, (void*)1)); - EXPECT_EQ("0x0", std::string(buf)); - SafeSPrintf(fmt, "%%%dp", - static_cast<size_t>(std::numeric_limits<ssize_t>::max())); -#if defined(NDEBUG) - EXPECT_EQ(2, SafeSPrintf(buf, fmt, 1)); - EXPECT_EQ("%p", std::string(buf)); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, fmt, 1), "padding <= max_padding"); -#endif - - // String - EXPECT_EQ(1, SafeSPrintf(buf, "%s", "A")); - EXPECT_EQ("A", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%2s", "A")); - EXPECT_EQ(" A", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%02s", "A")); - EXPECT_EQ(" A", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%2s", "AAA")); - EXPECT_EQ("AAA", std::string(buf)); - EXPECT_EQ(4, SafeSPrintf(buf, "%-2s", "A")); - EXPECT_EQ("%-2s", std::string(buf)); - SafeSPrintf(fmt, "%%%ds", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, "A")); - EXPECT_EQ(" ", std::string(buf)); - SafeSPrintf(fmt, "%%0%ds", std::numeric_limits<ssize_t>::max()-1); - EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, - SafeSNPrintf(buf, 4, fmt, "A")); - EXPECT_EQ(" ", std::string(buf)); - SafeSPrintf(fmt, "%%%ds", - static_cast<size_t>(std::numeric_limits<ssize_t>::max())); -#if defined(NDEBUG) - EXPECT_EQ(2, SafeSPrintf(buf, fmt, "A")); - EXPECT_EQ("%s", std::string(buf)); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, fmt, "A"), "padding <= max_padding"); -#endif -} - -TEST(SafeSPrintfTest, EmbeddedNul) { - char buf[] = { 'X', 'X', 'X', 'X' }; - EXPECT_EQ(2, SafeSPrintf(buf, "%3c", 0)); - EXPECT_EQ(' ', buf[0]); - EXPECT_EQ(' ', buf[1]); - EXPECT_EQ(0, buf[2]); - EXPECT_EQ('X', buf[3]); - - // Check handling of a NUL format character. N.B. this takes two different - // code paths depending on whether we are actually passing arguments. If - // we don't have any arguments, we are running in the fast-path code, that - // looks (almost) like a strncpy(). -#if defined(NDEBUG) - EXPECT_EQ(2, SafeSPrintf(buf, "%%%")); - EXPECT_EQ("%%", std::string(buf)); - EXPECT_EQ(2, SafeSPrintf(buf, "%%%", 0)); - EXPECT_EQ("%%", std::string(buf)); -#elif defined(ALLOW_DEATH_TEST) - EXPECT_DEATH(SafeSPrintf(buf, "%%%"), "src.1. == '%'"); - EXPECT_DEATH(SafeSPrintf(buf, "%%%", 0), "ch"); -#endif -} - -TEST(SafeSPrintfTest, EmitNULL) { - char buf[40]; -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion-null" -#endif - EXPECT_EQ(1, SafeSPrintf(buf, "%d", NULL)); - EXPECT_EQ("0", std::string(buf)); - EXPECT_EQ(3, SafeSPrintf(buf, "%p", NULL)); - EXPECT_EQ("0x0", std::string(buf)); - EXPECT_EQ(6, SafeSPrintf(buf, "%s", NULL)); - EXPECT_EQ("<NULL>", std::string(buf)); -#if defined(__GCC__) -#pragma GCC diagnostic pop -#endif -} - -TEST(SafeSPrintfTest, PointerSize) { - // The internal data representation is a 64bit value, independent of the - // native word size. We want to perform sign-extension for signed integers, - // but we want to avoid doing so for pointer types. This could be a - // problem on systems, where pointers are only 32bit. This tests verifies - // that there is no such problem. - char *str = reinterpret_cast<char *>(0x80000000u); - void *ptr = str; - char buf[40]; - EXPECT_EQ(10, SafeSPrintf(buf, "%p", str)); - EXPECT_EQ("0x80000000", std::string(buf)); - EXPECT_EQ(10, SafeSPrintf(buf, "%p", ptr)); - EXPECT_EQ("0x80000000", std::string(buf)); -} - -} // namespace strings -} // namespace base diff --git a/security/sandbox/chromium/base/strings/string16.cc b/security/sandbox/chromium/base/strings/string16.cc deleted file mode 100644 index f4c8cf746..000000000 --- a/security/sandbox/chromium/base/strings/string16.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/string16.h" - -#if defined(WCHAR_T_IS_UTF16) - -#error This file should not be used on 2-byte wchar_t systems -// If this winds up being needed on 2-byte wchar_t systems, either the -// definitions below can be used, or the host system's wide character -// functions like wmemcmp can be wrapped. - -#elif defined(WCHAR_T_IS_UTF32) - -#include <ostream> - -#include "base/strings/utf_string_conversions.h" - -namespace base { - -int c16memcmp(const char16* s1, const char16* s2, size_t n) { - // We cannot call memcmp because that changes the semantics. - while (n-- > 0) { - if (*s1 != *s2) { - // We cannot use (*s1 - *s2) because char16 is unsigned. - return ((*s1 < *s2) ? -1 : 1); - } - ++s1; - ++s2; - } - return 0; -} - -size_t c16len(const char16* s) { - const char16 *s_orig = s; - while (*s) { - ++s; - } - return s - s_orig; -} - -const char16* c16memchr(const char16* s, char16 c, size_t n) { - while (n-- > 0) { - if (*s == c) { - return s; - } - ++s; - } - return 0; -} - -char16* c16memmove(char16* s1, const char16* s2, size_t n) { - return static_cast<char16*>(memmove(s1, s2, n * sizeof(char16))); -} - -char16* c16memcpy(char16* s1, const char16* s2, size_t n) { - return static_cast<char16*>(memcpy(s1, s2, n * sizeof(char16))); -} - -char16* c16memset(char16* s, char16 c, size_t n) { - char16 *s_orig = s; - while (n-- > 0) { - *s = c; - ++s; - } - return s_orig; -} - -std::ostream& operator<<(std::ostream& out, const string16& str) { - return out << UTF16ToUTF8(str); -} - -void PrintTo(const string16& str, std::ostream* out) { - *out << str; -} - -} // namespace base - -template class std::basic_string<base::char16, base::string16_char_traits>; - -#endif // WCHAR_T_IS_UTF32 diff --git a/security/sandbox/chromium/base/strings/string16.h b/security/sandbox/chromium/base/strings/string16.h deleted file mode 100644 index e47669c1b..000000000 --- a/security/sandbox/chromium/base/strings/string16.h +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_STRING16_H_ -#define BASE_STRINGS_STRING16_H_ - -// WHAT: -// A version of std::basic_string that provides 2-byte characters even when -// wchar_t is not implemented as a 2-byte type. You can access this class as -// string16. We also define char16, which string16 is based upon. -// -// WHY: -// On Windows, wchar_t is 2 bytes, and it can conveniently handle UTF-16/UCS-2 -// data. Plenty of existing code operates on strings encoded as UTF-16. -// -// On many other platforms, sizeof(wchar_t) is 4 bytes by default. We can make -// it 2 bytes by using the GCC flag -fshort-wchar. But then std::wstring fails -// at run time, because it calls some functions (like wcslen) that come from -// the system's native C library -- which was built with a 4-byte wchar_t! -// It's wasteful to use 4-byte wchar_t strings to carry UTF-16 data, and it's -// entirely improper on those systems where the encoding of wchar_t is defined -// as UTF-32. -// -// Here, we define string16, which is similar to std::wstring but replaces all -// libc functions with custom, 2-byte-char compatible routines. It is capable -// of carrying UTF-16-encoded data. - -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <string> - -#include "base/base_export.h" -#include "build/build_config.h" - -#if defined(WCHAR_T_IS_UTF16) - -namespace base { - -typedef wchar_t char16; -typedef std::wstring string16; -typedef std::char_traits<wchar_t> string16_char_traits; - -} // namespace base - -#elif defined(WCHAR_T_IS_UTF32) - -namespace base { - -typedef uint16_t char16; - -// char16 versions of the functions required by string16_char_traits; these -// are based on the wide character functions of similar names ("w" or "wcs" -// instead of "c16"). -BASE_EXPORT int c16memcmp(const char16* s1, const char16* s2, size_t n); -BASE_EXPORT size_t c16len(const char16* s); -BASE_EXPORT const char16* c16memchr(const char16* s, char16 c, size_t n); -BASE_EXPORT char16* c16memmove(char16* s1, const char16* s2, size_t n); -BASE_EXPORT char16* c16memcpy(char16* s1, const char16* s2, size_t n); -BASE_EXPORT char16* c16memset(char16* s, char16 c, size_t n); - -struct string16_char_traits { - typedef char16 char_type; - typedef int int_type; - - // int_type needs to be able to hold each possible value of char_type, and in - // addition, the distinct value of eof(). - static_assert(sizeof(int_type) > sizeof(char_type), - "int must be larger than 16 bits wide"); - - typedef std::streamoff off_type; - typedef mbstate_t state_type; - typedef std::fpos<state_type> pos_type; - - static void assign(char_type& c1, const char_type& c2) { - c1 = c2; - } - - static bool eq(const char_type& c1, const char_type& c2) { - return c1 == c2; - } - static bool lt(const char_type& c1, const char_type& c2) { - return c1 < c2; - } - - static int compare(const char_type* s1, const char_type* s2, size_t n) { - return c16memcmp(s1, s2, n); - } - - static size_t length(const char_type* s) { - return c16len(s); - } - - static const char_type* find(const char_type* s, size_t n, - const char_type& a) { - return c16memchr(s, a, n); - } - - static char_type* move(char_type* s1, const char_type* s2, size_t n) { - return c16memmove(s1, s2, n); - } - - static char_type* copy(char_type* s1, const char_type* s2, size_t n) { - return c16memcpy(s1, s2, n); - } - - static char_type* assign(char_type* s, size_t n, char_type a) { - return c16memset(s, a, n); - } - - static int_type not_eof(const int_type& c) { - return eq_int_type(c, eof()) ? 0 : c; - } - - static char_type to_char_type(const int_type& c) { - return char_type(c); - } - - static int_type to_int_type(const char_type& c) { - return int_type(c); - } - - static bool eq_int_type(const int_type& c1, const int_type& c2) { - return c1 == c2; - } - - static int_type eof() { - return static_cast<int_type>(EOF); - } -}; - -typedef std::basic_string<char16, base::string16_char_traits> string16; - -BASE_EXPORT extern std::ostream& operator<<(std::ostream& out, - const string16& str); - -// This is required by googletest to print a readable output on test failures. -BASE_EXPORT extern void PrintTo(const string16& str, std::ostream* out); - -} // namespace base - -// The string class will be explicitly instantiated only once, in string16.cc. -// -// std::basic_string<> in GNU libstdc++ contains a static data member, -// _S_empty_rep_storage, to represent empty strings. When an operation such -// as assignment or destruction is performed on a string, causing its existing -// data member to be invalidated, it must not be freed if this static data -// member is being used. Otherwise, it counts as an attempt to free static -// (and not allocated) data, which is a memory error. -// -// Generally, due to C++ template magic, _S_empty_rep_storage will be marked -// as a coalesced symbol, meaning that the linker will combine multiple -// instances into a single one when generating output. -// -// If a string class is used by multiple shared libraries, a problem occurs. -// Each library will get its own copy of _S_empty_rep_storage. When strings -// are passed across a library boundary for alteration or destruction, memory -// errors will result. GNU libstdc++ contains a configuration option, -// --enable-fully-dynamic-string (_GLIBCXX_FULLY_DYNAMIC_STRING), which -// disables the static data member optimization, but it's a good optimization -// and non-STL code is generally at the mercy of the system's STL -// configuration. Fully-dynamic strings are not the default for GNU libstdc++ -// libstdc++ itself or for the libstdc++ installations on the systems we care -// about, such as Mac OS X and relevant flavors of Linux. -// -// See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24196 . -// -// To avoid problems, string classes need to be explicitly instantiated only -// once, in exactly one library. All other string users see it via an "extern" -// declaration. This is precisely how GNU libstdc++ handles -// std::basic_string<char> (string) and std::basic_string<wchar_t> (wstring). -// -// This also works around a Mac OS X linker bug in ld64-85.2.1 (Xcode 3.1.2), -// in which the linker does not fully coalesce symbols when dead code -// stripping is enabled. This bug causes the memory errors described above -// to occur even when a std::basic_string<> does not cross shared library -// boundaries, such as in statically-linked executables. -// -// TODO(mark): File this bug with Apple and update this note with a bug number. - -extern template -class BASE_EXPORT std::basic_string<base::char16, base::string16_char_traits>; - -#endif // WCHAR_T_IS_UTF32 - -#endif // BASE_STRINGS_STRING16_H_ diff --git a/security/sandbox/chromium/base/strings/string_number_conversions.cc b/security/sandbox/chromium/base/strings/string_number_conversions.cc deleted file mode 100644 index 07248501e..000000000 --- a/security/sandbox/chromium/base/strings/string_number_conversions.cc +++ /dev/null @@ -1,485 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/string_number_conversions.h" - -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> -#include <wctype.h> - -#include <limits> - -#include "base/logging.h" -#include "base/numerics/safe_conversions.h" -#include "base/numerics/safe_math.h" -#include "base/scoped_clear_errno.h" -#include "base/strings/utf_string_conversions.h" -#include "base/third_party/dmg_fp/dmg_fp.h" - -namespace base { - -namespace { - -template <typename STR, typename INT> -struct IntToStringT { - static STR IntToString(INT value) { - // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. - // So round up to allocate 3 output characters per byte, plus 1 for '-'. - const size_t kOutputBufSize = - 3 * sizeof(INT) + std::numeric_limits<INT>::is_signed; - - // Create the string in a temporary buffer, write it back to front, and - // then return the substr of what we ended up using. - using CHR = typename STR::value_type; - CHR outbuf[kOutputBufSize]; - - // The ValueOrDie call below can never fail, because UnsignedAbs is valid - // for all valid inputs. - auto res = CheckedNumeric<INT>(value).UnsignedAbs().ValueOrDie(); - - CHR* end = outbuf + kOutputBufSize; - CHR* i = end; - do { - --i; - DCHECK(i != outbuf); - *i = static_cast<CHR>((res % 10) + '0'); - res /= 10; - } while (res != 0); - if (IsValueNegative(value)) { - --i; - DCHECK(i != outbuf); - *i = static_cast<CHR>('-'); - } - return STR(i, end); - } -}; - -// Utility to convert a character to a digit in a given base -template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit { -}; - -// Faster specialization for bases <= 10 -template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> { - public: - static bool Convert(CHAR c, uint8_t* digit) { - if (c >= '0' && c < '0' + BASE) { - *digit = static_cast<uint8_t>(c - '0'); - return true; - } - return false; - } -}; - -// Specialization for bases where 10 < base <= 36 -template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> { - public: - static bool Convert(CHAR c, uint8_t* digit) { - if (c >= '0' && c <= '9') { - *digit = c - '0'; - } else if (c >= 'a' && c < 'a' + BASE - 10) { - *digit = c - 'a' + 10; - } else if (c >= 'A' && c < 'A' + BASE - 10) { - *digit = c - 'A' + 10; - } else { - return false; - } - return true; - } -}; - -template <int BASE, typename CHAR> -bool CharToDigit(CHAR c, uint8_t* digit) { - return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit); -} - -// There is an IsUnicodeWhitespace for wchars defined in string_util.h, but it -// is locale independent, whereas the functions we are replacing were -// locale-dependent. TBD what is desired, but for the moment let's not -// introduce a change in behaviour. -template<typename CHAR> class WhitespaceHelper { -}; - -template<> class WhitespaceHelper<char> { - public: - static bool Invoke(char c) { - return 0 != isspace(static_cast<unsigned char>(c)); - } -}; - -template<> class WhitespaceHelper<char16> { - public: - static bool Invoke(char16 c) { - return 0 != iswspace(c); - } -}; - -template<typename CHAR> bool LocalIsWhitespace(CHAR c) { - return WhitespaceHelper<CHAR>::Invoke(c); -} - -// IteratorRangeToNumberTraits should provide: -// - a typedef for iterator_type, the iterator type used as input. -// - a typedef for value_type, the target numeric type. -// - static functions min, max (returning the minimum and maximum permitted -// values) -// - constant kBase, the base in which to interpret the input -template<typename IteratorRangeToNumberTraits> -class IteratorRangeToNumber { - public: - typedef IteratorRangeToNumberTraits traits; - typedef typename traits::iterator_type const_iterator; - typedef typename traits::value_type value_type; - - // Generalized iterator-range-to-number conversion. - // - static bool Invoke(const_iterator begin, - const_iterator end, - value_type* output) { - bool valid = true; - - while (begin != end && LocalIsWhitespace(*begin)) { - valid = false; - ++begin; - } - - if (begin != end && *begin == '-') { - if (!std::numeric_limits<value_type>::is_signed) { - valid = false; - } else if (!Negative::Invoke(begin + 1, end, output)) { - valid = false; - } - } else { - if (begin != end && *begin == '+') { - ++begin; - } - if (!Positive::Invoke(begin, end, output)) { - valid = false; - } - } - - return valid; - } - - private: - // Sign provides: - // - a static function, CheckBounds, that determines whether the next digit - // causes an overflow/underflow - // - a static function, Increment, that appends the next digit appropriately - // according to the sign of the number being parsed. - template<typename Sign> - class Base { - public: - static bool Invoke(const_iterator begin, const_iterator end, - typename traits::value_type* output) { - *output = 0; - - if (begin == end) { - return false; - } - - // Note: no performance difference was found when using template - // specialization to remove this check in bases other than 16 - if (traits::kBase == 16 && end - begin > 2 && *begin == '0' && - (*(begin + 1) == 'x' || *(begin + 1) == 'X')) { - begin += 2; - } - - for (const_iterator current = begin; current != end; ++current) { - uint8_t new_digit = 0; - - if (!CharToDigit<traits::kBase>(*current, &new_digit)) { - return false; - } - - if (current != begin) { - if (!Sign::CheckBounds(output, new_digit)) { - return false; - } - *output *= traits::kBase; - } - - Sign::Increment(new_digit, output); - } - return true; - } - }; - - class Positive : public Base<Positive> { - public: - static bool CheckBounds(value_type* output, uint8_t new_digit) { - if (*output > static_cast<value_type>(traits::max() / traits::kBase) || - (*output == static_cast<value_type>(traits::max() / traits::kBase) && - new_digit > traits::max() % traits::kBase)) { - *output = traits::max(); - return false; - } - return true; - } - static void Increment(uint8_t increment, value_type* output) { - *output += increment; - } - }; - - class Negative : public Base<Negative> { - public: - static bool CheckBounds(value_type* output, uint8_t new_digit) { - if (*output < traits::min() / traits::kBase || - (*output == traits::min() / traits::kBase && - new_digit > 0 - traits::min() % traits::kBase)) { - *output = traits::min(); - return false; - } - return true; - } - static void Increment(uint8_t increment, value_type* output) { - *output -= increment; - } - }; -}; - -template<typename ITERATOR, typename VALUE, int BASE> -class BaseIteratorRangeToNumberTraits { - public: - typedef ITERATOR iterator_type; - typedef VALUE value_type; - static value_type min() { - return std::numeric_limits<value_type>::min(); - } - static value_type max() { - return std::numeric_limits<value_type>::max(); - } - static const int kBase = BASE; -}; - -template<typename ITERATOR> -class BaseHexIteratorRangeToIntTraits - : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> { -}; - -template <typename ITERATOR> -class BaseHexIteratorRangeToUIntTraits - : public BaseIteratorRangeToNumberTraits<ITERATOR, uint32_t, 16> {}; - -template <typename ITERATOR> -class BaseHexIteratorRangeToInt64Traits - : public BaseIteratorRangeToNumberTraits<ITERATOR, int64_t, 16> {}; - -template <typename ITERATOR> -class BaseHexIteratorRangeToUInt64Traits - : public BaseIteratorRangeToNumberTraits<ITERATOR, uint64_t, 16> {}; - -typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator> - HexIteratorRangeToIntTraits; - -typedef BaseHexIteratorRangeToUIntTraits<StringPiece::const_iterator> - HexIteratorRangeToUIntTraits; - -typedef BaseHexIteratorRangeToInt64Traits<StringPiece::const_iterator> - HexIteratorRangeToInt64Traits; - -typedef BaseHexIteratorRangeToUInt64Traits<StringPiece::const_iterator> - HexIteratorRangeToUInt64Traits; - -template <typename STR> -bool HexStringToBytesT(const STR& input, std::vector<uint8_t>* output) { - DCHECK_EQ(output->size(), 0u); - size_t count = input.size(); - if (count == 0 || (count % 2) != 0) - return false; - for (uintptr_t i = 0; i < count / 2; ++i) { - uint8_t msb = 0; // most significant 4 bits - uint8_t lsb = 0; // least significant 4 bits - if (!CharToDigit<16>(input[i * 2], &msb) || - !CharToDigit<16>(input[i * 2 + 1], &lsb)) - return false; - output->push_back((msb << 4) | lsb); - } - return true; -} - -template <typename VALUE, int BASE> -class StringPieceToNumberTraits - : public BaseIteratorRangeToNumberTraits<StringPiece::const_iterator, - VALUE, - BASE> { -}; - -template <typename VALUE> -bool StringToIntImpl(const StringPiece& input, VALUE* output) { - return IteratorRangeToNumber<StringPieceToNumberTraits<VALUE, 10> >::Invoke( - input.begin(), input.end(), output); -} - -template <typename VALUE, int BASE> -class StringPiece16ToNumberTraits - : public BaseIteratorRangeToNumberTraits<StringPiece16::const_iterator, - VALUE, - BASE> { -}; - -template <typename VALUE> -bool String16ToIntImpl(const StringPiece16& input, VALUE* output) { - return IteratorRangeToNumber<StringPiece16ToNumberTraits<VALUE, 10> >::Invoke( - input.begin(), input.end(), output); -} - -} // namespace - -std::string IntToString(int value) { - return IntToStringT<std::string, int>::IntToString(value); -} - -string16 IntToString16(int value) { - return IntToStringT<string16, int>::IntToString(value); -} - -std::string UintToString(unsigned int value) { - return IntToStringT<std::string, unsigned int>::IntToString(value); -} - -string16 UintToString16(unsigned int value) { - return IntToStringT<string16, unsigned int>::IntToString(value); -} - -std::string Int64ToString(int64_t value) { - return IntToStringT<std::string, int64_t>::IntToString(value); -} - -string16 Int64ToString16(int64_t value) { - return IntToStringT<string16, int64_t>::IntToString(value); -} - -std::string Uint64ToString(uint64_t value) { - return IntToStringT<std::string, uint64_t>::IntToString(value); -} - -string16 Uint64ToString16(uint64_t value) { - return IntToStringT<string16, uint64_t>::IntToString(value); -} - -std::string SizeTToString(size_t value) { - return IntToStringT<std::string, size_t>::IntToString(value); -} - -string16 SizeTToString16(size_t value) { - return IntToStringT<string16, size_t>::IntToString(value); -} - -std::string DoubleToString(double value) { - // According to g_fmt.cc, it is sufficient to declare a buffer of size 32. - char buffer[32]; - dmg_fp::g_fmt(buffer, value); - return std::string(buffer); -} - -bool StringToInt(const StringPiece& input, int* output) { - return StringToIntImpl(input, output); -} - -bool StringToInt(const StringPiece16& input, int* output) { - return String16ToIntImpl(input, output); -} - -bool StringToUint(const StringPiece& input, unsigned* output) { - return StringToIntImpl(input, output); -} - -bool StringToUint(const StringPiece16& input, unsigned* output) { - return String16ToIntImpl(input, output); -} - -bool StringToInt64(const StringPiece& input, int64_t* output) { - return StringToIntImpl(input, output); -} - -bool StringToInt64(const StringPiece16& input, int64_t* output) { - return String16ToIntImpl(input, output); -} - -bool StringToUint64(const StringPiece& input, uint64_t* output) { - return StringToIntImpl(input, output); -} - -bool StringToUint64(const StringPiece16& input, uint64_t* output) { - return String16ToIntImpl(input, output); -} - -bool StringToSizeT(const StringPiece& input, size_t* output) { - return StringToIntImpl(input, output); -} - -bool StringToSizeT(const StringPiece16& input, size_t* output) { - return String16ToIntImpl(input, output); -} - -bool StringToDouble(const std::string& input, double* output) { - // Thread-safe? It is on at least Mac, Linux, and Windows. - ScopedClearErrno clear_errno; - - char* endptr = NULL; - *output = dmg_fp::strtod(input.c_str(), &endptr); - - // Cases to return false: - // - If errno is ERANGE, there was an overflow or underflow. - // - If the input string is empty, there was nothing to parse. - // - If endptr does not point to the end of the string, there are either - // characters remaining in the string after a parsed number, or the string - // does not begin with a parseable number. endptr is compared to the - // expected end given the string's stated length to correctly catch cases - // where the string contains embedded NUL characters. - // - If the first character is a space, there was leading whitespace - return errno == 0 && - !input.empty() && - input.c_str() + input.length() == endptr && - !isspace(input[0]); -} - -// Note: if you need to add String16ToDouble, first ask yourself if it's -// really necessary. If it is, probably the best implementation here is to -// convert to 8-bit and then use the 8-bit version. - -// Note: if you need to add an iterator range version of StringToDouble, first -// ask yourself if it's really necessary. If it is, probably the best -// implementation here is to instantiate a string and use the string version. - -std::string HexEncode(const void* bytes, size_t size) { - static const char kHexChars[] = "0123456789ABCDEF"; - - // Each input byte creates two output hex characters. - std::string ret(size * 2, '\0'); - - for (size_t i = 0; i < size; ++i) { - char b = reinterpret_cast<const char*>(bytes)[i]; - ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; - ret[(i * 2) + 1] = kHexChars[b & 0xf]; - } - return ret; -} - -bool HexStringToInt(const StringPiece& input, int* output) { - return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke( - input.begin(), input.end(), output); -} - -bool HexStringToUInt(const StringPiece& input, uint32_t* output) { - return IteratorRangeToNumber<HexIteratorRangeToUIntTraits>::Invoke( - input.begin(), input.end(), output); -} - -bool HexStringToInt64(const StringPiece& input, int64_t* output) { - return IteratorRangeToNumber<HexIteratorRangeToInt64Traits>::Invoke( - input.begin(), input.end(), output); -} - -bool HexStringToUInt64(const StringPiece& input, uint64_t* output) { - return IteratorRangeToNumber<HexIteratorRangeToUInt64Traits>::Invoke( - input.begin(), input.end(), output); -} - -bool HexStringToBytes(const std::string& input, std::vector<uint8_t>* output) { - return HexStringToBytesT(input, output); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/strings/string_number_conversions.h b/security/sandbox/chromium/base/strings/string_number_conversions.h deleted file mode 100644 index 1265f0dcb..000000000 --- a/security/sandbox/chromium/base/strings/string_number_conversions.h +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_ -#define BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/base_export.h" -#include "base/strings/string16.h" -#include "base/strings/string_piece.h" - -// ---------------------------------------------------------------------------- -// IMPORTANT MESSAGE FROM YOUR SPONSOR -// -// This file contains no "wstring" variants. New code should use string16. If -// you need to make old code work, use the UTF8 version and convert. Please do -// not add wstring variants. -// -// Please do not add "convenience" functions for converting strings to integers -// that return the value and ignore success/failure. That encourages people to -// write code that doesn't properly handle the error conditions. -// ---------------------------------------------------------------------------- - -namespace base { - -// Number -> string conversions ------------------------------------------------ - -BASE_EXPORT std::string IntToString(int value); -BASE_EXPORT string16 IntToString16(int value); - -BASE_EXPORT std::string UintToString(unsigned value); -BASE_EXPORT string16 UintToString16(unsigned value); - -BASE_EXPORT std::string Int64ToString(int64_t value); -BASE_EXPORT string16 Int64ToString16(int64_t value); - -BASE_EXPORT std::string Uint64ToString(uint64_t value); -BASE_EXPORT string16 Uint64ToString16(uint64_t value); - -BASE_EXPORT std::string SizeTToString(size_t value); -BASE_EXPORT string16 SizeTToString16(size_t value); - -// DoubleToString converts the double to a string format that ignores the -// locale. If you want to use locale specific formatting, use ICU. -BASE_EXPORT std::string DoubleToString(double value); - -// String -> number conversions ------------------------------------------------ - -// Perform a best-effort conversion of the input string to a numeric type, -// setting |*output| to the result of the conversion. Returns true for -// "perfect" conversions; returns false in the following cases: -// - Overflow. |*output| will be set to the maximum value supported -// by the data type. -// - Underflow. |*output| will be set to the minimum value supported -// by the data type. -// - Trailing characters in the string after parsing the number. |*output| -// will be set to the value of the number that was parsed. -// - Leading whitespace in the string before parsing the number. |*output| will -// be set to the value of the number that was parsed. -// - No characters parseable as a number at the beginning of the string. -// |*output| will be set to 0. -// - Empty string. |*output| will be set to 0. -// WARNING: Will write to |output| even when returning false. -// Read the comments above carefully. -BASE_EXPORT bool StringToInt(const StringPiece& input, int* output); -BASE_EXPORT bool StringToInt(const StringPiece16& input, int* output); - -BASE_EXPORT bool StringToUint(const StringPiece& input, unsigned* output); -BASE_EXPORT bool StringToUint(const StringPiece16& input, unsigned* output); - -BASE_EXPORT bool StringToInt64(const StringPiece& input, int64_t* output); -BASE_EXPORT bool StringToInt64(const StringPiece16& input, int64_t* output); - -BASE_EXPORT bool StringToUint64(const StringPiece& input, uint64_t* output); -BASE_EXPORT bool StringToUint64(const StringPiece16& input, uint64_t* output); - -BASE_EXPORT bool StringToSizeT(const StringPiece& input, size_t* output); -BASE_EXPORT bool StringToSizeT(const StringPiece16& input, size_t* output); - -// For floating-point conversions, only conversions of input strings in decimal -// form are defined to work. Behavior with strings representing floating-point -// numbers in hexadecimal, and strings representing non-finite values (such as -// NaN and inf) is undefined. Otherwise, these behave the same as the integral -// variants. This expects the input string to NOT be specific to the locale. -// If your input is locale specific, use ICU to read the number. -// WARNING: Will write to |output| even when returning false. -// Read the comments here and above StringToInt() carefully. -BASE_EXPORT bool StringToDouble(const std::string& input, double* output); - -// Hex encoding ---------------------------------------------------------------- - -// Returns a hex string representation of a binary buffer. The returned hex -// string will be in upper case. This function does not check if |size| is -// within reasonable limits since it's written with trusted data in mind. If -// you suspect that the data you want to format might be large, the absolute -// max size for |size| should be is -// std::numeric_limits<size_t>::max() / 2 -BASE_EXPORT std::string HexEncode(const void* bytes, size_t size); - -// Best effort conversion, see StringToInt above for restrictions. -// Will only successful parse hex values that will fit into |output|, i.e. -// -0x80000000 < |input| < 0x7FFFFFFF. -BASE_EXPORT bool HexStringToInt(const StringPiece& input, int* output); - -// Best effort conversion, see StringToInt above for restrictions. -// Will only successful parse hex values that will fit into |output|, i.e. -// 0x00000000 < |input| < 0xFFFFFFFF. -// The string is not required to start with 0x. -BASE_EXPORT bool HexStringToUInt(const StringPiece& input, uint32_t* output); - -// Best effort conversion, see StringToInt above for restrictions. -// Will only successful parse hex values that will fit into |output|, i.e. -// -0x8000000000000000 < |input| < 0x7FFFFFFFFFFFFFFF. -BASE_EXPORT bool HexStringToInt64(const StringPiece& input, int64_t* output); - -// Best effort conversion, see StringToInt above for restrictions. -// Will only successful parse hex values that will fit into |output|, i.e. -// 0x0000000000000000 < |input| < 0xFFFFFFFFFFFFFFFF. -// The string is not required to start with 0x. -BASE_EXPORT bool HexStringToUInt64(const StringPiece& input, uint64_t* output); - -// Similar to the previous functions, except that output is a vector of bytes. -// |*output| will contain as many bytes as were successfully parsed prior to the -// error. There is no overflow, but input.size() must be evenly divisible by 2. -// Leading 0x or +/- are not allowed. -BASE_EXPORT bool HexStringToBytes(const std::string& input, - std::vector<uint8_t>* output); - -} // namespace base - -#endif // BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_ diff --git a/security/sandbox/chromium/base/strings/string_piece.cc b/security/sandbox/chromium/base/strings/string_piece.cc deleted file mode 100644 index c26bb3652..000000000 --- a/security/sandbox/chromium/base/strings/string_piece.cc +++ /dev/null @@ -1,452 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Copied from strings/stringpiece.cc with modifications - -#include "base/strings/string_piece.h" - -#include <limits.h> - -#include <algorithm> -#include <ostream> - -#include "base/logging.h" - -namespace base { -namespace { - -// For each character in characters_wanted, sets the index corresponding -// to the ASCII code of that character to 1 in table. This is used by -// the find_.*_of methods below to tell whether or not a character is in -// the lookup table in constant time. -// The argument `table' must be an array that is large enough to hold all -// the possible values of an unsigned char. Thus it should be be declared -// as follows: -// bool table[UCHAR_MAX + 1] -inline void BuildLookupTable(const StringPiece& characters_wanted, - bool* table) { - const size_t length = characters_wanted.length(); - const char* const data = characters_wanted.data(); - for (size_t i = 0; i < length; ++i) { - table[static_cast<unsigned char>(data[i])] = true; - } -} - -} // namespace - -// MSVC doesn't like complex extern templates and DLLs. -#if !defined(COMPILER_MSVC) -template class BasicStringPiece<std::string>; -template class BasicStringPiece<string16>; -#endif - -bool operator==(const StringPiece& x, const StringPiece& y) { - if (x.size() != y.size()) - return false; - - return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0; -} - -std::ostream& operator<<(std::ostream& o, const StringPiece& piece) { - o.write(piece.data(), static_cast<std::streamsize>(piece.size())); - return o; -} - -namespace internal { - -template<typename STR> -void CopyToStringT(const BasicStringPiece<STR>& self, STR* target) { - if (self.empty()) - target->clear(); - else - target->assign(self.data(), self.size()); -} - -void CopyToString(const StringPiece& self, std::string* target) { - CopyToStringT(self, target); -} - -void CopyToString(const StringPiece16& self, string16* target) { - CopyToStringT(self, target); -} - -template<typename STR> -void AppendToStringT(const BasicStringPiece<STR>& self, STR* target) { - if (!self.empty()) - target->append(self.data(), self.size()); -} - -void AppendToString(const StringPiece& self, std::string* target) { - AppendToStringT(self, target); -} - -void AppendToString(const StringPiece16& self, string16* target) { - AppendToStringT(self, target); -} - -template<typename STR> -size_t copyT(const BasicStringPiece<STR>& self, - typename STR::value_type* buf, - size_t n, - size_t pos) { - size_t ret = std::min(self.size() - pos, n); - memcpy(buf, self.data() + pos, ret * sizeof(typename STR::value_type)); - return ret; -} - -size_t copy(const StringPiece& self, char* buf, size_t n, size_t pos) { - return copyT(self, buf, n, pos); -} - -size_t copy(const StringPiece16& self, char16* buf, size_t n, size_t pos) { - return copyT(self, buf, n, pos); -} - -template<typename STR> -size_t findT(const BasicStringPiece<STR>& self, - const BasicStringPiece<STR>& s, - size_t pos) { - if (pos > self.size()) - return BasicStringPiece<STR>::npos; - - typename BasicStringPiece<STR>::const_iterator result = - std::search(self.begin() + pos, self.end(), s.begin(), s.end()); - const size_t xpos = - static_cast<size_t>(result - self.begin()); - return xpos + s.size() <= self.size() ? xpos : BasicStringPiece<STR>::npos; -} - -size_t find(const StringPiece& self, const StringPiece& s, size_t pos) { - return findT(self, s, pos); -} - -size_t find(const StringPiece16& self, const StringPiece16& s, size_t pos) { - return findT(self, s, pos); -} - -template<typename STR> -size_t findT(const BasicStringPiece<STR>& self, - typename STR::value_type c, - size_t pos) { - if (pos >= self.size()) - return BasicStringPiece<STR>::npos; - - typename BasicStringPiece<STR>::const_iterator result = - std::find(self.begin() + pos, self.end(), c); - return result != self.end() ? - static_cast<size_t>(result - self.begin()) : BasicStringPiece<STR>::npos; -} - -size_t find(const StringPiece& self, char c, size_t pos) { - return findT(self, c, pos); -} - -size_t find(const StringPiece16& self, char16 c, size_t pos) { - return findT(self, c, pos); -} - -template<typename STR> -size_t rfindT(const BasicStringPiece<STR>& self, - const BasicStringPiece<STR>& s, - size_t pos) { - if (self.size() < s.size()) - return BasicStringPiece<STR>::npos; - - if (s.empty()) - return std::min(self.size(), pos); - - typename BasicStringPiece<STR>::const_iterator last = - self.begin() + std::min(self.size() - s.size(), pos) + s.size(); - typename BasicStringPiece<STR>::const_iterator result = - std::find_end(self.begin(), last, s.begin(), s.end()); - return result != last ? - static_cast<size_t>(result - self.begin()) : BasicStringPiece<STR>::npos; -} - -size_t rfind(const StringPiece& self, const StringPiece& s, size_t pos) { - return rfindT(self, s, pos); -} - -size_t rfind(const StringPiece16& self, const StringPiece16& s, size_t pos) { - return rfindT(self, s, pos); -} - -template<typename STR> -size_t rfindT(const BasicStringPiece<STR>& self, - typename STR::value_type c, - size_t pos) { - if (self.size() == 0) - return BasicStringPiece<STR>::npos; - - for (size_t i = std::min(pos, self.size() - 1); ; - --i) { - if (self.data()[i] == c) - return i; - if (i == 0) - break; - } - return BasicStringPiece<STR>::npos; -} - -size_t rfind(const StringPiece& self, char c, size_t pos) { - return rfindT(self, c, pos); -} - -size_t rfind(const StringPiece16& self, char16 c, size_t pos) { - return rfindT(self, c, pos); -} - -// 8-bit version using lookup table. -size_t find_first_of(const StringPiece& self, - const StringPiece& s, - size_t pos) { - if (self.size() == 0 || s.size() == 0) - return StringPiece::npos; - - // Avoid the cost of BuildLookupTable() for a single-character search. - if (s.size() == 1) - return find(self, s.data()[0], pos); - - bool lookup[UCHAR_MAX + 1] = { false }; - BuildLookupTable(s, lookup); - for (size_t i = pos; i < self.size(); ++i) { - if (lookup[static_cast<unsigned char>(self.data()[i])]) { - return i; - } - } - return StringPiece::npos; -} - -// 16-bit brute force version. -size_t find_first_of(const StringPiece16& self, - const StringPiece16& s, - size_t pos) { - StringPiece16::const_iterator found = - std::find_first_of(self.begin() + pos, self.end(), s.begin(), s.end()); - if (found == self.end()) - return StringPiece16::npos; - return found - self.begin(); -} - -// 8-bit version using lookup table. -size_t find_first_not_of(const StringPiece& self, - const StringPiece& s, - size_t pos) { - if (self.size() == 0) - return StringPiece::npos; - - if (s.size() == 0) - return 0; - - // Avoid the cost of BuildLookupTable() for a single-character search. - if (s.size() == 1) - return find_first_not_of(self, s.data()[0], pos); - - bool lookup[UCHAR_MAX + 1] = { false }; - BuildLookupTable(s, lookup); - for (size_t i = pos; i < self.size(); ++i) { - if (!lookup[static_cast<unsigned char>(self.data()[i])]) { - return i; - } - } - return StringPiece::npos; -} - -// 16-bit brute-force version. -BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, - const StringPiece16& s, - size_t pos) { - if (self.size() == 0) - return StringPiece16::npos; - - for (size_t self_i = pos; self_i < self.size(); ++self_i) { - bool found = false; - for (size_t s_i = 0; s_i < s.size(); ++s_i) { - if (self[self_i] == s[s_i]) { - found = true; - break; - } - } - if (!found) - return self_i; - } - return StringPiece16::npos; -} - -template<typename STR> -size_t find_first_not_ofT(const BasicStringPiece<STR>& self, - typename STR::value_type c, - size_t pos) { - if (self.size() == 0) - return BasicStringPiece<STR>::npos; - - for (; pos < self.size(); ++pos) { - if (self.data()[pos] != c) { - return pos; - } - } - return BasicStringPiece<STR>::npos; -} - -size_t find_first_not_of(const StringPiece& self, - char c, - size_t pos) { - return find_first_not_ofT(self, c, pos); -} - -size_t find_first_not_of(const StringPiece16& self, - char16 c, - size_t pos) { - return find_first_not_ofT(self, c, pos); -} - -// 8-bit version using lookup table. -size_t find_last_of(const StringPiece& self, const StringPiece& s, size_t pos) { - if (self.size() == 0 || s.size() == 0) - return StringPiece::npos; - - // Avoid the cost of BuildLookupTable() for a single-character search. - if (s.size() == 1) - return rfind(self, s.data()[0], pos); - - bool lookup[UCHAR_MAX + 1] = { false }; - BuildLookupTable(s, lookup); - for (size_t i = std::min(pos, self.size() - 1); ; --i) { - if (lookup[static_cast<unsigned char>(self.data()[i])]) - return i; - if (i == 0) - break; - } - return StringPiece::npos; -} - -// 16-bit brute-force version. -size_t find_last_of(const StringPiece16& self, - const StringPiece16& s, - size_t pos) { - if (self.size() == 0) - return StringPiece16::npos; - - for (size_t self_i = std::min(pos, self.size() - 1); ; - --self_i) { - for (size_t s_i = 0; s_i < s.size(); s_i++) { - if (self.data()[self_i] == s[s_i]) - return self_i; - } - if (self_i == 0) - break; - } - return StringPiece16::npos; -} - -// 8-bit version using lookup table. -size_t find_last_not_of(const StringPiece& self, - const StringPiece& s, - size_t pos) { - if (self.size() == 0) - return StringPiece::npos; - - size_t i = std::min(pos, self.size() - 1); - if (s.size() == 0) - return i; - - // Avoid the cost of BuildLookupTable() for a single-character search. - if (s.size() == 1) - return find_last_not_of(self, s.data()[0], pos); - - bool lookup[UCHAR_MAX + 1] = { false }; - BuildLookupTable(s, lookup); - for (; ; --i) { - if (!lookup[static_cast<unsigned char>(self.data()[i])]) - return i; - if (i == 0) - break; - } - return StringPiece::npos; -} - -// 16-bit brute-force version. -size_t find_last_not_of(const StringPiece16& self, - const StringPiece16& s, - size_t pos) { - if (self.size() == 0) - return StringPiece::npos; - - for (size_t self_i = std::min(pos, self.size() - 1); ; --self_i) { - bool found = false; - for (size_t s_i = 0; s_i < s.size(); s_i++) { - if (self.data()[self_i] == s[s_i]) { - found = true; - break; - } - } - if (!found) - return self_i; - if (self_i == 0) - break; - } - return StringPiece16::npos; -} - -template<typename STR> -size_t find_last_not_ofT(const BasicStringPiece<STR>& self, - typename STR::value_type c, - size_t pos) { - if (self.size() == 0) - return BasicStringPiece<STR>::npos; - - for (size_t i = std::min(pos, self.size() - 1); ; --i) { - if (self.data()[i] != c) - return i; - if (i == 0) - break; - } - return BasicStringPiece<STR>::npos; -} - -size_t find_last_not_of(const StringPiece& self, - char c, - size_t pos) { - return find_last_not_ofT(self, c, pos); -} - -size_t find_last_not_of(const StringPiece16& self, - char16 c, - size_t pos) { - return find_last_not_ofT(self, c, pos); -} - -template<typename STR> -BasicStringPiece<STR> substrT(const BasicStringPiece<STR>& self, - size_t pos, - size_t n) { - if (pos > self.size()) pos = self.size(); - if (n > self.size() - pos) n = self.size() - pos; - return BasicStringPiece<STR>(self.data() + pos, n); -} - -StringPiece substr(const StringPiece& self, - size_t pos, - size_t n) { - return substrT(self, pos, n); -} - -StringPiece16 substr(const StringPiece16& self, - size_t pos, - size_t n) { - return substrT(self, pos, n); -} - -#if DCHECK_IS_ON() -void AssertIteratorsInOrder(std::string::const_iterator begin, - std::string::const_iterator end) { - DCHECK(begin <= end) << "StringPiece iterators swapped or invalid."; -} -void AssertIteratorsInOrder(string16::const_iterator begin, - string16::const_iterator end) { - DCHECK(begin <= end) << "StringPiece iterators swapped or invalid."; -} -#endif - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/strings/string_piece.h b/security/sandbox/chromium/base/strings/string_piece.h deleted file mode 100644 index 31e7596d1..000000000 --- a/security/sandbox/chromium/base/strings/string_piece.h +++ /dev/null @@ -1,469 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Copied from strings/stringpiece.h with modifications -// -// A string-like object that points to a sized piece of memory. -// -// You can use StringPiece as a function or method parameter. A StringPiece -// parameter can receive a double-quoted string literal argument, a "const -// char*" argument, a string argument, or a StringPiece argument with no data -// copying. Systematic use of StringPiece for arguments reduces data -// copies and strlen() calls. -// -// Prefer passing StringPieces by value: -// void MyFunction(StringPiece arg); -// If circumstances require, you may also pass by const reference: -// void MyFunction(const StringPiece& arg); // not preferred -// Both of these have the same lifetime semantics. Passing by value -// generates slightly smaller code. For more discussion, Googlers can see -// the thread go/stringpiecebyvalue on c-users. - -#ifndef BASE_STRINGS_STRING_PIECE_H_ -#define BASE_STRINGS_STRING_PIECE_H_ - -#include <stddef.h> - -#include <iosfwd> -#include <string> - -#include "base/base_export.h" -#include "base/containers/hash_tables.h" -#include "base/logging.h" -#include "base/strings/string16.h" - -namespace base { - -template <typename STRING_TYPE> class BasicStringPiece; -typedef BasicStringPiece<std::string> StringPiece; -typedef BasicStringPiece<string16> StringPiece16; - -// internal -------------------------------------------------------------------- - -// Many of the StringPiece functions use different implementations for the -// 8-bit and 16-bit versions, and we don't want lots of template expansions in -// this (very common) header that will slow down compilation. -// -// So here we define overloaded functions called by the StringPiece template. -// For those that share an implementation, the two versions will expand to a -// template internal to the .cc file. -namespace internal { - -BASE_EXPORT void CopyToString(const StringPiece& self, std::string* target); -BASE_EXPORT void CopyToString(const StringPiece16& self, string16* target); - -BASE_EXPORT void AppendToString(const StringPiece& self, std::string* target); -BASE_EXPORT void AppendToString(const StringPiece16& self, string16* target); - -BASE_EXPORT size_t copy(const StringPiece& self, - char* buf, - size_t n, - size_t pos); -BASE_EXPORT size_t copy(const StringPiece16& self, - char16* buf, - size_t n, - size_t pos); - -BASE_EXPORT size_t find(const StringPiece& self, - const StringPiece& s, - size_t pos); -BASE_EXPORT size_t find(const StringPiece16& self, - const StringPiece16& s, - size_t pos); -BASE_EXPORT size_t find(const StringPiece& self, - char c, - size_t pos); -BASE_EXPORT size_t find(const StringPiece16& self, - char16 c, - size_t pos); - -BASE_EXPORT size_t rfind(const StringPiece& self, - const StringPiece& s, - size_t pos); -BASE_EXPORT size_t rfind(const StringPiece16& self, - const StringPiece16& s, - size_t pos); -BASE_EXPORT size_t rfind(const StringPiece& self, - char c, - size_t pos); -BASE_EXPORT size_t rfind(const StringPiece16& self, - char16 c, - size_t pos); - -BASE_EXPORT size_t find_first_of(const StringPiece& self, - const StringPiece& s, - size_t pos); -BASE_EXPORT size_t find_first_of(const StringPiece16& self, - const StringPiece16& s, - size_t pos); - -BASE_EXPORT size_t find_first_not_of(const StringPiece& self, - const StringPiece& s, - size_t pos); -BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, - const StringPiece16& s, - size_t pos); -BASE_EXPORT size_t find_first_not_of(const StringPiece& self, - char c, - size_t pos); -BASE_EXPORT size_t find_first_not_of(const StringPiece16& self, - char16 c, - size_t pos); - -BASE_EXPORT size_t find_last_of(const StringPiece& self, - const StringPiece& s, - size_t pos); -BASE_EXPORT size_t find_last_of(const StringPiece16& self, - const StringPiece16& s, - size_t pos); -BASE_EXPORT size_t find_last_of(const StringPiece& self, - char c, - size_t pos); -BASE_EXPORT size_t find_last_of(const StringPiece16& self, - char16 c, - size_t pos); - -BASE_EXPORT size_t find_last_not_of(const StringPiece& self, - const StringPiece& s, - size_t pos); -BASE_EXPORT size_t find_last_not_of(const StringPiece16& self, - const StringPiece16& s, - size_t pos); -BASE_EXPORT size_t find_last_not_of(const StringPiece16& self, - char16 c, - size_t pos); -BASE_EXPORT size_t find_last_not_of(const StringPiece& self, - char c, - size_t pos); - -BASE_EXPORT StringPiece substr(const StringPiece& self, - size_t pos, - size_t n); -BASE_EXPORT StringPiece16 substr(const StringPiece16& self, - size_t pos, - size_t n); - -#if DCHECK_IS_ON() -// Asserts that begin <= end to catch some errors with iterator usage. -BASE_EXPORT void AssertIteratorsInOrder(std::string::const_iterator begin, - std::string::const_iterator end); -BASE_EXPORT void AssertIteratorsInOrder(string16::const_iterator begin, - string16::const_iterator end); -#endif - -} // namespace internal - -// BasicStringPiece ------------------------------------------------------------ - -// Defines the types, methods, operators, and data members common to both -// StringPiece and StringPiece16. Do not refer to this class directly, but -// rather to BasicStringPiece, StringPiece, or StringPiece16. -// -// This is templatized by string class type rather than character type, so -// BasicStringPiece<std::string> or BasicStringPiece<base::string16>. -template <typename STRING_TYPE> class BasicStringPiece { - public: - // Standard STL container boilerplate. - typedef size_t size_type; - typedef typename STRING_TYPE::value_type value_type; - typedef const value_type* pointer; - typedef const value_type& reference; - typedef const value_type& const_reference; - typedef ptrdiff_t difference_type; - typedef const value_type* const_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - - static const size_type npos; - - public: - // We provide non-explicit singleton constructors so users can pass - // in a "const char*" or a "string" wherever a "StringPiece" is - // expected (likewise for char16, string16, StringPiece16). - BasicStringPiece() : ptr_(NULL), length_(0) {} - BasicStringPiece(const value_type* str) - : ptr_(str), - length_((str == NULL) ? 0 : STRING_TYPE::traits_type::length(str)) {} - BasicStringPiece(const STRING_TYPE& str) - : ptr_(str.data()), length_(str.size()) {} - BasicStringPiece(const value_type* offset, size_type len) - : ptr_(offset), length_(len) {} - BasicStringPiece(const typename STRING_TYPE::const_iterator& begin, - const typename STRING_TYPE::const_iterator& end) { -#if DCHECK_IS_ON() - // This assertion is done out-of-line to avoid bringing in logging.h and - // instantiating logging macros for every instantiation. - internal::AssertIteratorsInOrder(begin, end); -#endif - length_ = static_cast<size_t>(std::distance(begin, end)); - - // The length test before assignment is to avoid dereferencing an iterator - // that may point to the end() of a string. - ptr_ = length_ > 0 ? &*begin : nullptr; - } - - // data() may return a pointer to a buffer with embedded NULs, and the - // returned buffer may or may not be null terminated. Therefore it is - // typically a mistake to pass data() to a routine that expects a NUL - // terminated string. - const value_type* data() const { return ptr_; } - size_type size() const { return length_; } - size_type length() const { return length_; } - bool empty() const { return length_ == 0; } - - void clear() { - ptr_ = NULL; - length_ = 0; - } - void set(const value_type* data, size_type len) { - ptr_ = data; - length_ = len; - } - void set(const value_type* str) { - ptr_ = str; - length_ = str ? STRING_TYPE::traits_type::length(str) : 0; - } - - value_type operator[](size_type i) const { return ptr_[i]; } - - void remove_prefix(size_type n) { - ptr_ += n; - length_ -= n; - } - - void remove_suffix(size_type n) { - length_ -= n; - } - - int compare(const BasicStringPiece<STRING_TYPE>& x) const { - int r = wordmemcmp( - ptr_, x.ptr_, (length_ < x.length_ ? length_ : x.length_)); - if (r == 0) { - if (length_ < x.length_) r = -1; - else if (length_ > x.length_) r = +1; - } - return r; - } - - STRING_TYPE as_string() const { - // std::string doesn't like to take a NULL pointer even with a 0 size. - return empty() ? STRING_TYPE() : STRING_TYPE(data(), size()); - } - - const_iterator begin() const { return ptr_; } - const_iterator end() const { return ptr_ + length_; } - const_reverse_iterator rbegin() const { - return const_reverse_iterator(ptr_ + length_); - } - const_reverse_iterator rend() const { - return const_reverse_iterator(ptr_); - } - - size_type max_size() const { return length_; } - size_type capacity() const { return length_; } - - static int wordmemcmp(const value_type* p, - const value_type* p2, - size_type N) { - return STRING_TYPE::traits_type::compare(p, p2, N); - } - - // Sets the value of the given string target type to be the current string. - // This saves a temporary over doing |a = b.as_string()| - void CopyToString(STRING_TYPE* target) const { - internal::CopyToString(*this, target); - } - - void AppendToString(STRING_TYPE* target) const { - internal::AppendToString(*this, target); - } - - size_type copy(value_type* buf, size_type n, size_type pos = 0) const { - return internal::copy(*this, buf, n, pos); - } - - // Does "this" start with "x" - bool starts_with(const BasicStringPiece& x) const { - return ((this->length_ >= x.length_) && - (wordmemcmp(this->ptr_, x.ptr_, x.length_) == 0)); - } - - // Does "this" end with "x" - bool ends_with(const BasicStringPiece& x) const { - return ((this->length_ >= x.length_) && - (wordmemcmp(this->ptr_ + (this->length_-x.length_), - x.ptr_, x.length_) == 0)); - } - - // find: Search for a character or substring at a given offset. - size_type find(const BasicStringPiece<STRING_TYPE>& s, - size_type pos = 0) const { - return internal::find(*this, s, pos); - } - size_type find(value_type c, size_type pos = 0) const { - return internal::find(*this, c, pos); - } - - // rfind: Reverse find. - size_type rfind(const BasicStringPiece& s, - size_type pos = BasicStringPiece::npos) const { - return internal::rfind(*this, s, pos); - } - size_type rfind(value_type c, size_type pos = BasicStringPiece::npos) const { - return internal::rfind(*this, c, pos); - } - - // find_first_of: Find the first occurence of one of a set of characters. - size_type find_first_of(const BasicStringPiece& s, - size_type pos = 0) const { - return internal::find_first_of(*this, s, pos); - } - size_type find_first_of(value_type c, size_type pos = 0) const { - return find(c, pos); - } - - // find_first_not_of: Find the first occurence not of a set of characters. - size_type find_first_not_of(const BasicStringPiece& s, - size_type pos = 0) const { - return internal::find_first_not_of(*this, s, pos); - } - size_type find_first_not_of(value_type c, size_type pos = 0) const { - return internal::find_first_not_of(*this, c, pos); - } - - // find_last_of: Find the last occurence of one of a set of characters. - size_type find_last_of(const BasicStringPiece& s, - size_type pos = BasicStringPiece::npos) const { - return internal::find_last_of(*this, s, pos); - } - size_type find_last_of(value_type c, - size_type pos = BasicStringPiece::npos) const { - return rfind(c, pos); - } - - // find_last_not_of: Find the last occurence not of a set of characters. - size_type find_last_not_of(const BasicStringPiece& s, - size_type pos = BasicStringPiece::npos) const { - return internal::find_last_not_of(*this, s, pos); - } - size_type find_last_not_of(value_type c, - size_type pos = BasicStringPiece::npos) const { - return internal::find_last_not_of(*this, c, pos); - } - - // substr. - BasicStringPiece substr(size_type pos, - size_type n = BasicStringPiece::npos) const { - return internal::substr(*this, pos, n); - } - - protected: - const value_type* ptr_; - size_type length_; -}; - -template <typename STRING_TYPE> -const typename BasicStringPiece<STRING_TYPE>::size_type -BasicStringPiece<STRING_TYPE>::npos = - typename BasicStringPiece<STRING_TYPE>::size_type(-1); - -// MSVC doesn't like complex extern templates and DLLs. -#if !defined(COMPILER_MSVC) -extern template class BASE_EXPORT BasicStringPiece<std::string>; -extern template class BASE_EXPORT BasicStringPiece<string16>; -#endif - -// StingPiece operators -------------------------------------------------------- - -BASE_EXPORT bool operator==(const StringPiece& x, const StringPiece& y); - -inline bool operator!=(const StringPiece& x, const StringPiece& y) { - return !(x == y); -} - -inline bool operator<(const StringPiece& x, const StringPiece& y) { - const int r = StringPiece::wordmemcmp( - x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); - return ((r < 0) || ((r == 0) && (x.size() < y.size()))); -} - -inline bool operator>(const StringPiece& x, const StringPiece& y) { - return y < x; -} - -inline bool operator<=(const StringPiece& x, const StringPiece& y) { - return !(x > y); -} - -inline bool operator>=(const StringPiece& x, const StringPiece& y) { - return !(x < y); -} - -// StringPiece16 operators ----------------------------------------------------- - -inline bool operator==(const StringPiece16& x, const StringPiece16& y) { - if (x.size() != y.size()) - return false; - - return StringPiece16::wordmemcmp(x.data(), y.data(), x.size()) == 0; -} - -inline bool operator!=(const StringPiece16& x, const StringPiece16& y) { - return !(x == y); -} - -inline bool operator<(const StringPiece16& x, const StringPiece16& y) { - const int r = StringPiece16::wordmemcmp( - x.data(), y.data(), (x.size() < y.size() ? x.size() : y.size())); - return ((r < 0) || ((r == 0) && (x.size() < y.size()))); -} - -inline bool operator>(const StringPiece16& x, const StringPiece16& y) { - return y < x; -} - -inline bool operator<=(const StringPiece16& x, const StringPiece16& y) { - return !(x > y); -} - -inline bool operator>=(const StringPiece16& x, const StringPiece16& y) { - return !(x < y); -} - -BASE_EXPORT std::ostream& operator<<(std::ostream& o, - const StringPiece& piece); - -} // namespace base - -// Hashing --------------------------------------------------------------------- - -// We provide appropriate hash functions so StringPiece and StringPiece16 can -// be used as keys in hash sets and maps. - -// This hash function is copied from base/containers/hash_tables.h. We don't -// use the ones already defined for string and string16 directly because it -// would require the string constructors to be called, which we don't want. -#define HASH_STRING_PIECE(StringPieceType, string_piece) \ - std::size_t result = 0; \ - for (StringPieceType::const_iterator i = string_piece.begin(); \ - i != string_piece.end(); ++i) \ - result = (result * 131) + *i; \ - return result; \ - -namespace BASE_HASH_NAMESPACE { - -template<> -struct hash<base::StringPiece> { - std::size_t operator()(const base::StringPiece& sp) const { - HASH_STRING_PIECE(base::StringPiece, sp); - } -}; -template<> -struct hash<base::StringPiece16> { - std::size_t operator()(const base::StringPiece16& sp16) const { - HASH_STRING_PIECE(base::StringPiece16, sp16); - } -}; - -} // namespace BASE_HASH_NAMESPACE - -#endif // BASE_STRINGS_STRING_PIECE_H_ diff --git a/security/sandbox/chromium/base/strings/string_split.cc b/security/sandbox/chromium/base/strings/string_split.cc deleted file mode 100644 index 6c949b989..000000000 --- a/security/sandbox/chromium/base/strings/string_split.cc +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/string_split.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "base/third_party/icu/icu_utf.h" - -namespace base { - -namespace { - -// PieceToOutputType converts a StringPiece as needed to a given output type, -// which is either the same type of StringPiece (a NOP) or the corresponding -// non-piece string type. -// -// The default converter is a NOP, it works when the OutputType is the -// correct StringPiece. -template<typename Str, typename OutputType> -OutputType PieceToOutputType(BasicStringPiece<Str> piece) { - return piece; -} -template<> // Convert StringPiece to std::string -std::string PieceToOutputType<std::string, std::string>(StringPiece piece) { - return piece.as_string(); -} -template<> // Convert StringPiece16 to string16. -string16 PieceToOutputType<string16, string16>(StringPiece16 piece) { - return piece.as_string(); -} - -// Returns either the ASCII or UTF-16 whitespace. -template<typename Str> BasicStringPiece<Str> WhitespaceForType(); -template<> StringPiece16 WhitespaceForType<string16>() { - return kWhitespaceUTF16; -} -template<> StringPiece WhitespaceForType<std::string>() { - return kWhitespaceASCII; -} - -// Optimize the single-character case to call find() on the string instead, -// since this is the common case and can be made faster. This could have been -// done with template specialization too, but would have been less clear. -// -// There is no corresponding FindFirstNotOf because StringPiece already -// implements these different versions that do the optimized searching. -size_t FindFirstOf(StringPiece piece, char c, size_t pos) { - return piece.find(c, pos); -} -size_t FindFirstOf(StringPiece16 piece, char16 c, size_t pos) { - return piece.find(c, pos); -} -size_t FindFirstOf(StringPiece piece, StringPiece one_of, size_t pos) { - return piece.find_first_of(one_of, pos); -} -size_t FindFirstOf(StringPiece16 piece, StringPiece16 one_of, size_t pos) { - return piece.find_first_of(one_of, pos); -} - -// General string splitter template. Can take 8- or 16-bit input, can produce -// the corresponding string or StringPiece output, and can take single- or -// multiple-character delimiters. -// -// DelimiterType is either a character (Str::value_type) or a string piece of -// multiple characters (BasicStringPiece<Str>). StringPiece has a version of -// find for both of these cases, and the single-character version is the most -// common and can be implemented faster, which is why this is a template. -template<typename Str, typename OutputStringType, typename DelimiterType> -static std::vector<OutputStringType> SplitStringT( - BasicStringPiece<Str> str, - DelimiterType delimiter, - WhitespaceHandling whitespace, - SplitResult result_type) { - std::vector<OutputStringType> result; - if (str.empty()) - return result; - - size_t start = 0; - while (start != Str::npos) { - size_t end = FindFirstOf(str, delimiter, start); - - BasicStringPiece<Str> piece; - if (end == Str::npos) { - piece = str.substr(start); - start = Str::npos; - } else { - piece = str.substr(start, end - start); - start = end + 1; - } - - if (whitespace == TRIM_WHITESPACE) - piece = TrimString(piece, WhitespaceForType<Str>(), TRIM_ALL); - - if (result_type == SPLIT_WANT_ALL || !piece.empty()) - result.push_back(PieceToOutputType<Str, OutputStringType>(piece)); - } - return result; -} - -bool AppendStringKeyValue(StringPiece input, - char delimiter, - StringPairs* result) { - // Always append a new item regardless of success (it might be empty). The - // below code will copy the strings directly into the result pair. - result->resize(result->size() + 1); - auto& result_pair = result->back(); - - // Find the delimiter. - size_t end_key_pos = input.find_first_of(delimiter); - if (end_key_pos == std::string::npos) { - DVLOG(1) << "cannot find delimiter in: " << input; - return false; // No delimiter. - } - input.substr(0, end_key_pos).CopyToString(&result_pair.first); - - // Find the value string. - StringPiece remains = input.substr(end_key_pos, input.size() - end_key_pos); - size_t begin_value_pos = remains.find_first_not_of(delimiter); - if (begin_value_pos == StringPiece::npos) { - DVLOG(1) << "cannot parse value from input: " << input; - return false; // No value. - } - remains.substr(begin_value_pos, remains.size() - begin_value_pos) - .CopyToString(&result_pair.second); - - return true; -} - -template <typename Str, typename OutputStringType> -void SplitStringUsingSubstrT(BasicStringPiece<Str> input, - BasicStringPiece<Str> delimiter, - WhitespaceHandling whitespace, - SplitResult result_type, - std::vector<OutputStringType>* result) { - using Piece = BasicStringPiece<Str>; - using size_type = typename Piece::size_type; - - result->clear(); - for (size_type begin_index = 0, end_index = 0; end_index != Piece::npos; - begin_index = end_index + delimiter.size()) { - end_index = input.find(delimiter, begin_index); - Piece term = end_index == Piece::npos - ? input.substr(begin_index) - : input.substr(begin_index, end_index - begin_index); - - if (whitespace == TRIM_WHITESPACE) - term = TrimString(term, WhitespaceForType<Str>(), TRIM_ALL); - - if (result_type == SPLIT_WANT_ALL || !term.empty()) - result->push_back(PieceToOutputType<Str, OutputStringType>(term)); - } -} - -} // namespace - -std::vector<std::string> SplitString(StringPiece input, - StringPiece separators, - WhitespaceHandling whitespace, - SplitResult result_type) { - if (separators.size() == 1) { - return SplitStringT<std::string, std::string, char>( - input, separators[0], whitespace, result_type); - } - return SplitStringT<std::string, std::string, StringPiece>( - input, separators, whitespace, result_type); -} - -std::vector<string16> SplitString(StringPiece16 input, - StringPiece16 separators, - WhitespaceHandling whitespace, - SplitResult result_type) { - if (separators.size() == 1) { - return SplitStringT<string16, string16, char16>( - input, separators[0], whitespace, result_type); - } - return SplitStringT<string16, string16, StringPiece16>( - input, separators, whitespace, result_type); -} - -std::vector<StringPiece> SplitStringPiece(StringPiece input, - StringPiece separators, - WhitespaceHandling whitespace, - SplitResult result_type) { - if (separators.size() == 1) { - return SplitStringT<std::string, StringPiece, char>( - input, separators[0], whitespace, result_type); - } - return SplitStringT<std::string, StringPiece, StringPiece>( - input, separators, whitespace, result_type); -} - -std::vector<StringPiece16> SplitStringPiece(StringPiece16 input, - StringPiece16 separators, - WhitespaceHandling whitespace, - SplitResult result_type) { - if (separators.size() == 1) { - return SplitStringT<string16, StringPiece16, char16>( - input, separators[0], whitespace, result_type); - } - return SplitStringT<string16, StringPiece16, StringPiece16>( - input, separators, whitespace, result_type); -} - -bool SplitStringIntoKeyValuePairs(StringPiece input, - char key_value_delimiter, - char key_value_pair_delimiter, - StringPairs* key_value_pairs) { - key_value_pairs->clear(); - - std::vector<StringPiece> pairs = SplitStringPiece( - input, std::string(1, key_value_pair_delimiter), - TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); - key_value_pairs->reserve(pairs.size()); - - bool success = true; - for (const StringPiece& pair : pairs) { - if (!AppendStringKeyValue(pair, key_value_delimiter, key_value_pairs)) { - // Don't return here, to allow for pairs without associated - // value or key; just record that the split failed. - success = false; - } - } - return success; -} - -void SplitStringUsingSubstr(StringPiece16 input, - StringPiece16 delimiter, - std::vector<string16>* result) { - SplitStringUsingSubstrT(input, delimiter, TRIM_WHITESPACE, SPLIT_WANT_ALL, - result); -} - -void SplitStringUsingSubstr(StringPiece input, - StringPiece delimiter, - std::vector<std::string>* result) { - SplitStringUsingSubstrT(input, delimiter, TRIM_WHITESPACE, SPLIT_WANT_ALL, - result); -} - -std::vector<StringPiece16> SplitStringPieceUsingSubstr( - StringPiece16 input, - StringPiece16 delimiter, - WhitespaceHandling whitespace, - SplitResult result_type) { - std::vector<StringPiece16> result; - SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); - return result; -} - -std::vector<StringPiece> SplitStringPieceUsingSubstr( - StringPiece input, - StringPiece delimiter, - WhitespaceHandling whitespace, - SplitResult result_type) { - std::vector<StringPiece> result; - SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); - return result; -} - -} // namespace base diff --git a/security/sandbox/chromium/base/strings/string_split.h b/security/sandbox/chromium/base/strings/string_split.h deleted file mode 100644 index ec9f24604..000000000 --- a/security/sandbox/chromium/base/strings/string_split.h +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_STRING_SPLIT_H_ -#define BASE_STRINGS_STRING_SPLIT_H_ - -#include <string> -#include <utility> -#include <vector> - -#include "base/base_export.h" -#include "base/strings/string16.h" -#include "base/strings/string_piece.h" - -namespace base { - -enum WhitespaceHandling { - KEEP_WHITESPACE, - TRIM_WHITESPACE, -}; - -enum SplitResult { - // Strictly return all results. - // - // If the input is ",," and the separator is ',' this will return a - // vector of three empty strings. - SPLIT_WANT_ALL, - - // Only nonempty results will be added to the results. Multiple separators - // will be coalesced. Separators at the beginning and end of the input will - // be ignored. With TRIM_WHITESPACE, whitespace-only results will be dropped. - // - // If the input is ",," and the separator is ',', this will return an empty - // vector. - SPLIT_WANT_NONEMPTY, -}; - -// Split the given string on ANY of the given separators, returning copies of -// the result. -// -// To split on either commas or semicolons, keeping all whitespace: -// -// std::vector<std::string> tokens = base::SplitString( -// input, ",;", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); -BASE_EXPORT std::vector<std::string> SplitString( - StringPiece input, - StringPiece separators, - WhitespaceHandling whitespace, - SplitResult result_type); -BASE_EXPORT std::vector<string16> SplitString( - StringPiece16 input, - StringPiece16 separators, - WhitespaceHandling whitespace, - SplitResult result_type); - -// Like SplitString above except it returns a vector of StringPieces which -// reference the original buffer without copying. Although you have to be -// careful to keep the original string unmodified, this provides an efficient -// way to iterate through tokens in a string. -// -// To iterate through all whitespace-separated tokens in an input string: -// -// for (const auto& cur : -// base::SplitStringPiece(input, base::kWhitespaceASCII, -// base::KEEP_WHITESPACE, -// base::SPLIT_WANT_NONEMPTY)) { -// ... -BASE_EXPORT std::vector<StringPiece> SplitStringPiece( - StringPiece input, - StringPiece separators, - WhitespaceHandling whitespace, - SplitResult result_type); -BASE_EXPORT std::vector<StringPiece16> SplitStringPiece( - StringPiece16 input, - StringPiece16 separators, - WhitespaceHandling whitespace, - SplitResult result_type); - -using StringPairs = std::vector<std::pair<std::string, std::string>>; - -// Splits |line| into key value pairs according to the given delimiters and -// removes whitespace leading each key and trailing each value. Returns true -// only if each pair has a non-empty key and value. |key_value_pairs| will -// include ("","") pairs for entries without |key_value_delimiter|. -BASE_EXPORT bool SplitStringIntoKeyValuePairs(StringPiece input, - char key_value_delimiter, - char key_value_pair_delimiter, - StringPairs* key_value_pairs); - -// Similar to SplitString, but use a substring delimiter instead of a list of -// characters that are all possible delimiters. -// -// TODO(brettw) this should probably be changed and expanded to provide a -// mirror of the SplitString[Piece] API above, just with the different -// delimiter handling. -BASE_EXPORT void SplitStringUsingSubstr(StringPiece16 input, - StringPiece16 delimiter, - std::vector<string16>* result); -BASE_EXPORT void SplitStringUsingSubstr(StringPiece input, - StringPiece delimiter, - std::vector<std::string>* result); - -// Like SplitStringUsingSubstr above except it returns a vector of StringPieces -// which reference the original buffer without copying. Although you have to be -// careful to keep the original string unmodified, this provides an efficient -// way to iterate through tokens in a string. -// -// To iterate through all newline-separated tokens in an input string: -// -// for (const auto& cur : -// base::SplitStringUsingSubstr(input, "\r\n", -// base::KEEP_WHITESPACE, -// base::SPLIT_WANT_NONEMPTY)) { -// ... -BASE_EXPORT std::vector<StringPiece16> SplitStringPieceUsingSubstr( - StringPiece16 input, - StringPiece16 delimiter, - WhitespaceHandling whitespace, - SplitResult result_type); -BASE_EXPORT std::vector<StringPiece> SplitStringPieceUsingSubstr( - StringPiece input, - StringPiece delimiter, - WhitespaceHandling whitespace, - SplitResult result_type); - -} // namespace base - -#endif // BASE_STRINGS_STRING_SPLIT_H_ diff --git a/security/sandbox/chromium/base/strings/string_util.cc b/security/sandbox/chromium/base/strings/string_util.cc deleted file mode 100644 index e8000abd4..000000000 --- a/security/sandbox/chromium/base/strings/string_util.cc +++ /dev/null @@ -1,1001 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/string_util.h" - -#include <ctype.h> -#include <errno.h> -#include <math.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <wchar.h> -#include <wctype.h> - -#include <algorithm> -#include <limits> -#include <vector> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "base/strings/string_split.h" -#include "base/strings/utf_string_conversion_utils.h" -#include "base/strings/utf_string_conversions.h" -#include "base/third_party/icu/icu_utf.h" -#include "build/build_config.h" - -namespace base { - -namespace { - -// Force the singleton used by EmptyString[16] to be a unique type. This -// prevents other code that might accidentally use Singleton<string> from -// getting our internal one. -struct EmptyStrings { - EmptyStrings() {} - const std::string s; - const string16 s16; - - static EmptyStrings* GetInstance() { - return Singleton<EmptyStrings>::get(); - } -}; - -// Used by ReplaceStringPlaceholders to track the position in the string of -// replaced parameters. -struct ReplacementOffset { - ReplacementOffset(uintptr_t parameter, size_t offset) - : parameter(parameter), - offset(offset) {} - - // Index of the parameter. - uintptr_t parameter; - - // Starting position in the string. - size_t offset; -}; - -static bool CompareParameter(const ReplacementOffset& elem1, - const ReplacementOffset& elem2) { - return elem1.parameter < elem2.parameter; -} - -// Assuming that a pointer is the size of a "machine word", then -// uintptr_t is an integer type that is also a machine word. -typedef uintptr_t MachineWord; -const uintptr_t kMachineWordAlignmentMask = sizeof(MachineWord) - 1; - -inline bool IsAlignedToMachineWord(const void* pointer) { - return !(reinterpret_cast<MachineWord>(pointer) & kMachineWordAlignmentMask); -} - -template<typename T> inline T* AlignToMachineWord(T* pointer) { - return reinterpret_cast<T*>(reinterpret_cast<MachineWord>(pointer) & - ~kMachineWordAlignmentMask); -} - -template<size_t size, typename CharacterType> struct NonASCIIMask; -template<> struct NonASCIIMask<4, char16> { - static inline uint32_t value() { return 0xFF80FF80U; } -}; -template<> struct NonASCIIMask<4, char> { - static inline uint32_t value() { return 0x80808080U; } -}; -template<> struct NonASCIIMask<8, char16> { - static inline uint64_t value() { return 0xFF80FF80FF80FF80ULL; } -}; -template<> struct NonASCIIMask<8, char> { - static inline uint64_t value() { return 0x8080808080808080ULL; } -}; -#if defined(WCHAR_T_IS_UTF32) -template<> struct NonASCIIMask<4, wchar_t> { - static inline uint32_t value() { return 0xFFFFFF80U; } -}; -template<> struct NonASCIIMask<8, wchar_t> { - static inline uint64_t value() { return 0xFFFFFF80FFFFFF80ULL; } -}; -#endif // WCHAR_T_IS_UTF32 - -} // namespace - -bool IsWprintfFormatPortable(const wchar_t* format) { - for (const wchar_t* position = format; *position != '\0'; ++position) { - if (*position == '%') { - bool in_specification = true; - bool modifier_l = false; - while (in_specification) { - // Eat up characters until reaching a known specifier. - if (*++position == '\0') { - // The format string ended in the middle of a specification. Call - // it portable because no unportable specifications were found. The - // string is equally broken on all platforms. - return true; - } - - if (*position == 'l') { - // 'l' is the only thing that can save the 's' and 'c' specifiers. - modifier_l = true; - } else if (((*position == 's' || *position == 'c') && !modifier_l) || - *position == 'S' || *position == 'C' || *position == 'F' || - *position == 'D' || *position == 'O' || *position == 'U') { - // Not portable. - return false; - } - - if (wcschr(L"diouxXeEfgGaAcspn%", *position)) { - // Portable, keep scanning the rest of the format string. - in_specification = false; - } - } - } - } - - return true; -} - -namespace { - -template<typename StringType> -StringType ToLowerASCIIImpl(BasicStringPiece<StringType> str) { - StringType ret; - ret.reserve(str.size()); - for (size_t i = 0; i < str.size(); i++) - ret.push_back(ToLowerASCII(str[i])); - return ret; -} - -template<typename StringType> -StringType ToUpperASCIIImpl(BasicStringPiece<StringType> str) { - StringType ret; - ret.reserve(str.size()); - for (size_t i = 0; i < str.size(); i++) - ret.push_back(ToUpperASCII(str[i])); - return ret; -} - -} // namespace - -std::string ToLowerASCII(StringPiece str) { - return ToLowerASCIIImpl<std::string>(str); -} - -string16 ToLowerASCII(StringPiece16 str) { - return ToLowerASCIIImpl<string16>(str); -} - -std::string ToUpperASCII(StringPiece str) { - return ToUpperASCIIImpl<std::string>(str); -} - -string16 ToUpperASCII(StringPiece16 str) { - return ToUpperASCIIImpl<string16>(str); -} - -template<class StringType> -int CompareCaseInsensitiveASCIIT(BasicStringPiece<StringType> a, - BasicStringPiece<StringType> b) { - // Find the first characters that aren't equal and compare them. If the end - // of one of the strings is found before a nonequal character, the lengths - // of the strings are compared. - size_t i = 0; - while (i < a.length() && i < b.length()) { - typename StringType::value_type lower_a = ToLowerASCII(a[i]); - typename StringType::value_type lower_b = ToLowerASCII(b[i]); - if (lower_a < lower_b) - return -1; - if (lower_a > lower_b) - return 1; - i++; - } - - // End of one string hit before finding a different character. Expect the - // common case to be "strings equal" at this point so check that first. - if (a.length() == b.length()) - return 0; - - if (a.length() < b.length()) - return -1; - return 1; -} - -int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b) { - return CompareCaseInsensitiveASCIIT<std::string>(a, b); -} - -int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) { - return CompareCaseInsensitiveASCIIT<string16>(a, b); -} - -bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b) { - if (a.length() != b.length()) - return false; - return CompareCaseInsensitiveASCIIT<std::string>(a, b) == 0; -} - -bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) { - if (a.length() != b.length()) - return false; - return CompareCaseInsensitiveASCIIT<string16>(a, b) == 0; -} - -const std::string& EmptyString() { - return EmptyStrings::GetInstance()->s; -} - -const string16& EmptyString16() { - return EmptyStrings::GetInstance()->s16; -} - -template<typename STR> -bool ReplaceCharsT(const STR& input, - const STR& replace_chars, - const STR& replace_with, - STR* output) { - bool removed = false; - size_t replace_length = replace_with.length(); - - *output = input; - - size_t found = output->find_first_of(replace_chars); - while (found != STR::npos) { - removed = true; - output->replace(found, 1, replace_with); - found = output->find_first_of(replace_chars, found + replace_length); - } - - return removed; -} - -bool ReplaceChars(const string16& input, - const StringPiece16& replace_chars, - const string16& replace_with, - string16* output) { - return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); -} - -bool ReplaceChars(const std::string& input, - const StringPiece& replace_chars, - const std::string& replace_with, - std::string* output) { - return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); -} - -bool RemoveChars(const string16& input, - const StringPiece16& remove_chars, - string16* output) { - return ReplaceChars(input, remove_chars.as_string(), string16(), output); -} - -bool RemoveChars(const std::string& input, - const StringPiece& remove_chars, - std::string* output) { - return ReplaceChars(input, remove_chars.as_string(), std::string(), output); -} - -template<typename Str> -TrimPositions TrimStringT(const Str& input, - BasicStringPiece<Str> trim_chars, - TrimPositions positions, - Str* output) { - // Find the edges of leading/trailing whitespace as desired. Need to use - // a StringPiece version of input to be able to call find* on it with the - // StringPiece version of trim_chars (normally the trim_chars will be a - // constant so avoid making a copy). - BasicStringPiece<Str> input_piece(input); - const size_t last_char = input.length() - 1; - const size_t first_good_char = (positions & TRIM_LEADING) ? - input_piece.find_first_not_of(trim_chars) : 0; - const size_t last_good_char = (positions & TRIM_TRAILING) ? - input_piece.find_last_not_of(trim_chars) : last_char; - - // When the string was all trimmed, report that we stripped off characters - // from whichever position the caller was interested in. For empty input, we - // stripped no characters, but we still need to clear |output|. - if (input.empty() || - (first_good_char == Str::npos) || (last_good_char == Str::npos)) { - bool input_was_empty = input.empty(); // in case output == &input - output->clear(); - return input_was_empty ? TRIM_NONE : positions; - } - - // Trim. - *output = - input.substr(first_good_char, last_good_char - first_good_char + 1); - - // Return where we trimmed from. - return static_cast<TrimPositions>( - ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | - ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); -} - -bool TrimString(const string16& input, - StringPiece16 trim_chars, - string16* output) { - return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; -} - -bool TrimString(const std::string& input, - StringPiece trim_chars, - std::string* output) { - return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; -} - -template<typename Str> -BasicStringPiece<Str> TrimStringPieceT(BasicStringPiece<Str> input, - BasicStringPiece<Str> trim_chars, - TrimPositions positions) { - size_t begin = (positions & TRIM_LEADING) ? - input.find_first_not_of(trim_chars) : 0; - size_t end = (positions & TRIM_TRAILING) ? - input.find_last_not_of(trim_chars) + 1 : input.size(); - return input.substr(begin, end - begin); -} - -StringPiece16 TrimString(StringPiece16 input, - const StringPiece16& trim_chars, - TrimPositions positions) { - return TrimStringPieceT(input, trim_chars, positions); -} - -StringPiece TrimString(StringPiece input, - const StringPiece& trim_chars, - TrimPositions positions) { - return TrimStringPieceT(input, trim_chars, positions); -} - -void TruncateUTF8ToByteSize(const std::string& input, - const size_t byte_size, - std::string* output) { - DCHECK(output); - if (byte_size > input.length()) { - *output = input; - return; - } - DCHECK_LE(byte_size, - static_cast<uint32_t>(std::numeric_limits<int32_t>::max())); - // Note: This cast is necessary because CBU8_NEXT uses int32_ts. - int32_t truncation_length = static_cast<int32_t>(byte_size); - int32_t char_index = truncation_length - 1; - const char* data = input.data(); - - // Using CBU8, we will move backwards from the truncation point - // to the beginning of the string looking for a valid UTF8 - // character. Once a full UTF8 character is found, we will - // truncate the string to the end of that character. - while (char_index >= 0) { - int32_t prev = char_index; - base_icu::UChar32 code_point = 0; - CBU8_NEXT(data, char_index, truncation_length, code_point); - if (!IsValidCharacter(code_point) || - !IsValidCodepoint(code_point)) { - char_index = prev - 1; - } else { - break; - } - } - - if (char_index >= 0 ) - *output = input.substr(0, char_index); - else - output->clear(); -} - -TrimPositions TrimWhitespace(const string16& input, - TrimPositions positions, - string16* output) { - return TrimStringT(input, StringPiece16(kWhitespaceUTF16), positions, output); -} - -StringPiece16 TrimWhitespace(StringPiece16 input, - TrimPositions positions) { - return TrimStringPieceT(input, StringPiece16(kWhitespaceUTF16), positions); -} - -TrimPositions TrimWhitespaceASCII(const std::string& input, - TrimPositions positions, - std::string* output) { - return TrimStringT(input, StringPiece(kWhitespaceASCII), positions, output); -} - -StringPiece TrimWhitespaceASCII(StringPiece input, TrimPositions positions) { - return TrimStringPieceT(input, StringPiece(kWhitespaceASCII), positions); -} - -template<typename STR> -STR CollapseWhitespaceT(const STR& text, - bool trim_sequences_with_line_breaks) { - STR result; - result.resize(text.size()); - - // Set flags to pretend we're already in a trimmed whitespace sequence, so we - // will trim any leading whitespace. - bool in_whitespace = true; - bool already_trimmed = true; - - int chars_written = 0; - for (typename STR::const_iterator i(text.begin()); i != text.end(); ++i) { - if (IsUnicodeWhitespace(*i)) { - if (!in_whitespace) { - // Reduce all whitespace sequences to a single space. - in_whitespace = true; - result[chars_written++] = L' '; - } - if (trim_sequences_with_line_breaks && !already_trimmed && - ((*i == '\n') || (*i == '\r'))) { - // Whitespace sequences containing CR or LF are eliminated entirely. - already_trimmed = true; - --chars_written; - } - } else { - // Non-whitespace chracters are copied straight across. - in_whitespace = false; - already_trimmed = false; - result[chars_written++] = *i; - } - } - - if (in_whitespace && !already_trimmed) { - // Any trailing whitespace is eliminated. - --chars_written; - } - - result.resize(chars_written); - return result; -} - -string16 CollapseWhitespace(const string16& text, - bool trim_sequences_with_line_breaks) { - return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); -} - -std::string CollapseWhitespaceASCII(const std::string& text, - bool trim_sequences_with_line_breaks) { - return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); -} - -bool ContainsOnlyChars(const StringPiece& input, - const StringPiece& characters) { - return input.find_first_not_of(characters) == StringPiece::npos; -} - -bool ContainsOnlyChars(const StringPiece16& input, - const StringPiece16& characters) { - return input.find_first_not_of(characters) == StringPiece16::npos; -} - -template <class Char> -inline bool DoIsStringASCII(const Char* characters, size_t length) { - MachineWord all_char_bits = 0; - const Char* end = characters + length; - - // Prologue: align the input. - while (!IsAlignedToMachineWord(characters) && characters != end) { - all_char_bits |= *characters; - ++characters; - } - - // Compare the values of CPU word size. - const Char* word_end = AlignToMachineWord(end); - const size_t loop_increment = sizeof(MachineWord) / sizeof(Char); - while (characters < word_end) { - all_char_bits |= *(reinterpret_cast<const MachineWord*>(characters)); - characters += loop_increment; - } - - // Process the remaining bytes. - while (characters != end) { - all_char_bits |= *characters; - ++characters; - } - - MachineWord non_ascii_bit_mask = - NonASCIIMask<sizeof(MachineWord), Char>::value(); - return !(all_char_bits & non_ascii_bit_mask); -} - -bool IsStringASCII(const StringPiece& str) { - return DoIsStringASCII(str.data(), str.length()); -} - -bool IsStringASCII(const StringPiece16& str) { - return DoIsStringASCII(str.data(), str.length()); -} - -bool IsStringASCII(const string16& str) { - return DoIsStringASCII(str.data(), str.length()); -} - -#if defined(WCHAR_T_IS_UTF32) -bool IsStringASCII(const std::wstring& str) { - return DoIsStringASCII(str.data(), str.length()); -} -#endif - -bool IsStringUTF8(const StringPiece& str) { - const char *src = str.data(); - int32_t src_len = static_cast<int32_t>(str.length()); - int32_t char_index = 0; - - while (char_index < src_len) { - int32_t code_point; - CBU8_NEXT(src, char_index, src_len, code_point); - if (!IsValidCharacter(code_point)) - return false; - } - return true; -} - -// Implementation note: Normally this function will be called with a hardcoded -// constant for the lowercase_ascii parameter. Constructing a StringPiece from -// a C constant requires running strlen, so the result will be two passes -// through the buffers, one to file the length of lowercase_ascii, and one to -// compare each letter. -// -// This function could have taken a const char* to avoid this and only do one -// pass through the string. But the strlen is faster than the case-insensitive -// compares and lets us early-exit in the case that the strings are different -// lengths (will often be the case for non-matches). So whether one approach or -// the other will be faster depends on the case. -// -// The hardcoded strings are typically very short so it doesn't matter, and the -// string piece gives additional flexibility for the caller (doesn't have to be -// null terminated) so we choose the StringPiece route. -template<typename Str> -static inline bool DoLowerCaseEqualsASCII(BasicStringPiece<Str> str, - StringPiece lowercase_ascii) { - if (str.size() != lowercase_ascii.size()) - return false; - for (size_t i = 0; i < str.size(); i++) { - if (ToLowerASCII(str[i]) != lowercase_ascii[i]) - return false; - } - return true; -} - -bool LowerCaseEqualsASCII(StringPiece str, StringPiece lowercase_ascii) { - return DoLowerCaseEqualsASCII<std::string>(str, lowercase_ascii); -} - -bool LowerCaseEqualsASCII(StringPiece16 str, StringPiece lowercase_ascii) { - return DoLowerCaseEqualsASCII<string16>(str, lowercase_ascii); -} - -bool EqualsASCII(StringPiece16 str, StringPiece ascii) { - if (str.length() != ascii.length()) - return false; - return std::equal(ascii.begin(), ascii.end(), str.begin()); -} - -template<typename Str> -bool StartsWithT(BasicStringPiece<Str> str, - BasicStringPiece<Str> search_for, - CompareCase case_sensitivity) { - if (search_for.size() > str.size()) - return false; - - BasicStringPiece<Str> source = str.substr(0, search_for.size()); - - switch (case_sensitivity) { - case CompareCase::SENSITIVE: - return source == search_for; - - case CompareCase::INSENSITIVE_ASCII: - return std::equal( - search_for.begin(), search_for.end(), - source.begin(), - CaseInsensitiveCompareASCII<typename Str::value_type>()); - - default: - NOTREACHED(); - return false; - } -} - -bool StartsWith(StringPiece str, - StringPiece search_for, - CompareCase case_sensitivity) { - return StartsWithT<std::string>(str, search_for, case_sensitivity); -} - -bool StartsWith(StringPiece16 str, - StringPiece16 search_for, - CompareCase case_sensitivity) { - return StartsWithT<string16>(str, search_for, case_sensitivity); -} - -template <typename Str> -bool EndsWithT(BasicStringPiece<Str> str, - BasicStringPiece<Str> search_for, - CompareCase case_sensitivity) { - if (search_for.size() > str.size()) - return false; - - BasicStringPiece<Str> source = str.substr(str.size() - search_for.size(), - search_for.size()); - - switch (case_sensitivity) { - case CompareCase::SENSITIVE: - return source == search_for; - - case CompareCase::INSENSITIVE_ASCII: - return std::equal( - source.begin(), source.end(), - search_for.begin(), - CaseInsensitiveCompareASCII<typename Str::value_type>()); - - default: - NOTREACHED(); - return false; - } -} - -bool EndsWith(StringPiece str, - StringPiece search_for, - CompareCase case_sensitivity) { - return EndsWithT<std::string>(str, search_for, case_sensitivity); -} - -bool EndsWith(StringPiece16 str, - StringPiece16 search_for, - CompareCase case_sensitivity) { - return EndsWithT<string16>(str, search_for, case_sensitivity); -} - -char HexDigitToInt(wchar_t c) { - DCHECK(IsHexDigit(c)); - if (c >= '0' && c <= '9') - return static_cast<char>(c - '0'); - if (c >= 'A' && c <= 'F') - return static_cast<char>(c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return static_cast<char>(c - 'a' + 10); - return 0; -} - -bool IsUnicodeWhitespace(wchar_t c) { - // kWhitespaceWide is a NULL-terminated string - for (const wchar_t* cur = kWhitespaceWide; *cur; ++cur) { - if (*cur == c) - return true; - } - return false; -} - -static const char* const kByteStringsUnlocalized[] = { - " B", - " kB", - " MB", - " GB", - " TB", - " PB" -}; - -string16 FormatBytesUnlocalized(int64_t bytes) { - double unit_amount = static_cast<double>(bytes); - size_t dimension = 0; - const int kKilo = 1024; - while (unit_amount >= kKilo && - dimension < arraysize(kByteStringsUnlocalized) - 1) { - unit_amount /= kKilo; - dimension++; - } - - char buf[64]; - if (bytes != 0 && dimension > 0 && unit_amount < 100) { - base::snprintf(buf, arraysize(buf), "%.1lf%s", unit_amount, - kByteStringsUnlocalized[dimension]); - } else { - base::snprintf(buf, arraysize(buf), "%.0lf%s", unit_amount, - kByteStringsUnlocalized[dimension]); - } - - return ASCIIToUTF16(buf); -} - -// Runs in O(n) time in the length of |str|. -template<class StringType> -void DoReplaceSubstringsAfterOffset(StringType* str, - size_t offset, - BasicStringPiece<StringType> find_this, - BasicStringPiece<StringType> replace_with, - bool replace_all) { - DCHECK(!find_this.empty()); - - // If the find string doesn't appear, there's nothing to do. - offset = str->find(find_this.data(), offset, find_this.size()); - if (offset == StringType::npos) - return; - - // If we're only replacing one instance, there's no need to do anything - // complicated. - size_t find_length = find_this.length(); - if (!replace_all) { - str->replace(offset, find_length, replace_with.data(), replace_with.size()); - return; - } - - // If the find and replace strings are the same length, we can simply use - // replace() on each instance, and finish the entire operation in O(n) time. - size_t replace_length = replace_with.length(); - if (find_length == replace_length) { - do { - str->replace(offset, find_length, - replace_with.data(), replace_with.size()); - offset = str->find(find_this.data(), offset + replace_length, - find_this.size()); - } while (offset != StringType::npos); - return; - } - - // Since the find and replace strings aren't the same length, a loop like the - // one above would be O(n^2) in the worst case, as replace() will shift the - // entire remaining string each time. We need to be more clever to keep - // things O(n). - // - // If we're shortening the string, we can alternate replacements with shifting - // forward the intervening characters using memmove(). - size_t str_length = str->length(); - if (find_length > replace_length) { - size_t write_offset = offset; - do { - if (replace_length) { - str->replace(write_offset, replace_length, - replace_with.data(), replace_with.size()); - write_offset += replace_length; - } - size_t read_offset = offset + find_length; - offset = std::min( - str->find(find_this.data(), read_offset, find_this.size()), - str_length); - size_t length = offset - read_offset; - if (length) { - memmove(&(*str)[write_offset], &(*str)[read_offset], - length * sizeof(typename StringType::value_type)); - write_offset += length; - } - } while (offset < str_length); - str->resize(write_offset); - return; - } - - // We're lengthening the string. We can use alternating replacements and - // memmove() calls like above, but we need to precalculate the final string - // length and then expand from back-to-front to avoid overwriting the string - // as we're reading it, needing to shift, or having to copy to a second string - // temporarily. - size_t first_match = offset; - - // First, calculate the final length and resize the string. - size_t final_length = str_length; - size_t expansion = replace_length - find_length; - size_t current_match; - do { - final_length += expansion; - // Minor optimization: save this offset into |current_match|, so that on - // exit from the loop, |current_match| will point at the last instance of - // the find string, and we won't need to find() it again immediately. - current_match = offset; - offset = str->find(find_this.data(), offset + find_length, - find_this.size()); - } while (offset != StringType::npos); - str->resize(final_length); - - // Now do the replacement loop, working backwards through the string. - for (size_t prev_match = str_length, write_offset = final_length; ; - current_match = str->rfind(find_this.data(), current_match - 1, - find_this.size())) { - size_t read_offset = current_match + find_length; - size_t length = prev_match - read_offset; - if (length) { - write_offset -= length; - memmove(&(*str)[write_offset], &(*str)[read_offset], - length * sizeof(typename StringType::value_type)); - } - write_offset -= replace_length; - str->replace(write_offset, replace_length, - replace_with.data(), replace_with.size()); - if (current_match == first_match) - return; - prev_match = current_match; - } -} - -void ReplaceFirstSubstringAfterOffset(string16* str, - size_t start_offset, - StringPiece16 find_this, - StringPiece16 replace_with) { - DoReplaceSubstringsAfterOffset<string16>( - str, start_offset, find_this, replace_with, false); // Replace first. -} - -void ReplaceFirstSubstringAfterOffset(std::string* str, - size_t start_offset, - StringPiece find_this, - StringPiece replace_with) { - DoReplaceSubstringsAfterOffset<std::string>( - str, start_offset, find_this, replace_with, false); // Replace first. -} - -void ReplaceSubstringsAfterOffset(string16* str, - size_t start_offset, - StringPiece16 find_this, - StringPiece16 replace_with) { - DoReplaceSubstringsAfterOffset<string16>( - str, start_offset, find_this, replace_with, true); // Replace all. -} - -void ReplaceSubstringsAfterOffset(std::string* str, - size_t start_offset, - StringPiece find_this, - StringPiece replace_with) { - DoReplaceSubstringsAfterOffset<std::string>( - str, start_offset, find_this, replace_with, true); // Replace all. -} - -template <class string_type> -inline typename string_type::value_type* WriteIntoT(string_type* str, - size_t length_with_null) { - DCHECK_GT(length_with_null, 1u); - str->reserve(length_with_null); - str->resize(length_with_null - 1); - return &((*str)[0]); -} - -char* WriteInto(std::string* str, size_t length_with_null) { - return WriteIntoT(str, length_with_null); -} - -char16* WriteInto(string16* str, size_t length_with_null) { - return WriteIntoT(str, length_with_null); -} - -template<typename STR> -static STR JoinStringT(const std::vector<STR>& parts, - BasicStringPiece<STR> sep) { - if (parts.empty()) - return STR(); - - STR result(parts[0]); - auto iter = parts.begin(); - ++iter; - - for (; iter != parts.end(); ++iter) { - sep.AppendToString(&result); - result += *iter; - } - - return result; -} - -std::string JoinString(const std::vector<std::string>& parts, - StringPiece separator) { - return JoinStringT(parts, separator); -} - -string16 JoinString(const std::vector<string16>& parts, - StringPiece16 separator) { - return JoinStringT(parts, separator); -} - -template<class FormatStringType, class OutStringType> -OutStringType DoReplaceStringPlaceholders( - const FormatStringType& format_string, - const std::vector<OutStringType>& subst, - std::vector<size_t>* offsets) { - size_t substitutions = subst.size(); - - size_t sub_length = 0; - for (const auto& cur : subst) - sub_length += cur.length(); - - OutStringType formatted; - formatted.reserve(format_string.length() + sub_length); - - std::vector<ReplacementOffset> r_offsets; - for (auto i = format_string.begin(); i != format_string.end(); ++i) { - if ('$' == *i) { - if (i + 1 != format_string.end()) { - ++i; - DCHECK('$' == *i || '1' <= *i) << "Invalid placeholder: " << *i; - if ('$' == *i) { - while (i != format_string.end() && '$' == *i) { - formatted.push_back('$'); - ++i; - } - --i; - } else { - uintptr_t index = 0; - while (i != format_string.end() && '0' <= *i && *i <= '9') { - index *= 10; - index += *i - '0'; - ++i; - } - --i; - index -= 1; - if (offsets) { - ReplacementOffset r_offset(index, - static_cast<int>(formatted.size())); - r_offsets.insert(std::lower_bound(r_offsets.begin(), - r_offsets.end(), - r_offset, - &CompareParameter), - r_offset); - } - if (index < substitutions) - formatted.append(subst.at(index)); - } - } - } else { - formatted.push_back(*i); - } - } - if (offsets) { - for (const auto& cur : r_offsets) - offsets->push_back(cur.offset); - } - return formatted; -} - -string16 ReplaceStringPlaceholders(const string16& format_string, - const std::vector<string16>& subst, - std::vector<size_t>* offsets) { - return DoReplaceStringPlaceholders(format_string, subst, offsets); -} - -std::string ReplaceStringPlaceholders(const StringPiece& format_string, - const std::vector<std::string>& subst, - std::vector<size_t>* offsets) { - return DoReplaceStringPlaceholders(format_string, subst, offsets); -} - -string16 ReplaceStringPlaceholders(const string16& format_string, - const string16& a, - size_t* offset) { - std::vector<size_t> offsets; - std::vector<string16> subst; - subst.push_back(a); - string16 result = ReplaceStringPlaceholders(format_string, subst, &offsets); - - DCHECK_EQ(1U, offsets.size()); - if (offset) - *offset = offsets[0]; - return result; -} - -// The following code is compatible with the OpenBSD lcpy interface. See: -// http://www.gratisoft.us/todd/papers/strlcpy.html -// ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c - -namespace { - -template <typename CHAR> -size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { - for (size_t i = 0; i < dst_size; ++i) { - if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL. - return i; - } - - // We were left off at dst_size. We over copied 1 byte. Null terminate. - if (dst_size != 0) - dst[dst_size - 1] = 0; - - // Count the rest of the |src|, and return it's length in characters. - while (src[dst_size]) ++dst_size; - return dst_size; -} - -} // namespace - -size_t strlcpy(char* dst, const char* src, size_t dst_size) { - return lcpyT<char>(dst, src, dst_size); -} -size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { - return lcpyT<wchar_t>(dst, src, dst_size); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/strings/string_util.h b/security/sandbox/chromium/base/strings/string_util.h deleted file mode 100644 index e369f294d..000000000 --- a/security/sandbox/chromium/base/strings/string_util.h +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This file defines utility functions for working with strings. - -#ifndef BASE_STRINGS_STRING_UTIL_H_ -#define BASE_STRINGS_STRING_UTIL_H_ - -#include <ctype.h> -#include <stdarg.h> // va_list -#include <stddef.h> -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/strings/string16.h" -#include "base/strings/string_piece.h" // For implicit conversions. -#include "build/build_config.h" - -namespace base { - -// C standard-library functions that aren't cross-platform are provided as -// "base::...", and their prototypes are listed below. These functions are -// then implemented as inline calls to the platform-specific equivalents in the -// platform-specific headers. - -// Wrapper for vsnprintf that always null-terminates and always returns the -// number of characters that would be in an untruncated formatted -// string, even when truncation occurs. -int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) - PRINTF_FORMAT(3, 0); - -// Some of these implementations need to be inlined. - -// We separate the declaration from the implementation of this inline -// function just so the PRINTF_FORMAT works. -inline int snprintf(char* buffer, - size_t size, - _Printf_format_string_ const char* format, - ...) PRINTF_FORMAT(3, 4); -inline int snprintf(char* buffer, - size_t size, - _Printf_format_string_ const char* format, - ...) { - va_list arguments; - va_start(arguments, format); - int result = vsnprintf(buffer, size, format, arguments); - va_end(arguments); - return result; -} - -// BSD-style safe and consistent string copy functions. -// Copies |src| to |dst|, where |dst_size| is the total allocated size of |dst|. -// Copies at most |dst_size|-1 characters, and always NULL terminates |dst|, as -// long as |dst_size| is not 0. Returns the length of |src| in characters. -// If the return value is >= dst_size, then the output was truncated. -// NOTE: All sizes are in number of characters, NOT in bytes. -BASE_EXPORT size_t strlcpy(char* dst, const char* src, size_t dst_size); -BASE_EXPORT size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size); - -// Scan a wprintf format string to determine whether it's portable across a -// variety of systems. This function only checks that the conversion -// specifiers used by the format string are supported and have the same meaning -// on a variety of systems. It doesn't check for other errors that might occur -// within a format string. -// -// Nonportable conversion specifiers for wprintf are: -// - 's' and 'c' without an 'l' length modifier. %s and %c operate on char -// data on all systems except Windows, which treat them as wchar_t data. -// Use %ls and %lc for wchar_t data instead. -// - 'S' and 'C', which operate on wchar_t data on all systems except Windows, -// which treat them as char data. Use %ls and %lc for wchar_t data -// instead. -// - 'F', which is not identified by Windows wprintf documentation. -// - 'D', 'O', and 'U', which are deprecated and not available on all systems. -// Use %ld, %lo, and %lu instead. -// -// Note that there is no portable conversion specifier for char data when -// working with wprintf. -// -// This function is intended to be called from base::vswprintf. -BASE_EXPORT bool IsWprintfFormatPortable(const wchar_t* format); - -// ASCII-specific tolower. The standard library's tolower is locale sensitive, -// so we don't want to use it here. -inline char ToLowerASCII(char c) { - return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c; -} -inline char16 ToLowerASCII(char16 c) { - return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c; -} - -// ASCII-specific toupper. The standard library's toupper is locale sensitive, -// so we don't want to use it here. -inline char ToUpperASCII(char c) { - return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c; -} -inline char16 ToUpperASCII(char16 c) { - return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c; -} - -// Converts the given string to it's ASCII-lowercase equivalent. -BASE_EXPORT std::string ToLowerASCII(StringPiece str); -BASE_EXPORT string16 ToLowerASCII(StringPiece16 str); - -// Converts the given string to it's ASCII-uppercase equivalent. -BASE_EXPORT std::string ToUpperASCII(StringPiece str); -BASE_EXPORT string16 ToUpperASCII(StringPiece16 str); - -// Functor for case-insensitive ASCII comparisons for STL algorithms like -// std::search. -// -// Note that a full Unicode version of this functor is not possible to write -// because case mappings might change the number of characters, depend on -// context (combining accents), and require handling UTF-16. If you need -// proper Unicode support, use base::i18n::ToLower/FoldCase and then just -// use a normal operator== on the result. -template<typename Char> struct CaseInsensitiveCompareASCII { - public: - bool operator()(Char x, Char y) const { - return ToLowerASCII(x) == ToLowerASCII(y); - } -}; - -// Like strcasecmp for case-insensitive ASCII characters only. Returns: -// -1 (a < b) -// 0 (a == b) -// 1 (a > b) -// (unlike strcasecmp which can return values greater or less than 1/-1). For -// full Unicode support, use base::i18n::ToLower or base::i18h::FoldCase -// and then just call the normal string operators on the result. -BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b); -BASE_EXPORT int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b); - -// Equality for ASCII case-insensitive comparisons. For full Unicode support, -// use base::i18n::ToLower or base::i18h::FoldCase and then compare with either -// == or !=. -BASE_EXPORT bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b); -BASE_EXPORT bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b); - -// These threadsafe functions return references to globally unique empty -// strings. -// -// It is likely faster to construct a new empty string object (just a few -// instructions to set the length to 0) than to get the empty string singleton -// returned by these functions (which requires threadsafe singleton access). -// -// Therefore, DO NOT USE THESE AS A GENERAL-PURPOSE SUBSTITUTE FOR DEFAULT -// CONSTRUCTORS. There is only one case where you should use these: functions -// which need to return a string by reference (e.g. as a class member -// accessor), and don't have an empty string to use (e.g. in an error case). -// These should not be used as initializers, function arguments, or return -// values for functions which return by value or outparam. -BASE_EXPORT const std::string& EmptyString(); -BASE_EXPORT const string16& EmptyString16(); - -// Contains the set of characters representing whitespace in the corresponding -// encoding. Null-terminated. The ASCII versions are the whitespaces as defined -// by HTML5, and don't include control characters. -BASE_EXPORT extern const wchar_t kWhitespaceWide[]; // Includes Unicode. -BASE_EXPORT extern const char16 kWhitespaceUTF16[]; // Includes Unicode. -BASE_EXPORT extern const char kWhitespaceASCII[]; -BASE_EXPORT extern const char16 kWhitespaceASCIIAs16[]; // No unicode. - -// Null-terminated string representing the UTF-8 byte order mark. -BASE_EXPORT extern const char kUtf8ByteOrderMark[]; - -// Removes characters in |remove_chars| from anywhere in |input|. Returns true -// if any characters were removed. |remove_chars| must be null-terminated. -// NOTE: Safe to use the same variable for both |input| and |output|. -BASE_EXPORT bool RemoveChars(const string16& input, - const StringPiece16& remove_chars, - string16* output); -BASE_EXPORT bool RemoveChars(const std::string& input, - const StringPiece& remove_chars, - std::string* output); - -// Replaces characters in |replace_chars| from anywhere in |input| with -// |replace_with|. Each character in |replace_chars| will be replaced with -// the |replace_with| string. Returns true if any characters were replaced. -// |replace_chars| must be null-terminated. -// NOTE: Safe to use the same variable for both |input| and |output|. -BASE_EXPORT bool ReplaceChars(const string16& input, - const StringPiece16& replace_chars, - const string16& replace_with, - string16* output); -BASE_EXPORT bool ReplaceChars(const std::string& input, - const StringPiece& replace_chars, - const std::string& replace_with, - std::string* output); - -enum TrimPositions { - TRIM_NONE = 0, - TRIM_LEADING = 1 << 0, - TRIM_TRAILING = 1 << 1, - TRIM_ALL = TRIM_LEADING | TRIM_TRAILING, -}; - -// Removes characters in |trim_chars| from the beginning and end of |input|. -// The 8-bit version only works on 8-bit characters, not UTF-8. -// -// It is safe to use the same variable for both |input| and |output| (this is -// the normal usage to trim in-place). -BASE_EXPORT bool TrimString(const string16& input, - StringPiece16 trim_chars, - string16* output); -BASE_EXPORT bool TrimString(const std::string& input, - StringPiece trim_chars, - std::string* output); - -// StringPiece versions of the above. The returned pieces refer to the original -// buffer. -BASE_EXPORT StringPiece16 TrimString(StringPiece16 input, - const StringPiece16& trim_chars, - TrimPositions positions); -BASE_EXPORT StringPiece TrimString(StringPiece input, - const StringPiece& trim_chars, - TrimPositions positions); - -// Truncates a string to the nearest UTF-8 character that will leave -// the string less than or equal to the specified byte size. -BASE_EXPORT void TruncateUTF8ToByteSize(const std::string& input, - const size_t byte_size, - std::string* output); - -// Trims any whitespace from either end of the input string. -// -// The StringPiece versions return a substring referencing the input buffer. -// The ASCII versions look only for ASCII whitespace. -// -// The std::string versions return where whitespace was found. -// NOTE: Safe to use the same variable for both input and output. -BASE_EXPORT TrimPositions TrimWhitespace(const string16& input, - TrimPositions positions, - string16* output); -BASE_EXPORT StringPiece16 TrimWhitespace(StringPiece16 input, - TrimPositions positions); -BASE_EXPORT TrimPositions TrimWhitespaceASCII(const std::string& input, - TrimPositions positions, - std::string* output); -BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input, - TrimPositions positions); - -// Searches for CR or LF characters. Removes all contiguous whitespace -// strings that contain them. This is useful when trying to deal with text -// copied from terminals. -// Returns |text|, with the following three transformations: -// (1) Leading and trailing whitespace is trimmed. -// (2) If |trim_sequences_with_line_breaks| is true, any other whitespace -// sequences containing a CR or LF are trimmed. -// (3) All other whitespace sequences are converted to single spaces. -BASE_EXPORT string16 CollapseWhitespace( - const string16& text, - bool trim_sequences_with_line_breaks); -BASE_EXPORT std::string CollapseWhitespaceASCII( - const std::string& text, - bool trim_sequences_with_line_breaks); - -// Returns true if |input| is empty or contains only characters found in -// |characters|. -BASE_EXPORT bool ContainsOnlyChars(const StringPiece& input, - const StringPiece& characters); -BASE_EXPORT bool ContainsOnlyChars(const StringPiece16& input, - const StringPiece16& characters); - -// Returns true if the specified string matches the criteria. How can a wide -// string be 8-bit or UTF8? It contains only characters that are < 256 (in the -// first case) or characters that use only 8-bits and whose 8-bit -// representation looks like a UTF-8 string (the second case). -// -// Note that IsStringUTF8 checks not only if the input is structurally -// valid but also if it doesn't contain any non-character codepoint -// (e.g. U+FFFE). It's done on purpose because all the existing callers want -// to have the maximum 'discriminating' power from other encodings. If -// there's a use case for just checking the structural validity, we have to -// add a new function for that. -// -// IsStringASCII assumes the input is likely all ASCII, and does not leave early -// if it is not the case. -BASE_EXPORT bool IsStringUTF8(const StringPiece& str); -BASE_EXPORT bool IsStringASCII(const StringPiece& str); -BASE_EXPORT bool IsStringASCII(const StringPiece16& str); -// A convenience adaptor for WebStrings, as they don't convert into -// StringPieces directly. -BASE_EXPORT bool IsStringASCII(const string16& str); -#if defined(WCHAR_T_IS_UTF32) -BASE_EXPORT bool IsStringASCII(const std::wstring& str); -#endif - -// Compare the lower-case form of the given string against the given -// previously-lower-cased ASCII string (typically a constant). -BASE_EXPORT bool LowerCaseEqualsASCII(StringPiece str, - StringPiece lowecase_ascii); -BASE_EXPORT bool LowerCaseEqualsASCII(StringPiece16 str, - StringPiece lowecase_ascii); - -// Performs a case-sensitive string compare of the given 16-bit string against -// the given 8-bit ASCII string (typically a constant). The behavior is -// undefined if the |ascii| string is not ASCII. -BASE_EXPORT bool EqualsASCII(StringPiece16 str, StringPiece ascii); - -// Indicates case sensitivity of comparisons. Only ASCII case insensitivity -// is supported. Full Unicode case-insensitive conversions would need to go in -// base/i18n so it can use ICU. -// -// If you need to do Unicode-aware case-insensitive StartsWith/EndsWith, it's -// best to call base::i18n::ToLower() or base::i18n::FoldCase() (see -// base/i18n/case_conversion.h for usage advice) on the arguments, and then use -// the results to a case-sensitive comparison. -enum class CompareCase { - SENSITIVE, - INSENSITIVE_ASCII, -}; - -BASE_EXPORT bool StartsWith(StringPiece str, - StringPiece search_for, - CompareCase case_sensitivity); -BASE_EXPORT bool StartsWith(StringPiece16 str, - StringPiece16 search_for, - CompareCase case_sensitivity); -BASE_EXPORT bool EndsWith(StringPiece str, - StringPiece search_for, - CompareCase case_sensitivity); -BASE_EXPORT bool EndsWith(StringPiece16 str, - StringPiece16 search_for, - CompareCase case_sensitivity); - -// Determines the type of ASCII character, independent of locale (the C -// library versions will change based on locale). -template <typename Char> -inline bool IsAsciiWhitespace(Char c) { - return c == ' ' || c == '\r' || c == '\n' || c == '\t'; -} -template <typename Char> -inline bool IsAsciiAlpha(Char c) { - return ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')); -} -template <typename Char> -inline bool IsAsciiDigit(Char c) { - return c >= '0' && c <= '9'; -} - -template <typename Char> -inline bool IsHexDigit(Char c) { - return (c >= '0' && c <= '9') || - (c >= 'A' && c <= 'F') || - (c >= 'a' && c <= 'f'); -} - -// Returns the integer corresponding to the given hex character. For example: -// '4' -> 4 -// 'a' -> 10 -// 'B' -> 11 -// Assumes the input is a valid hex character. DCHECKs in debug builds if not. -BASE_EXPORT char HexDigitToInt(wchar_t c); - -// Returns true if it's a Unicode whitespace character. -BASE_EXPORT bool IsUnicodeWhitespace(wchar_t c); - -// Return a byte string in human-readable format with a unit suffix. Not -// appropriate for use in any UI; use of FormatBytes and friends in ui/base is -// highly recommended instead. TODO(avi): Figure out how to get callers to use -// FormatBytes instead; remove this. -BASE_EXPORT string16 FormatBytesUnlocalized(int64_t bytes); - -// Starting at |start_offset| (usually 0), replace the first instance of -// |find_this| with |replace_with|. -BASE_EXPORT void ReplaceFirstSubstringAfterOffset( - base::string16* str, - size_t start_offset, - StringPiece16 find_this, - StringPiece16 replace_with); -BASE_EXPORT void ReplaceFirstSubstringAfterOffset( - std::string* str, - size_t start_offset, - StringPiece find_this, - StringPiece replace_with); - -// Starting at |start_offset| (usually 0), look through |str| and replace all -// instances of |find_this| with |replace_with|. -// -// This does entire substrings; use std::replace in <algorithm> for single -// characters, for example: -// std::replace(str.begin(), str.end(), 'a', 'b'); -BASE_EXPORT void ReplaceSubstringsAfterOffset( - string16* str, - size_t start_offset, - StringPiece16 find_this, - StringPiece16 replace_with); -BASE_EXPORT void ReplaceSubstringsAfterOffset( - std::string* str, - size_t start_offset, - StringPiece find_this, - StringPiece replace_with); - -// Reserves enough memory in |str| to accommodate |length_with_null| characters, -// sets the size of |str| to |length_with_null - 1| characters, and returns a -// pointer to the underlying contiguous array of characters. This is typically -// used when calling a function that writes results into a character array, but -// the caller wants the data to be managed by a string-like object. It is -// convenient in that is can be used inline in the call, and fast in that it -// avoids copying the results of the call from a char* into a string. -// -// |length_with_null| must be at least 2, since otherwise the underlying string -// would have size 0, and trying to access &((*str)[0]) in that case can result -// in a number of problems. -// -// Internally, this takes linear time because the resize() call 0-fills the -// underlying array for potentially all -// (|length_with_null - 1| * sizeof(string_type::value_type)) bytes. Ideally we -// could avoid this aspect of the resize() call, as we expect the caller to -// immediately write over this memory, but there is no other way to set the size -// of the string, and not doing that will mean people who access |str| rather -// than str.c_str() will get back a string of whatever size |str| had on entry -// to this function (probably 0). -BASE_EXPORT char* WriteInto(std::string* str, size_t length_with_null); -BASE_EXPORT char16* WriteInto(string16* str, size_t length_with_null); -#ifndef OS_WIN -BASE_EXPORT wchar_t* WriteInto(std::wstring* str, size_t length_with_null); -#endif - -// Does the opposite of SplitString(). -BASE_EXPORT std::string JoinString(const std::vector<std::string>& parts, - StringPiece separator); -BASE_EXPORT string16 JoinString(const std::vector<string16>& parts, - StringPiece16 separator); - -// Replace $1-$2-$3..$9 in the format string with |a|-|b|-|c|..|i| respectively. -// Additionally, any number of consecutive '$' characters is replaced by that -// number less one. Eg $$->$, $$$->$$, etc. The offsets parameter here can be -// NULL. This only allows you to use up to nine replacements. -BASE_EXPORT string16 ReplaceStringPlaceholders( - const string16& format_string, - const std::vector<string16>& subst, - std::vector<size_t>* offsets); - -BASE_EXPORT std::string ReplaceStringPlaceholders( - const StringPiece& format_string, - const std::vector<std::string>& subst, - std::vector<size_t>* offsets); - -// Single-string shortcut for ReplaceStringHolders. |offset| may be NULL. -BASE_EXPORT string16 ReplaceStringPlaceholders(const string16& format_string, - const string16& a, - size_t* offset); - -} // namespace base - -#if defined(OS_WIN) -#include "base/strings/string_util_win.h" -#elif defined(OS_POSIX) -#include "base/strings/string_util_posix.h" -#else -#error Define string operations appropriately for your platform -#endif - -#endif // BASE_STRINGS_STRING_UTIL_H_ diff --git a/security/sandbox/chromium/base/strings/string_util_constants.cc b/security/sandbox/chromium/base/strings/string_util_constants.cc deleted file mode 100644 index aba1b12b8..000000000 --- a/security/sandbox/chromium/base/strings/string_util_constants.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/string_util.h" - -namespace base { - -#define WHITESPACE_UNICODE \ - 0x0009, /* CHARACTER TABULATION */ \ - 0x000A, /* LINE FEED (LF) */ \ - 0x000B, /* LINE TABULATION */ \ - 0x000C, /* FORM FEED (FF) */ \ - 0x000D, /* CARRIAGE RETURN (CR) */ \ - 0x0020, /* SPACE */ \ - 0x0085, /* NEXT LINE (NEL) */ \ - 0x00A0, /* NO-BREAK SPACE */ \ - 0x1680, /* OGHAM SPACE MARK */ \ - 0x2000, /* EN QUAD */ \ - 0x2001, /* EM QUAD */ \ - 0x2002, /* EN SPACE */ \ - 0x2003, /* EM SPACE */ \ - 0x2004, /* THREE-PER-EM SPACE */ \ - 0x2005, /* FOUR-PER-EM SPACE */ \ - 0x2006, /* SIX-PER-EM SPACE */ \ - 0x2007, /* FIGURE SPACE */ \ - 0x2008, /* PUNCTUATION SPACE */ \ - 0x2009, /* THIN SPACE */ \ - 0x200A, /* HAIR SPACE */ \ - 0x2028, /* LINE SEPARATOR */ \ - 0x2029, /* PARAGRAPH SEPARATOR */ \ - 0x202F, /* NARROW NO-BREAK SPACE */ \ - 0x205F, /* MEDIUM MATHEMATICAL SPACE */ \ - 0x3000, /* IDEOGRAPHIC SPACE */ \ - 0 - -const wchar_t kWhitespaceWide[] = { - WHITESPACE_UNICODE -}; - -const char16 kWhitespaceUTF16[] = { - WHITESPACE_UNICODE -}; - -const char kWhitespaceASCII[] = { - 0x09, // CHARACTER TABULATION - 0x0A, // LINE FEED (LF) - 0x0B, // LINE TABULATION - 0x0C, // FORM FEED (FF) - 0x0D, // CARRIAGE RETURN (CR) - 0x20, // SPACE - 0 -}; - -const char16 kWhitespaceASCIIAs16[] = { - 0x09, // CHARACTER TABULATION - 0x0A, // LINE FEED (LF) - 0x0B, // LINE TABULATION - 0x0C, // FORM FEED (FF) - 0x0D, // CARRIAGE RETURN (CR) - 0x20, // SPACE - 0 -}; - -const char kUtf8ByteOrderMark[] = "\xEF\xBB\xBF"; - -} // namespace base diff --git a/security/sandbox/chromium/base/strings/string_util_posix.h b/security/sandbox/chromium/base/strings/string_util_posix.h deleted file mode 100644 index 8299118e1..000000000 --- a/security/sandbox/chromium/base/strings/string_util_posix.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_STRING_UTIL_POSIX_H_ -#define BASE_STRINGS_STRING_UTIL_POSIX_H_ - -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include <wchar.h> - -#include "base/logging.h" - -namespace base { - -// Chromium code style is to not use malloc'd strings; this is only for use -// for interaction with APIs that require it. -inline char* strdup(const char* str) { - return ::strdup(str); -} - -inline int vsnprintf(char* buffer, size_t size, - const char* format, va_list arguments) { - return ::vsnprintf(buffer, size, format, arguments); -} - -inline int vswprintf(wchar_t* buffer, size_t size, - const wchar_t* format, va_list arguments) { - DCHECK(IsWprintfFormatPortable(format)); - return ::vswprintf(buffer, size, format, arguments); -} - -} // namespace base - -#endif // BASE_STRINGS_STRING_UTIL_POSIX_H_ diff --git a/security/sandbox/chromium/base/strings/string_util_win.h b/security/sandbox/chromium/base/strings/string_util_win.h deleted file mode 100644 index 7f260bfc8..000000000 --- a/security/sandbox/chromium/base/strings/string_util_win.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_STRING_UTIL_WIN_H_ -#define BASE_STRINGS_STRING_UTIL_WIN_H_ - -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include <wchar.h> - -#include "base/logging.h" - -namespace base { - -// Chromium code style is to not use malloc'd strings; this is only for use -// for interaction with APIs that require it. -inline char* strdup(const char* str) { - return _strdup(str); -} - -inline int vsnprintf(char* buffer, size_t size, - const char* format, va_list arguments) { - int length = vsnprintf_s(buffer, size, size - 1, format, arguments); - if (length < 0) - return _vscprintf(format, arguments); - return length; -} - -inline int vswprintf(wchar_t* buffer, size_t size, - const wchar_t* format, va_list arguments) { - DCHECK(IsWprintfFormatPortable(format)); - - int length = _vsnwprintf_s(buffer, size, size - 1, format, arguments); - if (length < 0) - return _vscwprintf(format, arguments); - return length; -} - -} // namespace base - -#endif // BASE_STRINGS_STRING_UTIL_WIN_H_ diff --git a/security/sandbox/chromium/base/strings/stringprintf.cc b/security/sandbox/chromium/base/strings/stringprintf.cc deleted file mode 100644 index 415845d61..000000000 --- a/security/sandbox/chromium/base/strings/stringprintf.cc +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/stringprintf.h" - -#include <errno.h> -#include <stddef.h> - -#include <vector> - -#include "base/macros.h" -#include "base/scoped_clear_errno.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" - -namespace base { - -namespace { - -// Overloaded wrappers around vsnprintf and vswprintf. The buf_size parameter -// is the size of the buffer. These return the number of characters in the -// formatted string excluding the NUL terminator. If the buffer is not -// large enough to accommodate the formatted string without truncation, they -// return the number of characters that would be in the fully-formatted string -// (vsnprintf, and vswprintf on Windows), or -1 (vswprintf on POSIX platforms). -inline int vsnprintfT(char* buffer, - size_t buf_size, - const char* format, - va_list argptr) { - return base::vsnprintf(buffer, buf_size, format, argptr); -} - -#if defined(OS_WIN) -inline int vsnprintfT(wchar_t* buffer, - size_t buf_size, - const wchar_t* format, - va_list argptr) { - return base::vswprintf(buffer, buf_size, format, argptr); -} -#endif - -// Templatized backend for StringPrintF/StringAppendF. This does not finalize -// the va_list, the caller is expected to do that. -template <class StringType> -static void StringAppendVT(StringType* dst, - const typename StringType::value_type* format, - va_list ap) { - // First try with a small fixed size buffer. - // This buffer size should be kept in sync with StringUtilTest.GrowBoundary - // and StringUtilTest.StringPrintfBounds. - typename StringType::value_type stack_buf[1024]; - - va_list ap_copy; - va_copy(ap_copy, ap); - -#if !defined(OS_WIN) - ScopedClearErrno clear_errno; -#endif - int result = vsnprintfT(stack_buf, arraysize(stack_buf), format, ap_copy); - va_end(ap_copy); - - if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) { - // It fit. - dst->append(stack_buf, result); - return; - } - - // Repeatedly increase buffer size until it fits. - int mem_length = arraysize(stack_buf); - while (true) { - if (result < 0) { -#if defined(OS_WIN) - // On Windows, vsnprintfT always returns the number of characters in a - // fully-formatted string, so if we reach this point, something else is - // wrong and no amount of buffer-doubling is going to fix it. - return; -#else - if (errno != 0 && errno != EOVERFLOW) - return; - // Try doubling the buffer size. - mem_length *= 2; -#endif - } else { - // We need exactly "result + 1" characters. - mem_length = result + 1; - } - - if (mem_length > 32 * 1024 * 1024) { - // That should be plenty, don't try anything larger. This protects - // against huge allocations when using vsnprintfT implementations that - // return -1 for reasons other than overflow without setting errno. - DLOG(WARNING) << "Unable to printf the requested string due to size."; - return; - } - - std::vector<typename StringType::value_type> mem_buf(mem_length); - - // NOTE: You can only use a va_list once. Since we're in a while loop, we - // need to make a new copy each time so we don't use up the original. - va_copy(ap_copy, ap); - result = vsnprintfT(&mem_buf[0], mem_length, format, ap_copy); - va_end(ap_copy); - - if ((result >= 0) && (result < mem_length)) { - // It fit. - dst->append(&mem_buf[0], result); - return; - } - } -} - -} // namespace - -std::string StringPrintf(const char* format, ...) { - va_list ap; - va_start(ap, format); - std::string result; - StringAppendV(&result, format, ap); - va_end(ap); - return result; -} - -#if defined(OS_WIN) -std::wstring StringPrintf(const wchar_t* format, ...) { - va_list ap; - va_start(ap, format); - std::wstring result; - StringAppendV(&result, format, ap); - va_end(ap); - return result; -} -#endif - -std::string StringPrintV(const char* format, va_list ap) { - std::string result; - StringAppendV(&result, format, ap); - return result; -} - -const std::string& SStringPrintf(std::string* dst, const char* format, ...) { - va_list ap; - va_start(ap, format); - dst->clear(); - StringAppendV(dst, format, ap); - va_end(ap); - return *dst; -} - -#if defined(OS_WIN) -const std::wstring& SStringPrintf(std::wstring* dst, - const wchar_t* format, ...) { - va_list ap; - va_start(ap, format); - dst->clear(); - StringAppendV(dst, format, ap); - va_end(ap); - return *dst; -} -#endif - -void StringAppendF(std::string* dst, const char* format, ...) { - va_list ap; - va_start(ap, format); - StringAppendV(dst, format, ap); - va_end(ap); -} - -#if defined(OS_WIN) -void StringAppendF(std::wstring* dst, const wchar_t* format, ...) { - va_list ap; - va_start(ap, format); - StringAppendV(dst, format, ap); - va_end(ap); -} -#endif - -void StringAppendV(std::string* dst, const char* format, va_list ap) { - StringAppendVT(dst, format, ap); -} - -#if defined(OS_WIN) -void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) { - StringAppendVT(dst, format, ap); -} -#endif - -} // namespace base diff --git a/security/sandbox/chromium/base/strings/stringprintf.h b/security/sandbox/chromium/base/strings/stringprintf.h deleted file mode 100644 index 7a75d89e1..000000000 --- a/security/sandbox/chromium/base/strings/stringprintf.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_STRINGPRINTF_H_ -#define BASE_STRINGS_STRINGPRINTF_H_ - -#include <stdarg.h> // va_list - -#include <string> - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "build/build_config.h" - -namespace base { - -// Return a C++ string given printf-like input. -BASE_EXPORT std::string StringPrintf(_Printf_format_string_ const char* format, - ...) - PRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT; -#if defined(OS_WIN) -BASE_EXPORT std::wstring StringPrintf( - _Printf_format_string_ const wchar_t* format, - ...) WPRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT; -#endif - -// Return a C++ string given vprintf-like input. -BASE_EXPORT std::string StringPrintV(const char* format, va_list ap) - PRINTF_FORMAT(1, 0) WARN_UNUSED_RESULT; - -// Store result into a supplied string and return it. -BASE_EXPORT const std::string& SStringPrintf( - std::string* dst, - _Printf_format_string_ const char* format, - ...) PRINTF_FORMAT(2, 3); -#if defined(OS_WIN) -BASE_EXPORT const std::wstring& SStringPrintf( - std::wstring* dst, - _Printf_format_string_ const wchar_t* format, - ...) WPRINTF_FORMAT(2, 3); -#endif - -// Append result to a supplied string. -BASE_EXPORT void StringAppendF(std::string* dst, - _Printf_format_string_ const char* format, - ...) PRINTF_FORMAT(2, 3); -#if defined(OS_WIN) -BASE_EXPORT void StringAppendF(std::wstring* dst, - _Printf_format_string_ const wchar_t* format, - ...) WPRINTF_FORMAT(2, 3); -#endif - -// Lower-level routine that takes a va_list and appends to a specified -// string. All other routines are just convenience wrappers around it. -BASE_EXPORT void StringAppendV(std::string* dst, const char* format, va_list ap) - PRINTF_FORMAT(2, 0); -#if defined(OS_WIN) -BASE_EXPORT void StringAppendV(std::wstring* dst, - const wchar_t* format, va_list ap) - WPRINTF_FORMAT(2, 0); -#endif - -} // namespace base - -#endif // BASE_STRINGS_STRINGPRINTF_H_ diff --git a/security/sandbox/chromium/base/strings/utf_string_conversion_utils.cc b/security/sandbox/chromium/base/strings/utf_string_conversion_utils.cc deleted file mode 100644 index 3101a6028..000000000 --- a/security/sandbox/chromium/base/strings/utf_string_conversion_utils.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/utf_string_conversion_utils.h" - -#include "base/third_party/icu/icu_utf.h" - -namespace base { - -// ReadUnicodeCharacter -------------------------------------------------------- - -bool ReadUnicodeCharacter(const char* src, - int32_t src_len, - int32_t* char_index, - uint32_t* code_point_out) { - // U8_NEXT expects to be able to use -1 to signal an error, so we must - // use a signed type for code_point. But this function returns false - // on error anyway, so code_point_out is unsigned. - int32_t code_point; - CBU8_NEXT(src, *char_index, src_len, code_point); - *code_point_out = static_cast<uint32_t>(code_point); - - // The ICU macro above moves to the next char, we want to point to the last - // char consumed. - (*char_index)--; - - // Validate the decoded value. - return IsValidCodepoint(code_point); -} - -bool ReadUnicodeCharacter(const char16* src, - int32_t src_len, - int32_t* char_index, - uint32_t* code_point) { - if (CBU16_IS_SURROGATE(src[*char_index])) { - if (!CBU16_IS_SURROGATE_LEAD(src[*char_index]) || - *char_index + 1 >= src_len || - !CBU16_IS_TRAIL(src[*char_index + 1])) { - // Invalid surrogate pair. - return false; - } - - // Valid surrogate pair. - *code_point = CBU16_GET_SUPPLEMENTARY(src[*char_index], - src[*char_index + 1]); - (*char_index)++; - } else { - // Not a surrogate, just one 16-bit word. - *code_point = src[*char_index]; - } - - return IsValidCodepoint(*code_point); -} - -#if defined(WCHAR_T_IS_UTF32) -bool ReadUnicodeCharacter(const wchar_t* src, - int32_t src_len, - int32_t* char_index, - uint32_t* code_point) { - // Conversion is easy since the source is 32-bit. - *code_point = src[*char_index]; - - // Validate the value. - return IsValidCodepoint(*code_point); -} -#endif // defined(WCHAR_T_IS_UTF32) - -// WriteUnicodeCharacter ------------------------------------------------------- - -size_t WriteUnicodeCharacter(uint32_t code_point, std::string* output) { - if (code_point <= 0x7f) { - // Fast path the common case of one byte. - output->push_back(static_cast<char>(code_point)); - return 1; - } - - - // CBU8_APPEND_UNSAFE can append up to 4 bytes. - size_t char_offset = output->length(); - size_t original_char_offset = char_offset; - output->resize(char_offset + CBU8_MAX_LENGTH); - - CBU8_APPEND_UNSAFE(&(*output)[0], char_offset, code_point); - - // CBU8_APPEND_UNSAFE will advance our pointer past the inserted character, so - // it will represent the new length of the string. - output->resize(char_offset); - return char_offset - original_char_offset; -} - -size_t WriteUnicodeCharacter(uint32_t code_point, string16* output) { - if (CBU16_LENGTH(code_point) == 1) { - // Thie code point is in the Basic Multilingual Plane (BMP). - output->push_back(static_cast<char16>(code_point)); - return 1; - } - // Non-BMP characters use a double-character encoding. - size_t char_offset = output->length(); - output->resize(char_offset + CBU16_MAX_LENGTH); - CBU16_APPEND_UNSAFE(&(*output)[0], char_offset, code_point); - return CBU16_MAX_LENGTH; -} - -// Generalized Unicode converter ----------------------------------------------- - -template<typename CHAR> -void PrepareForUTF8Output(const CHAR* src, - size_t src_len, - std::string* output) { - output->clear(); - if (src_len == 0) - return; - if (src[0] < 0x80) { - // Assume that the entire input will be ASCII. - output->reserve(src_len); - } else { - // Assume that the entire input is non-ASCII and will have 3 bytes per char. - output->reserve(src_len * 3); - } -} - -// Instantiate versions we know callers will need. -template void PrepareForUTF8Output(const wchar_t*, size_t, std::string*); -template void PrepareForUTF8Output(const char16*, size_t, std::string*); - -template<typename STRING> -void PrepareForUTF16Or32Output(const char* src, - size_t src_len, - STRING* output) { - output->clear(); - if (src_len == 0) - return; - if (static_cast<unsigned char>(src[0]) < 0x80) { - // Assume the input is all ASCII, which means 1:1 correspondence. - output->reserve(src_len); - } else { - // Otherwise assume that the UTF-8 sequences will have 2 bytes for each - // character. - output->reserve(src_len / 2); - } -} - -// Instantiate versions we know callers will need. -template void PrepareForUTF16Or32Output(const char*, size_t, std::wstring*); -template void PrepareForUTF16Or32Output(const char*, size_t, string16*); - -} // namespace base diff --git a/security/sandbox/chromium/base/strings/utf_string_conversion_utils.h b/security/sandbox/chromium/base/strings/utf_string_conversion_utils.h deleted file mode 100644 index c71640453..000000000 --- a/security/sandbox/chromium/base/strings/utf_string_conversion_utils.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_UTF_STRING_CONVERSION_UTILS_H_ -#define BASE_STRINGS_UTF_STRING_CONVERSION_UTILS_H_ - -// This should only be used by the various UTF string conversion files. - -#include <stddef.h> -#include <stdint.h> - -#include "base/base_export.h" -#include "base/strings/string16.h" - -namespace base { - -inline bool IsValidCodepoint(uint32_t code_point) { - // Excludes the surrogate code points ([0xD800, 0xDFFF]) and - // codepoints larger than 0x10FFFF (the highest codepoint allowed). - // Non-characters and unassigned codepoints are allowed. - return code_point < 0xD800u || - (code_point >= 0xE000u && code_point <= 0x10FFFFu); -} - -inline bool IsValidCharacter(uint32_t code_point) { - // Excludes non-characters (U+FDD0..U+FDEF, and all codepoints ending in - // 0xFFFE or 0xFFFF) from the set of valid code points. - return code_point < 0xD800u || (code_point >= 0xE000u && - code_point < 0xFDD0u) || (code_point > 0xFDEFu && - code_point <= 0x10FFFFu && (code_point & 0xFFFEu) != 0xFFFEu); -} - -// ReadUnicodeCharacter -------------------------------------------------------- - -// Reads a UTF-8 stream, placing the next code point into the given output -// |*code_point|. |src| represents the entire string to read, and |*char_index| -// is the character offset within the string to start reading at. |*char_index| -// will be updated to index the last character read, such that incrementing it -// (as in a for loop) will take the reader to the next character. -// -// Returns true on success. On false, |*code_point| will be invalid. -BASE_EXPORT bool ReadUnicodeCharacter(const char* src, - int32_t src_len, - int32_t* char_index, - uint32_t* code_point_out); - -// Reads a UTF-16 character. The usage is the same as the 8-bit version above. -BASE_EXPORT bool ReadUnicodeCharacter(const char16* src, - int32_t src_len, - int32_t* char_index, - uint32_t* code_point); - -#if defined(WCHAR_T_IS_UTF32) -// Reads UTF-32 character. The usage is the same as the 8-bit version above. -BASE_EXPORT bool ReadUnicodeCharacter(const wchar_t* src, - int32_t src_len, - int32_t* char_index, - uint32_t* code_point); -#endif // defined(WCHAR_T_IS_UTF32) - -// WriteUnicodeCharacter ------------------------------------------------------- - -// Appends a UTF-8 character to the given 8-bit string. Returns the number of -// bytes written. -BASE_EXPORT size_t WriteUnicodeCharacter(uint32_t code_point, - std::string* output); - -// Appends the given code point as a UTF-16 character to the given 16-bit -// string. Returns the number of 16-bit values written. -BASE_EXPORT size_t WriteUnicodeCharacter(uint32_t code_point, string16* output); - -#if defined(WCHAR_T_IS_UTF32) -// Appends the given UTF-32 character to the given 32-bit string. Returns the -// number of 32-bit values written. -inline size_t WriteUnicodeCharacter(uint32_t code_point, std::wstring* output) { - // This is the easy case, just append the character. - output->push_back(code_point); - return 1; -} -#endif // defined(WCHAR_T_IS_UTF32) - -// Generalized Unicode converter ----------------------------------------------- - -// Guesses the length of the output in UTF-8 in bytes, clears that output -// string, and reserves that amount of space. We assume that the input -// character types are unsigned, which will be true for UTF-16 and -32 on our -// systems. -template<typename CHAR> -void PrepareForUTF8Output(const CHAR* src, size_t src_len, std::string* output); - -// Prepares an output buffer (containing either UTF-16 or -32 data) given some -// UTF-8 input that will be converted to it. See PrepareForUTF8Output(). -template<typename STRING> -void PrepareForUTF16Or32Output(const char* src, size_t src_len, STRING* output); - -} // namespace base - -#endif // BASE_STRINGS_UTF_STRING_CONVERSION_UTILS_H_ diff --git a/security/sandbox/chromium/base/strings/utf_string_conversions.cc b/security/sandbox/chromium/base/strings/utf_string_conversions.cc deleted file mode 100644 index 6b17eacd6..000000000 --- a/security/sandbox/chromium/base/strings/utf_string_conversions.cc +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/utf_string_conversions.h" - -#include <stdint.h> - -#include "base/strings/string_piece.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversion_utils.h" -#include "build/build_config.h" - -namespace base { - -namespace { - -// Generalized Unicode converter ----------------------------------------------- - -// Converts the given source Unicode character type to the given destination -// Unicode character type as a STL string. The given input buffer and size -// determine the source, and the given output STL string will be replaced by -// the result. -template<typename SRC_CHAR, typename DEST_STRING> -bool ConvertUnicode(const SRC_CHAR* src, - size_t src_len, - DEST_STRING* output) { - // ICU requires 32-bit numbers. - bool success = true; - int32_t src_len32 = static_cast<int32_t>(src_len); - for (int32_t i = 0; i < src_len32; i++) { - uint32_t code_point; - if (ReadUnicodeCharacter(src, src_len32, &i, &code_point)) { - WriteUnicodeCharacter(code_point, output); - } else { - WriteUnicodeCharacter(0xFFFD, output); - success = false; - } - } - - return success; -} - -} // namespace - -// UTF-8 <-> Wide -------------------------------------------------------------- - -bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) { - if (IsStringASCII(std::wstring(src, src_len))) { - output->assign(src, src + src_len); - return true; - } else { - PrepareForUTF8Output(src, src_len, output); - return ConvertUnicode(src, src_len, output); - } -} - -std::string WideToUTF8(const std::wstring& wide) { - if (IsStringASCII(wide)) { - return std::string(wide.data(), wide.data() + wide.length()); - } - - std::string ret; - PrepareForUTF8Output(wide.data(), wide.length(), &ret); - ConvertUnicode(wide.data(), wide.length(), &ret); - return ret; -} - -bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output) { - if (IsStringASCII(StringPiece(src, src_len))) { - output->assign(src, src + src_len); - return true; - } else { - PrepareForUTF16Or32Output(src, src_len, output); - return ConvertUnicode(src, src_len, output); - } -} - -std::wstring UTF8ToWide(StringPiece utf8) { - if (IsStringASCII(utf8)) { - return std::wstring(utf8.begin(), utf8.end()); - } - - std::wstring ret; - PrepareForUTF16Or32Output(utf8.data(), utf8.length(), &ret); - ConvertUnicode(utf8.data(), utf8.length(), &ret); - return ret; -} - -// UTF-16 <-> Wide ------------------------------------------------------------- - -#if defined(WCHAR_T_IS_UTF16) - -// When wide == UTF-16, then conversions are a NOP. -bool WideToUTF16(const wchar_t* src, size_t src_len, string16* output) { - output->assign(src, src_len); - return true; -} - -string16 WideToUTF16(const std::wstring& wide) { - return wide; -} - -bool UTF16ToWide(const char16* src, size_t src_len, std::wstring* output) { - output->assign(src, src_len); - return true; -} - -std::wstring UTF16ToWide(const string16& utf16) { - return utf16; -} - -#elif defined(WCHAR_T_IS_UTF32) - -bool WideToUTF16(const wchar_t* src, size_t src_len, string16* output) { - output->clear(); - // Assume that normally we won't have any non-BMP characters so the counts - // will be the same. - output->reserve(src_len); - return ConvertUnicode(src, src_len, output); -} - -string16 WideToUTF16(const std::wstring& wide) { - string16 ret; - WideToUTF16(wide.data(), wide.length(), &ret); - return ret; -} - -bool UTF16ToWide(const char16* src, size_t src_len, std::wstring* output) { - output->clear(); - // Assume that normally we won't have any non-BMP characters so the counts - // will be the same. - output->reserve(src_len); - return ConvertUnicode(src, src_len, output); -} - -std::wstring UTF16ToWide(const string16& utf16) { - std::wstring ret; - UTF16ToWide(utf16.data(), utf16.length(), &ret); - return ret; -} - -#endif // defined(WCHAR_T_IS_UTF32) - -// UTF16 <-> UTF8 -------------------------------------------------------------- - -#if defined(WCHAR_T_IS_UTF32) - -bool UTF8ToUTF16(const char* src, size_t src_len, string16* output) { - if (IsStringASCII(StringPiece(src, src_len))) { - output->assign(src, src + src_len); - return true; - } else { - PrepareForUTF16Or32Output(src, src_len, output); - return ConvertUnicode(src, src_len, output); - } -} - -string16 UTF8ToUTF16(StringPiece utf8) { - if (IsStringASCII(utf8)) { - return string16(utf8.begin(), utf8.end()); - } - - string16 ret; - PrepareForUTF16Or32Output(utf8.data(), utf8.length(), &ret); - // Ignore the success flag of this call, it will do the best it can for - // invalid input, which is what we want here. - ConvertUnicode(utf8.data(), utf8.length(), &ret); - return ret; -} - -bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output) { - if (IsStringASCII(StringPiece16(src, src_len))) { - output->assign(src, src + src_len); - return true; - } else { - PrepareForUTF8Output(src, src_len, output); - return ConvertUnicode(src, src_len, output); - } -} - -std::string UTF16ToUTF8(StringPiece16 utf16) { - if (IsStringASCII(utf16)) { - return std::string(utf16.begin(), utf16.end()); - } - - std::string ret; - // Ignore the success flag of this call, it will do the best it can for - // invalid input, which is what we want here. - UTF16ToUTF8(utf16.data(), utf16.length(), &ret); - return ret; -} - -#elif defined(WCHAR_T_IS_UTF16) -// Easy case since we can use the "wide" versions we already wrote above. - -bool UTF8ToUTF16(const char* src, size_t src_len, string16* output) { - return UTF8ToWide(src, src_len, output); -} - -string16 UTF8ToUTF16(StringPiece utf8) { - return UTF8ToWide(utf8); -} - -bool UTF16ToUTF8(const char16* src, size_t src_len, std::string* output) { - return WideToUTF8(src, src_len, output); -} - -std::string UTF16ToUTF8(StringPiece16 utf16) { - if (IsStringASCII(utf16)) - return std::string(utf16.data(), utf16.data() + utf16.length()); - - std::string ret; - PrepareForUTF8Output(utf16.data(), utf16.length(), &ret); - ConvertUnicode(utf16.data(), utf16.length(), &ret); - return ret; -} - -#endif - -string16 ASCIIToUTF16(StringPiece ascii) { - DCHECK(IsStringASCII(ascii)) << ascii; - return string16(ascii.begin(), ascii.end()); -} - -std::string UTF16ToASCII(StringPiece16 utf16) { - DCHECK(IsStringASCII(utf16)) << UTF16ToUTF8(utf16); - return std::string(utf16.begin(), utf16.end()); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/strings/utf_string_conversions.h b/security/sandbox/chromium/base/strings/utf_string_conversions.h deleted file mode 100644 index 2995f4cbc..000000000 --- a/security/sandbox/chromium/base/strings/utf_string_conversions.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_UTF_STRING_CONVERSIONS_H_ -#define BASE_STRINGS_UTF_STRING_CONVERSIONS_H_ - -#include <stddef.h> - -#include <string> - -#include "base/base_export.h" -#include "base/strings/string16.h" -#include "base/strings/string_piece.h" - -namespace base { - -// These convert between UTF-8, -16, and -32 strings. They are potentially slow, -// so avoid unnecessary conversions. The low-level versions return a boolean -// indicating whether the conversion was 100% valid. In this case, it will still -// do the best it can and put the result in the output buffer. The versions that -// return strings ignore this error and just return the best conversion -// possible. -BASE_EXPORT bool WideToUTF8(const wchar_t* src, size_t src_len, - std::string* output); -BASE_EXPORT std::string WideToUTF8(const std::wstring& wide); -BASE_EXPORT bool UTF8ToWide(const char* src, size_t src_len, - std::wstring* output); -BASE_EXPORT std::wstring UTF8ToWide(StringPiece utf8); - -BASE_EXPORT bool WideToUTF16(const wchar_t* src, size_t src_len, - string16* output); -BASE_EXPORT string16 WideToUTF16(const std::wstring& wide); -BASE_EXPORT bool UTF16ToWide(const char16* src, size_t src_len, - std::wstring* output); -BASE_EXPORT std::wstring UTF16ToWide(const string16& utf16); - -BASE_EXPORT bool UTF8ToUTF16(const char* src, size_t src_len, string16* output); -BASE_EXPORT string16 UTF8ToUTF16(StringPiece utf8); -BASE_EXPORT bool UTF16ToUTF8(const char16* src, size_t src_len, - std::string* output); -BASE_EXPORT std::string UTF16ToUTF8(StringPiece16 utf16); - -// This converts an ASCII string, typically a hardcoded constant, to a UTF16 -// string. -BASE_EXPORT string16 ASCIIToUTF16(StringPiece ascii); - -// Converts to 7-bit ASCII by truncating. The result must be known to be ASCII -// beforehand. -BASE_EXPORT std::string UTF16ToASCII(StringPiece16 utf16); - -} // namespace base - -#endif // BASE_STRINGS_UTF_STRING_CONVERSIONS_H_ diff --git a/security/sandbox/chromium/base/synchronization/condition_variable.h b/security/sandbox/chromium/base/synchronization/condition_variable.h deleted file mode 100644 index a41b2ba5a..000000000 --- a/security/sandbox/chromium/base/synchronization/condition_variable.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ConditionVariable wraps pthreads condition variable synchronization or, on -// Windows, simulates it. This functionality is very helpful for having -// several threads wait for an event, as is common with a thread pool managed -// by a master. The meaning of such an event in the (worker) thread pool -// scenario is that additional tasks are now available for processing. It is -// used in Chrome in the DNS prefetching system to notify worker threads that -// a queue now has items (tasks) which need to be tended to. A related use -// would have a pool manager waiting on a ConditionVariable, waiting for a -// thread in the pool to announce (signal) that there is now more room in a -// (bounded size) communications queue for the manager to deposit tasks, or, -// as a second example, that the queue of tasks is completely empty and all -// workers are waiting. -// -// USAGE NOTE 1: spurious signal events are possible with this and -// most implementations of condition variables. As a result, be -// *sure* to retest your condition before proceeding. The following -// is a good example of doing this correctly: -// -// while (!work_to_be_done()) Wait(...); -// -// In contrast do NOT do the following: -// -// if (!work_to_be_done()) Wait(...); // Don't do this. -// -// Especially avoid the above if you are relying on some other thread only -// issuing a signal up *if* there is work-to-do. There can/will -// be spurious signals. Recheck state on waiting thread before -// assuming the signal was intentional. Caveat caller ;-). -// -// USAGE NOTE 2: Broadcast() frees up all waiting threads at once, -// which leads to contention for the locks they all held when they -// called Wait(). This results in POOR performance. A much better -// approach to getting a lot of threads out of Wait() is to have each -// thread (upon exiting Wait()) call Signal() to free up another -// Wait'ing thread. Look at condition_variable_unittest.cc for -// both examples. -// -// Broadcast() can be used nicely during teardown, as it gets the job -// done, and leaves no sleeping threads... and performance is less -// critical at that point. -// -// The semantics of Broadcast() are carefully crafted so that *all* -// threads that were waiting when the request was made will indeed -// get signaled. Some implementations mess up, and don't signal them -// all, while others allow the wait to be effectively turned off (for -// a while while waiting threads come around). This implementation -// appears correct, as it will not "lose" any signals, and will guarantee -// that all threads get signaled by Broadcast(). -// -// This implementation offers support for "performance" in its selection of -// which thread to revive. Performance, in direct contrast with "fairness," -// assures that the thread that most recently began to Wait() is selected by -// Signal to revive. Fairness would (if publicly supported) assure that the -// thread that has Wait()ed the longest is selected. The default policy -// may improve performance, as the selected thread may have a greater chance of -// having some of its stack data in various CPU caches. -// -// For a discussion of the many very subtle implementation details, see the FAQ -// at the end of condition_variable_win.cc. - -#ifndef BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ -#define BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "build/build_config.h" - -#if defined(OS_POSIX) -#include <pthread.h> -#endif - -namespace base { - -class ConditionVarImpl; -class TimeDelta; - -class BASE_EXPORT ConditionVariable { - public: - // Construct a cv for use with ONLY one user lock. - explicit ConditionVariable(Lock* user_lock); - - ~ConditionVariable(); - - // Wait() releases the caller's critical section atomically as it starts to - // sleep, and the reacquires it when it is signaled. - void Wait(); - void TimedWait(const TimeDelta& max_time); - - // Broadcast() revives all waiting threads. - void Broadcast(); - // Signal() revives one waiting thread. - void Signal(); - - private: - -#if defined(OS_WIN) - ConditionVarImpl* impl_; -#elif defined(OS_POSIX) - pthread_cond_t condition_; - pthread_mutex_t* user_mutex_; -#if DCHECK_IS_ON() - base::Lock* user_lock_; // Needed to adjust shadow lock state on wait. -#endif - -#endif - - DISALLOW_COPY_AND_ASSIGN(ConditionVariable); -}; - -} // namespace base - -#endif // BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ diff --git a/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc b/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc deleted file mode 100644 index d86fd180e..000000000 --- a/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/synchronization/condition_variable.h" - -#include <errno.h> -#include <stdint.h> -#include <sys/time.h> - -#include "base/synchronization/lock.h" -#include "base/threading/thread_restrictions.h" -#include "base/time/time.h" -#include "build/build_config.h" - -namespace base { - -ConditionVariable::ConditionVariable(Lock* user_lock) - : user_mutex_(user_lock->lock_.native_handle()) -#if DCHECK_IS_ON() - , user_lock_(user_lock) -#endif -{ - int rv = 0; - // http://crbug.com/293736 - // NaCl doesn't support monotonic clock based absolute deadlines. - // On older Android platform versions, it's supported through the - // non-standard pthread_cond_timedwait_monotonic_np. Newer platform - // versions have pthread_condattr_setclock. - // Mac can use relative time deadlines. -#if !defined(OS_MACOSX) && !defined(OS_NACL) && \ - !(defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) - pthread_condattr_t attrs; - rv = pthread_condattr_init(&attrs); - DCHECK_EQ(0, rv); - pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC); - rv = pthread_cond_init(&condition_, &attrs); - pthread_condattr_destroy(&attrs); -#else - rv = pthread_cond_init(&condition_, NULL); -#endif - DCHECK_EQ(0, rv); -} - -ConditionVariable::~ConditionVariable() { -#if defined(OS_MACOSX) - // This hack is necessary to avoid a fatal pthreads subsystem bug in the - // Darwin kernel. http://crbug.com/517681. - { - base::Lock lock; - base::AutoLock l(lock); - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 1; - pthread_cond_timedwait_relative_np(&condition_, lock.lock_.native_handle(), - &ts); - } -#endif - - int rv = pthread_cond_destroy(&condition_); - DCHECK_EQ(0, rv); -} - -void ConditionVariable::Wait() { - base::ThreadRestrictions::AssertWaitAllowed(); -#if DCHECK_IS_ON() - user_lock_->CheckHeldAndUnmark(); -#endif - int rv = pthread_cond_wait(&condition_, user_mutex_); - DCHECK_EQ(0, rv); -#if DCHECK_IS_ON() - user_lock_->CheckUnheldAndMark(); -#endif -} - -void ConditionVariable::TimedWait(const TimeDelta& max_time) { - base::ThreadRestrictions::AssertWaitAllowed(); - int64_t usecs = max_time.InMicroseconds(); - struct timespec relative_time; - relative_time.tv_sec = usecs / Time::kMicrosecondsPerSecond; - relative_time.tv_nsec = - (usecs % Time::kMicrosecondsPerSecond) * Time::kNanosecondsPerMicrosecond; - -#if DCHECK_IS_ON() - user_lock_->CheckHeldAndUnmark(); -#endif - -#if defined(OS_MACOSX) - int rv = pthread_cond_timedwait_relative_np( - &condition_, user_mutex_, &relative_time); -#else - // The timeout argument to pthread_cond_timedwait is in absolute time. - struct timespec absolute_time; -#if defined(OS_NACL) - // See comment in constructor for why this is different in NaCl. - struct timeval now; - gettimeofday(&now, NULL); - absolute_time.tv_sec = now.tv_sec; - absolute_time.tv_nsec = now.tv_usec * Time::kNanosecondsPerMicrosecond; -#else - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - absolute_time.tv_sec = now.tv_sec; - absolute_time.tv_nsec = now.tv_nsec; -#endif - - absolute_time.tv_sec += relative_time.tv_sec; - absolute_time.tv_nsec += relative_time.tv_nsec; - absolute_time.tv_sec += absolute_time.tv_nsec / Time::kNanosecondsPerSecond; - absolute_time.tv_nsec %= Time::kNanosecondsPerSecond; - DCHECK_GE(absolute_time.tv_sec, now.tv_sec); // Overflow paranoia - -#if defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) - int rv = pthread_cond_timedwait_monotonic_np( - &condition_, user_mutex_, &absolute_time); -#else - int rv = pthread_cond_timedwait(&condition_, user_mutex_, &absolute_time); -#endif // OS_ANDROID && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC -#endif // OS_MACOSX - - DCHECK(rv == 0 || rv == ETIMEDOUT); -#if DCHECK_IS_ON() - user_lock_->CheckUnheldAndMark(); -#endif -} - -void ConditionVariable::Broadcast() { - int rv = pthread_cond_broadcast(&condition_); - DCHECK_EQ(0, rv); -} - -void ConditionVariable::Signal() { - int rv = pthread_cond_signal(&condition_); - DCHECK_EQ(0, rv); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/synchronization/lock.cc b/security/sandbox/chromium/base/synchronization/lock.cc deleted file mode 100644 index 03297ada5..000000000 --- a/security/sandbox/chromium/base/synchronization/lock.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is used for debugging assertion support. The Lock class -// is functionally a wrapper around the LockImpl class, so the only -// real intelligence in the class is in the debugging logic. - -#include "base/synchronization/lock.h" - -#if DCHECK_IS_ON() - -namespace base { - -Lock::Lock() : lock_() { -} - -Lock::~Lock() { - DCHECK(owning_thread_ref_.is_null()); -} - -void Lock::AssertAcquired() const { - DCHECK(owning_thread_ref_ == PlatformThread::CurrentRef()); -} - -void Lock::CheckHeldAndUnmark() { - DCHECK(owning_thread_ref_ == PlatformThread::CurrentRef()); - owning_thread_ref_ = PlatformThreadRef(); -} - -void Lock::CheckUnheldAndMark() { - DCHECK(owning_thread_ref_.is_null()); - owning_thread_ref_ = PlatformThread::CurrentRef(); -} - -} // namespace base - -#endif // DCHECK_IS_ON() diff --git a/security/sandbox/chromium/base/synchronization/lock.h b/security/sandbox/chromium/base/synchronization/lock.h deleted file mode 100644 index f7dd35dcc..000000000 --- a/security/sandbox/chromium/base/synchronization/lock.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SYNCHRONIZATION_LOCK_H_ -#define BASE_SYNCHRONIZATION_LOCK_H_ - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/synchronization/lock_impl.h" -#include "base/threading/platform_thread.h" -#include "build/build_config.h" - -namespace base { - -// A convenient wrapper for an OS specific critical section. The only real -// intelligence in this class is in debug mode for the support for the -// AssertAcquired() method. -class BASE_EXPORT Lock { - public: -#if !DCHECK_IS_ON() - // Optimized wrapper implementation - Lock() : lock_() {} - ~Lock() {} - void Acquire() { lock_.Lock(); } - void Release() { lock_.Unlock(); } - - // If the lock is not held, take it and return true. If the lock is already - // held by another thread, immediately return false. This must not be called - // by a thread already holding the lock (what happens is undefined and an - // assertion may fail). - bool Try() { return lock_.Try(); } - - // Null implementation if not debug. - void AssertAcquired() const {} -#else - Lock(); - ~Lock(); - - // NOTE: Although windows critical sections support recursive locks, we do not - // allow this, and we will commonly fire a DCHECK() if a thread attempts to - // acquire the lock a second time (while already holding it). - void Acquire() { - lock_.Lock(); - CheckUnheldAndMark(); - } - void Release() { - CheckHeldAndUnmark(); - lock_.Unlock(); - } - - bool Try() { - bool rv = lock_.Try(); - if (rv) { - CheckUnheldAndMark(); - } - return rv; - } - - void AssertAcquired() const; -#endif // DCHECK_IS_ON() - -#if defined(OS_POSIX) - // The posix implementation of ConditionVariable needs to be able - // to see our lock and tweak our debugging counters, as it releases - // and acquires locks inside of pthread_cond_{timed,}wait. - friend class ConditionVariable; -#elif defined(OS_WIN) - // The Windows Vista implementation of ConditionVariable needs the - // native handle of the critical section. - friend class WinVistaCondVar; -#endif - - private: -#if DCHECK_IS_ON() - // Members and routines taking care of locks assertions. - // Note that this checks for recursive locks and allows them - // if the variable is set. This is allowed by the underlying implementation - // on windows but not on Posix, so we're doing unneeded checks on Posix. - // It's worth it to share the code. - void CheckHeldAndUnmark(); - void CheckUnheldAndMark(); - - // All private data is implicitly protected by lock_. - // Be VERY careful to only access members under that lock. - base::PlatformThreadRef owning_thread_ref_; -#endif // DCHECK_IS_ON() - - // Platform specific underlying lock implementation. - internal::LockImpl lock_; - - DISALLOW_COPY_AND_ASSIGN(Lock); -}; - -// A helper class that acquires the given Lock while the AutoLock is in scope. -class AutoLock { - public: - struct AlreadyAcquired {}; - - explicit AutoLock(Lock& lock) : lock_(lock) { - lock_.Acquire(); - } - - AutoLock(Lock& lock, const AlreadyAcquired&) : lock_(lock) { - lock_.AssertAcquired(); - } - - ~AutoLock() { - lock_.AssertAcquired(); - lock_.Release(); - } - - private: - Lock& lock_; - DISALLOW_COPY_AND_ASSIGN(AutoLock); -}; - -// AutoUnlock is a helper that will Release() the |lock| argument in the -// constructor, and re-Acquire() it in the destructor. -class AutoUnlock { - public: - explicit AutoUnlock(Lock& lock) : lock_(lock) { - // We require our caller to have the lock. - lock_.AssertAcquired(); - lock_.Release(); - } - - ~AutoUnlock() { - lock_.Acquire(); - } - - private: - Lock& lock_; - DISALLOW_COPY_AND_ASSIGN(AutoUnlock); -}; - -} // namespace base - -#endif // BASE_SYNCHRONIZATION_LOCK_H_ diff --git a/security/sandbox/chromium/base/synchronization/lock_impl.h b/security/sandbox/chromium/base/synchronization/lock_impl.h deleted file mode 100644 index ed85987b3..000000000 --- a/security/sandbox/chromium/base/synchronization/lock_impl.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SYNCHRONIZATION_LOCK_IMPL_H_ -#define BASE_SYNCHRONIZATION_LOCK_IMPL_H_ - -#include "base/base_export.h" -#include "base/macros.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#elif defined(OS_POSIX) -#include <pthread.h> -#endif - -namespace base { -namespace internal { - -// This class implements the underlying platform-specific spin-lock mechanism -// used for the Lock class. Most users should not use LockImpl directly, but -// should instead use Lock. -class BASE_EXPORT LockImpl { - public: -#if defined(OS_WIN) - typedef CRITICAL_SECTION NativeHandle; -#elif defined(OS_POSIX) - typedef pthread_mutex_t NativeHandle; -#endif - - LockImpl(); - ~LockImpl(); - - // If the lock is not held, take it and return true. If the lock is already - // held by something else, immediately return false. - bool Try(); - - // Take the lock, blocking until it is available if necessary. - void Lock(); - - // Release the lock. This must only be called by the lock's holder: after - // a successful call to Try, or a call to Lock. - void Unlock(); - - // Return the native underlying lock. - // TODO(awalker): refactor lock and condition variables so that this is - // unnecessary. - NativeHandle* native_handle() { return &native_handle_; } - - private: - NativeHandle native_handle_; - - DISALLOW_COPY_AND_ASSIGN(LockImpl); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_SYNCHRONIZATION_LOCK_IMPL_H_ diff --git a/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc b/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc deleted file mode 100644 index 5619adaf5..000000000 --- a/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/synchronization/lock_impl.h" - -#include <errno.h> -#include <string.h> - -#include "base/logging.h" - -namespace base { -namespace internal { - -LockImpl::LockImpl() { -#ifndef NDEBUG - // In debug, setup attributes for lock error checking. - pthread_mutexattr_t mta; - int rv = pthread_mutexattr_init(&mta); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); - rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); - rv = pthread_mutex_init(&native_handle_, &mta); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); - rv = pthread_mutexattr_destroy(&mta); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); -#else - // In release, go with the default lock attributes. - pthread_mutex_init(&native_handle_, NULL); -#endif -} - -LockImpl::~LockImpl() { - int rv = pthread_mutex_destroy(&native_handle_); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); -} - -bool LockImpl::Try() { - int rv = pthread_mutex_trylock(&native_handle_); - DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv); - return rv == 0; -} - -void LockImpl::Lock() { - int rv = pthread_mutex_lock(&native_handle_); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); -} - -void LockImpl::Unlock() { - int rv = pthread_mutex_unlock(&native_handle_); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); -} - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/synchronization/lock_impl_win.cc b/security/sandbox/chromium/base/synchronization/lock_impl_win.cc deleted file mode 100644 index fbc1bdd46..000000000 --- a/security/sandbox/chromium/base/synchronization/lock_impl_win.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/synchronization/lock_impl.h" - -namespace base { -namespace internal { - -LockImpl::LockImpl() { - // The second parameter is the spin count, for short-held locks it avoid the - // contending thread from going to sleep which helps performance greatly. - ::InitializeCriticalSectionAndSpinCount(&native_handle_, 2000); -} - -LockImpl::~LockImpl() { - ::DeleteCriticalSection(&native_handle_); -} - -bool LockImpl::Try() { - if (::TryEnterCriticalSection(&native_handle_) != FALSE) { - return true; - } - return false; -} - -void LockImpl::Lock() { - ::EnterCriticalSection(&native_handle_); -} - -void LockImpl::Unlock() { - ::LeaveCriticalSection(&native_handle_); -} - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/synchronization/waitable_event.h b/security/sandbox/chromium/base/synchronization/waitable_event.h deleted file mode 100644 index b5d91d00b..000000000 --- a/security/sandbox/chromium/base/synchronization/waitable_event.h +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ -#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ - -#include <stddef.h> - -#include "base/base_export.h" -#include "base/macros.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include "base/win/scoped_handle.h" -#endif - -#if defined(OS_POSIX) -#include <list> -#include <utility> -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#endif - -namespace base { - -class TimeDelta; - -// A WaitableEvent can be a useful thread synchronization tool when you want to -// allow one thread to wait for another thread to finish some work. For -// non-Windows systems, this can only be used from within a single address -// space. -// -// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to -// protect a simple boolean value. However, if you find yourself using a -// WaitableEvent in conjunction with a Lock to wait for a more complex state -// change (e.g., for an item to be added to a queue), then you should probably -// be using a ConditionVariable instead of a WaitableEvent. -// -// NOTE: On Windows, this class provides a subset of the functionality afforded -// by a Windows event object. This is intentional. If you are writing Windows -// specific code and you need other features of a Windows event, then you might -// be better off just using an Windows event directly. -class BASE_EXPORT WaitableEvent { - public: - // If manual_reset is true, then to set the event state to non-signaled, a - // consumer must call the Reset method. If this parameter is false, then the - // system automatically resets the event state to non-signaled after a single - // waiting thread has been released. - WaitableEvent(bool manual_reset, bool initially_signaled); - -#if defined(OS_WIN) - // Create a WaitableEvent from an Event HANDLE which has already been - // created. This objects takes ownership of the HANDLE and will close it when - // deleted. - explicit WaitableEvent(win::ScopedHandle event_handle); -#endif - - ~WaitableEvent(); - - // Put the event in the un-signaled state. - void Reset(); - - // Put the event in the signaled state. Causing any thread blocked on Wait - // to be woken up. - void Signal(); - - // Returns true if the event is in the signaled state, else false. If this - // is not a manual reset event, then this test will cause a reset. - bool IsSignaled(); - - // Wait indefinitely for the event to be signaled. Wait's return "happens - // after" |Signal| has completed. This means that it's safe for a - // WaitableEvent to synchronise its own destruction, like this: - // - // WaitableEvent *e = new WaitableEvent; - // SendToOtherThread(e); - // e->Wait(); - // delete e; - void Wait(); - - // Wait up until max_time has passed for the event to be signaled. Returns - // true if the event was signaled. If this method returns false, then it - // does not necessarily mean that max_time was exceeded. - // - // TimedWait can synchronise its own destruction like |Wait|. - bool TimedWait(const TimeDelta& max_time); - -#if defined(OS_WIN) - HANDLE handle() const { return handle_.Get(); } -#endif - - // Wait, synchronously, on multiple events. - // waitables: an array of WaitableEvent pointers - // count: the number of elements in @waitables - // - // returns: the index of a WaitableEvent which has been signaled. - // - // You MUST NOT delete any of the WaitableEvent objects while this wait is - // happening, however WaitMany's return "happens after" the |Signal| call - // that caused it has completed, like |Wait|. - static size_t WaitMany(WaitableEvent** waitables, size_t count); - - // For asynchronous waiting, see WaitableEventWatcher - - // This is a private helper class. It's here because it's used by friends of - // this class (such as WaitableEventWatcher) to be able to enqueue elements - // of the wait-list - class Waiter { - public: - // Signal the waiter to wake up. - // - // Consider the case of a Waiter which is in multiple WaitableEvent's - // wait-lists. Each WaitableEvent is automatic-reset and two of them are - // signaled at the same time. Now, each will wake only the first waiter in - // the wake-list before resetting. However, if those two waiters happen to - // be the same object (as can happen if another thread didn't have a chance - // to dequeue the waiter from the other wait-list in time), two auto-resets - // will have happened, but only one waiter has been signaled! - // - // Because of this, a Waiter may "reject" a wake by returning false. In - // this case, the auto-reset WaitableEvent shouldn't act as if anything has - // been notified. - virtual bool Fire(WaitableEvent* signaling_event) = 0; - - // Waiters may implement this in order to provide an extra condition for - // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the - // pointers match then this function is called as a final check. See the - // comments in ~Handle for why. - virtual bool Compare(void* tag) = 0; - - protected: - virtual ~Waiter() {} - }; - - private: - friend class WaitableEventWatcher; - -#if defined(OS_WIN) - win::ScopedHandle handle_; -#else - // On Windows, one can close a HANDLE which is currently being waited on. The - // MSDN documentation says that the resulting behaviour is 'undefined', but - // it doesn't crash. However, if we were to include the following members - // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an - // event which gets deleted. This mismatch has bitten us several times now, - // so we have a kernel of the WaitableEvent, which is reference counted. - // WaitableEventWatchers may then take a reference and thus match the Windows - // behaviour. - struct WaitableEventKernel : - public RefCountedThreadSafe<WaitableEventKernel> { - public: - WaitableEventKernel(bool manual_reset, bool initially_signaled); - - bool Dequeue(Waiter* waiter, void* tag); - - base::Lock lock_; - const bool manual_reset_; - bool signaled_; - std::list<Waiter*> waiters_; - - private: - friend class RefCountedThreadSafe<WaitableEventKernel>; - ~WaitableEventKernel(); - }; - - typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; - - // When dealing with arrays of WaitableEvent*, we want to sort by the address - // of the WaitableEvent in order to have a globally consistent locking order. - // In that case we keep them, in sorted order, in an array of pairs where the - // second element is the index of the WaitableEvent in the original, - // unsorted, array. - static size_t EnqueueMany(WaiterAndIndex* waitables, - size_t count, Waiter* waiter); - - bool SignalAll(); - bool SignalOne(); - void Enqueue(Waiter* waiter); - - scoped_refptr<WaitableEventKernel> kernel_; -#endif - - DISALLOW_COPY_AND_ASSIGN(WaitableEvent); -}; - -} // namespace base - -#endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ diff --git a/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc b/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc deleted file mode 100644 index 64d4376fe..000000000 --- a/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> - -#include <algorithm> -#include <vector> - -#include "base/logging.h" -#include "base/synchronization/condition_variable.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread_restrictions.h" - -// ----------------------------------------------------------------------------- -// A WaitableEvent on POSIX is implemented as a wait-list. Currently we don't -// support cross-process events (where one process can signal an event which -// others are waiting on). Because of this, we can avoid having one thread per -// listener in several cases. -// -// The WaitableEvent maintains a list of waiters, protected by a lock. Each -// waiter is either an async wait, in which case we have a Task and the -// MessageLoop to run it on, or a blocking wait, in which case we have the -// condition variable to signal. -// -// Waiting involves grabbing the lock and adding oneself to the wait list. Async -// waits can be canceled, which means grabbing the lock and removing oneself -// from the list. -// -// Waiting on multiple events is handled by adding a single, synchronous wait to -// the wait-list of many events. An event passes a pointer to itself when -// firing a waiter and so we can store that pointer to find out which event -// triggered. -// ----------------------------------------------------------------------------- - -namespace base { - -// ----------------------------------------------------------------------------- -// This is just an abstract base class for waking the two types of waiters -// ----------------------------------------------------------------------------- -WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled) - : kernel_(new WaitableEventKernel(manual_reset, initially_signaled)) { -} - -WaitableEvent::~WaitableEvent() { -} - -void WaitableEvent::Reset() { - base::AutoLock locked(kernel_->lock_); - kernel_->signaled_ = false; -} - -void WaitableEvent::Signal() { - base::AutoLock locked(kernel_->lock_); - - if (kernel_->signaled_) - return; - - if (kernel_->manual_reset_) { - SignalAll(); - kernel_->signaled_ = true; - } else { - // In the case of auto reset, if no waiters were woken, we remain - // signaled. - if (!SignalOne()) - kernel_->signaled_ = true; - } -} - -bool WaitableEvent::IsSignaled() { - base::AutoLock locked(kernel_->lock_); - - const bool result = kernel_->signaled_; - if (result && !kernel_->manual_reset_) - kernel_->signaled_ = false; - return result; -} - -// ----------------------------------------------------------------------------- -// Synchronous waits - -// ----------------------------------------------------------------------------- -// This is a synchronous waiter. The thread is waiting on the given condition -// variable and the fired flag in this object. -// ----------------------------------------------------------------------------- -class SyncWaiter : public WaitableEvent::Waiter { - public: - SyncWaiter() - : fired_(false), - signaling_event_(NULL), - lock_(), - cv_(&lock_) { - } - - bool Fire(WaitableEvent* signaling_event) override { - base::AutoLock locked(lock_); - - if (fired_) - return false; - - fired_ = true; - signaling_event_ = signaling_event; - - cv_.Broadcast(); - - // Unlike AsyncWaiter objects, SyncWaiter objects are stack-allocated on - // the blocking thread's stack. There is no |delete this;| in Fire. The - // SyncWaiter object is destroyed when it goes out of scope. - - return true; - } - - WaitableEvent* signaling_event() const { - return signaling_event_; - } - - // --------------------------------------------------------------------------- - // These waiters are always stack allocated and don't delete themselves. Thus - // there's no problem and the ABA tag is the same as the object pointer. - // --------------------------------------------------------------------------- - bool Compare(void* tag) override { return this == tag; } - - // --------------------------------------------------------------------------- - // Called with lock held. - // --------------------------------------------------------------------------- - bool fired() const { - return fired_; - } - - // --------------------------------------------------------------------------- - // During a TimedWait, we need a way to make sure that an auto-reset - // WaitableEvent doesn't think that this event has been signaled between - // unlocking it and removing it from the wait-list. Called with lock held. - // --------------------------------------------------------------------------- - void Disable() { - fired_ = true; - } - - base::Lock* lock() { - return &lock_; - } - - base::ConditionVariable* cv() { - return &cv_; - } - - private: - bool fired_; - WaitableEvent* signaling_event_; // The WaitableEvent which woke us - base::Lock lock_; - base::ConditionVariable cv_; -}; - -void WaitableEvent::Wait() { - bool result = TimedWait(TimeDelta::FromSeconds(-1)); - DCHECK(result) << "TimedWait() should never fail with infinite timeout"; -} - -bool WaitableEvent::TimedWait(const TimeDelta& max_time) { - base::ThreadRestrictions::AssertWaitAllowed(); - const TimeTicks end_time(TimeTicks::Now() + max_time); - const bool finite_time = max_time.ToInternalValue() >= 0; - - kernel_->lock_.Acquire(); - if (kernel_->signaled_) { - if (!kernel_->manual_reset_) { - // In this case we were signaled when we had no waiters. Now that - // someone has waited upon us, we can automatically reset. - kernel_->signaled_ = false; - } - - kernel_->lock_.Release(); - return true; - } - - SyncWaiter sw; - sw.lock()->Acquire(); - - Enqueue(&sw); - kernel_->lock_.Release(); - // We are violating locking order here by holding the SyncWaiter lock but not - // the WaitableEvent lock. However, this is safe because we don't lock @lock_ - // again before unlocking it. - - for (;;) { - const TimeTicks current_time(TimeTicks::Now()); - - if (sw.fired() || (finite_time && current_time >= end_time)) { - const bool return_value = sw.fired(); - - // We can't acquire @lock_ before releasing the SyncWaiter lock (because - // of locking order), however, in between the two a signal could be fired - // and @sw would accept it, however we will still return false, so the - // signal would be lost on an auto-reset WaitableEvent. Thus we call - // Disable which makes sw::Fire return false. - sw.Disable(); - sw.lock()->Release(); - - // This is a bug that has been enshrined in the interface of - // WaitableEvent now: |Dequeue| is called even when |sw.fired()| is true, - // even though it'll always return false in that case. However, taking - // the lock ensures that |Signal| has completed before we return and - // means that a WaitableEvent can synchronise its own destruction. - kernel_->lock_.Acquire(); - kernel_->Dequeue(&sw, &sw); - kernel_->lock_.Release(); - - return return_value; - } - - if (finite_time) { - const TimeDelta max_wait(end_time - current_time); - sw.cv()->TimedWait(max_wait); - } else { - sw.cv()->Wait(); - } - } -} - -// ----------------------------------------------------------------------------- -// Synchronous waiting on multiple objects. - -static bool // StrictWeakOrdering -cmp_fst_addr(const std::pair<WaitableEvent*, unsigned> &a, - const std::pair<WaitableEvent*, unsigned> &b) { - return a.first < b.first; -} - -// static -size_t WaitableEvent::WaitMany(WaitableEvent** raw_waitables, - size_t count) { - base::ThreadRestrictions::AssertWaitAllowed(); - DCHECK(count) << "Cannot wait on no events"; - - // We need to acquire the locks in a globally consistent order. Thus we sort - // the array of waitables by address. We actually sort a pairs so that we can - // map back to the original index values later. - std::vector<std::pair<WaitableEvent*, size_t> > waitables; - waitables.reserve(count); - for (size_t i = 0; i < count; ++i) - waitables.push_back(std::make_pair(raw_waitables[i], i)); - - DCHECK_EQ(count, waitables.size()); - - sort(waitables.begin(), waitables.end(), cmp_fst_addr); - - // The set of waitables must be distinct. Since we have just sorted by - // address, we can check this cheaply by comparing pairs of consecutive - // elements. - for (size_t i = 0; i < waitables.size() - 1; ++i) { - DCHECK(waitables[i].first != waitables[i+1].first); - } - - SyncWaiter sw; - - const size_t r = EnqueueMany(&waitables[0], count, &sw); - if (r) { - // One of the events is already signaled. The SyncWaiter has not been - // enqueued anywhere. EnqueueMany returns the count of remaining waitables - // when the signaled one was seen, so the index of the signaled event is - // @count - @r. - return waitables[count - r].second; - } - - // At this point, we hold the locks on all the WaitableEvents and we have - // enqueued our waiter in them all. - sw.lock()->Acquire(); - // Release the WaitableEvent locks in the reverse order - for (size_t i = 0; i < count; ++i) { - waitables[count - (1 + i)].first->kernel_->lock_.Release(); - } - - for (;;) { - if (sw.fired()) - break; - - sw.cv()->Wait(); - } - sw.lock()->Release(); - - // The address of the WaitableEvent which fired is stored in the SyncWaiter. - WaitableEvent *const signaled_event = sw.signaling_event(); - // This will store the index of the raw_waitables which fired. - size_t signaled_index = 0; - - // Take the locks of each WaitableEvent in turn (except the signaled one) and - // remove our SyncWaiter from the wait-list - for (size_t i = 0; i < count; ++i) { - if (raw_waitables[i] != signaled_event) { - raw_waitables[i]->kernel_->lock_.Acquire(); - // There's no possible ABA issue with the address of the SyncWaiter here - // because it lives on the stack. Thus the tag value is just the pointer - // value again. - raw_waitables[i]->kernel_->Dequeue(&sw, &sw); - raw_waitables[i]->kernel_->lock_.Release(); - } else { - // By taking this lock here we ensure that |Signal| has completed by the - // time we return, because |Signal| holds this lock. This matches the - // behaviour of |Wait| and |TimedWait|. - raw_waitables[i]->kernel_->lock_.Acquire(); - raw_waitables[i]->kernel_->lock_.Release(); - signaled_index = i; - } - } - - return signaled_index; -} - -// ----------------------------------------------------------------------------- -// If return value == 0: -// The locks of the WaitableEvents have been taken in order and the Waiter has -// been enqueued in the wait-list of each. None of the WaitableEvents are -// currently signaled -// else: -// None of the WaitableEvent locks are held. The Waiter has not been enqueued -// in any of them and the return value is the index of the first WaitableEvent -// which was signaled, from the end of the array. -// ----------------------------------------------------------------------------- -// static -size_t WaitableEvent::EnqueueMany - (std::pair<WaitableEvent*, size_t>* waitables, - size_t count, Waiter* waiter) { - if (!count) - return 0; - - waitables[0].first->kernel_->lock_.Acquire(); - if (waitables[0].first->kernel_->signaled_) { - if (!waitables[0].first->kernel_->manual_reset_) - waitables[0].first->kernel_->signaled_ = false; - waitables[0].first->kernel_->lock_.Release(); - return count; - } - - const size_t r = EnqueueMany(waitables + 1, count - 1, waiter); - if (r) { - waitables[0].first->kernel_->lock_.Release(); - } else { - waitables[0].first->Enqueue(waiter); - } - - return r; -} - -// ----------------------------------------------------------------------------- - - -// ----------------------------------------------------------------------------- -// Private functions... - -WaitableEvent::WaitableEventKernel::WaitableEventKernel(bool manual_reset, - bool initially_signaled) - : manual_reset_(manual_reset), - signaled_(initially_signaled) { -} - -WaitableEvent::WaitableEventKernel::~WaitableEventKernel() { -} - -// ----------------------------------------------------------------------------- -// Wake all waiting waiters. Called with lock held. -// ----------------------------------------------------------------------------- -bool WaitableEvent::SignalAll() { - bool signaled_at_least_one = false; - - for (std::list<Waiter*>::iterator - i = kernel_->waiters_.begin(); i != kernel_->waiters_.end(); ++i) { - if ((*i)->Fire(this)) - signaled_at_least_one = true; - } - - kernel_->waiters_.clear(); - return signaled_at_least_one; -} - -// --------------------------------------------------------------------------- -// Try to wake a single waiter. Return true if one was woken. Called with lock -// held. -// --------------------------------------------------------------------------- -bool WaitableEvent::SignalOne() { - for (;;) { - if (kernel_->waiters_.empty()) - return false; - - const bool r = (*kernel_->waiters_.begin())->Fire(this); - kernel_->waiters_.pop_front(); - if (r) - return true; - } -} - -// ----------------------------------------------------------------------------- -// Add a waiter to the list of those waiting. Called with lock held. -// ----------------------------------------------------------------------------- -void WaitableEvent::Enqueue(Waiter* waiter) { - kernel_->waiters_.push_back(waiter); -} - -// ----------------------------------------------------------------------------- -// Remove a waiter from the list of those waiting. Return true if the waiter was -// actually removed. Called with lock held. -// ----------------------------------------------------------------------------- -bool WaitableEvent::WaitableEventKernel::Dequeue(Waiter* waiter, void* tag) { - for (std::list<Waiter*>::iterator - i = waiters_.begin(); i != waiters_.end(); ++i) { - if (*i == waiter && (*i)->Compare(tag)) { - waiters_.erase(i); - return true; - } - } - - return false; -} - -// ----------------------------------------------------------------------------- - -} // namespace base diff --git a/security/sandbox/chromium/base/task_runner.h b/security/sandbox/chromium/base/task_runner.h deleted file mode 100644 index 6dd82ccac..000000000 --- a/security/sandbox/chromium/base/task_runner.h +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TASK_RUNNER_H_ -#define BASE_TASK_RUNNER_H_ - -#include <stddef.h> - -#include "base/base_export.h" -#include "base/callback_forward.h" -#include "base/memory/ref_counted.h" -#include "base/time/time.h" - -namespace tracked_objects { -class Location; -} // namespace tracked_objects - -namespace base { - -struct TaskRunnerTraits; - -// A TaskRunner is an object that runs posted tasks (in the form of -// Closure objects). The TaskRunner interface provides a way of -// decoupling task posting from the mechanics of how each task will be -// run. TaskRunner provides very weak guarantees as to how posted -// tasks are run (or if they're run at all). In particular, it only -// guarantees: -// -// - Posting a task will not run it synchronously. That is, no -// Post*Task method will call task.Run() directly. -// -// - Increasing the delay can only delay when the task gets run. -// That is, increasing the delay may not affect when the task gets -// run, or it could make it run later than it normally would, but -// it won't make it run earlier than it normally would. -// -// TaskRunner does not guarantee the order in which posted tasks are -// run, whether tasks overlap, or whether they're run on a particular -// thread. Also it does not guarantee a memory model for shared data -// between tasks. (In other words, you should use your own -// synchronization/locking primitives if you need to share data -// between tasks.) -// -// Implementations of TaskRunner should be thread-safe in that all -// methods must be safe to call on any thread. Ownership semantics -// for TaskRunners are in general not clear, which is why the -// interface itself is RefCountedThreadSafe. -// -// Some theoretical implementations of TaskRunner: -// -// - A TaskRunner that uses a thread pool to run posted tasks. -// -// - A TaskRunner that, for each task, spawns a non-joinable thread -// to run that task and immediately quit. -// -// - A TaskRunner that stores the list of posted tasks and has a -// method Run() that runs each runnable task in random order. -class BASE_EXPORT TaskRunner - : public RefCountedThreadSafe<TaskRunner, TaskRunnerTraits> { - public: - // Posts the given task to be run. Returns true if the task may be - // run at some point in the future, and false if the task definitely - // will not be run. - // - // Equivalent to PostDelayedTask(from_here, task, 0). - bool PostTask(const tracked_objects::Location& from_here, - const Closure& task); - - // Like PostTask, but tries to run the posted task only after - // |delay_ms| has passed. - // - // It is valid for an implementation to ignore |delay_ms|; that is, - // to have PostDelayedTask behave the same as PostTask. - virtual bool PostDelayedTask(const tracked_objects::Location& from_here, - const Closure& task, - base::TimeDelta delay) = 0; - - // Returns true if the current thread is a thread on which a task - // may be run, and false if no task will be run on the current - // thread. - // - // It is valid for an implementation to always return true, or in - // general to use 'true' as a default value. - virtual bool RunsTasksOnCurrentThread() const = 0; - - // Posts |task| on the current TaskRunner. On completion, |reply| - // is posted to the thread that called PostTaskAndReply(). Both - // |task| and |reply| are guaranteed to be deleted on the thread - // from which PostTaskAndReply() is invoked. This allows objects - // that must be deleted on the originating thread to be bound into - // the |task| and |reply| Closures. In particular, it can be useful - // to use WeakPtr<> in the |reply| Closure so that the reply - // operation can be canceled. See the following pseudo-code: - // - // class DataBuffer : public RefCountedThreadSafe<DataBuffer> { - // public: - // // Called to add data into a buffer. - // void AddData(void* buf, size_t length); - // ... - // }; - // - // - // class DataLoader : public SupportsWeakPtr<DataLoader> { - // public: - // void GetData() { - // scoped_refptr<DataBuffer> buffer = new DataBuffer(); - // target_thread_.task_runner()->PostTaskAndReply( - // FROM_HERE, - // base::Bind(&DataBuffer::AddData, buffer), - // base::Bind(&DataLoader::OnDataReceived, AsWeakPtr(), buffer)); - // } - // - // private: - // void OnDataReceived(scoped_refptr<DataBuffer> buffer) { - // // Do something with buffer. - // } - // }; - // - // - // Things to notice: - // * Results of |task| are shared with |reply| by binding a shared argument - // (a DataBuffer instance). - // * The DataLoader object has no special thread safety. - // * The DataLoader object can be deleted while |task| is still running, - // and the reply will cancel itself safely because it is bound to a - // WeakPtr<>. - bool PostTaskAndReply(const tracked_objects::Location& from_here, - const Closure& task, - const Closure& reply); - - protected: - friend struct TaskRunnerTraits; - - // Only the Windows debug build seems to need this: see - // http://crbug.com/112250. - friend class RefCountedThreadSafe<TaskRunner, TaskRunnerTraits>; - - TaskRunner(); - virtual ~TaskRunner(); - - // Called when this object should be destroyed. By default simply - // deletes |this|, but can be overridden to do something else, like - // delete on a certain thread. - virtual void OnDestruct() const; -}; - -struct BASE_EXPORT TaskRunnerTraits { - static void Destruct(const TaskRunner* task_runner); -}; - -} // namespace base - -#endif // BASE_TASK_RUNNER_H_ diff --git a/security/sandbox/chromium/base/template_util.h b/security/sandbox/chromium/base/template_util.h deleted file mode 100644 index d58807a77..000000000 --- a/security/sandbox/chromium/base/template_util.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TEMPLATE_UTIL_H_ -#define BASE_TEMPLATE_UTIL_H_ - -#include <stddef.h> - -#include "build/build_config.h" - -namespace base { - -// template definitions from tr1 - -template<class T, T v> -struct integral_constant { - static const T value = v; - typedef T value_type; - typedef integral_constant<T, v> type; -}; - -template <class T, T v> const T integral_constant<T, v>::value; - -typedef integral_constant<bool, true> true_type; -typedef integral_constant<bool, false> false_type; - -template <class T> struct is_pointer : false_type {}; -template <class T> struct is_pointer<T*> : true_type {}; - -// Member function pointer detection. This is built-in to C++ 11's stdlib, and -// we can remove this when we switch to it. -template<typename T> -struct is_member_function_pointer : false_type {}; - -template <typename R, typename Z, typename... A> -struct is_member_function_pointer<R(Z::*)(A...)> : true_type {}; -template <typename R, typename Z, typename... A> -struct is_member_function_pointer<R(Z::*)(A...) const> : true_type {}; - - -template <class T, class U> struct is_same : public false_type {}; -template <class T> struct is_same<T,T> : true_type {}; - -template<class> struct is_array : public false_type {}; -template<class T, size_t n> struct is_array<T[n]> : public true_type {}; -template<class T> struct is_array<T[]> : public true_type {}; - -template <class T> struct is_non_const_reference : false_type {}; -template <class T> struct is_non_const_reference<T&> : true_type {}; -template <class T> struct is_non_const_reference<const T&> : false_type {}; - -template <class T> struct is_const : false_type {}; -template <class T> struct is_const<const T> : true_type {}; - -template <class T> struct is_void : false_type {}; -template <> struct is_void<void> : true_type {}; - -namespace internal { - -// Types YesType and NoType are guaranteed such that sizeof(YesType) < -// sizeof(NoType). -typedef char YesType; - -struct NoType { - YesType dummy[2]; -}; - -// This class is an implementation detail for is_convertible, and you -// don't need to know how it works to use is_convertible. For those -// who care: we declare two different functions, one whose argument is -// of type To and one with a variadic argument list. We give them -// return types of different size, so we can use sizeof to trick the -// compiler into telling us which function it would have chosen if we -// had called it with an argument of type From. See Alexandrescu's -// _Modern C++ Design_ for more details on this sort of trick. - -struct ConvertHelper { - template <typename To> - static YesType Test(To); - - template <typename To> - static NoType Test(...); - - template <typename From> - static From& Create(); -}; - -// Used to determine if a type is a struct/union/class. Inspired by Boost's -// is_class type_trait implementation. -struct IsClassHelper { - template <typename C> - static YesType Test(void(C::*)(void)); - - template <typename C> - static NoType Test(...); -}; - -} // namespace internal - -// Inherits from true_type if From is convertible to To, false_type otherwise. -// -// Note that if the type is convertible, this will be a true_type REGARDLESS -// of whether or not the conversion would emit a warning. -template <typename From, typename To> -struct is_convertible - : integral_constant<bool, - sizeof(internal::ConvertHelper::Test<To>( - internal::ConvertHelper::Create<From>())) == - sizeof(internal::YesType)> { -}; - -template <typename T> -struct is_class - : integral_constant<bool, - sizeof(internal::IsClassHelper::Test<T>(0)) == - sizeof(internal::YesType)> { -}; - -} // namespace base - -#endif // BASE_TEMPLATE_UTIL_H_ diff --git a/security/sandbox/chromium/base/third_party/dmg_fp/LICENSE b/security/sandbox/chromium/base/third_party/dmg_fp/LICENSE deleted file mode 100644 index 716f1ef2b..000000000 --- a/security/sandbox/chromium/base/third_party/dmg_fp/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ diff --git a/security/sandbox/chromium/base/third_party/dmg_fp/dmg_fp.h b/security/sandbox/chromium/base/third_party/dmg_fp/dmg_fp.h deleted file mode 100644 index 4795397ec..000000000 --- a/security/sandbox/chromium/base/third_party/dmg_fp/dmg_fp.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_DMG_FP_H_ -#define THIRD_PARTY_DMG_FP_H_ - -namespace dmg_fp { - -// Return a nearest machine number to the input decimal -// string (or set errno to ERANGE). With IEEE arithmetic, ties are -// broken by the IEEE round-even rule. Otherwise ties are broken by -// biased rounding (add half and chop). -double strtod(const char* s00, char** se); - -// Convert double to ASCII string. For meaning of parameters -// see dtoa.cc file. -char* dtoa(double d, int mode, int ndigits, - int* decpt, int* sign, char** rve); - -// Must be used to free values returned by dtoa. -void freedtoa(char* s); - -// Store the closest decimal approximation to x in b (null terminated). -// Returns a pointer to b. It is sufficient for |b| to be 32 characters. -char* g_fmt(char* b, double x); - -} // namespace dmg_fp - -#endif // THIRD_PARTY_DMG_FP_H_ diff --git a/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc b/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc deleted file mode 100644 index 502c16cc7..000000000 --- a/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc +++ /dev/null @@ -1,4234 +0,0 @@ -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -/* On a machine with IEEE extended-precision registers, it is - * necessary to specify double-precision (53-bit) rounding precision - * before invoking strtod or dtoa. If the machine uses (the equivalent - * of) Intel 80x87 arithmetic, the call - * _control87(PC_53, MCW_PC); - * does this with many compilers. Whether this or another call is - * appropriate depends on the compiler; for this to work, it may be - * necessary to #include "float.h" or another system-dependent header - * file. - */ - -/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. - * - * This strtod returns a nearest machine number to the input decimal - * string (or sets errno to ERANGE). With IEEE arithmetic, ties are - * broken by the IEEE round-even rule. Otherwise ties are broken by - * biased rounding (add half and chop). - * - * Inspired loosely by William D. Clinger's paper "How to Read Floating - * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. - * - * Modifications: - * - * 1. We only require IEEE, IBM, or VAX double-precision - * arithmetic (not IEEE double-extended). - * 2. We get by with floating-point arithmetic in a case that - * Clinger missed -- when we're computing d * 10^n - * for a small integer d and the integer n is not too - * much larger than 22 (the maximum integer k for which - * we can represent 10^k exactly), we may be able to - * compute (d*10^k) * 10^(e-k) with just one roundoff. - * 3. Rather than a bit-at-a-time adjustment of the binary - * result in the hard case, we use floating-point - * arithmetic to determine the adjustment to within - * one bit; only in really hard cases do we need to - * compute a second residual. - * 4. Because of 3., we don't need a large table of powers of 10 - * for ten-to-e (just some small tables, e.g. of 10^k - * for 0 <= k <= 22). - */ - -/* - * #define IEEE_8087 for IEEE-arithmetic machines where the least - * significant byte has the lowest address. - * #define IEEE_MC68k for IEEE-arithmetic machines where the most - * significant byte has the lowest address. - * #define Long int on machines with 32-bit ints and 64-bit longs. - * #define IBM for IBM mainframe-style floating-point arithmetic. - * #define VAX for VAX-style floating-point arithmetic (D_floating). - * #define No_leftright to omit left-right logic in fast floating-point - * computation of dtoa. - * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 - * and strtod and dtoa should round accordingly. Unless Trust_FLT_ROUNDS - * is also #defined, fegetround() will be queried for the rounding mode. - * Note that both FLT_ROUNDS and fegetround() are specified by the C99 - * standard (and are specified to be consistent, with fesetround() - * affecting the value of FLT_ROUNDS), but that some (Linux) systems - * do not work correctly in this regard, so using fegetround() is more - * portable than using FLT_FOUNDS directly. - * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 - * and Honor_FLT_ROUNDS is not #defined. - * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines - * that use extended-precision instructions to compute rounded - * products and quotients) with IBM. - * #define ROUND_BIASED for IEEE-format with biased rounding. - * #define Inaccurate_Divide for IEEE-format with correctly rounded - * products but inaccurate quotients, e.g., for Intel i860. - * #define NO_LONG_LONG on machines that do not have a "long long" - * integer type (of >= 64 bits). On such machines, you can - * #define Just_16 to store 16 bits per 32-bit Long when doing - * high-precision integer arithmetic. Whether this speeds things - * up or slows things down depends on the machine and the number - * being converted. If long long is available and the name is - * something other than "long long", #define Llong to be the name, - * and if "unsigned Llong" does not work as an unsigned version of - * Llong, #define #ULLong to be the corresponding unsigned type. - * #define KR_headers for old-style C function headers. - * #define Bad_float_h if your system lacks a float.h or if it does not - * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, - * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. - * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) - * if memory is available and otherwise does something you deem - * appropriate. If MALLOC is undefined, malloc will be invoked - * directly -- and assumed always to succeed. Similarly, if you - * want something other than the system's free() to be called to - * recycle memory acquired from MALLOC, #define FREE to be the - * name of the alternate routine. (FREE or free is only called in - * pathological cases, e.g., in a dtoa call after a dtoa return in - * mode 3 with thousands of digits requested.) - * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making - * memory allocations from a private pool of memory when possible. - * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, - * unless #defined to be a different length. This default length - * suffices to get rid of MALLOC calls except for unusual cases, - * such as decimal-to-binary conversion of a very long string of - * digits. The longest string dtoa can return is about 751 bytes - * long. For conversions by strtod of strings of 800 digits and - * all dtoa conversions in single-threaded executions with 8-byte - * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte - * pointers, PRIVATE_MEM >= 7112 appears adequate. - * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK - * #defined automatically on IEEE systems. On such systems, - * when INFNAN_CHECK is #defined, strtod checks - * for Infinity and NaN (case insensitively). On some systems - * (e.g., some HP systems), it may be necessary to #define NAN_WORD0 - * appropriately -- to the most significant word of a quiet NaN. - * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) - * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, - * strtod also accepts (case insensitively) strings of the form - * NaN(x), where x is a string of hexadecimal digits and spaces; - * if there is only one string of hexadecimal digits, it is taken - * for the 52 fraction bits of the resulting NaN; if there are two - * or more strings of hex digits, the first is for the high 20 bits, - * the second and subsequent for the low 32 bits, with intervening - * white space ignored; but if this results in none of the 52 - * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 - * and NAN_WORD1 are used instead. - * #define MULTIPLE_THREADS if the system offers preemptively scheduled - * multiple threads. In this case, you must provide (or suitably - * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed - * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed - * in pow5mult, ensures lazy evaluation of only one copy of high - * powers of 5; omitting this lock would introduce a small - * probability of wasting memory, but would otherwise be harmless.) - * You must also invoke freedtoa(s) to free the value s returned by - * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. - * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that - * avoids underflows on inputs whose result does not underflow. - * If you #define NO_IEEE_Scale on a machine that uses IEEE-format - * floating-point numbers and flushes underflows to zero rather - * than implementing gradual underflow, then you must also #define - * Sudden_Underflow. - * #define USE_LOCALE to use the current locale's decimal_point value. - * #define SET_INEXACT if IEEE arithmetic is being used and extra - * computation should be done to set the inexact flag when the - * result is inexact and avoid setting inexact when the result - * is exact. In this case, dtoa.c must be compiled in - * an environment, perhaps provided by #include "dtoa.c" in a - * suitable wrapper, that defines two functions, - * int get_inexact(void); - * void clear_inexact(void); - * such that get_inexact() returns a nonzero value if the - * inexact bit is already set, and clear_inexact() sets the - * inexact bit to 0. When SET_INEXACT is #defined, strtod - * also does extra computations to set the underflow and overflow - * flags when appropriate (i.e., when the result is tiny and - * inexact or when it is a numeric value rounded to +-infinity). - * #define NO_ERRNO if strtod should not assign errno = ERANGE when - * the result overflows to +-Infinity or underflows to 0. - * #define NO_HEX_FP to omit recognition of hexadecimal floating-point - * values by strtod. - * #define NO_STRTOD_BIGCOMP (on IEEE-arithmetic systems only for now) - * to disable logic for "fast" testing of very long input strings - * to strtod. This testing proceeds by initially truncating the - * input string, then if necessary comparing the whole string with - * a decimal expansion to decide close cases. This logic is only - * used for input more than STRTOD_DIGLIM digits long (default 40). - */ - -#define IEEE_8087 -#define NO_HEX_FP - -#ifndef Long -#if __LP64__ -#define Long int -#else -#define Long long -#endif -#endif -#ifndef ULong -typedef unsigned Long ULong; -#endif - -#ifdef DEBUG -#include "stdio.h" -#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} -#endif - -#include "stdlib.h" -#include "string.h" - -#ifdef USE_LOCALE -#include "locale.h" -#endif - -#ifdef Honor_FLT_ROUNDS -#ifndef Trust_FLT_ROUNDS -#include <fenv.h> -#endif -#endif - -#ifdef MALLOC -#ifdef KR_headers -extern char *MALLOC(); -#else -extern void *MALLOC(size_t); -#endif -#else -#define MALLOC malloc -#endif - -#ifndef Omit_Private_Memory -#ifndef PRIVATE_MEM -#define PRIVATE_MEM 2304 -#endif -#define PRIVATE_mem ((unsigned)((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))) -static double private_mem[PRIVATE_mem], *pmem_next = private_mem; -#endif - -#undef IEEE_Arith -#undef Avoid_Underflow -#ifdef IEEE_MC68k -#define IEEE_Arith -#endif -#ifdef IEEE_8087 -#define IEEE_Arith -#endif - -#ifdef IEEE_Arith -#ifndef NO_INFNAN_CHECK -#undef INFNAN_CHECK -#define INFNAN_CHECK -#endif -#else -#undef INFNAN_CHECK -#define NO_STRTOD_BIGCOMP -#endif - -#include "errno.h" - -#ifdef Bad_float_h - -#ifdef IEEE_Arith -#define DBL_DIG 15 -#define DBL_MAX_10_EXP 308 -#define DBL_MAX_EXP 1024 -#define FLT_RADIX 2 -#endif /*IEEE_Arith*/ - -#ifdef IBM -#define DBL_DIG 16 -#define DBL_MAX_10_EXP 75 -#define DBL_MAX_EXP 63 -#define FLT_RADIX 16 -#define DBL_MAX 7.2370055773322621e+75 -#endif - -#ifdef VAX -#define DBL_DIG 16 -#define DBL_MAX_10_EXP 38 -#define DBL_MAX_EXP 127 -#define FLT_RADIX 2 -#define DBL_MAX 1.7014118346046923e+38 -#endif - -#ifndef LONG_MAX -#define LONG_MAX 2147483647 -#endif - -#else /* ifndef Bad_float_h */ -#include "float.h" -#endif /* Bad_float_h */ - -#ifndef __MATH_H__ -#include "math.h" -#endif - -namespace dmg_fp { - -#ifndef CONST -#ifdef KR_headers -#define CONST /* blank */ -#else -#define CONST const -#endif -#endif - -#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 -Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. -#endif - -typedef union { double d; ULong L[2]; } U; - -#ifdef IEEE_8087 -#define word0(x) (x)->L[1] -#define word1(x) (x)->L[0] -#else -#define word0(x) (x)->L[0] -#define word1(x) (x)->L[1] -#endif -#define dval(x) (x)->d - -#ifndef STRTOD_DIGLIM -#define STRTOD_DIGLIM 40 -#endif - -#ifdef DIGLIM_DEBUG -extern int strtod_diglim; -#else -#define strtod_diglim STRTOD_DIGLIM -#endif - -/* The following definition of Storeinc is appropriate for MIPS processors. - * An alternative that might be better on some machines is - * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) - */ -#if defined(IEEE_8087) + defined(VAX) -#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ -((unsigned short *)a)[0] = (unsigned short)c, a++) -#else -#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ -((unsigned short *)a)[1] = (unsigned short)c, a++) -#endif - -/* #define P DBL_MANT_DIG */ -/* Ten_pmax = floor(P*log(2)/log(5)) */ -/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ -/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ -/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ - -#ifdef IEEE_Arith -#define Exp_shift 20 -#define Exp_shift1 20 -#define Exp_msk1 0x100000 -#define Exp_msk11 0x100000 -#define Exp_mask 0x7ff00000 -#define P 53 -#define Nbits 53 -#define Bias 1023 -#define Emax 1023 -#define Emin (-1022) -#define Exp_1 0x3ff00000 -#define Exp_11 0x3ff00000 -#define Ebits 11 -#define Frac_mask 0xfffff -#define Frac_mask1 0xfffff -#define Ten_pmax 22 -#define Bletch 0x10 -#define Bndry_mask 0xfffff -#define Bndry_mask1 0xfffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 1 -#define Tiny0 0 -#define Tiny1 1 -#define Quick_max 14 -#define Int_max 14 -#ifndef NO_IEEE_Scale -#define Avoid_Underflow -#ifdef Flush_Denorm /* debugging option */ -#undef Sudden_Underflow -#endif -#endif - -#ifndef Flt_Rounds -#ifdef FLT_ROUNDS -#define Flt_Rounds FLT_ROUNDS -#else -#define Flt_Rounds 1 -#endif -#endif /*Flt_Rounds*/ - -#ifdef Honor_FLT_ROUNDS -#undef Check_FLT_ROUNDS -#define Check_FLT_ROUNDS -#else -#define Rounding Flt_Rounds -#endif - -#else /* ifndef IEEE_Arith */ -#undef Check_FLT_ROUNDS -#undef Honor_FLT_ROUNDS -#undef SET_INEXACT -#undef Sudden_Underflow -#define Sudden_Underflow -#ifdef IBM -#undef Flt_Rounds -#define Flt_Rounds 0 -#define Exp_shift 24 -#define Exp_shift1 24 -#define Exp_msk1 0x1000000 -#define Exp_msk11 0x1000000 -#define Exp_mask 0x7f000000 -#define P 14 -#define Nbits 56 -#define Bias 65 -#define Emax 248 -#define Emin (-260) -#define Exp_1 0x41000000 -#define Exp_11 0x41000000 -#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ -#define Frac_mask 0xffffff -#define Frac_mask1 0xffffff -#define Bletch 4 -#define Ten_pmax 22 -#define Bndry_mask 0xefffff -#define Bndry_mask1 0xffffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 4 -#define Tiny0 0x100000 -#define Tiny1 0 -#define Quick_max 14 -#define Int_max 15 -#else /* VAX */ -#undef Flt_Rounds -#define Flt_Rounds 1 -#define Exp_shift 23 -#define Exp_shift1 7 -#define Exp_msk1 0x80 -#define Exp_msk11 0x800000 -#define Exp_mask 0x7f80 -#define P 56 -#define Nbits 56 -#define Bias 129 -#define Emax 126 -#define Emin (-129) -#define Exp_1 0x40800000 -#define Exp_11 0x4080 -#define Ebits 8 -#define Frac_mask 0x7fffff -#define Frac_mask1 0xffff007f -#define Ten_pmax 24 -#define Bletch 2 -#define Bndry_mask 0xffff007f -#define Bndry_mask1 0xffff007f -#define LSB 0x10000 -#define Sign_bit 0x8000 -#define Log2P 1 -#define Tiny0 0x80 -#define Tiny1 0 -#define Quick_max 15 -#define Int_max 15 -#endif /* IBM, VAX */ -#endif /* IEEE_Arith */ - -#ifndef IEEE_Arith -#define ROUND_BIASED -#endif - -#ifdef RND_PRODQUOT -#define rounded_product(a,b) a = rnd_prod(a, b) -#define rounded_quotient(a,b) a = rnd_quot(a, b) -#ifdef KR_headers -extern double rnd_prod(), rnd_quot(); -#else -extern double rnd_prod(double, double), rnd_quot(double, double); -#endif -#else -#define rounded_product(a,b) a *= b -#define rounded_quotient(a,b) a /= b -#endif - -#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) -#define Big1 0xffffffff - -#ifndef Pack_32 -#define Pack_32 -#endif - -typedef struct BCinfo BCinfo; - struct -BCinfo { int dp0, dp1, dplen, dsign, e0, inexact, nd, nd0, rounding, scale, uflchk; }; - -#ifdef KR_headers -#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff) -#else -#define FFFFFFFF 0xffffffffUL -#endif - -#ifdef NO_LONG_LONG -#undef ULLong -#ifdef Just_16 -#undef Pack_32 -/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. - * This makes some inner loops simpler and sometimes saves work - * during multiplications, but it often seems to make things slightly - * slower. Hence the default is now to store 32 bits per Long. - */ -#endif -#else /* long long available */ -#ifndef Llong -#define Llong long long -#endif -#ifndef ULLong -#define ULLong unsigned Llong -#endif -#endif /* NO_LONG_LONG */ - -#ifndef MULTIPLE_THREADS -#define ACQUIRE_DTOA_LOCK(n) /*nothing*/ -#define FREE_DTOA_LOCK(n) /*nothing*/ -#endif - -#define Kmax 7 - -double strtod(const char *s00, char **se); -char *dtoa(double d, int mode, int ndigits, - int *decpt, int *sign, char **rve); - - struct -Bigint { - struct Bigint *next; - int k, maxwds, sign, wds; - ULong x[1]; - }; - - typedef struct Bigint Bigint; - - static Bigint *freelist[Kmax+1]; - - static Bigint * -Balloc -#ifdef KR_headers - (k) int k; -#else - (int k) -#endif -{ - int x; - Bigint *rv; -#ifndef Omit_Private_Memory - unsigned int len; -#endif - - ACQUIRE_DTOA_LOCK(0); - /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ - /* but this case seems very unlikely. */ - if (k <= Kmax && freelist[k]) { - rv = freelist[k]; - freelist[k] = rv->next; - } - else { - x = 1 << k; -#ifdef Omit_Private_Memory - rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); -#else - len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) - /sizeof(double); - if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { - rv = (Bigint*)pmem_next; - pmem_next += len; - } - else - rv = (Bigint*)MALLOC(len*sizeof(double)); -#endif - rv->k = k; - rv->maxwds = x; - } - FREE_DTOA_LOCK(0); - rv->sign = rv->wds = 0; - return rv; - } - - static void -Bfree -#ifdef KR_headers - (v) Bigint *v; -#else - (Bigint *v) -#endif -{ - if (v) { - if (v->k > Kmax) -#ifdef FREE - FREE((void*)v); -#else - free((void*)v); -#endif - else { - ACQUIRE_DTOA_LOCK(0); - v->next = freelist[v->k]; - freelist[v->k] = v; - FREE_DTOA_LOCK(0); - } - } - } - -#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ -y->wds*sizeof(Long) + 2*sizeof(int)) - - static Bigint * -multadd -#ifdef KR_headers - (b, m, a) Bigint *b; int m, a; -#else - (Bigint *b, int m, int a) /* multiply by m and add a */ -#endif -{ - int i, wds; -#ifdef ULLong - ULong *x; - ULLong carry, y; -#else - ULong carry, *x, y; -#ifdef Pack_32 - ULong xi, z; -#endif -#endif - Bigint *b1; - - wds = b->wds; - x = b->x; - i = 0; - carry = a; - do { -#ifdef ULLong - y = *x * (ULLong)m + carry; - carry = y >> 32; - *x++ = y & FFFFFFFF; -#else -#ifdef Pack_32 - xi = *x; - y = (xi & 0xffff) * m + carry; - z = (xi >> 16) * m + (y >> 16); - carry = z >> 16; - *x++ = (z << 16) + (y & 0xffff); -#else - y = *x * m + carry; - carry = y >> 16; - *x++ = y & 0xffff; -#endif -#endif - } - while(++i < wds); - if (carry) { - if (wds >= b->maxwds) { - b1 = Balloc(b->k+1); - Bcopy(b1, b); - Bfree(b); - b = b1; - } - b->x[wds++] = (ULong)carry; - b->wds = wds; - } - return b; - } - - static Bigint * -s2b -#ifdef KR_headers - (s, nd0, nd, y9, dplen) CONST char *s; int nd0, nd, dplen; ULong y9; -#else - (CONST char *s, int nd0, int nd, ULong y9, int dplen) -#endif -{ - Bigint *b; - int i, k; - Long x, y; - - x = (nd + 8) / 9; - for(k = 0, y = 1; x > y; y <<= 1, k++) ; -#ifdef Pack_32 - b = Balloc(k); - b->x[0] = y9; - b->wds = 1; -#else - b = Balloc(k+1); - b->x[0] = y9 & 0xffff; - b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; -#endif - - i = 9; - if (9 < nd0) { - s += 9; - do b = multadd(b, 10, *s++ - '0'); - while(++i < nd0); - s += dplen; - } - else - s += dplen + 9; - for(; i < nd; i++) - b = multadd(b, 10, *s++ - '0'); - return b; - } - - static int -hi0bits -#ifdef KR_headers - (x) ULong x; -#else - (ULong x) -#endif -{ - int k = 0; - - if (!(x & 0xffff0000)) { - k = 16; - x <<= 16; - } - if (!(x & 0xff000000)) { - k += 8; - x <<= 8; - } - if (!(x & 0xf0000000)) { - k += 4; - x <<= 4; - } - if (!(x & 0xc0000000)) { - k += 2; - x <<= 2; - } - if (!(x & 0x80000000)) { - k++; - if (!(x & 0x40000000)) - return 32; - } - return k; - } - - static int -lo0bits -#ifdef KR_headers - (y) ULong *y; -#else - (ULong *y) -#endif -{ - int k; - ULong x = *y; - - if (x & 7) { - if (x & 1) - return 0; - if (x & 2) { - *y = x >> 1; - return 1; - } - *y = x >> 2; - return 2; - } - k = 0; - if (!(x & 0xffff)) { - k = 16; - x >>= 16; - } - if (!(x & 0xff)) { - k += 8; - x >>= 8; - } - if (!(x & 0xf)) { - k += 4; - x >>= 4; - } - if (!(x & 0x3)) { - k += 2; - x >>= 2; - } - if (!(x & 1)) { - k++; - x >>= 1; - if (!x) - return 32; - } - *y = x; - return k; - } - - static Bigint * -i2b -#ifdef KR_headers - (i) int i; -#else - (int i) -#endif -{ - Bigint *b; - - b = Balloc(1); - b->x[0] = i; - b->wds = 1; - return b; - } - - static Bigint * -mult -#ifdef KR_headers - (a, b) Bigint *a, *b; -#else - (Bigint *a, Bigint *b) -#endif -{ - Bigint *c; - int k, wa, wb, wc; - ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; - ULong y; -#ifdef ULLong - ULLong carry, z; -#else - ULong carry, z; -#ifdef Pack_32 - ULong z2; -#endif -#endif - - if (a->wds < b->wds) { - c = a; - a = b; - b = c; - } - k = a->k; - wa = a->wds; - wb = b->wds; - wc = wa + wb; - if (wc > a->maxwds) - k++; - c = Balloc(k); - for(x = c->x, xa = x + wc; x < xa; x++) - *x = 0; - xa = a->x; - xae = xa + wa; - xb = b->x; - xbe = xb + wb; - xc0 = c->x; -#ifdef ULLong - for(; xb < xbe; xc0++) { - y = *xb++; - if (y) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * (ULLong)y + *xc + carry; - carry = z >> 32; - *xc++ = z & FFFFFFFF; - } - while(x < xae); - *xc = (ULong)carry; - } - } -#else -#ifdef Pack_32 - for(; xb < xbe; xb++, xc0++) { - if (y = *xb & 0xffff) { - x = xa; - xc = xc0; - carry = 0; - do { - z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; - carry = z >> 16; - z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; - carry = z2 >> 16; - Storeinc(xc, z2, z); - } - while(x < xae); - *xc = carry; - } - if (y = *xb >> 16) { - x = xa; - xc = xc0; - carry = 0; - z2 = *xc; - do { - z = (*x & 0xffff) * y + (*xc >> 16) + carry; - carry = z >> 16; - Storeinc(xc, z, z2); - z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; - carry = z2 >> 16; - } - while(x < xae); - *xc = z2; - } - } -#else - for(; xb < xbe; xc0++) { - if (y = *xb++) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * y + *xc + carry; - carry = z >> 16; - *xc++ = z & 0xffff; - } - while(x < xae); - *xc = carry; - } - } -#endif -#endif - for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; - c->wds = wc; - return c; - } - - static Bigint *p5s; - - static Bigint * -pow5mult -#ifdef KR_headers - (b, k) Bigint *b; int k; -#else - (Bigint *b, int k) -#endif -{ - Bigint *b1, *p5, *p51; - int i; - static int p05[3] = { 5, 25, 125 }; - - i = k & 3; - if (i) - b = multadd(b, p05[i-1], 0); - - if (!(k >>= 2)) - return b; - p5 = p5s; - if (!p5) { - /* first time */ -#ifdef MULTIPLE_THREADS - ACQUIRE_DTOA_LOCK(1); - p5 = p5s; - if (!p5) { - p5 = p5s = i2b(625); - p5->next = 0; - } - FREE_DTOA_LOCK(1); -#else - p5 = p5s = i2b(625); - p5->next = 0; -#endif - } - for(;;) { - if (k & 1) { - b1 = mult(b, p5); - Bfree(b); - b = b1; - } - if (!(k >>= 1)) - break; - p51 = p5->next; - if (!p51) { -#ifdef MULTIPLE_THREADS - ACQUIRE_DTOA_LOCK(1); - p51 = p5->next; - if (!p51) { - p51 = p5->next = mult(p5,p5); - p51->next = 0; - } - FREE_DTOA_LOCK(1); -#else - p51 = p5->next = mult(p5,p5); - p51->next = 0; -#endif - } - p5 = p51; - } - return b; - } - - static Bigint * -lshift -#ifdef KR_headers - (b, k) Bigint *b; int k; -#else - (Bigint *b, int k) -#endif -{ - int i, k1, n, n1; - Bigint *b1; - ULong *x, *x1, *xe, z; - -#ifdef Pack_32 - n = k >> 5; -#else - n = k >> 4; -#endif - k1 = b->k; - n1 = n + b->wds + 1; - for(i = b->maxwds; n1 > i; i <<= 1) - k1++; - b1 = Balloc(k1); - x1 = b1->x; - for(i = 0; i < n; i++) - *x1++ = 0; - x = b->x; - xe = x + b->wds; -#ifdef Pack_32 - if (k &= 0x1f) { - k1 = 32 - k; - z = 0; - do { - *x1++ = *x << k | z; - z = *x++ >> k1; - } - while(x < xe); - *x1 = z; - if (*x1) - ++n1; - } -#else - if (k &= 0xf) { - k1 = 16 - k; - z = 0; - do { - *x1++ = *x << k & 0xffff | z; - z = *x++ >> k1; - } - while(x < xe); - if (*x1 = z) - ++n1; - } -#endif - else do - *x1++ = *x++; - while(x < xe); - b1->wds = n1 - 1; - Bfree(b); - return b1; - } - - static int -cmp -#ifdef KR_headers - (a, b) Bigint *a, *b; -#else - (Bigint *a, Bigint *b) -#endif -{ - ULong *xa, *xa0, *xb, *xb0; - int i, j; - - i = a->wds; - j = b->wds; -#ifdef DEBUG - if (i > 1 && !a->x[i-1]) - Bug("cmp called with a->x[a->wds-1] == 0"); - if (j > 1 && !b->x[j-1]) - Bug("cmp called with b->x[b->wds-1] == 0"); -#endif - if (i -= j) - return i; - xa0 = a->x; - xa = xa0 + j; - xb0 = b->x; - xb = xb0 + j; - for(;;) { - if (*--xa != *--xb) - return *xa < *xb ? -1 : 1; - if (xa <= xa0) - break; - } - return 0; - } - - static Bigint * -diff -#ifdef KR_headers - (a, b) Bigint *a, *b; -#else - (Bigint *a, Bigint *b) -#endif -{ - Bigint *c; - int i, wa, wb; - ULong *xa, *xae, *xb, *xbe, *xc; -#ifdef ULLong - ULLong borrow, y; -#else - ULong borrow, y; -#ifdef Pack_32 - ULong z; -#endif -#endif - - i = cmp(a,b); - if (!i) { - c = Balloc(0); - c->wds = 1; - c->x[0] = 0; - return c; - } - if (i < 0) { - c = a; - a = b; - b = c; - i = 1; - } - else - i = 0; - c = Balloc(a->k); - c->sign = i; - wa = a->wds; - xa = a->x; - xae = xa + wa; - wb = b->wds; - xb = b->x; - xbe = xb + wb; - xc = c->x; - borrow = 0; -#ifdef ULLong - do { - y = (ULLong)*xa++ - *xb++ - borrow; - borrow = y >> 32 & (ULong)1; - *xc++ = y & FFFFFFFF; - } - while(xb < xbe); - while(xa < xae) { - y = *xa++ - borrow; - borrow = y >> 32 & (ULong)1; - *xc++ = y & FFFFFFFF; - } -#else -#ifdef Pack_32 - do { - y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } - while(xb < xbe); - while(xa < xae) { - y = (*xa & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } -#else - do { - y = *xa++ - *xb++ - borrow; - borrow = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } - while(xb < xbe); - while(xa < xae) { - y = *xa++ - borrow; - borrow = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } -#endif -#endif - while(!*--xc) - wa--; - c->wds = wa; - return c; - } - - static double -ulp -#ifdef KR_headers - (x) U *x; -#else - (U *x) -#endif -{ - Long L; - U u; - - L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; -#ifndef Avoid_Underflow -#ifndef Sudden_Underflow - if (L > 0) { -#endif -#endif -#ifdef IBM - L |= Exp_msk1 >> 4; -#endif - word0(&u) = L; - word1(&u) = 0; -#ifndef Avoid_Underflow -#ifndef Sudden_Underflow - } - else { - L = -L >> Exp_shift; - if (L < Exp_shift) { - word0(&u) = 0x80000 >> L; - word1(&u) = 0; - } - else { - word0(&u) = 0; - L -= Exp_shift; - word1(&u) = L >= 31 ? 1 : 1 << 31 - L; - } - } -#endif -#endif - return dval(&u); - } - - static double -b2d -#ifdef KR_headers - (a, e) Bigint *a; int *e; -#else - (Bigint *a, int *e) -#endif -{ - ULong *xa, *xa0, w, y, z; - int k; - U d; -#ifdef VAX - ULong d0, d1; -#else -#define d0 word0(&d) -#define d1 word1(&d) -#endif - - xa0 = a->x; - xa = xa0 + a->wds; - y = *--xa; -#ifdef DEBUG - if (!y) Bug("zero y in b2d"); -#endif - k = hi0bits(y); - *e = 32 - k; -#ifdef Pack_32 - if (k < Ebits) { - d0 = Exp_1 | y >> (Ebits - k); - w = xa > xa0 ? *--xa : 0; - d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - if (k -= Ebits) { - d0 = Exp_1 | y << k | z >> (32 - k); - y = xa > xa0 ? *--xa : 0; - d1 = z << k | y >> (32 - k); - } - else { - d0 = Exp_1 | y; - d1 = z; - } -#else - if (k < Ebits + 16) { - z = xa > xa0 ? *--xa : 0; - d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; - w = xa > xa0 ? *--xa : 0; - y = xa > xa0 ? *--xa : 0; - d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - w = xa > xa0 ? *--xa : 0; - k -= Ebits + 16; - d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; - y = xa > xa0 ? *--xa : 0; - d1 = w << k + 16 | y << k; -#endif - ret_d: -#ifdef VAX - word0(&d) = d0 >> 16 | d0 << 16; - word1(&d) = d1 >> 16 | d1 << 16; -#else -#undef d0 -#undef d1 -#endif - return dval(&d); - } - - static Bigint * -d2b -#ifdef KR_headers - (d, e, bits) U *d; int *e, *bits; -#else - (U *d, int *e, int *bits) -#endif -{ - Bigint *b; - int de, k; - ULong *x, y, z; -#ifndef Sudden_Underflow - int i; -#endif -#ifdef VAX - ULong d0, d1; - d0 = word0(d) >> 16 | word0(d) << 16; - d1 = word1(d) >> 16 | word1(d) << 16; -#else -#define d0 word0(d) -#define d1 word1(d) -#endif - -#ifdef Pack_32 - b = Balloc(1); -#else - b = Balloc(2); -#endif - x = b->x; - - z = d0 & Frac_mask; - d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ -#ifdef Sudden_Underflow - de = (int)(d0 >> Exp_shift); -#ifndef IBM - z |= Exp_msk11; -#endif -#else - de = (int)(d0 >> Exp_shift); - if (de) - z |= Exp_msk1; -#endif -#ifdef Pack_32 - y = d1; - if (y) { - k = lo0bits(&y); - if (k) { - x[0] = y | z << (32 - k); - z >>= k; - } - else - x[0] = y; - x[1] = z; - b->wds = x[1] ? 2 : 1; -#ifndef Sudden_Underflow - i = b->wds; -#endif - } - else { - k = lo0bits(&z); - x[0] = z; -#ifndef Sudden_Underflow - i = -#endif - b->wds = 1; - k += 32; - } -#else - if (y = d1) { - if (k = lo0bits(&y)) - if (k >= 16) { - x[0] = y | z << 32 - k & 0xffff; - x[1] = z >> k - 16 & 0xffff; - x[2] = z >> k; - i = 2; - } - else { - x[0] = y & 0xffff; - x[1] = y >> 16 | z << 16 - k & 0xffff; - x[2] = z >> k & 0xffff; - x[3] = z >> k+16; - i = 3; - } - else { - x[0] = y & 0xffff; - x[1] = y >> 16; - x[2] = z & 0xffff; - x[3] = z >> 16; - i = 3; - } - } - else { -#ifdef DEBUG - if (!z) - Bug("Zero passed to d2b"); -#endif - k = lo0bits(&z); - if (k >= 16) { - x[0] = z; - i = 0; - } - else { - x[0] = z & 0xffff; - x[1] = z >> 16; - i = 1; - } - k += 32; - } - while(!x[i]) - --i; - b->wds = i + 1; -#endif -#ifndef Sudden_Underflow - if (de) { -#endif -#ifdef IBM - *e = (de - Bias - (P-1) << 2) + k; - *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); -#else - *e = de - Bias - (P-1) + k; - *bits = P - k; -#endif -#ifndef Sudden_Underflow - } - else { - *e = de - Bias - (P-1) + 1 + k; -#ifdef Pack_32 - *bits = 32*i - hi0bits(x[i-1]); -#else - *bits = (i+2)*16 - hi0bits(x[i]); -#endif - } -#endif - return b; - } -#undef d0 -#undef d1 - - static double -ratio -#ifdef KR_headers - (a, b) Bigint *a, *b; -#else - (Bigint *a, Bigint *b) -#endif -{ - U da, db; - int k, ka, kb; - - dval(&da) = b2d(a, &ka); - dval(&db) = b2d(b, &kb); -#ifdef Pack_32 - k = ka - kb + 32*(a->wds - b->wds); -#else - k = ka - kb + 16*(a->wds - b->wds); -#endif -#ifdef IBM - if (k > 0) { - word0(&da) += (k >> 2)*Exp_msk1; - if (k &= 3) - dval(&da) *= 1 << k; - } - else { - k = -k; - word0(&db) += (k >> 2)*Exp_msk1; - if (k &= 3) - dval(&db) *= 1 << k; - } -#else - if (k > 0) - word0(&da) += k*Exp_msk1; - else { - k = -k; - word0(&db) += k*Exp_msk1; - } -#endif - return dval(&da) / dval(&db); - } - - static CONST double -tens[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22 -#ifdef VAX - , 1e23, 1e24 -#endif - }; - - static CONST double -#ifdef IEEE_Arith -bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; -static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, -#ifdef Avoid_Underflow - 9007199254740992.*9007199254740992.e-256 - /* = 2^106 * 1e-256 */ -#else - 1e-256 -#endif - }; -/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ -/* flag unnecessarily. It leads to a song and dance at the end of strtod. */ -#define Scale_Bit 0x10 -#define n_bigtens 5 -#else -#ifdef IBM -bigtens[] = { 1e16, 1e32, 1e64 }; -static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 }; -#define n_bigtens 3 -#else -bigtens[] = { 1e16, 1e32 }; -static CONST double tinytens[] = { 1e-16, 1e-32 }; -#define n_bigtens 2 -#endif -#endif - -#undef Need_Hexdig -#ifdef INFNAN_CHECK -#ifndef No_Hex_NaN -#define Need_Hexdig -#endif -#endif - -#ifndef Need_Hexdig -#ifndef NO_HEX_FP -#define Need_Hexdig -#endif -#endif - -#ifdef Need_Hexdig /*{*/ -static unsigned char hexdig[256]; - - static void -#ifdef KR_headers -htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc; -#else -htinit(unsigned char *h, unsigned char *s, int inc) -#endif -{ - int i, j; - for(i = 0; (j = s[i]) !=0; i++) - h[j] = (unsigned char)(i + inc); - } - - static void -#ifdef KR_headers -hexdig_init() -#else -hexdig_init(void) -#endif -{ -#define USC (unsigned char *) - htinit(hexdig, USC "0123456789", 0x10); - htinit(hexdig, USC "abcdef", 0x10 + 10); - htinit(hexdig, USC "ABCDEF", 0x10 + 10); - } -#endif /* } Need_Hexdig */ - -#ifdef INFNAN_CHECK - -#ifndef NAN_WORD0 -#define NAN_WORD0 0x7ff80000 -#endif - -#ifndef NAN_WORD1 -#define NAN_WORD1 0 -#endif - - static int -match -#ifdef KR_headers - (sp, t) char **sp, *t; -#else - (CONST char **sp, CONST char *t) -#endif -{ - int c, d; - CONST char *s = *sp; - - for(d = *t++; d; d = *t++) { - if ((c = *++s) >= 'A' && c <= 'Z') - c += 'a' - 'A'; - if (c != d) - return 0; - } - *sp = s + 1; - return 1; - } - -#ifndef No_Hex_NaN - static void -hexnan -#ifdef KR_headers - (rvp, sp) U *rvp; CONST char **sp; -#else - (U *rvp, CONST char **sp) -#endif -{ - ULong c, x[2]; - CONST char *s; - int c1, havedig, udx0, xshift; - - if (!hexdig['0']) - hexdig_init(); - x[0] = x[1] = 0; - havedig = xshift = 0; - udx0 = 1; - s = *sp; - /* allow optional initial 0x or 0X */ - for(c = *(CONST unsigned char*)(s+1); c && c <= ' '; c = *(CONST unsigned char*)(s+1)) - ++s; - if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')) - s += 2; - for(c = *(CONST unsigned char*)++s; c; c = *(CONST unsigned char*)++s) { - c1 = hexdig[c]; - if (c1) - c = c1 & 0xf; - else if (c <= ' ') { - if (udx0 && havedig) { - udx0 = 0; - xshift = 1; - } - continue; - } -#ifdef GDTOA_NON_PEDANTIC_NANCHECK - else if (/*(*/ c == ')' && havedig) { - *sp = s + 1; - break; - } - else - return; /* invalid form: don't change *sp */ -#else - else { - do { - if (/*(*/ c == ')') { - *sp = s + 1; - break; - } - c = *++s; - } while(c); - break; - } -#endif - havedig = 1; - if (xshift) { - xshift = 0; - x[0] = x[1]; - x[1] = 0; - } - if (udx0) - x[0] = (x[0] << 4) | (x[1] >> 28); - x[1] = (x[1] << 4) | c; - } - if ((x[0] &= 0xfffff) || x[1]) { - word0(rvp) = Exp_mask | x[0]; - word1(rvp) = x[1]; - } - } -#endif /*No_Hex_NaN*/ -#endif /* INFNAN_CHECK */ - -#ifdef Pack_32 -#define ULbits 32 -#define kshift 5 -#define kmask 31 -#else -#define ULbits 16 -#define kshift 4 -#define kmask 15 -#endif -#ifndef NO_HEX_FP /*{*/ - - static void -#ifdef KR_headers -rshift(b, k) Bigint *b; int k; -#else -rshift(Bigint *b, int k) -#endif -{ - ULong *x, *x1, *xe, y; - int n; - - x = x1 = b->x; - n = k >> kshift; - if (n < b->wds) { - xe = x + b->wds; - x += n; - if (k &= kmask) { - n = 32 - k; - y = *x++ >> k; - while(x < xe) { - *x1++ = (y | (*x << n)) & 0xffffffff; - y = *x++ >> k; - } - if ((*x1 = y) !=0) - x1++; - } - else - while(x < xe) - *x1++ = *x++; - } - if ((b->wds = x1 - b->x) == 0) - b->x[0] = 0; - } - - static ULong -#ifdef KR_headers -any_on(b, k) Bigint *b; int k; -#else -any_on(Bigint *b, int k) -#endif -{ - int n, nwds; - ULong *x, *x0, x1, x2; - - x = b->x; - nwds = b->wds; - n = k >> kshift; - if (n > nwds) - n = nwds; - else if (n < nwds && (k &= kmask)) { - x1 = x2 = x[n]; - x1 >>= k; - x1 <<= k; - if (x1 != x2) - return 1; - } - x0 = x; - x += n; - while(x > x0) - if (*--x) - return 1; - return 0; - } - -enum { /* rounding values: same as FLT_ROUNDS */ - Round_zero = 0, - Round_near = 1, - Round_up = 2, - Round_down = 3 - }; - - static Bigint * -#ifdef KR_headers -increment(b) Bigint *b; -#else -increment(Bigint *b) -#endif -{ - ULong *x, *xe; - Bigint *b1; - - x = b->x; - xe = x + b->wds; - do { - if (*x < (ULong)0xffffffffL) { - ++*x; - return b; - } - *x++ = 0; - } while(x < xe); - { - if (b->wds >= b->maxwds) { - b1 = Balloc(b->k+1); - Bcopy(b1,b); - Bfree(b); - b = b1; - } - b->x[b->wds++] = 1; - } - return b; - } - - void -#ifdef KR_headers -gethex(sp, rvp, rounding, sign) - CONST char **sp; U *rvp; int rounding, sign; -#else -gethex( CONST char **sp, U *rvp, int rounding, int sign) -#endif -{ - Bigint *b; - CONST unsigned char *decpt, *s0, *s, *s1; - Long e, e1; - ULong L, lostbits, *x; - int big, denorm, esign, havedig, k, n, nbits, up, zret; -#ifdef IBM - int j; -#endif - enum { -#ifdef IEEE_Arith /*{{*/ - emax = 0x7fe - Bias - P + 1, - emin = Emin - P + 1 -#else /*}{*/ - emin = Emin - P, -#ifdef VAX - emax = 0x7ff - Bias - P + 1 -#endif -#ifdef IBM - emax = 0x7f - Bias - P -#endif -#endif /*}}*/ - }; -#ifdef USE_LOCALE - int i; -#ifdef NO_LOCALE_CACHE - const unsigned char *decimalpoint = (unsigned char*) - localeconv()->decimal_point; -#else - const unsigned char *decimalpoint; - static unsigned char *decimalpoint_cache; - if (!(s0 = decimalpoint_cache)) { - s0 = (unsigned char*)localeconv()->decimal_point; - if ((decimalpoint_cache = (unsigned char*) - MALLOC(strlen((CONST char*)s0) + 1))) { - strcpy((char*)decimalpoint_cache, (CONST char*)s0); - s0 = decimalpoint_cache; - } - } - decimalpoint = s0; -#endif -#endif - - if (!hexdig['0']) - hexdig_init(); - havedig = 0; - s0 = *(CONST unsigned char **)sp + 2; - while(s0[havedig] == '0') - havedig++; - s0 += havedig; - s = s0; - decpt = 0; - zret = 0; - e = 0; - if (hexdig[*s]) - havedig++; - else { - zret = 1; -#ifdef USE_LOCALE - for(i = 0; decimalpoint[i]; ++i) { - if (s[i] != decimalpoint[i]) - goto pcheck; - } - decpt = s += i; -#else - if (*s != '.') - goto pcheck; - decpt = ++s; -#endif - if (!hexdig[*s]) - goto pcheck; - while(*s == '0') - s++; - if (hexdig[*s]) - zret = 0; - havedig = 1; - s0 = s; - } - while(hexdig[*s]) - s++; -#ifdef USE_LOCALE - if (*s == *decimalpoint && !decpt) { - for(i = 1; decimalpoint[i]; ++i) { - if (s[i] != decimalpoint[i]) - goto pcheck; - } - decpt = s += i; -#else - if (*s == '.' && !decpt) { - decpt = ++s; -#endif - while(hexdig[*s]) - s++; - }/*}*/ - if (decpt) - e = -(((Long)(s-decpt)) << 2); - pcheck: - s1 = s; - big = esign = 0; - switch(*s) { - case 'p': - case 'P': - switch(*++s) { - case '-': - esign = 1; - /* no break */ - case '+': - s++; - } - if ((n = hexdig[*s]) == 0 || n > 0x19) { - s = s1; - break; - } - e1 = n - 0x10; - while((n = hexdig[*++s]) !=0 && n <= 0x19) { - if (e1 & 0xf8000000) - big = 1; - e1 = 10*e1 + n - 0x10; - } - if (esign) - e1 = -e1; - e += e1; - } - *sp = (char*)s; - if (!havedig) - *sp = (char*)s0 - 1; - if (zret) - goto retz1; - if (big) { - if (esign) { -#ifdef IEEE_Arith - switch(rounding) { - case Round_up: - if (sign) - break; - goto ret_tiny; - case Round_down: - if (!sign) - break; - goto ret_tiny; - } -#endif - goto retz; -#ifdef IEEE_Arith - ret_tiny: -#ifndef NO_ERRNO - errno = ERANGE; -#endif - word0(rvp) = 0; - word1(rvp) = 1; - return; -#endif /* IEEE_Arith */ - } - switch(rounding) { - case Round_near: - goto ovfl1; - case Round_up: - if (!sign) - goto ovfl1; - goto ret_big; - case Round_down: - if (sign) - goto ovfl1; - goto ret_big; - } - ret_big: - word0(rvp) = Big0; - word1(rvp) = Big1; - return; - } - n = s1 - s0 - 1; - for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) - k++; - b = Balloc(k); - x = b->x; - n = 0; - L = 0; -#ifdef USE_LOCALE - for(i = 0; decimalpoint[i+1]; ++i); -#endif - while(s1 > s0) { -#ifdef USE_LOCALE - if (*--s1 == decimalpoint[i]) { - s1 -= i; - continue; - } -#else - if (*--s1 == '.') - continue; -#endif - if (n == ULbits) { - *x++ = L; - L = 0; - n = 0; - } - L |= (hexdig[*s1] & 0x0f) << n; - n += 4; - } - *x++ = L; - b->wds = n = x - b->x; - n = ULbits*n - hi0bits(L); - nbits = Nbits; - lostbits = 0; - x = b->x; - if (n > nbits) { - n -= nbits; - if (any_on(b,n)) { - lostbits = 1; - k = n - 1; - if (x[k>>kshift] & 1 << (k & kmask)) { - lostbits = 2; - if (k > 0 && any_on(b,k)) - lostbits = 3; - } - } - rshift(b, n); - e += n; - } - else if (n < nbits) { - n = nbits - n; - b = lshift(b, n); - e -= n; - x = b->x; - } - if (e > Emax) { - ovfl: - Bfree(b); - ovfl1: -#ifndef NO_ERRNO - errno = ERANGE; -#endif - word0(rvp) = Exp_mask; - word1(rvp) = 0; - return; - } - denorm = 0; - if (e < emin) { - denorm = 1; - n = emin - e; - if (n >= nbits) { -#ifdef IEEE_Arith /*{*/ - switch (rounding) { - case Round_near: - if (n == nbits && (n < 2 || any_on(b,n-1))) - goto ret_tiny; - break; - case Round_up: - if (!sign) - goto ret_tiny; - break; - case Round_down: - if (sign) - goto ret_tiny; - } -#endif /* } IEEE_Arith */ - Bfree(b); - retz: -#ifndef NO_ERRNO - errno = ERANGE; -#endif - retz1: - rvp->d = 0.; - return; - } - k = n - 1; - if (lostbits) - lostbits = 1; - else if (k > 0) - lostbits = any_on(b,k); - if (x[k>>kshift] & 1 << (k & kmask)) - lostbits |= 2; - nbits -= n; - rshift(b,n); - e = emin; - } - if (lostbits) { - up = 0; - switch(rounding) { - case Round_zero: - break; - case Round_near: - if (lostbits & 2 - && (lostbits & 1) | (x[0] & 1)) - up = 1; - break; - case Round_up: - up = 1 - sign; - break; - case Round_down: - up = sign; - } - if (up) { - k = b->wds; - b = increment(b); - x = b->x; - if (denorm) { -#if 0 - if (nbits == Nbits - 1 - && x[nbits >> kshift] & 1 << (nbits & kmask)) - denorm = 0; /* not currently used */ -#endif - } - else if (b->wds > k - || ((n = nbits & kmask) !=0 - && hi0bits(x[k-1]) < 32-n)) { - rshift(b,1); - if (++e > Emax) - goto ovfl; - } - } - } -#ifdef IEEE_Arith - if (denorm) - word0(rvp) = b->wds > 1 ? b->x[1] & ~0x100000 : 0; - else - word0(rvp) = (b->x[1] & ~0x100000) | ((e + 0x3ff + 52) << 20); - word1(rvp) = b->x[0]; -#endif -#ifdef IBM - if ((j = e & 3)) { - k = b->x[0] & ((1 << j) - 1); - rshift(b,j); - if (k) { - switch(rounding) { - case Round_up: - if (!sign) - increment(b); - break; - case Round_down: - if (sign) - increment(b); - break; - case Round_near: - j = 1 << (j-1); - if (k & j && ((k & (j-1)) | lostbits)) - increment(b); - } - } - } - e >>= 2; - word0(rvp) = b->x[1] | ((e + 65 + 13) << 24); - word1(rvp) = b->x[0]; -#endif -#ifdef VAX - /* The next two lines ignore swap of low- and high-order 2 bytes. */ - /* word0(rvp) = (b->x[1] & ~0x800000) | ((e + 129 + 55) << 23); */ - /* word1(rvp) = b->x[0]; */ - word0(rvp) = ((b->x[1] & ~0x800000) >> 16) | ((e + 129 + 55) << 7) | (b->x[1] << 16); - word1(rvp) = (b->x[0] >> 16) | (b->x[0] << 16); -#endif - Bfree(b); - } -#endif /*}!NO_HEX_FP*/ - - static int -#ifdef KR_headers -dshift(b, p2) Bigint *b; int p2; -#else -dshift(Bigint *b, int p2) -#endif -{ - int rv = hi0bits(b->x[b->wds-1]) - 4; - if (p2 > 0) - rv -= p2; - return rv & kmask; - } - - static int -quorem -#ifdef KR_headers - (b, S) Bigint *b, *S; -#else - (Bigint *b, Bigint *S) -#endif -{ - int n; - ULong *bx, *bxe, q, *sx, *sxe; -#ifdef ULLong - ULLong borrow, carry, y, ys; -#else - ULong borrow, carry, y, ys; -#ifdef Pack_32 - ULong si, z, zs; -#endif -#endif - - n = S->wds; -#ifdef DEBUG - /*debug*/ if (b->wds > n) - /*debug*/ Bug("oversize b in quorem"); -#endif - if (b->wds < n) - return 0; - sx = S->x; - sxe = sx + --n; - bx = b->x; - bxe = bx + n; - q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ -#ifdef DEBUG - /*debug*/ if (q > 9) - /*debug*/ Bug("oversized quotient in quorem"); -#endif - if (q) { - borrow = 0; - carry = 0; - do { -#ifdef ULLong - ys = *sx++ * (ULLong)q + carry; - carry = ys >> 32; - y = *bx - (ys & FFFFFFFF) - borrow; - borrow = y >> 32 & (ULong)1; - *bx++ = y & FFFFFFFF; -#else -#ifdef Pack_32 - si = *sx++; - ys = (si & 0xffff) * q + carry; - zs = (si >> 16) * q + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#else - ys = *sx++ * q + carry; - carry = ys >> 16; - y = *bx - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - *bx++ = y & 0xffff; -#endif -#endif - } - while(sx <= sxe); - if (!*bxe) { - bx = b->x; - while(--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - if (cmp(b, S) >= 0) { - q++; - borrow = 0; - carry = 0; - bx = b->x; - sx = S->x; - do { -#ifdef ULLong - ys = *sx++ + carry; - carry = ys >> 32; - y = *bx - (ys & FFFFFFFF) - borrow; - borrow = y >> 32 & (ULong)1; - *bx++ = y & FFFFFFFF; -#else -#ifdef Pack_32 - si = *sx++; - ys = (si & 0xffff) + carry; - zs = (si >> 16) + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#else - ys = *sx++ + carry; - carry = ys >> 16; - y = *bx - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - *bx++ = y & 0xffff; -#endif -#endif - } - while(sx <= sxe); - bx = b->x; - bxe = bx + n; - if (!*bxe) { - while(--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - return q; - } - -#ifndef NO_STRTOD_BIGCOMP - - static void -bigcomp -#ifdef KR_headers - (rv, s0, bc) - U *rv; CONST char *s0; BCinfo *bc; -#else - (U *rv, CONST char *s0, BCinfo *bc) -#endif -{ - Bigint *b, *d; - int b2, bbits, d2, dd, dig, dsign, i, j, nd, nd0, p2, p5, speccase; - - dsign = bc->dsign; - nd = bc->nd; - nd0 = bc->nd0; - p5 = nd + bc->e0 - 1; - dd = speccase = 0; -#ifndef Sudden_Underflow - if (rv->d == 0.) { /* special case: value near underflow-to-zero */ - /* threshold was rounded to zero */ - b = i2b(1); - p2 = Emin - P + 1; - bbits = 1; -#ifdef Avoid_Underflow - word0(rv) = (P+2) << Exp_shift; -#else - word1(rv) = 1; -#endif - i = 0; -#ifdef Honor_FLT_ROUNDS - if (bc->rounding == 1) -#endif - { - speccase = 1; - --p2; - dsign = 0; - goto have_i; - } - } - else -#endif - b = d2b(rv, &p2, &bbits); -#ifdef Avoid_Underflow - p2 -= bc->scale; -#endif - /* floor(log2(rv)) == bbits - 1 + p2 */ - /* Check for denormal case. */ - i = P - bbits; - if (i > (j = P - Emin - 1 + p2)) { -#ifdef Sudden_Underflow - Bfree(b); - b = i2b(1); - p2 = Emin; - i = P - 1; -#ifdef Avoid_Underflow - word0(rv) = (1 + bc->scale) << Exp_shift; -#else - word0(rv) = Exp_msk1; -#endif - word1(rv) = 0; -#else - i = j; -#endif - } -#ifdef Honor_FLT_ROUNDS - if (bc->rounding != 1) { - if (i > 0) - b = lshift(b, i); - if (dsign) - b = increment(b); - } - else -#endif - { - b = lshift(b, ++i); - b->x[0] |= 1; - } -#ifndef Sudden_Underflow - have_i: -#endif - p2 -= p5 + i; - d = i2b(1); - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - */ - if (p5 > 0) - d = pow5mult(d, p5); - else if (p5 < 0) - b = pow5mult(b, -p5); - if (p2 > 0) { - b2 = p2; - d2 = 0; - } - else { - b2 = 0; - d2 = -p2; - } - i = dshift(d, d2); - if ((b2 += i) > 0) - b = lshift(b, b2); - if ((d2 += i) > 0) - d = lshift(d, d2); - - /* Now b/d = exactly half-way between the two floating-point values */ - /* on either side of the input string. Compute first digit of b/d. */ - - dig = quorem(b,d); - if (!dig) { - b = multadd(b, 10, 0); /* very unlikely */ - dig = quorem(b,d); - } - - /* Compare b/d with s0 */ - - for(i = 0; i < nd0; ) { - dd = s0[i++] - '0' - dig; - if (dd) - goto ret; - if (!b->x[0] && b->wds == 1) { - if (i < nd) - dd = 1; - goto ret; - } - b = multadd(b, 10, 0); - dig = quorem(b,d); - } - for(j = bc->dp1; i++ < nd;) { - dd = s0[j++] - '0' - dig; - if (dd) - goto ret; - if (!b->x[0] && b->wds == 1) { - if (i < nd) - dd = 1; - goto ret; - } - b = multadd(b, 10, 0); - dig = quorem(b,d); - } - if (b->x[0] || b->wds > 1) - dd = -1; - ret: - Bfree(b); - Bfree(d); -#ifdef Honor_FLT_ROUNDS - if (bc->rounding != 1) { - if (dd < 0) { - if (bc->rounding == 0) { - if (!dsign) - goto retlow1; - } - else if (dsign) - goto rethi1; - } - else if (dd > 0) { - if (bc->rounding == 0) { - if (dsign) - goto rethi1; - goto ret1; - } - if (!dsign) - goto rethi1; - dval(rv) += 2.*ulp(rv); - } - else { - bc->inexact = 0; - if (dsign) - goto rethi1; - } - } - else -#endif - if (speccase) { - if (dd <= 0) - rv->d = 0.; - } - else if (dd < 0) { - if (!dsign) /* does not happen for round-near */ -retlow1: - dval(rv) -= ulp(rv); - } - else if (dd > 0) { - if (dsign) { - rethi1: - dval(rv) += ulp(rv); - } - } - else { - /* Exact half-way case: apply round-even rule. */ - if (word1(rv) & 1) { - if (dsign) - goto rethi1; - goto retlow1; - } - } - -#ifdef Honor_FLT_ROUNDS - ret1: -#endif - return; - } -#endif /* NO_STRTOD_BIGCOMP */ - - double -strtod -#ifdef KR_headers - (s00, se) CONST char *s00; char **se; -#else - (CONST char *s00, char **se) -#endif -{ - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1; - int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; - CONST char *s, *s0, *s1; - double aadj, aadj1; - Long L; - U aadj2, adj, rv, rv0; - ULong y, z; - BCinfo bc; - Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; -#ifdef SET_INEXACT - int oldinexact; -#endif -#ifdef Honor_FLT_ROUNDS /*{*/ -#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ - bc.rounding = Flt_Rounds; -#else /*}{*/ - bc.rounding = 1; - switch(fegetround()) { - case FE_TOWARDZERO: bc.rounding = 0; break; - case FE_UPWARD: bc.rounding = 2; break; - case FE_DOWNWARD: bc.rounding = 3; - } -#endif /*}}*/ -#endif /*}*/ -#ifdef USE_LOCALE - CONST char *s2; -#endif - - sign = nz0 = nz = bc.dplen = bc.uflchk = 0; - dval(&rv) = 0.; - for(s = s00;;s++) switch(*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - goto ret0; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - default: - goto break2; - } - break2: - if (*s == '0') { -#ifndef NO_HEX_FP /*{*/ - switch(s[1]) { - case 'x': - case 'X': -#ifdef Honor_FLT_ROUNDS - gethex(&s, &rv, bc.rounding, sign); -#else - gethex(&s, &rv, 1, sign); -#endif - goto ret; - } -#endif /*}*/ - nz0 = 1; - while(*++s == '0') ; - if (!*s) - goto ret; - } - s0 = s; - y = z = 0; - for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = 10*y + c - '0'; - else if (nd < 16) - z = 10*z + c - '0'; - nd0 = nd; - bc.dp0 = bc.dp1 = s - s0; -#ifdef USE_LOCALE - s1 = localeconv()->decimal_point; - if (c == *s1) { - c = '.'; - if (*++s1) { - s2 = s; - for(;;) { - if (*++s2 != *s1) { - c = 0; - break; - } - if (!*++s1) { - s = s2; - break; - } - } - } - } -#endif - if (c == '.') { - c = *++s; - bc.dp1 = s - s0; - bc.dplen = bc.dp1 - bc.dp0; - if (!nd) { - for(; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto have_dig; - } - goto dig_done; - } - for(; c >= '0' && c <= '9'; c = *++s) { - have_dig: - nz++; - if (c -= '0') { - nf += nz; - for(i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 1) - z *= 10; - if (nd++ < 9) - y = 10*y + c; - else if (nd <= DBL_DIG + 1) - z = 10*z + c; - nz = 0; - } - } - } - dig_done: - e = 0; - if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) { - goto ret0; - } - s00 = s; - esign = 0; - switch(c = *++s) { - case '-': - esign = 1; - case '+': - c = *++s; - } - if (c >= '0' && c <= '9') { - while(c == '0') - c = *++s; - if (c > '0' && c <= '9') { - L = c - '0'; - s1 = s; - while((c = *++s) >= '0' && c <= '9') - L = 10*L + c - '0'; - if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = 19999; /* safe for 16 bit ints */ - else - e = (int)L; - if (esign) - e = -e; - } - else - e = 0; - } - else - s = s00; - } - if (!nd) { - if (!nz && !nz0) { -#ifdef INFNAN_CHECK - /* Check for Nan and Infinity */ - if (!bc.dplen) - switch(c) { - case 'i': - case 'I': - if (match(&s,"nf")) { - --s; - if (!match(&s,"inity")) - ++s; - word0(&rv) = 0x7ff00000; - word1(&rv) = 0; - goto ret; - } - break; - case 'n': - case 'N': - if (match(&s, "an")) { - word0(&rv) = NAN_WORD0; - word1(&rv) = NAN_WORD1; -#ifndef No_Hex_NaN - if (*s == '(') /*)*/ - hexnan(&rv, &s); -#endif - goto ret; - } - } -#endif /* INFNAN_CHECK */ - ret0: - s = s00; - sign = 0; - } - goto ret; - } - bc.e0 = e1 = e -= nf; - - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - if (!nd0) - nd0 = nd; - k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - dval(&rv) = y; - if (k > 9) { -#ifdef SET_INEXACT - if (k > DBL_DIG) - oldinexact = get_inexact(); -#endif - dval(&rv) = tens[k - 9] * dval(&rv) + z; - } - bd0 = 0; - if (nd <= DBL_DIG -#ifndef RND_PRODQUOT -#ifndef Honor_FLT_ROUNDS - && Flt_Rounds == 1 -#endif -#endif - ) { - if (!e) - goto ret; - if (e > 0) { - if (e <= Ten_pmax) { -#ifdef VAX - goto vax_ovfl_check; -#else -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - rv.d = -rv.d; - sign = 0; - } -#endif - /* rv = */ rounded_product(dval(&rv), tens[e]); - goto ret; -#endif - } - i = DBL_DIG - nd; - if (e <= Ten_pmax + i) { - /* A fancier test would sometimes let us do - * this for larger i values. - */ -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - rv.d = -rv.d; - sign = 0; - } -#endif - e -= i; - dval(&rv) *= tens[i]; -#ifdef VAX - /* VAX exponent range is so narrow we must - * worry about overflow here... - */ - vax_ovfl_check: - word0(&rv) -= P*Exp_msk1; - /* rv = */ rounded_product(dval(&rv), tens[e]); - if ((word0(&rv) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) - goto ovfl; - word0(&rv) += P*Exp_msk1; -#else - /* rv = */ rounded_product(dval(&rv), tens[e]); -#endif - goto ret; - } - } -#ifndef Inaccurate_Divide - else if (e >= -Ten_pmax) { -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - rv.d = -rv.d; - sign = 0; - } -#endif - /* rv = */ rounded_quotient(dval(&rv), tens[-e]); - goto ret; - } -#endif - } - e1 += nd - k; - -#ifdef IEEE_Arith -#ifdef SET_INEXACT - bc.inexact = 1; - if (k <= DBL_DIG) - oldinexact = get_inexact(); -#endif -#ifdef Avoid_Underflow - bc.scale = 0; -#endif -#ifdef Honor_FLT_ROUNDS - if (bc.rounding >= 2) { - if (sign) - bc.rounding = bc.rounding == 2 ? 0 : 2; - else - if (bc.rounding != 2) - bc.rounding = 0; - } -#endif -#endif /*IEEE_Arith*/ - - /* Get starting approximation = rv * 10**e1 */ - - if (e1 > 0) { - i = e1 & 15; - if (i) - dval(&rv) *= tens[i]; - if (e1 &= ~15) { - if (e1 > DBL_MAX_10_EXP) { - ovfl: -#ifndef NO_ERRNO - errno = ERANGE; -#endif - /* Can't trust HUGE_VAL */ -#ifdef IEEE_Arith -#ifdef Honor_FLT_ROUNDS - switch(bc.rounding) { - case 0: /* toward 0 */ - case 3: /* toward -infinity */ - word0(&rv) = Big0; - word1(&rv) = Big1; - break; - default: - word0(&rv) = Exp_mask; - word1(&rv) = 0; - } -#else /*Honor_FLT_ROUNDS*/ - word0(&rv) = Exp_mask; - word1(&rv) = 0; -#endif /*Honor_FLT_ROUNDS*/ -#ifdef SET_INEXACT - /* set overflow bit */ - dval(&rv0) = 1e300; - dval(&rv0) *= dval(&rv0); -#endif -#else /*IEEE_Arith*/ - word0(&rv) = Big0; - word1(&rv) = Big1; -#endif /*IEEE_Arith*/ - goto ret; - } - e1 >>= 4; - for(j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= bigtens[j]; - /* The last multiplication could overflow. */ - word0(&rv) -= P*Exp_msk1; - dval(&rv) *= bigtens[j]; - if ((z = word0(&rv) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-P)) - goto ovfl; - if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { - /* set to largest number */ - /* (Can't trust DBL_MAX) */ - word0(&rv) = Big0; - word1(&rv) = Big1; - } - else - word0(&rv) += P*Exp_msk1; - } - } - else if (e1 < 0) { - e1 = -e1; - i = e1 & 15; - if (i) - dval(&rv) /= tens[i]; - if (e1 >>= 4) { - if (e1 >= 1 << n_bigtens) - goto undfl; -#ifdef Avoid_Underflow - if (e1 & Scale_Bit) - bc.scale = 2*P; - for(j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= tinytens[j]; - if (bc.scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask) - >> Exp_shift)) > 0) { - /* scaled rv is denormal; clear j low bits */ - if (j >= 32) { - word1(&rv) = 0; - if (j >= 53) - word0(&rv) = (P+2)*Exp_msk1; - else - word0(&rv) &= 0xffffffff << (j-32); - } - else - word1(&rv) &= 0xffffffff << j; - } -#else - for(j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(&rv) *= tinytens[j]; - /* The last multiplication could underflow. */ - dval(&rv0) = dval(&rv); - dval(&rv) *= tinytens[j]; - if (!dval(&rv)) { - dval(&rv) = 2.*dval(&rv0); - dval(&rv) *= tinytens[j]; -#endif - if (!dval(&rv)) { - undfl: - dval(&rv) = 0.; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - goto ret; - } -#ifndef Avoid_Underflow - word0(&rv) = Tiny0; - word1(&rv) = Tiny1; - /* The refinement below will clean - * this approximation up. - */ - } -#endif - } - } - - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - - bc.nd = nd; -#ifndef NO_STRTOD_BIGCOMP - bc.nd0 = nd0; /* Only needed if nd > strtod_diglim, but done here */ - /* to silence an erroneous warning about bc.nd0 */ - /* possibly not being initialized. */ - if (nd > strtod_diglim) { - /* ASSERT(strtod_diglim >= 18); 18 == one more than the */ - /* minimum number of decimal digits to distinguish double values */ - /* in IEEE arithmetic. */ - i = j = 18; - if (i > nd0) - j += bc.dplen; - for(;;) { - if (--j <= bc.dp1 && j >= bc.dp0) - j = bc.dp0 - 1; - if (s0[j] != '0') - break; - --i; - } - e += nd - i; - nd = i; - if (nd0 > nd) - nd0 = nd; - if (nd < 9) { /* must recompute y */ - y = 0; - for(i = 0; i < nd0; ++i) - y = 10*y + s0[i] - '0'; - for(j = bc.dp1; i < nd; ++i) - y = 10*y + s0[j++] - '0'; - } - } -#endif - bd0 = s2b(s0, nd0, nd, y, bc.dplen); - - for(;;) { - bd = Balloc(bd0->k); - Bcopy(bd, bd0); - bb = d2b(&rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ - bs = i2b(1); - - if (e >= 0) { - bb2 = bb5 = 0; - bd2 = bd5 = e; - } - else { - bb2 = bb5 = -e; - bd2 = bd5 = 0; - } - if (bbe >= 0) - bb2 += bbe; - else - bd2 -= bbe; - bs2 = bb2; -#ifdef Honor_FLT_ROUNDS - if (bc.rounding != 1) - bs2++; -#endif -#ifdef Avoid_Underflow - j = bbe - bc.scale; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; -#else /*Avoid_Underflow*/ -#ifdef Sudden_Underflow -#ifdef IBM - j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); -#else - j = P + 1 - bbbits; -#endif -#else /*Sudden_Underflow*/ - j = bbe; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - bb2 += j; - bd2 += j; -#ifdef Avoid_Underflow - bd2 += bc.scale; -#endif - i = bb2 < bd2 ? bb2 : bd2; - if (i > bs2) - i = bs2; - if (i > 0) { - bb2 -= i; - bd2 -= i; - bs2 -= i; - } - if (bb5 > 0) { - bs = pow5mult(bs, bb5); - bb1 = mult(bs, bb); - Bfree(bb); - bb = bb1; - } - if (bb2 > 0) - bb = lshift(bb, bb2); - if (bd5 > 0) - bd = pow5mult(bd, bd5); - if (bd2 > 0) - bd = lshift(bd, bd2); - if (bs2 > 0) - bs = lshift(bs, bs2); - delta = diff(bb, bd); - bc.dsign = delta->sign; - delta->sign = 0; - i = cmp(delta, bs); -#ifndef NO_STRTOD_BIGCOMP - if (bc.nd > nd && i <= 0) { - if (bc.dsign) - break; /* Must use bigcomp(). */ -#ifdef Honor_FLT_ROUNDS - if (bc.rounding != 1) { - if (i < 0) - break; - } - else -#endif - { - bc.nd = nd; - i = -1; /* Discarded digits make delta smaller. */ - } - } -#endif -#ifdef Honor_FLT_ROUNDS - if (bc.rounding != 1) { - if (i < 0) { - /* Error is less than an ulp */ - if (!delta->x[0] && delta->wds <= 1) { - /* exact */ -#ifdef SET_INEXACT - bc.inexact = 0; -#endif - break; - } - if (bc.rounding) { - if (bc.dsign) { - adj.d = 1.; - goto apply_adj; - } - } - else if (!bc.dsign) { - adj.d = -1.; - if (!word1(&rv) - && !(word0(&rv) & Frac_mask)) { - y = word0(&rv) & Exp_mask; -#ifdef Avoid_Underflow - if (!bc.scale || y > 2*P*Exp_msk1) -#else - if (y) -#endif - { - delta = lshift(delta,Log2P); - if (cmp(delta, bs) <= 0) - adj.d = -0.5; - } - } - apply_adj: -#ifdef Avoid_Underflow - if (bc.scale && (y = word0(&rv) & Exp_mask) - <= 2*P*Exp_msk1) - word0(&adj) += (2*P+1)*Exp_msk1 - y; -#else -#ifdef Sudden_Underflow - if ((word0(&rv) & Exp_mask) <= - P*Exp_msk1) { - word0(&rv) += P*Exp_msk1; - dval(&rv) += adj.d*ulp(dval(&rv)); - word0(&rv) -= P*Exp_msk1; - } - else -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - dval(&rv) += adj.d*ulp(&rv); - } - break; - } - adj.d = ratio(delta, bs); - if (adj.d < 1.) - adj.d = 1.; - if (adj.d <= 0x7ffffffe) { - /* adj = rounding ? ceil(adj) : floor(adj); */ - y = adj.d; - if (y != adj.d) { - if (!((bc.rounding>>1) ^ bc.dsign)) - y++; - adj.d = y; - } - } -#ifdef Avoid_Underflow - if (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) - word0(&adj) += (2*P+1)*Exp_msk1 - y; -#else -#ifdef Sudden_Underflow - if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { - word0(&rv) += P*Exp_msk1; - adj.d *= ulp(dval(&rv)); - if (bc.dsign) - dval(&rv) += adj.d; - else - dval(&rv) -= adj.d; - word0(&rv) -= P*Exp_msk1; - goto cont; - } -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - adj.d *= ulp(&rv); - if (bc.dsign) { - if (word0(&rv) == Big0 && word1(&rv) == Big1) - goto ovfl; - dval(&rv) += adj.d; - } - else - dval(&rv) -= adj.d; - goto cont; - } -#endif /*Honor_FLT_ROUNDS*/ - - if (i < 0) { - /* Error is less than half an ulp -- check for - * special case of mantissa a power of two. - */ - if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask -#ifdef IEEE_Arith -#ifdef Avoid_Underflow - || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 -#else - || (word0(&rv) & Exp_mask) <= Exp_msk1 -#endif -#endif - ) { -#ifdef SET_INEXACT - if (!delta->x[0] && delta->wds <= 1) - bc.inexact = 0; -#endif - break; - } - if (!delta->x[0] && delta->wds <= 1) { - /* exact result */ -#ifdef SET_INEXACT - bc.inexact = 0; -#endif - break; - } - delta = lshift(delta,Log2P); - if (cmp(delta, bs) > 0) - goto drop_down; - break; - } - if (i == 0) { - /* exactly half-way between */ - if (bc.dsign) { - if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 - && word1(&rv) == ( -#ifdef Avoid_Underflow - (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) - ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : -#endif - 0xffffffff)) { - /*boundary case -- increment exponent*/ - word0(&rv) = (word0(&rv) & Exp_mask) - + Exp_msk1 -#ifdef IBM - | Exp_msk1 >> 4 -#endif - ; - word1(&rv) = 0; -#ifdef Avoid_Underflow - bc.dsign = 0; -#endif - break; - } - } - else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { - drop_down: - /* boundary case -- decrement exponent */ -#ifdef Sudden_Underflow /*{{*/ - L = word0(&rv) & Exp_mask; -#ifdef IBM - if (L < Exp_msk1) -#else -#ifdef Avoid_Underflow - if (L <= (bc.scale ? (2*P+1)*Exp_msk1 : Exp_msk1)) -#else - if (L <= Exp_msk1) -#endif /*Avoid_Underflow*/ -#endif /*IBM*/ - { - if (bc.nd >nd) { - bc.uflchk = 1; - break; - } - goto undfl; - } - L -= Exp_msk1; -#else /*Sudden_Underflow}{*/ -#ifdef Avoid_Underflow - if (bc.scale) { - L = word0(&rv) & Exp_mask; - if (L <= (2*P+1)*Exp_msk1) { - if (L > (P+2)*Exp_msk1) - /* round even ==> */ - /* accept rv */ - break; - /* rv = smallest denormal */ - if (bc.nd >nd) { - bc.uflchk = 1; - break; - } - goto undfl; - } - } -#endif /*Avoid_Underflow*/ - L = (word0(&rv) & Exp_mask) - Exp_msk1; -#endif /*Sudden_Underflow}}*/ - word0(&rv) = L | Bndry_mask1; - word1(&rv) = 0xffffffff; -#ifdef IBM - goto cont; -#else - break; -#endif - } -#ifndef ROUND_BIASED - if (!(word1(&rv) & LSB)) - break; -#endif - if (bc.dsign) - dval(&rv) += ulp(&rv); -#ifndef ROUND_BIASED - else { - dval(&rv) -= ulp(&rv); -#ifndef Sudden_Underflow - if (!dval(&rv)) { - if (bc.nd >nd) { - bc.uflchk = 1; - break; - } - goto undfl; - } -#endif - } -#ifdef Avoid_Underflow - bc.dsign = 1 - bc.dsign; -#endif -#endif - break; - } - if ((aadj = ratio(delta, bs)) <= 2.) { - if (bc.dsign) - aadj = aadj1 = 1.; - else if (word1(&rv) || word0(&rv) & Bndry_mask) { -#ifndef Sudden_Underflow - if (word1(&rv) == Tiny1 && !word0(&rv)) { - if (bc.nd >nd) { - bc.uflchk = 1; - break; - } - goto undfl; - } -#endif - aadj = 1.; - aadj1 = -1.; - } - else { - /* special case -- power of FLT_RADIX to be */ - /* rounded down... */ - - if (aadj < 2./FLT_RADIX) - aadj = 1./FLT_RADIX; - else - aadj *= 0.5; - aadj1 = -aadj; - } - } - else { - aadj *= 0.5; - aadj1 = bc.dsign ? aadj : -aadj; -#ifdef Check_FLT_ROUNDS - switch(bc.rounding) { - case 2: /* towards +infinity */ - aadj1 -= 0.5; - break; - case 0: /* towards 0 */ - case 3: /* towards -infinity */ - aadj1 += 0.5; - } -#else - if (Flt_Rounds == 0) - aadj1 += 0.5; -#endif /*Check_FLT_ROUNDS*/ - } - y = word0(&rv) & Exp_mask; - - /* Check for overflow */ - - if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { - dval(&rv0) = dval(&rv); - word0(&rv) -= P*Exp_msk1; - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; - if ((word0(&rv) & Exp_mask) >= - Exp_msk1*(DBL_MAX_EXP+Bias-P)) { - if (word0(&rv0) == Big0 && word1(&rv0) == Big1) - goto ovfl; - word0(&rv) = Big0; - word1(&rv) = Big1; - goto cont; - } - else - word0(&rv) += P*Exp_msk1; - } - else { -#ifdef Avoid_Underflow - if (bc.scale && y <= 2*P*Exp_msk1) { - if (aadj <= 0x7fffffff) { - if ((z = (ULong)aadj) <= 0) - z = 1; - aadj = z; - aadj1 = bc.dsign ? aadj : -aadj; - } - dval(&aadj2) = aadj1; - word0(&aadj2) += (2*P+1)*Exp_msk1 - y; - aadj1 = dval(&aadj2); - } - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; -#else -#ifdef Sudden_Underflow - if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { - dval(&rv0) = dval(&rv); - word0(&rv) += P*Exp_msk1; - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; -#ifdef IBM - if ((word0(&rv) & Exp_mask) < P*Exp_msk1) -#else - if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) -#endif - { - if (word0(&rv0) == Tiny0 - && word1(&rv0) == Tiny1) { - if (bc.nd >nd) { - bc.uflchk = 1; - break; - } - goto undfl; - } - word0(&rv) = Tiny0; - word1(&rv) = Tiny1; - goto cont; - } - else - word0(&rv) -= P*Exp_msk1; - } - else { - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; - } -#else /*Sudden_Underflow*/ - /* Compute adj so that the IEEE rounding rules will - * correctly round rv + adj in some half-way cases. - * If rv * ulp(rv) is denormalized (i.e., - * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid - * trouble from bits lost to denormalization; - * example: 1.2e-307 . - */ - if (y <= (P-1)*Exp_msk1 && aadj > 1.) { - aadj1 = (double)(int)(aadj + 0.5); - if (!bc.dsign) - aadj1 = -aadj1; - } - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - } - z = word0(&rv) & Exp_mask; -#ifndef SET_INEXACT - if (bc.nd == nd) { -#ifdef Avoid_Underflow - if (!bc.scale) -#endif - if (y == z) { - /* Can we stop now? */ - L = (Long)aadj; - aadj -= L; - /* The tolerances below are conservative. */ - if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask) { - if (aadj < .4999999 || aadj > .5000001) - break; - } - else if (aadj < .4999999/FLT_RADIX) - break; - } - } -#endif - cont: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); - } - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); -#ifndef NO_STRTOD_BIGCOMP - if (bc.nd > nd) - bigcomp(&rv, s0, &bc); -#endif -#ifdef SET_INEXACT - if (bc.inexact) { - if (!oldinexact) { - word0(&rv0) = Exp_1 + (70 << Exp_shift); - word1(&rv0) = 0; - dval(&rv0) += 1.; - } - } - else if (!oldinexact) - clear_inexact(); -#endif -#ifdef Avoid_Underflow - if (bc.scale) { - word0(&rv0) = Exp_1 - 2*P*Exp_msk1; - word1(&rv0) = 0; - dval(&rv) *= dval(&rv0); -#ifndef NO_ERRNO - /* try to avoid the bug of testing an 8087 register value */ -#ifdef IEEE_Arith - if (!(word0(&rv) & Exp_mask)) -#else - if (word0(&rv) == 0 && word1(&rv) == 0) -#endif - errno = ERANGE; -#endif - } -#endif /* Avoid_Underflow */ -#ifdef SET_INEXACT - if (bc.inexact && !(word0(&rv) & Exp_mask)) { - /* set underflow bit */ - dval(&rv0) = 1e-300; - dval(&rv0) *= dval(&rv0); - } -#endif - ret: - if (se) - *se = (char *)s; - return sign ? -dval(&rv) : dval(&rv); - } - -#ifndef MULTIPLE_THREADS - static char *dtoa_result; -#endif - - static char * -#ifdef KR_headers -rv_alloc(i) int i; -#else -rv_alloc(int i) -#endif -{ - int j, k, *r; - - j = sizeof(ULong); - for(k = 0; - sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)i; - j <<= 1) - k++; - r = (int*)Balloc(k); - *r = k; - return -#ifndef MULTIPLE_THREADS - dtoa_result = -#endif - (char *)(r+1); - } - - static char * -#ifdef KR_headers -nrv_alloc(s, rve, n) char *s, **rve; int n; -#else -nrv_alloc(CONST char *s, char **rve, int n) -#endif -{ - char *rv, *t; - - t = rv = rv_alloc(n); - for(*t = *s++; *t; *t = *s++) t++; - if (rve) - *rve = t; - return rv; - } - -/* freedtoa(s) must be used to free values s returned by dtoa - * when MULTIPLE_THREADS is #defined. It should be used in all cases, - * but for consistency with earlier versions of dtoa, it is optional - * when MULTIPLE_THREADS is not defined. - */ - - void -#ifdef KR_headers -freedtoa(s) char *s; -#else -freedtoa(char *s) -#endif -{ - Bigint *b = (Bigint *)((int *)s - 1); - b->maxwds = 1 << (b->k = *(int*)b); - Bfree(b); -#ifndef MULTIPLE_THREADS - if (s == dtoa_result) - dtoa_result = 0; -#endif - } - -/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - * - * Inspired by "How to Print Floating-Point Numbers Accurately" by - * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. - * - * Modifications: - * 1. Rather than iterating, we use a simple numeric overestimate - * to determine k = floor(log10(d)). We scale relevant - * quantities using O(log2(k)) rather than O(k) multiplications. - * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - * try to generate digits strictly left to right. Instead, we - * compute with fewer bits and propagate the carry if necessary - * when rounding the final digit up. This is often faster. - * 3. Under the assumption that input will be rounded nearest, - * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - * That is, we allow equality in stopping tests when the - * round-nearest rule will give the same floating-point value - * as would satisfaction of the stopping test with strict - * inequality. - * 4. We remove common factors of powers of 2 from relevant - * quantities. - * 5. When converting floating-point integers less than 1e16, - * we use floating-point arithmetic rather than resorting - * to multiple-precision integers. - * 6. When asked to produce fewer than 15 digits, we first try - * to get by with floating-point arithmetic; we resort to - * multiple-precision integer arithmetic only if we cannot - * guarantee that the floating-point calculation has given - * the correctly rounded result. For k requested digits and - * "uniformly" distributed input, the probability is - * something like 10^(k-15) that we must resort to the Long - * calculation. - */ - - char * -dtoa -#ifdef KR_headers - (dd, mode, ndigits, decpt, sign, rve) - double dd; int mode, ndigits, *decpt, *sign; char **rve; -#else - (double dd, int mode, int ndigits, int *decpt, int *sign, char **rve) -#endif -{ - /* Arguments ndigits, decpt, sign are similar to those - of ecvt and fcvt; trailing zeros are suppressed from - the returned string. If not null, *rve is set to point - to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to 9999. - - mode: - 0 ==> shortest string that yields d when read in - and rounded to nearest. - 1 ==> like 0, but with Steele & White stopping rule; - e.g. with IEEE P754 arithmetic , mode 0 gives - 1e23 whereas mode 1 gives 9.999999999999999e22. - 2 ==> max(1,ndigits) significant digits. This gives a - return value similar to that of ecvt, except - that trailing zeros are suppressed. - 3 ==> through ndigits past the decimal point. This - gives a return value similar to that from fcvt, - except that trailing zeros are suppressed, and - ndigits can be negative. - 4,5 ==> similar to 2 and 3, respectively, but (in - round-nearest mode) with the tests of mode 0 to - possibly return a shorter string that rounds to d. - With IEEE arithmetic and compilation with - -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same - as modes 2 and 3 when FLT_ROUNDS != 1. - 6-9 ==> Debugging modes similar to mode - 4: don't try - fast floating-point estimate (if applicable). - - Values of mode other than 0-9 are treated as mode 0. - - Sufficient space is allocated to the return value - to hold the suppressed trailing zeros. - */ - - int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, - j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, - spec_case, try_quick; - Long L; -#ifndef Sudden_Underflow - int denorm; - ULong x; -#endif - Bigint *b, *b1, *delta, *mlo = NULL, *mhi, *S; - U d2, eps, u; - double ds; - char *s, *s0; -#ifdef SET_INEXACT - int inexact, oldinexact; -#endif -#ifdef Honor_FLT_ROUNDS /*{*/ - int Rounding; -#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ - Rounding = Flt_Rounds; -#else /*}{*/ - Rounding = 1; - switch(fegetround()) { - case FE_TOWARDZERO: Rounding = 0; break; - case FE_UPWARD: Rounding = 2; break; - case FE_DOWNWARD: Rounding = 3; - } -#endif /*}}*/ -#endif /*}*/ - -#ifndef MULTIPLE_THREADS - if (dtoa_result) { - freedtoa(dtoa_result); - dtoa_result = 0; - } -#endif - - u.d = dd; - if (word0(&u) & Sign_bit) { - /* set sign for everything, including 0's and NaNs */ - *sign = 1; - word0(&u) &= ~Sign_bit; /* clear sign bit */ - } - else - *sign = 0; - -#if defined(IEEE_Arith) + defined(VAX) -#ifdef IEEE_Arith - if ((word0(&u) & Exp_mask) == Exp_mask) -#else - if (word0(&u) == 0x8000) -#endif - { - /* Infinity or NaN */ - *decpt = 9999; -#ifdef IEEE_Arith - if (!word1(&u) && !(word0(&u) & 0xfffff)) - return nrv_alloc("Infinity", rve, 8); -#endif - return nrv_alloc("NaN", rve, 3); - } -#endif -#ifdef IBM - dval(&u) += 0; /* normalize */ -#endif - if (!dval(&u)) { - *decpt = 1; - return nrv_alloc("0", rve, 1); - } - -#ifdef SET_INEXACT - try_quick = oldinexact = get_inexact(); - inexact = 1; -#endif -#ifdef Honor_FLT_ROUNDS - if (Rounding >= 2) { - if (*sign) - Rounding = Rounding == 2 ? 0 : 2; - else - if (Rounding != 2) - Rounding = 0; - } -#endif - - b = d2b(&u, &be, &bbits); - i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); -#ifndef Sudden_Underflow - if (i) { -#endif - dval(&d2) = dval(&u); - word0(&d2) &= Frac_mask1; - word0(&d2) |= Exp_11; -#ifdef IBM - if (j = 11 - hi0bits(word0(&d2) & Frac_mask)) - dval(&d2) /= 1 << j; -#endif - - /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 - * log10(x) = log(x) / log(10) - * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) - * - * This suggests computing an approximation k to log10(d) by - * - * k = (i - Bias)*0.301029995663981 - * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - * - * We want k to be too large rather than too small. - * The error in the first-order Taylor series approximation - * is in our favor, so we just round up the constant enough - * to compensate for any error in the multiplication of - * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - * adding 1e-13 to the constant term more than suffices. - * Hence we adjust the constant term to 0.1760912590558. - * (We could get a more accurate k by invoking log10, - * but this is probably not worthwhile.) - */ - - i -= Bias; -#ifdef IBM - i <<= 2; - i += j; -#endif -#ifndef Sudden_Underflow - denorm = 0; - } - else { - /* d is denormalized */ - - i = bbits + be + (Bias + (P-1) - 1); - x = i > 32 ? word0(&u) << (64 - i) | word1(&u) >> (i - 32) - : word1(&u) << (32 - i); - dval(&d2) = x; - word0(&d2) -= 31*Exp_msk1; /* adjust exponent */ - i -= (Bias + (P-1) - 1) + 1; - denorm = 1; - } -#endif - ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; - k = (int)ds; - if (ds < 0. && ds != k) - k--; /* want k = floor(ds) */ - k_check = 1; - if (k >= 0 && k <= Ten_pmax) { - if (dval(&u) < tens[k]) - k--; - k_check = 0; - } - j = bbits - i - 1; - if (j >= 0) { - b2 = 0; - s2 = j; - } - else { - b2 = -j; - s2 = 0; - } - if (k >= 0) { - b5 = 0; - s5 = k; - s2 += k; - } - else { - b2 -= k; - b5 = -k; - s5 = 0; - } - if (mode < 0 || mode > 9) - mode = 0; - -#ifndef SET_INEXACT -#ifdef Check_FLT_ROUNDS - try_quick = Rounding == 1; -#else - try_quick = 1; -#endif -#endif /*SET_INEXACT*/ - - if (mode > 5) { - mode -= 4; - try_quick = 0; - } - leftright = 1; - ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ - /* silence erroneous "gcc -Wall" warning. */ - switch(mode) { - case 0: - case 1: - i = 18; - ndigits = 0; - break; - case 2: - leftright = 0; - /* no break */ - case 4: - if (ndigits <= 0) - ndigits = 1; - ilim = ilim1 = i = ndigits; - break; - case 3: - leftright = 0; - /* no break */ - case 5: - i = ndigits + k + 1; - ilim = i; - ilim1 = i - 1; - if (i <= 0) - i = 1; - } - s = s0 = rv_alloc(i); - -#ifdef Honor_FLT_ROUNDS - if (mode > 1 && Rounding != 1) - leftright = 0; -#endif - - if (ilim >= 0 && ilim <= Quick_max && try_quick) { - - /* Try to get by with floating-point arithmetic. */ - - i = 0; - dval(&d2) = dval(&u); - k0 = k; - ilim0 = ilim; - ieps = 2; /* conservative */ - if (k > 0) { - ds = tens[k&0xf]; - j = k >> 4; - if (j & Bletch) { - /* prevent overflows */ - j &= Bletch - 1; - dval(&u) /= bigtens[n_bigtens-1]; - ieps++; - } - for(; j; j >>= 1, i++) - if (j & 1) { - ieps++; - ds *= bigtens[i]; - } - dval(&u) /= ds; - } - else { - j1 = -k; - if (j1) { - dval(&u) *= tens[j1 & 0xf]; - for(j = j1 >> 4; j; j >>= 1, i++) - if (j & 1) { - ieps++; - dval(&u) *= bigtens[i]; - } - } - } - if (k_check && dval(&u) < 1. && ilim > 0) { - if (ilim1 <= 0) - goto fast_failed; - ilim = ilim1; - k--; - dval(&u) *= 10.; - ieps++; - } - dval(&eps) = ieps*dval(&u) + 7.; - word0(&eps) -= (P-1)*Exp_msk1; - if (ilim == 0) { - S = mhi = 0; - dval(&u) -= 5.; - if (dval(&u) > dval(&eps)) - goto one_digit; - if (dval(&u) < -dval(&eps)) - goto no_digits; - goto fast_failed; - } -#ifndef No_leftright - if (leftright) { - /* Use Steele & White method of only - * generating digits needed. - */ - dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); - for(i = 0;;) { - L = (long)dval(&u); - dval(&u) -= L; - *s++ = '0' + (char)L; - if (dval(&u) < dval(&eps)) - goto ret1; - if (1. - dval(&u) < dval(&eps)) - goto bump_up; - if (++i >= ilim) - break; - dval(&eps) *= 10.; - dval(&u) *= 10.; - } - } - else { -#endif - /* Generate ilim digits, then fix them up. */ - dval(&eps) *= tens[ilim-1]; - for(i = 1;; i++, dval(&u) *= 10.) { - L = (Long)(dval(&u)); - if (!(dval(&u) -= L)) - ilim = i; - *s++ = '0' + (char)L; - if (i == ilim) { - if (dval(&u) > 0.5 + dval(&eps)) - goto bump_up; - else if (dval(&u) < 0.5 - dval(&eps)) { - while(*--s == '0') {} - s++; - goto ret1; - } - break; - } - } -#ifndef No_leftright - } -#endif - fast_failed: - s = s0; - dval(&u) = dval(&d2); - k = k0; - ilim = ilim0; - } - - /* Do we have a "small" integer? */ - - if (be >= 0 && k <= Int_max) { - /* Yes. */ - ds = tens[k]; - if (ndigits < 0 && ilim <= 0) { - S = mhi = 0; - if (ilim < 0 || dval(&u) <= 5*ds) - goto no_digits; - goto one_digit; - } - for(i = 1; i <= k + 1; i++, dval(&u) *= 10.) { - L = (Long)(dval(&u) / ds); - dval(&u) -= L*ds; -#ifdef Check_FLT_ROUNDS - /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(&u) < 0) { - L--; - dval(&u) += ds; - } -#endif - *s++ = '0' + (char)L; - if (!dval(&u)) { -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - if (i == ilim) { -#ifdef Honor_FLT_ROUNDS - if (mode > 1) - switch(Rounding) { - case 0: goto ret1; - case 2: goto bump_up; - } -#endif - dval(&u) += dval(&u); - if (dval(&u) > ds || (dval(&u) == ds && L & 1)) { - bump_up: - while(*--s == '9') - if (s == s0) { - k++; - *s = '0'; - break; - } - ++*s++; - } - break; - } - } - goto ret1; - } - - m2 = b2; - m5 = b5; - mhi = mlo = 0; - if (leftright) { - i = -#ifndef Sudden_Underflow - denorm ? be + (Bias + (P-1) - 1 + 1) : -#endif -#ifdef IBM - 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); -#else - 1 + P - bbits; -#endif - b2 += i; - s2 += i; - mhi = i2b(1); - } - if (m2 > 0 && s2 > 0) { - i = m2 < s2 ? m2 : s2; - b2 -= i; - m2 -= i; - s2 -= i; - } - if (b5 > 0) { - if (leftright) { - if (m5 > 0) { - mhi = pow5mult(mhi, m5); - b1 = mult(mhi, b); - Bfree(b); - b = b1; - } - j = b5 - m5; - if (j) - b = pow5mult(b, j); - } - else - b = pow5mult(b, b5); - } - S = i2b(1); - if (s5 > 0) - S = pow5mult(S, s5); - - /* Check for special case that d is a normalized power of 2. */ - - spec_case = 0; - if ((mode < 2 || leftright) -#ifdef Honor_FLT_ROUNDS - && Rounding == 1 -#endif - ) { - if (!word1(&u) && !(word0(&u) & Bndry_mask) -#ifndef Sudden_Underflow - && word0(&u) & (Exp_mask & ~Exp_msk1) -#endif - ) { - /* The special case */ - b2 += Log2P; - s2 += Log2P; - spec_case = 1; - } - } - - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - * - * Perhaps we should just compute leading 28 bits of S once - * and for all and pass them and a shift to quorem, so it - * can do shifts and ors to compute the numerator for q. - */ -#ifdef Pack_32 - i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f; - if (i) - i = 32 - i; -#define iInc 28 -#else - if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) - i = 16 - i; -#define iInc 12 -#endif - i = dshift(S, s2); - b2 += i; - m2 += i; - s2 += i; - if (b2 > 0) - b = lshift(b, b2); - if (s2 > 0) - S = lshift(S, s2); - if (k_check) { - if (cmp(b,S) < 0) { - k--; - b = multadd(b, 10, 0); /* we botched the k estimate */ - if (leftright) - mhi = multadd(mhi, 10, 0); - ilim = ilim1; - } - } - if (ilim <= 0 && (mode == 3 || mode == 5)) { - if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { - /* no digits, fcvt style */ - no_digits: - k = -1 - ndigits; - goto ret; - } - one_digit: - *s++ = '1'; - k++; - goto ret; - } - if (leftright) { - if (m2 > 0) - mhi = lshift(mhi, m2); - - /* Compute mlo -- check for special case - * that d is a normalized power of 2. - */ - - mlo = mhi; - if (spec_case) { - mhi = Balloc(mhi->k); - Bcopy(mhi, mlo); - mhi = lshift(mhi, Log2P); - } - - for(i = 1;;i++) { - dig = quorem(b,S) + '0'; - /* Do we yet have the shortest decimal string - * that will round to d? - */ - j = cmp(b, mlo); - delta = diff(S, mhi); - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); -#ifndef ROUND_BIASED - if (j1 == 0 && mode != 1 && !(word1(&u) & 1) -#ifdef Honor_FLT_ROUNDS - && Rounding >= 1 -#endif - ) { - if (dig == '9') - goto round_9_up; - if (j > 0) - dig++; -#ifdef SET_INEXACT - else if (!b->x[0] && b->wds <= 1) - inexact = 0; -#endif - *s++ = (char)dig; - goto ret; - } -#endif - if (j < 0 || (j == 0 && mode != 1 -#ifndef ROUND_BIASED - && !(word1(&u) & 1) -#endif - )) { - if (!b->x[0] && b->wds <= 1) { -#ifdef SET_INEXACT - inexact = 0; -#endif - goto accept_dig; - } -#ifdef Honor_FLT_ROUNDS - if (mode > 1) - switch(Rounding) { - case 0: goto accept_dig; - case 2: goto keep_dig; - } -#endif /*Honor_FLT_ROUNDS*/ - if (j1 > 0) { - b = lshift(b, 1); - j1 = cmp(b, S); - if ((j1 > 0 || (j1 == 0 && dig & 1)) - && dig++ == '9') - goto round_9_up; - } - accept_dig: - *s++ = (char)dig; - goto ret; - } - if (j1 > 0) { -#ifdef Honor_FLT_ROUNDS - if (!Rounding) - goto accept_dig; -#endif - if (dig == '9') { /* possible if i == 1 */ - round_9_up: - *s++ = '9'; - goto roundoff; - } - *s++ = (char)dig + 1; - goto ret; - } -#ifdef Honor_FLT_ROUNDS - keep_dig: -#endif - *s++ = (char)dig; - if (i == ilim) - break; - b = multadd(b, 10, 0); - if (mlo == mhi) - mlo = mhi = multadd(mhi, 10, 0); - else { - mlo = multadd(mlo, 10, 0); - mhi = multadd(mhi, 10, 0); - } - } - } - else - for(i = 1;; i++) { - dig = quorem(b,S) + '0'; - *s++ = (char)dig; - if (!b->x[0] && b->wds <= 1) { -#ifdef SET_INEXACT - inexact = 0; -#endif - goto ret; - } - if (i >= ilim) - break; - b = multadd(b, 10, 0); - } - - /* Round off last digit */ - -#ifdef Honor_FLT_ROUNDS - switch(Rounding) { - case 0: goto trimzeros; - case 2: goto roundoff; - } -#endif - b = lshift(b, 1); - j = cmp(b, S); - if (j > 0 || (j == 0 && dig & 1)) { - roundoff: - while(*--s == '9') - if (s == s0) { - k++; - *s++ = '1'; - goto ret; - } - ++*s++; - } - else { -#ifdef Honor_FLT_ROUNDS - trimzeros: -#endif - while(*--s == '0') {} - s++; - } - ret: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } - ret1: -#ifdef SET_INEXACT - if (inexact) { - if (!oldinexact) { - word0(&u) = Exp_1 + (70 << Exp_shift); - word1(&u) = 0; - dval(&u) += 1.; - } - } - else if (!oldinexact) - clear_inexact(); -#endif - Bfree(b); - *s = 0; - *decpt = k + 1; - if (rve) - *rve = s; - return s0; - } - -} // namespace dmg_fp diff --git a/security/sandbox/chromium/base/third_party/dmg_fp/g_fmt.cc b/security/sandbox/chromium/base/third_party/dmg_fp/g_fmt.cc deleted file mode 100644 index bfa358d15..000000000 --- a/security/sandbox/chromium/base/third_party/dmg_fp/g_fmt.cc +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 1996 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ - -/* g_fmt(buf,x) stores the closest decimal approximation to x in buf; - * it suffices to declare buf - * char buf[32]; - */ - -#include "dmg_fp.h" - -namespace dmg_fp { - - char * -g_fmt(register char *b, double x) -{ - register int i, k; - register char *s; - int decpt, j, sign; - char *b0, *s0, *se; - - b0 = b; -#ifdef IGNORE_ZERO_SIGN - if (!x) { - *b++ = '0'; - *b = 0; - goto done; - } -#endif - s = s0 = dtoa(x, 0, 0, &decpt, &sign, &se); - if (sign) - *b++ = '-'; - if (decpt == 9999) /* Infinity or Nan */ { - for(*b = *s++; *b++; *b = *s++) {} - goto done0; - } - if (decpt <= -4 || decpt > se - s + 5) { - *b++ = *s++; - if (*s) { - *b++ = '.'; - for(*b = *s++; *b; *b = *s++) - b++; - } - *b++ = 'e'; - /* sprintf(b, "%+.2d", decpt - 1); */ - if (--decpt < 0) { - *b++ = '-'; - decpt = -decpt; - } - else - *b++ = '+'; - for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10) {} - for(;;) { - i = decpt / k; - *b++ = (char)i + '0'; - if (--j <= 0) - break; - decpt -= i*k; - decpt *= 10; - } - *b = 0; - } - else if (decpt <= 0) { - *b++ = '.'; - for(; decpt < 0; decpt++) - *b++ = '0'; - for(*b = *s++; *b++; *b = *s++) {} - } - else { - for(*b = *s++; *b; *b = *s++) { - b++; - if (--decpt == 0 && *s) - *b++ = '.'; - } - for(; decpt > 0; decpt--) - *b++ = '0'; - *b = 0; - } - done0: - freedtoa(s0); -#ifdef IGNORE_ZERO_SIGN - done: -#endif - return b0; - } - -} // namespace dmg_fp diff --git a/security/sandbox/chromium/base/third_party/dynamic_annotations/LICENSE b/security/sandbox/chromium/base/third_party/dynamic_annotations/LICENSE deleted file mode 100644 index 5c581a939..000000000 --- a/security/sandbox/chromium/base/third_party/dynamic_annotations/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (c) 2008-2009, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * --- - * Author: Kostya Serebryany - */ diff --git a/security/sandbox/chromium/base/third_party/dynamic_annotations/dynamic_annotations.h b/security/sandbox/chromium/base/third_party/dynamic_annotations/dynamic_annotations.h deleted file mode 100644 index 8d7f05202..000000000 --- a/security/sandbox/chromium/base/third_party/dynamic_annotations/dynamic_annotations.h +++ /dev/null @@ -1,595 +0,0 @@ -/* Copyright (c) 2011, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* This file defines dynamic annotations for use with dynamic analysis - tool such as valgrind, PIN, etc. - - Dynamic annotation is a source code annotation that affects - the generated code (that is, the annotation is not a comment). - Each such annotation is attached to a particular - instruction and/or to a particular object (address) in the program. - - The annotations that should be used by users are macros in all upper-case - (e.g., ANNOTATE_NEW_MEMORY). - - Actual implementation of these macros may differ depending on the - dynamic analysis tool being used. - - See http://code.google.com/p/data-race-test/ for more information. - - This file supports the following dynamic analysis tools: - - None (DYNAMIC_ANNOTATIONS_ENABLED is not defined or zero). - Macros are defined empty. - - ThreadSanitizer, Helgrind, DRD (DYNAMIC_ANNOTATIONS_ENABLED is 1). - Macros are defined as calls to non-inlinable empty functions - that are intercepted by Valgrind. */ - -#ifndef __DYNAMIC_ANNOTATIONS_H__ -#define __DYNAMIC_ANNOTATIONS_H__ - -#ifndef DYNAMIC_ANNOTATIONS_PREFIX -# define DYNAMIC_ANNOTATIONS_PREFIX -#endif - -#ifndef DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND -# define DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND 1 -#endif - -#ifdef DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK -# ifdef __GNUC__ -# define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK __attribute__((weak)) -# else -/* TODO(glider): for Windows support we may want to change this macro in order - to prepend __declspec(selectany) to the annotations' declarations. */ -# error weak annotations are not supported for your compiler -# endif -#else -# define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK -#endif - -/* The following preprocessor magic prepends the value of - DYNAMIC_ANNOTATIONS_PREFIX to annotation function names. */ -#define DYNAMIC_ANNOTATIONS_GLUE0(A, B) A##B -#define DYNAMIC_ANNOTATIONS_GLUE(A, B) DYNAMIC_ANNOTATIONS_GLUE0(A, B) -#define DYNAMIC_ANNOTATIONS_NAME(name) \ - DYNAMIC_ANNOTATIONS_GLUE(DYNAMIC_ANNOTATIONS_PREFIX, name) - -#ifndef DYNAMIC_ANNOTATIONS_ENABLED -# define DYNAMIC_ANNOTATIONS_ENABLED 0 -#endif - -#if DYNAMIC_ANNOTATIONS_ENABLED != 0 - - /* ------------------------------------------------------------- - Annotations useful when implementing condition variables such as CondVar, - using conditional critical sections (Await/LockWhen) and when constructing - user-defined synchronization mechanisms. - - The annotations ANNOTATE_HAPPENS_BEFORE() and ANNOTATE_HAPPENS_AFTER() can - be used to define happens-before arcs in user-defined synchronization - mechanisms: the race detector will infer an arc from the former to the - latter when they share the same argument pointer. - - Example 1 (reference counting): - - void Unref() { - ANNOTATE_HAPPENS_BEFORE(&refcount_); - if (AtomicDecrementByOne(&refcount_) == 0) { - ANNOTATE_HAPPENS_AFTER(&refcount_); - delete this; - } - } - - Example 2 (message queue): - - void MyQueue::Put(Type *e) { - MutexLock lock(&mu_); - ANNOTATE_HAPPENS_BEFORE(e); - PutElementIntoMyQueue(e); - } - - Type *MyQueue::Get() { - MutexLock lock(&mu_); - Type *e = GetElementFromMyQueue(); - ANNOTATE_HAPPENS_AFTER(e); - return e; - } - - Note: when possible, please use the existing reference counting and message - queue implementations instead of inventing new ones. */ - - /* Report that wait on the condition variable at address "cv" has succeeded - and the lock at address "lock" is held. */ - #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(__FILE__, __LINE__, cv, lock) - - /* Report that wait on the condition variable at "cv" has succeeded. Variant - w/o lock. */ - #define ANNOTATE_CONDVAR_WAIT(cv) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)(__FILE__, __LINE__, cv, NULL) - - /* Report that we are about to signal on the condition variable at address - "cv". */ - #define ANNOTATE_CONDVAR_SIGNAL(cv) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)(__FILE__, __LINE__, cv) - - /* Report that we are about to signal_all on the condition variable at address - "cv". */ - #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)(__FILE__, __LINE__, cv) - - /* Annotations for user-defined synchronization mechanisms. */ - #define ANNOTATE_HAPPENS_BEFORE(obj) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensBefore)(__FILE__, __LINE__, obj) - #define ANNOTATE_HAPPENS_AFTER(obj) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensAfter)(__FILE__, __LINE__, obj) - - /* DEPRECATED. Don't use it. */ - #define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)(__FILE__, __LINE__, \ - pointer, size) - - /* DEPRECATED. Don't use it. */ - #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)(__FILE__, __LINE__, \ - pointer, size) - - /* DEPRECATED. Don't use it. */ - #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size) \ - do { \ - ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size); \ - ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size); \ - } while (0) - - /* Instruct the tool to create a happens-before arc between mu->Unlock() and - mu->Lock(). This annotation may slow down the race detector and hide real - races. Normally it is used only when it would be difficult to annotate each - of the mutex's critical sections individually using the annotations above. - This annotation makes sense only for hybrid race detectors. For pure - happens-before detectors this is a no-op. For more details see - http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */ - #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(__FILE__, __LINE__, \ - mu) - - /* Opposite to ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. - Instruct the tool to NOT create h-b arcs between Unlock and Lock, even in - pure happens-before mode. For a hybrid mode this is a no-op. */ - #define ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(mu) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)(__FILE__, __LINE__, mu) - - /* Deprecated. Use ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX. */ - #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)(__FILE__, __LINE__, \ - mu) - - /* ------------------------------------------------------------- - Annotations useful when defining memory allocators, or when memory that - was protected in one way starts to be protected in another. */ - - /* Report that a new memory at "address" of size "size" has been allocated. - This might be used when the memory has been retrieved from a free list and - is about to be reused, or when a the locking discipline for a variable - changes. */ - #define ANNOTATE_NEW_MEMORY(address, size) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)(__FILE__, __LINE__, address, \ - size) - - /* ------------------------------------------------------------- - Annotations useful when defining FIFO queues that transfer data between - threads. */ - - /* Report that the producer-consumer queue (such as ProducerConsumerQueue) at - address "pcq" has been created. The ANNOTATE_PCQ_* annotations - should be used only for FIFO queues. For non-FIFO queues use - ANNOTATE_HAPPENS_BEFORE (for put) and ANNOTATE_HAPPENS_AFTER (for get). */ - #define ANNOTATE_PCQ_CREATE(pcq) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)(__FILE__, __LINE__, pcq) - - /* Report that the queue at address "pcq" is about to be destroyed. */ - #define ANNOTATE_PCQ_DESTROY(pcq) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)(__FILE__, __LINE__, pcq) - - /* Report that we are about to put an element into a FIFO queue at address - "pcq". */ - #define ANNOTATE_PCQ_PUT(pcq) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)(__FILE__, __LINE__, pcq) - - /* Report that we've just got an element from a FIFO queue at address - "pcq". */ - #define ANNOTATE_PCQ_GET(pcq) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)(__FILE__, __LINE__, pcq) - - /* ------------------------------------------------------------- - Annotations that suppress errors. It is usually better to express the - program's synchronization using the other annotations, but these can - be used when all else fails. */ - - /* Report that we may have a benign race at "pointer", with size - "sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the - point where "pointer" has been allocated, preferably close to the point - where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */ - #define ANNOTATE_BENIGN_RACE(pointer, description) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(__FILE__, __LINE__, \ - pointer, sizeof(*(pointer)), description) - - /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to - the memory range [address, address+size). */ - #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)(__FILE__, __LINE__, \ - address, size, description) - - /* Request the analysis tool to ignore all reads in the current thread - until ANNOTATE_IGNORE_READS_END is called. - Useful to ignore intentional racey reads, while still checking - other reads and all writes. - See also ANNOTATE_UNPROTECTED_READ. */ - #define ANNOTATE_IGNORE_READS_BEGIN() \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__) - - /* Stop ignoring reads. */ - #define ANNOTATE_IGNORE_READS_END() \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__) - - /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */ - #define ANNOTATE_IGNORE_WRITES_BEGIN() \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__) - - /* Stop ignoring writes. */ - #define ANNOTATE_IGNORE_WRITES_END() \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__) - - /* Start ignoring all memory accesses (reads and writes). */ - #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \ - do {\ - ANNOTATE_IGNORE_READS_BEGIN();\ - ANNOTATE_IGNORE_WRITES_BEGIN();\ - }while(0)\ - - /* Stop ignoring all memory accesses. */ - #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \ - do {\ - ANNOTATE_IGNORE_WRITES_END();\ - ANNOTATE_IGNORE_READS_END();\ - }while(0)\ - - /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore synchronization events: - RWLOCK* and CONDVAR*. */ - #define ANNOTATE_IGNORE_SYNC_BEGIN() \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)(__FILE__, __LINE__) - - /* Stop ignoring sync events. */ - #define ANNOTATE_IGNORE_SYNC_END() \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)(__FILE__, __LINE__) - - - /* Enable (enable!=0) or disable (enable==0) race detection for all threads. - This annotation could be useful if you want to skip expensive race analysis - during some period of program execution, e.g. during initialization. */ - #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)(__FILE__, __LINE__, \ - enable) - - /* ------------------------------------------------------------- - Annotations useful for debugging. */ - - /* Request to trace every access to "address". */ - #define ANNOTATE_TRACE_MEMORY(address) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)(__FILE__, __LINE__, address) - - /* Report the current thread name to a race detector. */ - #define ANNOTATE_THREAD_NAME(name) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)(__FILE__, __LINE__, name) - - /* ------------------------------------------------------------- - Annotations useful when implementing locks. They are not - normally needed by modules that merely use locks. - The "lock" argument is a pointer to the lock object. */ - - /* Report that a lock has been created at address "lock". */ - #define ANNOTATE_RWLOCK_CREATE(lock) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)(__FILE__, __LINE__, lock) - - /* Report that the lock at address "lock" is about to be destroyed. */ - #define ANNOTATE_RWLOCK_DESTROY(lock) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock) - - /* Report that the lock at address "lock" has been acquired. - is_w=1 for writer lock, is_w=0 for reader lock. */ - #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)(__FILE__, __LINE__, lock, \ - is_w) - - /* Report that the lock at address "lock" is about to be released. */ - #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)(__FILE__, __LINE__, lock, \ - is_w) - - /* ------------------------------------------------------------- - Annotations useful when implementing barriers. They are not - normally needed by modules that merely use barriers. - The "barrier" argument is a pointer to the barrier object. */ - - /* Report that the "barrier" has been initialized with initial "count". - If 'reinitialization_allowed' is true, initialization is allowed to happen - multiple times w/o calling barrier_destroy() */ - #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)(__FILE__, __LINE__, barrier, \ - count, reinitialization_allowed) - - /* Report that we are about to enter barrier_wait("barrier"). */ - #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)(__FILE__, __LINE__, \ - barrier) - - /* Report that we just exited barrier_wait("barrier"). */ - #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)(__FILE__, __LINE__, \ - barrier) - - /* Report that the "barrier" has been destroyed. */ - #define ANNOTATE_BARRIER_DESTROY(barrier) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)(__FILE__, __LINE__, \ - barrier) - - /* ------------------------------------------------------------- - Annotations useful for testing race detectors. */ - - /* Report that we expect a race on the variable at "address". - Use only in unit tests for a race detector. */ - #define ANNOTATE_EXPECT_RACE(address, description) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)(__FILE__, __LINE__, address, \ - description) - - #define ANNOTATE_FLUSH_EXPECTED_RACES() \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)(__FILE__, __LINE__) - - /* A no-op. Insert where you like to test the interceptors. */ - #define ANNOTATE_NO_OP(arg) \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)(__FILE__, __LINE__, arg) - - /* Force the race detector to flush its state. The actual effect depends on - * the implementation of the detector. */ - #define ANNOTATE_FLUSH_STATE() \ - DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)(__FILE__, __LINE__) - - -#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */ - - #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */ - #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */ - #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */ - #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */ - #define ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) /* */ - #define ANNOTATE_BARRIER_WAIT_BEFORE(barrier) /* empty */ - #define ANNOTATE_BARRIER_WAIT_AFTER(barrier) /* empty */ - #define ANNOTATE_BARRIER_DESTROY(barrier) /* empty */ - #define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) /* empty */ - #define ANNOTATE_CONDVAR_WAIT(cv) /* empty */ - #define ANNOTATE_CONDVAR_SIGNAL(cv) /* empty */ - #define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) /* empty */ - #define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */ - #define ANNOTATE_HAPPENS_AFTER(obj) /* empty */ - #define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) /* empty */ - #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size) /* empty */ - #define ANNOTATE_SWAP_MEMORY_RANGE(address, size) /* empty */ - #define ANNOTATE_PCQ_CREATE(pcq) /* empty */ - #define ANNOTATE_PCQ_DESTROY(pcq) /* empty */ - #define ANNOTATE_PCQ_PUT(pcq) /* empty */ - #define ANNOTATE_PCQ_GET(pcq) /* empty */ - #define ANNOTATE_NEW_MEMORY(address, size) /* empty */ - #define ANNOTATE_EXPECT_RACE(address, description) /* empty */ - #define ANNOTATE_FLUSH_EXPECTED_RACES(address, description) /* empty */ - #define ANNOTATE_BENIGN_RACE(address, description) /* empty */ - #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */ - #define ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */ - #define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) /* empty */ - #define ANNOTATE_TRACE_MEMORY(arg) /* empty */ - #define ANNOTATE_THREAD_NAME(name) /* empty */ - #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */ - #define ANNOTATE_IGNORE_READS_END() /* empty */ - #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */ - #define ANNOTATE_IGNORE_WRITES_END() /* empty */ - #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */ - #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */ - #define ANNOTATE_IGNORE_SYNC_BEGIN() /* empty */ - #define ANNOTATE_IGNORE_SYNC_END() /* empty */ - #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */ - #define ANNOTATE_NO_OP(arg) /* empty */ - #define ANNOTATE_FLUSH_STATE() /* empty */ - -#endif /* DYNAMIC_ANNOTATIONS_ENABLED */ - -/* Use the macros above rather than using these functions directly. */ -#ifdef __cplusplus -extern "C" { -#endif - - -void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockCreate)( - const char *file, int line, - const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockDestroy)( - const char *file, int line, - const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockAcquired)( - const char *file, int line, - const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateRWLockReleased)( - const char *file, int line, - const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierInit)( - const char *file, int line, const volatile void *barrier, long count, - long reinitialization_allowed) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitBefore)( - const char *file, int line, - const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierWaitAfter)( - const char *file, int line, - const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateBarrierDestroy)( - const char *file, int line, - const volatile void *barrier) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarWait)( - const char *file, int line, const volatile void *cv, - const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignal)( - const char *file, int line, - const volatile void *cv) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateCondVarSignalAll)( - const char *file, int line, - const volatile void *cv) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensBefore)( - const char *file, int line, - const volatile void *obj) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateHappensAfter)( - const char *file, int line, - const volatile void *obj) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotatePublishMemoryRange)( - const char *file, int line, - const volatile void *address, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateUnpublishMemoryRange)( - const char *file, int line, - const volatile void *address, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQCreate)( - const char *file, int line, - const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQDestroy)( - const char *file, int line, - const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQPut)( - const char *file, int line, - const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotatePCQGet)( - const char *file, int line, - const volatile void *pcq) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateNewMemory)( - const char *file, int line, - const volatile void *mem, long size) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateExpectRace)( - const char *file, int line, const volatile void *mem, - const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushExpectedRaces)( - const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRace)( - const char *file, int line, const volatile void *mem, - const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateBenignRaceSized)( - const char *file, int line, const volatile void *mem, long size, - const char *description) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsUsedAsCondVar)( - const char *file, int line, - const volatile void *mu) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateMutexIsNotPHB)( - const char *file, int line, - const volatile void *mu) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateTraceMemory)( - const char *file, int line, - const volatile void *arg) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateThreadName)( - const char *file, int line, - const char *name) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsBegin)( - const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreReadsEnd)( - const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesBegin)( - const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreWritesEnd)( - const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncBegin)( - const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateIgnoreSyncEnd)( - const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateEnableRaceDetection)( - const char *file, int line, int enable) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateNoOp)( - const char *file, int line, - const volatile void *arg) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -void DYNAMIC_ANNOTATIONS_NAME(AnnotateFlushState)( - const char *file, int line) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; - -#if DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1 -/* Return non-zero value if running under valgrind. - - If "valgrind.h" is included into dynamic_annotations.c, - the regular valgrind mechanism will be used. - See http://valgrind.org/docs/manual/manual-core-adv.html about - RUNNING_ON_VALGRIND and other valgrind "client requests". - The file "valgrind.h" may be obtained by doing - svn co svn://svn.valgrind.org/valgrind/trunk/include - - If for some reason you can't use "valgrind.h" or want to fake valgrind, - there are two ways to make this function return non-zero: - - Use environment variable: export RUNNING_ON_VALGRIND=1 - - Make your tool intercept the function RunningOnValgrind() and - change its return value. - */ -int RunningOnValgrind(void) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK; -#endif /* DYNAMIC_ANNOTATIONS_PROVIDE_RUNNING_ON_VALGRIND == 1 */ - -#ifdef __cplusplus -} -#endif - -#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus) - - /* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads. - - Instead of doing - ANNOTATE_IGNORE_READS_BEGIN(); - ... = x; - ANNOTATE_IGNORE_READS_END(); - one can use - ... = ANNOTATE_UNPROTECTED_READ(x); */ - template <class T> - inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) { - ANNOTATE_IGNORE_READS_BEGIN(); - T res = x; - ANNOTATE_IGNORE_READS_END(); - return res; - } - /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */ - #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \ - namespace { \ - class static_var ## _annotator { \ - public: \ - static_var ## _annotator() { \ - ANNOTATE_BENIGN_RACE_SIZED(&static_var, \ - sizeof(static_var), \ - # static_var ": " description); \ - } \ - }; \ - static static_var ## _annotator the ## static_var ## _annotator;\ - } -#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */ - - #define ANNOTATE_UNPROTECTED_READ(x) (x) - #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */ - -#endif /* DYNAMIC_ANNOTATIONS_ENABLED */ - -#endif /* __DYNAMIC_ANNOTATIONS_H__ */ diff --git a/security/sandbox/chromium/base/third_party/icu/LICENSE b/security/sandbox/chromium/base/third_party/icu/LICENSE deleted file mode 100644 index 40282f494..000000000 --- a/security/sandbox/chromium/base/third_party/icu/LICENSE +++ /dev/null @@ -1,32 +0,0 @@ -ICU License - ICU 1.8.1 and later - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2009 International Business Machines Corporation and others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY -SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER -RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF -CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. diff --git a/security/sandbox/chromium/base/third_party/icu/icu_utf.cc b/security/sandbox/chromium/base/third_party/icu/icu_utf.cc deleted file mode 100644 index 2b67c5d9c..000000000 --- a/security/sandbox/chromium/base/third_party/icu/icu_utf.cc +++ /dev/null @@ -1,227 +0,0 @@ -/* -****************************************************************************** -* -* Copyright (C) 1999-2006, International Business Machines -* Corporation and others. All Rights Reserved. -* -****************************************************************************** -* file name: utf_impl.c -* encoding: US-ASCII -* tab size: 8 (not used) -* indentation:4 -* -* created on: 1999sep13 -* created by: Markus W. Scherer -* -* This file provides implementation functions for macros in the utfXX.h -* that would otherwise be too long as macros. -*/ - -#include "base/third_party/icu/icu_utf.h" - -namespace base_icu { - -/** - * UTF8_ERROR_VALUE_1 and UTF8_ERROR_VALUE_2 are special error values for UTF-8, - * which need 1 or 2 bytes in UTF-8: - * \code - * U+0015 = NAK = Negative Acknowledge, C0 control character - * U+009f = highest C1 control character - * \endcode - * - * These are used by UTF8_..._SAFE macros so that they can return an error value - * that needs the same number of code units (bytes) as were seen by - * a macro. They should be tested with UTF_IS_ERROR() or UTF_IS_VALID(). - * - * @deprecated ICU 2.4. Obsolete, see utf_old.h. - */ -#define CBUTF8_ERROR_VALUE_1 0x15 - -/** - * See documentation on UTF8_ERROR_VALUE_1 for details. - * - * @deprecated ICU 2.4. Obsolete, see utf_old.h. - */ -#define CBUTF8_ERROR_VALUE_2 0x9f - - -/** - * Error value for all UTFs. This code point value will be set by macros with e> - * checking if an error is detected. - * - * @deprecated ICU 2.4. Obsolete, see utf_old.h. - */ -#define CBUTF_ERROR_VALUE 0xffff - -/* - * This table could be replaced on many machines by - * a few lines of assembler code using an - * "index of first 0-bit from msb" instruction and - * one or two more integer instructions. - * - * For example, on an i386, do something like - * - MOV AL, leadByte - * - NOT AL (8-bit, leave b15..b8==0..0, reverse only b7..b0) - * - MOV AH, 0 - * - BSR BX, AX (16-bit) - * - MOV AX, 6 (result) - * - JZ finish (ZF==1 if leadByte==0xff) - * - SUB AX, BX (result) - * -finish: - * (BSR: Bit Scan Reverse, scans for a 1-bit, starting from the MSB) - * - * In Unicode, all UTF-8 byte sequences with more than 4 bytes are illegal; - * lead bytes above 0xf4 are illegal. - * We keep them in this table for skipping long ISO 10646-UTF-8 sequences. - */ -const uint8_t utf8_countTrailBytes[256] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, - 3, 3, /* illegal in Unicode */ - 4, 4, 4, 4, /* illegal in Unicode */ - 5, 5, /* illegal in Unicode */ - 0, 0 /* illegal bytes 0xfe and 0xff */ -}; - -static const UChar32 -utf8_minLegal[4]={ 0, 0x80, 0x800, 0x10000 }; - -static const UChar32 -utf8_errorValue[6]={ - CBUTF8_ERROR_VALUE_1, CBUTF8_ERROR_VALUE_2, CBUTF_ERROR_VALUE, 0x10ffff, - 0x3ffffff, 0x7fffffff -}; - -/* - * Handle the non-inline part of the U8_NEXT() macro and its obsolete sibling - * UTF8_NEXT_CHAR_SAFE(). - * - * The "strict" parameter controls the error behavior: - * <0 "Safe" behavior of U8_NEXT(): All illegal byte sequences yield a negative - * code point result. - * 0 Obsolete "safe" behavior of UTF8_NEXT_CHAR_SAFE(..., FALSE): - * All illegal byte sequences yield a positive code point such that this - * result code point would be encoded with the same number of bytes as - * the illegal sequence. - * >0 Obsolete "strict" behavior of UTF8_NEXT_CHAR_SAFE(..., TRUE): - * Same as the obsolete "safe" behavior, but non-characters are also treated - * like illegal sequences. - * - * The special negative (<0) value -2 is used for lenient treatment of surrogate - * code points as legal. Some implementations use this for roundtripping of - * Unicode 16-bit strings that are not well-formed UTF-16, that is, they - * contain unpaired surrogates. - * - * Note that a UBool is the same as an int8_t. - */ -UChar32 utf8_nextCharSafeBody(const uint8_t* s, - int32_t* pi, - int32_t length, - UChar32 c, - UBool strict) { - int32_t i = *pi; - uint8_t count = CBU8_COUNT_TRAIL_BYTES(c); - if((i)+count<=(length)) { - uint8_t trail, illegal = 0; - - CBU8_MASK_LEAD_BYTE((c), count); - /* count==0 for illegally leading trail bytes and the illegal bytes 0xfe and 0xff */ - switch(count) { - /* each branch falls through to the next one */ - case 5: - case 4: - /* count>=4 is always illegal: no more than 3 trail bytes in Unicode's UTF-8 */ - illegal=1; - break; - case 3: - trail=s[(i)++]; - (c)=((c)<<6)|(trail&0x3f); - if(c<0x110) { - illegal|=(trail&0xc0)^0x80; - } else { - /* code point>0x10ffff, outside Unicode */ - illegal=1; - break; - } - case 2: - trail=s[(i)++]; - (c)=((c)<<6)|(trail&0x3f); - illegal|=(trail&0xc0)^0x80; - case 1: - trail=s[(i)++]; - (c)=((c)<<6)|(trail&0x3f); - illegal|=(trail&0xc0)^0x80; - break; - case 0: - if(strict>=0) { - return CBUTF8_ERROR_VALUE_1; - } else { - return CBU_SENTINEL; - } - /* no default branch to optimize switch() - all values are covered */ - } - - /* - * All the error handling should return a value - * that needs count bytes so that UTF8_GET_CHAR_SAFE() works right. - * - * Starting with Unicode 3.0.1, non-shortest forms are illegal. - * Starting with Unicode 3.2, surrogate code points must not be - * encoded in UTF-8, and there are no irregular sequences any more. - * - * U8_ macros (new in ICU 2.4) return negative values for error conditions. - */ - - /* correct sequence - all trail bytes have (b7..b6)==(10)? */ - /* illegal is also set if count>=4 */ - if(illegal || (c)<utf8_minLegal[count] || (CBU_IS_SURROGATE(c) && strict!=-2)) { - /* error handling */ - uint8_t errorCount = count; - /* don't go beyond this sequence */ - i=*pi; - while(count>0 && CBU8_IS_TRAIL(s[i])) { - ++(i); - --count; - } - if(strict>=0) { - c=utf8_errorValue[errorCount-count]; - } else { - c=CBU_SENTINEL; - } - } else if((strict)>0 && CBU_IS_UNICODE_NONCHAR(c)) { - /* strict: forbid non-characters like U+fffe */ - c=utf8_errorValue[count]; - } - } else /* too few bytes left */ { - /* error handling */ - int32_t i0 = i; - /* don't just set (i)=(length) in case there is an illegal sequence */ - while((i)<(length) && CBU8_IS_TRAIL(s[i])) { - ++(i); - } - if(strict>=0) { - c=utf8_errorValue[i-i0]; - } else { - c=CBU_SENTINEL; - } - } - *pi=i; - return c; -} - -} // namespace base_icu diff --git a/security/sandbox/chromium/base/third_party/icu/icu_utf.h b/security/sandbox/chromium/base/third_party/icu/icu_utf.h deleted file mode 100644 index 4370fdec1..000000000 --- a/security/sandbox/chromium/base/third_party/icu/icu_utf.h +++ /dev/null @@ -1,400 +0,0 @@ -/* -******************************************************************************* -* -* Copyright (C) 1999-2004, International Business Machines -* Corporation and others. All Rights Reserved. -* -******************************************************************************* -* file name: utf.h -* encoding: US-ASCII -* tab size: 8 (not used) -* indentation:4 -* -* created on: 1999sep09 -* created by: Markus W. Scherer -*/ - -#ifndef BASE_THIRD_PARTY_ICU_ICU_UTF_H_ -#define BASE_THIRD_PARTY_ICU_ICU_UTF_H_ - -#include <stdint.h> - -namespace base_icu { - -typedef int32_t UChar32; -typedef uint16_t UChar; -typedef int8_t UBool; - -// General --------------------------------------------------------------------- -// from utf.h - -/** - * This value is intended for sentinel values for APIs that - * (take or) return single code points (UChar32). - * It is outside of the Unicode code point range 0..0x10ffff. - * - * For example, a "done" or "error" value in a new API - * could be indicated with CBU_SENTINEL. - * - * ICU APIs designed before ICU 2.4 usually define service-specific "done" - * values, mostly 0xffff. - * Those may need to be distinguished from - * actual U+ffff text contents by calling functions like - * CharacterIterator::hasNext() or UnicodeString::length(). - * - * @return -1 - * @see UChar32 - * @stable ICU 2.4 - */ -#define CBU_SENTINEL (-1) - -/** - * Is this code point a Unicode noncharacter? - * @param c 32-bit code point - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU_IS_UNICODE_NONCHAR(c) \ - ((c) >= 0xfdd0 && ((uint32_t)(c) <= 0xfdef || ((c)&0xfffe) == 0xfffe) && \ - (uint32_t)(c) <= 0x10ffff) - -/** - * Is c a Unicode code point value (0..U+10ffff) - * that can be assigned a character? - * - * Code points that are not characters include: - * - single surrogate code points (U+d800..U+dfff, 2048 code points) - * - the last two code points on each plane (U+__fffe and U+__ffff, 34 code points) - * - U+fdd0..U+fdef (new with Unicode 3.1, 32 code points) - * - the highest Unicode code point value is U+10ffff - * - * This means that all code points below U+d800 are character code points, - * and that boundary is tested first for performance. - * - * @param c 32-bit code point - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU_IS_UNICODE_CHAR(c) \ - ((uint32_t)(c) < 0xd800 || \ - ((uint32_t)(c) > 0xdfff && (uint32_t)(c) <= 0x10ffff && \ - !CBU_IS_UNICODE_NONCHAR(c))) - -/** - * Is this code point a surrogate (U+d800..U+dfff)? - * @param c 32-bit code point - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800) - -/** - * Assuming c is a surrogate code point (U_IS_SURROGATE(c)), - * is it a lead surrogate? - * @param c 32-bit code point - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU_IS_SURROGATE_LEAD(c) (((c)&0x400)==0) - - -// UTF-8 macros ---------------------------------------------------------------- -// from utf8.h - -extern const uint8_t utf8_countTrailBytes[256]; - -/** - * Count the trail bytes for a UTF-8 lead byte. - * @internal - */ -#define CBU8_COUNT_TRAIL_BYTES(leadByte) \ - (base_icu::utf8_countTrailBytes[(uint8_t)leadByte]) - -/** - * Mask a UTF-8 lead byte, leave only the lower bits that form part of the code point value. - * @internal - */ -#define CBU8_MASK_LEAD_BYTE(leadByte, countTrailBytes) ((leadByte)&=(1<<(6-(countTrailBytes)))-1) - -/** - * Does this code unit (byte) encode a code point by itself (US-ASCII 0..0x7f)? - * @param c 8-bit code unit (byte) - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU8_IS_SINGLE(c) (((c)&0x80)==0) - -/** - * Is this code unit (byte) a UTF-8 lead byte? - * @param c 8-bit code unit (byte) - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU8_IS_LEAD(c) ((uint8_t)((c)-0xc0) < 0x3e) - -/** - * Is this code unit (byte) a UTF-8 trail byte? - * @param c 8-bit code unit (byte) - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU8_IS_TRAIL(c) (((c)&0xc0)==0x80) - -/** - * How many code units (bytes) are used for the UTF-8 encoding - * of this Unicode code point? - * @param c 32-bit code point - * @return 1..4, or 0 if c is a surrogate or not a Unicode code point - * @stable ICU 2.4 - */ -#define CBU8_LENGTH(c) \ - ((uint32_t)(c) <= 0x7f \ - ? 1 \ - : ((uint32_t)(c) <= 0x7ff \ - ? 2 \ - : ((uint32_t)(c) <= 0xd7ff \ - ? 3 \ - : ((uint32_t)(c) <= 0xdfff || (uint32_t)(c) > 0x10ffff \ - ? 0 \ - : ((uint32_t)(c) <= 0xffff ? 3 : 4))))) - -/** - * The maximum number of UTF-8 code units (bytes) per Unicode code point (U+0000..U+10ffff). - * @return 4 - * @stable ICU 2.4 - */ -#define CBU8_MAX_LENGTH 4 - -/** - * Function for handling "next code point" with error-checking. - * @internal - */ -UChar32 utf8_nextCharSafeBody(const uint8_t* s, - int32_t* pi, - int32_t length, - UChar32 c, - UBool strict); - -/** - * Get a code point from a string at a code point boundary offset, - * and advance the offset to the next code point boundary. - * (Post-incrementing forward iteration.) - * "Safe" macro, checks for illegal sequences and for string boundaries. - * - * The offset may point to the lead byte of a multi-byte sequence, - * in which case the macro will read the whole sequence. - * If the offset points to a trail byte or an illegal UTF-8 sequence, then - * c is set to a negative value. - * - * @param s const uint8_t * string - * @param i string offset, i<length - * @param length string length - * @param c output UChar32 variable, set to <0 in case of an error - * @see CBU8_NEXT_UNSAFE - * @stable ICU 2.4 - */ -#define CBU8_NEXT(s, i, length, c) \ - { \ - (c) = (s)[(i)++]; \ - if (((uint8_t)(c)) >= 0x80) { \ - if (CBU8_IS_LEAD(c)) { \ - (c) = base_icu::utf8_nextCharSafeBody((const uint8_t*)s, &(i), \ - (int32_t)(length), c, -1); \ - } else { \ - (c) = CBU_SENTINEL; \ - } \ - } \ - } - -/** - * Append a code point to a string, overwriting 1 to 4 bytes. - * The offset points to the current end of the string contents - * and is advanced (post-increment). - * "Unsafe" macro, assumes a valid code point and sufficient space in the - * string. - * Otherwise, the result is undefined. - * - * @param s const uint8_t * string buffer - * @param i string offset - * @param c code point to append - * @see CBU8_APPEND - * @stable ICU 2.4 - */ -#define CBU8_APPEND_UNSAFE(s, i, c) \ - { \ - if ((uint32_t)(c) <= 0x7f) { \ - (s)[(i)++] = (uint8_t)(c); \ - } else { \ - if ((uint32_t)(c) <= 0x7ff) { \ - (s)[(i)++] = (uint8_t)(((c) >> 6) | 0xc0); \ - } else { \ - if ((uint32_t)(c) <= 0xffff) { \ - (s)[(i)++] = (uint8_t)(((c) >> 12) | 0xe0); \ - } else { \ - (s)[(i)++] = (uint8_t)(((c) >> 18) | 0xf0); \ - (s)[(i)++] = (uint8_t)((((c) >> 12) & 0x3f) | 0x80); \ - } \ - (s)[(i)++] = (uint8_t)((((c) >> 6) & 0x3f) | 0x80); \ - } \ - (s)[(i)++] = (uint8_t)(((c)&0x3f) | 0x80); \ - } \ - } - -// UTF-16 macros --------------------------------------------------------------- -// from utf16.h - -/** - * Does this code unit alone encode a code point (BMP, not a surrogate)? - * @param c 16-bit code unit - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU16_IS_SINGLE(c) !CBU_IS_SURROGATE(c) - -/** - * Is this code unit a lead surrogate (U+d800..U+dbff)? - * @param c 16-bit code unit - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800) - -/** - * Is this code unit a trail surrogate (U+dc00..U+dfff)? - * @param c 16-bit code unit - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) - -/** - * Is this code unit a surrogate (U+d800..U+dfff)? - * @param c 16-bit code unit - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU16_IS_SURROGATE(c) CBU_IS_SURROGATE(c) - -/** - * Assuming c is a surrogate code point (U16_IS_SURROGATE(c)), - * is it a lead surrogate? - * @param c 16-bit code unit - * @return TRUE or FALSE - * @stable ICU 2.4 - */ -#define CBU16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0) - -/** - * Helper constant for CBU16_GET_SUPPLEMENTARY. - * @internal - */ -#define CBU16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000) - -/** - * Get a supplementary code point value (U+10000..U+10ffff) - * from its lead and trail surrogates. - * The result is undefined if the input values are not - * lead and trail surrogates. - * - * @param lead lead surrogate (U+d800..U+dbff) - * @param trail trail surrogate (U+dc00..U+dfff) - * @return supplementary code point (U+10000..U+10ffff) - * @stable ICU 2.4 - */ -#define CBU16_GET_SUPPLEMENTARY(lead, trail) \ - (((base_icu::UChar32)(lead)<<10UL)+(base_icu::UChar32)(trail)-CBU16_SURROGATE_OFFSET) - - -/** - * Get the lead surrogate (0xd800..0xdbff) for a - * supplementary code point (0x10000..0x10ffff). - * @param supplementary 32-bit code point (U+10000..U+10ffff) - * @return lead surrogate (U+d800..U+dbff) for supplementary - * @stable ICU 2.4 - */ -#define CBU16_LEAD(supplementary) \ - (base_icu::UChar)(((supplementary)>>10)+0xd7c0) - -/** - * Get the trail surrogate (0xdc00..0xdfff) for a - * supplementary code point (0x10000..0x10ffff). - * @param supplementary 32-bit code point (U+10000..U+10ffff) - * @return trail surrogate (U+dc00..U+dfff) for supplementary - * @stable ICU 2.4 - */ -#define CBU16_TRAIL(supplementary) \ - (base_icu::UChar)(((supplementary)&0x3ff)|0xdc00) - -/** - * How many 16-bit code units are used to encode this Unicode code point? (1 or 2) - * The result is not defined if c is not a Unicode code point (U+0000..U+10ffff). - * @param c 32-bit code point - * @return 1 or 2 - * @stable ICU 2.4 - */ -#define CBU16_LENGTH(c) ((uint32_t)(c) <= 0xffff ? 1 : 2) - -/** - * The maximum number of 16-bit code units per Unicode code point (U+0000..U+10ffff). - * @return 2 - * @stable ICU 2.4 - */ -#define CBU16_MAX_LENGTH 2 - -/** - * Get a code point from a string at a code point boundary offset, - * and advance the offset to the next code point boundary. - * (Post-incrementing forward iteration.) - * "Safe" macro, handles unpaired surrogates and checks for string boundaries. - * - * The offset may point to the lead surrogate unit - * for a supplementary code point, in which case the macro will read - * the following trail surrogate as well. - * If the offset points to a trail surrogate or - * to a single, unpaired lead surrogate, then that itself - * will be returned as the code point. - * - * @param s const UChar * string - * @param i string offset, i<length - * @param length string length - * @param c output UChar32 variable - * @stable ICU 2.4 - */ -#define CBU16_NEXT(s, i, length, c) \ - { \ - (c) = (s)[(i)++]; \ - if (CBU16_IS_LEAD(c)) { \ - uint16_t __c2; \ - if ((i) < (length) && CBU16_IS_TRAIL(__c2 = (s)[(i)])) { \ - ++(i); \ - (c) = CBU16_GET_SUPPLEMENTARY((c), __c2); \ - } \ - } \ - } - -/** - * Append a code point to a string, overwriting 1 or 2 code units. - * The offset points to the current end of the string contents - * and is advanced (post-increment). - * "Unsafe" macro, assumes a valid code point and sufficient space in the string. - * Otherwise, the result is undefined. - * - * @param s const UChar * string buffer - * @param i string offset - * @param c code point to append - * @see CBU16_APPEND - * @stable ICU 2.4 - */ -#define CBU16_APPEND_UNSAFE(s, i, c) \ - { \ - if ((uint32_t)(c) <= 0xffff) { \ - (s)[(i)++] = (uint16_t)(c); \ - } else { \ - (s)[(i)++] = (uint16_t)(((c) >> 10) + 0xd7c0); \ - (s)[(i)++] = (uint16_t)(((c)&0x3ff) | 0xdc00); \ - } \ - } - -} // namesapce base_icu - -#endif // BASE_THIRD_PARTY_ICU_ICU_UTF_H_ diff --git a/security/sandbox/chromium/base/third_party/superfasthash/LICENSE b/security/sandbox/chromium/base/third_party/superfasthash/LICENSE deleted file mode 100644 index 3c40a3ecd..000000000 --- a/security/sandbox/chromium/base/third_party/superfasthash/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Paul Hsieh OLD BSD license - -Copyright (c) 2010, Paul Hsieh -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. -* Neither my name, Paul Hsieh, nor the names of any other contributors to the - code use may not be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/security/sandbox/chromium/base/third_party/superfasthash/README.chromium b/security/sandbox/chromium/base/third_party/superfasthash/README.chromium deleted file mode 100644 index d41ed7724..000000000 --- a/security/sandbox/chromium/base/third_party/superfasthash/README.chromium +++ /dev/null @@ -1,29 +0,0 @@ -Name: Paul Hsieh's SuperFastHash -Short Name: SuperFastHash -URL: http://www.azillionmonkeys.com/qed/hash.html -Version: 0 -Date: 2012-02-21 -License: BSD -License File: LICENSE -Security Critical: yes - -Description: -A fast string hashing algorithm. - -Local Modifications: -- Added LICENSE. -- Added license text as a comment to the top of superfasthash.c. -- #include <stdint.h> instead of "pstdint.h". -- #include <stdlib.h>. - -The license is a standard 3-clause BSD license with the following minor changes: - -"nor the names of its contributors may be used" -is replaced with: -"nor the names of any other contributors to the code use may not be used" - -and - -"IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE" -is replaced with: -"IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE" diff --git a/security/sandbox/chromium/base/third_party/superfasthash/superfasthash.c b/security/sandbox/chromium/base/third_party/superfasthash/superfasthash.c deleted file mode 100644 index 6e7687e13..000000000 --- a/security/sandbox/chromium/base/third_party/superfasthash/superfasthash.c +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2010, Paul Hsieh -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither my name, Paul Hsieh, nor the names of any other contributors to the -// code use may not be used to endorse or promote products derived from this -// software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include <stdint.h> -#include <stdlib.h> -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif - -uint32_t SuperFastHash (const char * data, int len) { -uint32_t hash = len, tmp; -int rem; - - if (len <= 0 || data == NULL) return 0; - - rem = len & 3; - len >>= 2; - - /* Main loop */ - for (;len > 0; len--) { - hash += get16bits (data); - tmp = (get16bits (data+2) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2*sizeof (uint16_t); - hash += hash >> 11; - } - - /* Handle end cases */ - switch (rem) { - case 3: hash += get16bits (data); - hash ^= hash << 16; - hash ^= ((signed char)data[sizeof (uint16_t)]) << 18; - hash += hash >> 11; - break; - case 2: hash += get16bits (data); - hash ^= hash << 11; - hash += hash >> 17; - break; - case 1: hash += (signed char)*data; - hash ^= hash << 10; - hash += hash >> 1; - } - - /* Force "avalanching" of final 127 bits */ - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 4; - hash += hash >> 17; - hash ^= hash << 25; - hash += hash >> 6; - - return hash; -} diff --git a/security/sandbox/chromium/base/third_party/valgrind/LICENSE b/security/sandbox/chromium/base/third_party/valgrind/LICENSE deleted file mode 100644 index 41f677bd1..000000000 --- a/security/sandbox/chromium/base/third_party/valgrind/LICENSE +++ /dev/null @@ -1,39 +0,0 @@ - Notice that the following BSD-style license applies to the Valgrind header - files used by Chromium (valgrind.h and memcheck.h). However, the rest of - Valgrind is licensed under the terms of the GNU General Public License, - version 2, unless otherwise indicated. - - ---------------------------------------------------------------- - - Copyright (C) 2000-2008 Julian Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/security/sandbox/chromium/base/third_party/valgrind/valgrind.h b/security/sandbox/chromium/base/third_party/valgrind/valgrind.h deleted file mode 100644 index 0bae0aa13..000000000 --- a/security/sandbox/chromium/base/third_party/valgrind/valgrind.h +++ /dev/null @@ -1,4792 +0,0 @@ -/* -*- c -*- - ---------------------------------------------------------------- - - Notice that the following BSD-style license applies to this one - file (valgrind.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. - - ---------------------------------------------------------------- - - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2010 Julian Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ---------------------------------------------------------------- - - Notice that the above BSD-style license applies to this one file - (valgrind.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. - - ---------------------------------------------------------------- -*/ - - -/* This file is for inclusion into client (your!) code. - - You can use these macros to manipulate and query Valgrind's - execution inside your own programs. - - The resulting executables will still run without Valgrind, just a - little bit more slowly than they otherwise would, but otherwise - unchanged. When not running on valgrind, each client request - consumes very few (eg. 7) instructions, so the resulting performance - loss is negligible unless you plan to execute client requests - millions of times per second. Nevertheless, if that is still a - problem, you can compile with the NVALGRIND symbol defined (gcc - -DNVALGRIND) so that client requests are not even compiled in. */ - -#ifndef __VALGRIND_H -#define __VALGRIND_H - - -/* ------------------------------------------------------------------ */ -/* VERSION NUMBER OF VALGRIND */ -/* ------------------------------------------------------------------ */ - -/* Specify Valgrind's version number, so that user code can - conditionally compile based on our version number. Note that these - were introduced at version 3.6 and so do not exist in version 3.5 - or earlier. The recommended way to use them to check for "version - X.Y or later" is (eg) - -#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \ - && (__VALGRIND_MAJOR__ > 3 \ - || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) -*/ -#define __VALGRIND_MAJOR__ 3 -#define __VALGRIND_MINOR__ 6 - - -#include <stdarg.h> - -/* Nb: this file might be included in a file compiled with -ansi. So - we can't use C++ style "//" comments nor the "asm" keyword (instead - use "__asm__"). */ - -/* Derive some tags indicating what the target platform is. Note - that in this file we're using the compiler's CPP symbols for - identifying architectures, which are different to the ones we use - within the rest of Valgrind. Note, __powerpc__ is active for both - 32 and 64-bit PPC, whereas __powerpc64__ is only active for the - latter (on Linux, that is). - - Misc note: how to find out what's predefined in gcc by default: - gcc -Wp,-dM somefile.c -*/ -#undef PLAT_ppc64_aix5 -#undef PLAT_ppc32_aix5 -#undef PLAT_x86_darwin -#undef PLAT_amd64_darwin -#undef PLAT_x86_win32 -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_arm_linux - -#if defined(_AIX) && defined(__64BIT__) -# define PLAT_ppc64_aix5 1 -#elif defined(_AIX) && !defined(__64BIT__) -# define PLAT_ppc32_aix5 1 -#elif defined(__APPLE__) && defined(__i386__) -# define PLAT_x86_darwin 1 -#elif defined(__APPLE__) && defined(__x86_64__) -# define PLAT_amd64_darwin 1 -#elif defined(__MINGW32__) || defined(__CYGWIN32__) || defined(_WIN32) && defined(_M_IX86) -# define PLAT_x86_win32 1 -#elif defined(__linux__) && defined(__i386__) -# define PLAT_x86_linux 1 -#elif defined(__linux__) && defined(__x86_64__) -# define PLAT_amd64_linux 1 -#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) -# define PLAT_ppc32_linux 1 -#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) -# define PLAT_ppc64_linux 1 -#elif defined(__linux__) && defined(__arm__) -# define PLAT_arm_linux 1 -#else -/* If we're not compiling for our target platform, don't generate - any inline asms. */ -# if !defined(NVALGRIND) -# define NVALGRIND 1 -# endif -#endif - - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ -/* in here of use to end-users -- skip to the next section. */ -/* ------------------------------------------------------------------ */ - -#if defined(NVALGRIND) - -/* Define NVALGRIND to completely remove the Valgrind magic sequence - from the compiled code (analogous to NDEBUG's effects on - assert()) */ -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { \ - (_zzq_rlval) = (_zzq_default); \ - } - -#else /* ! NVALGRIND */ - -/* The following defines the magic code sequences which the JITter - spots and handles magically. Don't look too closely at them as - they will rot your brain. - - The assembly code sequences for all architectures is in this one - file. This is because this file must be stand-alone, and we don't - want to have multiple files. - - For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default - value gets put in the return slot, so that everything works when - this is executed not under Valgrind. Args are passed in a memory - block, and so there's no intrinsic limit to the number that could - be passed, but it's currently five. - - The macro args are: - _zzq_rlval result lvalue - _zzq_default default value (result returned when running on real CPU) - _zzq_request request code - _zzq_arg1..5 request params - - The other two macros are used to support function wrapping, and are - a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the - guest's NRADDR pseudo-register and whatever other information is - needed to safely run the call original from the wrapper: on - ppc64-linux, the R2 value at the divert point is also needed. This - information is abstracted into a user-visible type, OrigFn. - - VALGRIND_CALL_NOREDIR_* behaves the same as the following on the - guest, but guarantees that the branch instruction will not be - redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: - branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a - complete inline asm, since it needs to be combined with more magic - inline asm stuff to be useful. -*/ - -/* ------------------------- x86-{linux,darwin} ---------------- */ - -#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ - || (defined(PLAT_x86_win32) && defined(__GNUC__)) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "roll $3, %%edi ; roll $13, %%edi\n\t" \ - "roll $29, %%edi ; roll $19, %%edi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile unsigned int _zzq_args[6]; \ - volatile unsigned int _zzq_result; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EDX = client_request ( %EAX ) */ \ - "xchgl %%ebx,%%ebx" \ - : "=d" (_zzq_result) \ - : "a" (&_zzq_args[0]), "0" (_zzq_default) \ - : "cc", "memory" \ - ); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EAX = guest_NRADDR */ \ - "xchgl %%ecx,%%ecx" \ - : "=a" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_EAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%EAX */ \ - "xchgl %%edx,%%edx\n\t" -#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */ - -/* ------------------------- x86-Win32 ------------------------- */ - -#if defined(PLAT_x86_win32) && !defined(__GNUC__) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#if defined(_MSC_VER) - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - __asm rol edi, 3 __asm rol edi, 13 \ - __asm rol edi, 29 __asm rol edi, 19 - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile uintptr_t _zzq_args[6]; \ - volatile unsigned int _zzq_result; \ - _zzq_args[0] = (uintptr_t)(_zzq_request); \ - _zzq_args[1] = (uintptr_t)(_zzq_arg1); \ - _zzq_args[2] = (uintptr_t)(_zzq_arg2); \ - _zzq_args[3] = (uintptr_t)(_zzq_arg3); \ - _zzq_args[4] = (uintptr_t)(_zzq_arg4); \ - _zzq_args[5] = (uintptr_t)(_zzq_arg5); \ - __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EDX = client_request ( %EAX ) */ \ - __asm xchg ebx,ebx \ - __asm mov _zzq_result, edx \ - } \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned int __addr; \ - __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EAX = guest_NRADDR */ \ - __asm xchg ecx,ecx \ - __asm mov __addr, eax \ - } \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_EAX ERROR - -#else -#error Unsupported compiler. -#endif - -#endif /* PLAT_x86_win32 */ - -/* ------------------------ amd64-{linux,darwin} --------------- */ - -#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ - "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile unsigned long long int _zzq_args[6]; \ - volatile unsigned long long int _zzq_result; \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %RDX = client_request ( %RAX ) */ \ - "xchgq %%rbx,%%rbx" \ - : "=d" (_zzq_result) \ - : "a" (&_zzq_args[0]), "0" (_zzq_default) \ - : "cc", "memory" \ - ); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %RAX = guest_NRADDR */ \ - "xchgq %%rcx,%%rcx" \ - : "=a" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_RAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%RAX */ \ - "xchgq %%rdx,%%rdx\n\t" -#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned int _zzq_args[6]; \ - unsigned int _zzq_result; \ - unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 3,%1\n\t" /*default*/ \ - "mr 4,%2\n\t" /*ptr*/ \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" /*result*/ \ - : "=b" (_zzq_result) \ - : "b" (_zzq_default), "b" (_zzq_ptr) \ - : "cc", "memory", "r3", "r4"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "cc", "memory", "r3" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned long long int _zzq_args[6]; \ - register unsigned long long int _zzq_result __asm__("r3"); \ - register unsigned long long int* _zzq_ptr __asm__("r4"); \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1" \ - : "=r" (_zzq_result) \ - : "0" (_zzq_default), "r" (_zzq_ptr) \ - : "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr __asm__("r3"); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2" \ - : "=r" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4" \ - : "=r" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------- arm-linux ------------------------- */ - -#if defined(PLAT_arm_linux) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \ - "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { volatile unsigned int _zzq_args[6]; \ - volatile unsigned int _zzq_result; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - __asm__ volatile("mov r3, %1\n\t" /*default*/ \ - "mov r4, %2\n\t" /*ptr*/ \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* R3 = client_request ( R4 ) */ \ - "orr r10, r10, r10\n\t" \ - "mov %0, r3" /*result*/ \ - : "=r" (_zzq_result) \ - : "r" (_zzq_default), "r" (&_zzq_args[0]) \ - : "cc","memory", "r3", "r4"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* R3 = guest_NRADDR */ \ - "orr r11, r11, r11\n\t" \ - "mov %0, r3" \ - : "=r" (__addr) \ - : \ - : "cc", "memory", "r3" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R4 */ \ - "orr r12, r12, r12\n\t" - -#endif /* PLAT_arm_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - unsigned int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned int _zzq_args[7]; \ - register unsigned int _zzq_result; \ - register unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 4,%1\n\t" \ - "lwz 3, 24(4)\n\t" \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b" (_zzq_result) \ - : "b" (_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned long long int _zzq_args[7]; \ - register unsigned long long int _zzq_result; \ - register unsigned long long int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int long long)(_zzq_request); \ - _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int long long)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 4,%1\n\t" \ - "ld 3, 48(4)\n\t" \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b" (_zzq_result) \ - : "b" (_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_aix5 */ - -/* Insert assembly code for other platforms here... */ - -#endif /* NVALGRIND */ - - -/* ------------------------------------------------------------------ */ -/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ -/* ugly. It's the least-worst tradeoff I can think of. */ -/* ------------------------------------------------------------------ */ - -/* This section defines magic (a.k.a appalling-hack) macros for doing - guaranteed-no-redirection macros, so as to get from function - wrappers to the functions they are wrapping. The whole point is to - construct standard call sequences, but to do the call itself with a - special no-redirect call pseudo-instruction that the JIT - understands and handles specially. This section is long and - repetitious, and I can't see a way to make it shorter. - - The naming scheme is as follows: - - CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} - - 'W' stands for "word" and 'v' for "void". Hence there are - different macros for calling arity 0, 1, 2, 3, 4, etc, functions, - and for each, the possibility of returning a word-typed result, or - no result. -*/ - -/* Use these to write the name of your wrapper. NOTE: duplicates - VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ - -/* Use an extra level of macroisation so as to ensure the soname/fnname - args are fully macro-expanded before pasting them together. */ -#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd - -#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ - VG_CONCAT4(_vgwZU_,soname,_,fnname) - -#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ - VG_CONCAT4(_vgwZZ_,soname,_,fnname) - -/* Use this macro from within a wrapper function to collect the - context (address and possibly other info) of the original function. - Once you have that you can then use it in one of the CALL_FN_ - macros. The type of the argument _lval is OrigFn. */ -#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) - -/* Derivatives of the main macros below, for calling functions - returning void. */ - -#define CALL_FN_v_v(fnptr) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_v(_junk,fnptr); } while (0) - -#define CALL_FN_v_W(fnptr, arg1) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_W(_junk,fnptr,arg1); } while (0) - -#define CALL_FN_v_WW(fnptr, arg1,arg2) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) - -#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) - -#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0) - -#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0) - -#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0) - -#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0) - -/* ------------------------- x86-{linux,darwin} ---------------- */ - -#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) - -/* These regs are trashed by the hidden call. No need to mention eax - as gcc can already see that, plus causes gcc to bomb. */ -#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" - -/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "subl $12, %%esp\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $16, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "subl $8, %%esp\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $16, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "subl $4, %%esp\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $16, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $16, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "subl $12, %%esp\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $32, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "subl $8, %%esp\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $32, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "subl $4, %%esp\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $32, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $32, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "subl $12, %%esp\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $48, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "subl $8, %%esp\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $48, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "subl $4, %%esp\n\t" \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $48, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "pushl 48(%%eax)\n\t" \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $48, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_x86_linux || PLAT_x86_darwin */ - -/* ------------------------ amd64-{linux,darwin} --------------- */ - -#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) - -/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ - "rdi", "r8", "r9", "r10", "r11" - -/* This is all pretty complex. It's so as to make stack unwinding - work reliably. See bug 243270. The basic problem is the sub and - add of 128 of %rsp in all of the following macros. If gcc believes - the CFA is in %rsp, then unwinding may fail, because what's at the - CFA is not what gcc "expected" when it constructs the CFIs for the - places where the macros are instantiated. - - But we can't just add a CFI annotation to increase the CFA offset - by 128, to match the sub of 128 from %rsp, because we don't know - whether gcc has chosen %rsp as the CFA at that point, or whether it - has chosen some other register (eg, %rbp). In the latter case, - adding a CFI annotation to change the CFA offset is simply wrong. - - So the solution is to get hold of the CFA using - __builtin_dwarf_cfa(), put it in a known register, and add a - CFI annotation to say what the register is. We choose %rbp for - this (perhaps perversely), because: - - (1) %rbp is already subject to unwinding. If a new register was - chosen then the unwinder would have to unwind it in all stack - traces, which is expensive, and - - (2) %rbp is already subject to precise exception updates in the - JIT. If a new register was chosen, we'd have to have precise - exceptions for it too, which reduces performance of the - generated code. - - However .. one extra complication. We can't just whack the result - of __builtin_dwarf_cfa() into %rbp and then add %rbp to the - list of trashed registers at the end of the inline assembly - fragments; gcc won't allow %rbp to appear in that list. Hence - instead we need to stash %rbp in %r15 for the duration of the asm, - and say that %r15 is trashed instead. gcc seems happy to go with - that. - - Oh .. and this all needs to be conditionalised so that it is - unchanged from before this commit, when compiled with older gccs - that don't support __builtin_dwarf_cfa. Furthermore, since - this header file is freestanding, it has to be independent of - config.h, and so the following conditionalisation cannot depend on - configure time checks. - - Although it's not clear from - 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)', - this expression excludes Darwin. - .cfi directives in Darwin assembly appear to be completely - different and I haven't investigated how they work. - - For even more entertainment value, note we have to use the - completely undocumented __builtin_dwarf_cfa(), which appears to - really compute the CFA, whereas __builtin_frame_address(0) claims - to but actually doesn't. See - https://bugs.kde.org/show_bug.cgi?id=243270#c47 -*/ -#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) -# define __FRAME_POINTER \ - ,"r"(__builtin_dwarf_cfa()) -# define VALGRIND_CFI_PROLOGUE \ - "movq %%rbp, %%r15\n\t" \ - "movq %2, %%rbp\n\t" \ - ".cfi_remember_state\n\t" \ - ".cfi_def_cfa rbp, 0\n\t" -# define VALGRIND_CFI_EPILOGUE \ - "movq %%r15, %%rbp\n\t" \ - ".cfi_restore_state\n\t" -#else -# define __FRAME_POINTER -# define VALGRIND_CFI_PROLOGUE -# define VALGRIND_CFI_EPILOGUE -#endif - - -/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned - long) == 8. */ - -/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ - macros. In order not to trash the stack redzone, we need to drop - %rsp by 128 before the hidden call, and restore afterwards. The - nastyness is that it is only by luck that the stack still appears - to be unwindable during the hidden call - since then the behaviour - of any routine using this macro does not match what the CFI data - says. Sigh. - - Why is this important? Imagine that a wrapper has a stack - allocated local, and passes to the hidden call, a pointer to it. - Because gcc does not know about the hidden call, it may allocate - that local in the redzone. Unfortunately the hidden call may then - trash it before it comes to use it. So we must step clear of the - redzone, for the duration of the hidden call, to make it safe. - - Probably the same problem afflicts the other redzone-style ABIs too - (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is - self describing (none of this CFI nonsense) so at least messing - with the stack pointer doesn't give a danger of non-unwindable - stack. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $136,%%rsp\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $8, %%rsp\n" \ - "addq $136,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $16, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $136,%%rsp\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $24, %%rsp\n" \ - "addq $136,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $32, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $136,%%rsp\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $40, %%rsp\n" \ - "addq $136,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - VALGRIND_CFI_PROLOGUE \ - "subq $128,%%rsp\n\t" \ - "pushq 96(%%rax)\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $48, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CFI_EPILOGUE \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -/* This is useful for finding out about the on-stack stuff: - - extern int f9 ( int,int,int,int,int,int,int,int,int ); - extern int f10 ( int,int,int,int,int,int,int,int,int,int ); - extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); - extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); - - int g9 ( void ) { - return f9(11,22,33,44,55,66,77,88,99); - } - int g10 ( void ) { - return f10(11,22,33,44,55,66,77,88,99,110); - } - int g11 ( void ) { - return f11(11,22,33,44,55,66,77,88,99,110,121); - } - int g12 ( void ) { - return f12(11,22,33,44,55,66,77,88,99,110,121,132); - } -*/ - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc32-linux, - sizeof(unsigned long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - _argvec[12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,20(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------- arm-linux ------------------------- */ - -#if defined(PLAT_arm_linux) - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14" - -/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0\n" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0\n" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0\n" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0\n" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "push {r0} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #4 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "push {r0, r1} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #8 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "push {r0, r1, r2} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #12 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "push {r0, r1, r2, r3} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #16 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "ldr r4, [%1, #36] \n\t" \ - "push {r0, r1, r2, r3, r4} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #20 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "ldr r0, [%1, #40] \n\t" \ - "push {r0} \n\t" \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "ldr r4, [%1, #36] \n\t" \ - "push {r0, r1, r2, r3, r4} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #24 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "ldr r0, [%1, #40] \n\t" \ - "ldr r1, [%1, #44] \n\t" \ - "push {r0, r1} \n\t" \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "ldr r4, [%1, #36] \n\t" \ - "push {r0, r1, r2, r3, r4} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #28 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "ldr r0, [%1, #40] \n\t" \ - "ldr r1, [%1, #44] \n\t" \ - "ldr r2, [%1, #48] \n\t" \ - "push {r0, r1, r2} \n\t" \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "ldr r4, [%1, #36] \n\t" \ - "push {r0, r1, r2, r3, r4} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #32 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_arm_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr "\n\t" \ - "lwz 3," #_n_fr "(1)\n\t" \ - "stw 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) \ - "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,68(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr "\n\t" \ - "ld 3," #_n_fr "(1)\n\t" \ - "std 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) \ - "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc64_aix5 */ - - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ -/* */ -/* ------------------------------------------------------------------ */ - -/* Some request codes. There are many more of these, but most are not - exposed to end-user view. These are the public ones, all of the - form 0x1000 + small_number. - - Core ones are in the range 0x00000000--0x0000ffff. The non-public - ones start at 0x2000. -*/ - -/* These macros are used by tools -- they must be public, but don't - embed them into other programs. */ -#define VG_USERREQ_TOOL_BASE(a,b) \ - ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) -#define VG_IS_TOOL_USERREQ(a, b, v) \ - (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) - -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! - This enum comprises an ABI exported by Valgrind to programs - which use client requests. DO NOT CHANGE THE ORDER OF THESE - ENTRIES, NOR DELETE ANY -- add new ones at the end. */ -typedef - enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, - VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, - - /* These allow any function to be called from the simulated - CPU but run on the real CPU. Nb: the first arg passed to - the function is always the ThreadId of the running - thread! So CLIENT_CALL0 actually requires a 1 arg - function, etc. */ - VG_USERREQ__CLIENT_CALL0 = 0x1101, - VG_USERREQ__CLIENT_CALL1 = 0x1102, - VG_USERREQ__CLIENT_CALL2 = 0x1103, - VG_USERREQ__CLIENT_CALL3 = 0x1104, - - /* Can be useful in regression testing suites -- eg. can - send Valgrind's output to /dev/null and still count - errors. */ - VG_USERREQ__COUNT_ERRORS = 0x1201, - - /* These are useful and can be interpreted by any tool that - tracks malloc() et al, by using vg_replace_malloc.c. */ - VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, - VG_USERREQ__FREELIKE_BLOCK = 0x1302, - /* Memory pool support. */ - VG_USERREQ__CREATE_MEMPOOL = 0x1303, - VG_USERREQ__DESTROY_MEMPOOL = 0x1304, - VG_USERREQ__MEMPOOL_ALLOC = 0x1305, - VG_USERREQ__MEMPOOL_FREE = 0x1306, - VG_USERREQ__MEMPOOL_TRIM = 0x1307, - VG_USERREQ__MOVE_MEMPOOL = 0x1308, - VG_USERREQ__MEMPOOL_CHANGE = 0x1309, - VG_USERREQ__MEMPOOL_EXISTS = 0x130a, - - /* Allow printfs to valgrind log. */ - /* The first two pass the va_list argument by value, which - assumes it is the same size as or smaller than a UWord, - which generally isn't the case. Hence are deprecated. - The second two pass the vargs by reference and so are - immune to this problem. */ - /* both :: char* fmt, va_list vargs (DEPRECATED) */ - VG_USERREQ__PRINTF = 0x1401, - VG_USERREQ__PRINTF_BACKTRACE = 0x1402, - /* both :: char* fmt, va_list* vargs */ - VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403, - VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404, - - /* Stack support. */ - VG_USERREQ__STACK_REGISTER = 0x1501, - VG_USERREQ__STACK_DEREGISTER = 0x1502, - VG_USERREQ__STACK_CHANGE = 0x1503, - - /* Wine support */ - VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601, - - /* Querying of debug info. */ - VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701 - } Vg_ClientRequest; - -#if !defined(__GNUC__) -# define __extension__ /* */ -#endif - - -/* - * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind - * client request and whose value equals the client request result. - */ - -#if defined(NVALGRIND) - -#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ - _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - (_zzq_default) - -#else /*defined(NVALGRIND)*/ - -#if defined(_MSC_VER) - -#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ - _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - (vg_VALGRIND_DO_CLIENT_REQUEST_EXPR((uintptr_t)(_zzq_default), \ - (_zzq_request), (uintptr_t)(_zzq_arg1), (uintptr_t)(_zzq_arg2), \ - (uintptr_t)(_zzq_arg3), (uintptr_t)(_zzq_arg4), \ - (uintptr_t)(_zzq_arg5))) - -static __inline unsigned -vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default, - unsigned _zzq_request, uintptr_t _zzq_arg1, - uintptr_t _zzq_arg2, uintptr_t _zzq_arg3, - uintptr_t _zzq_arg4, uintptr_t _zzq_arg5) -{ - unsigned _zzq_rlval; - VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5); - return _zzq_rlval; -} - -#else /*defined(_MSC_VER)*/ - -#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ - _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - (__extension__({unsigned int _zzq_rlval; \ - VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - _zzq_rlval; \ - })) - -#endif /*defined(_MSC_VER)*/ - -#endif /*defined(NVALGRIND)*/ - - -/* Returns the number of Valgrinds this code is running under. That - is, 0 if running natively, 1 if running under Valgrind, 2 if - running under Valgrind which is running under another Valgrind, - etc. */ -#define RUNNING_ON_VALGRIND \ - VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \ - VG_USERREQ__RUNNING_ON_VALGRIND, \ - 0, 0, 0, 0, 0) \ - - -/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + - _qzz_len - 1]. Useful if you are debugging a JITter or some such, - since it provides a way to make sure valgrind will retranslate the - invalidated area. Returns no value. */ -#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DISCARD_TRANSLATIONS, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - } - - -/* These requests are for getting Valgrind itself to print something. - Possibly with a backtrace. This is a really ugly hack. The return value - is the number of characters printed, excluding the "**<pid>** " part at the - start and the backtrace (if present). */ - -#if defined(NVALGRIND) - -# define VALGRIND_PRINTF(...) -# define VALGRIND_PRINTF_BACKTRACE(...) - -#else /* NVALGRIND */ - -#if !defined(_MSC_VER) -/* Modern GCC will optimize the static routine out if unused, - and unused attribute will shut down warnings about it. */ -static int VALGRIND_PRINTF(const char *format, ...) - __attribute__((format(__printf__, 1, 2), __unused__)); -#endif -static int -#if defined(_MSC_VER) -__inline -#endif -VALGRIND_PRINTF(const char *format, ...) -{ - unsigned long _qzz_res; - va_list vargs; - va_start(vargs, format); -#if defined(_MSC_VER) - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, - VG_USERREQ__PRINTF_VALIST_BY_REF, - (uintptr_t)format, - (uintptr_t)&vargs, - 0, 0, 0); -#else - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, - VG_USERREQ__PRINTF_VALIST_BY_REF, - (unsigned long)format, - (unsigned long)&vargs, - 0, 0, 0); -#endif - va_end(vargs); - return (int)_qzz_res; -} - -#if !defined(_MSC_VER) -static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) - __attribute__((format(__printf__, 1, 2), __unused__)); -#endif -static int -#if defined(_MSC_VER) -__inline -#endif -VALGRIND_PRINTF_BACKTRACE(const char *format, ...) -{ - unsigned long _qzz_res; - va_list vargs; - va_start(vargs, format); -#if defined(_MSC_VER) - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, - VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, - (uintptr_t)format, - (uintptr_t)&vargs, - 0, 0, 0); -#else - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, - VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, - (unsigned long)format, - (unsigned long)&vargs, - 0, 0, 0); -#endif - va_end(vargs); - return (int)_qzz_res; -} - -#endif /* NVALGRIND */ - - -/* These requests allow control to move from the simulated CPU to the - real CPU, calling an arbitary function. - - Note that the current ThreadId is inserted as the first argument. - So this call: - - VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) - - requires f to have this signature: - - Word f(Word tid, Word arg1, Word arg2) - - where "Word" is a word-sized type. - - Note that these client requests are not entirely reliable. For example, - if you call a function with them that subsequently calls printf(), - there's a high chance Valgrind will crash. Generally, your prospects of - these working are made higher if the called function does not refer to - any global variables, and does not refer to any libc or other functions - (printf et al). Any kind of entanglement with libc or dynamic linking is - likely to have a bad outcome, for tricky reasons which we've grappled - with a lot in the past. -*/ -#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL0, \ - _qyy_fn, \ - 0, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL1, \ - _qyy_fn, \ - _qyy_arg1, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL2, \ - _qyy_fn, \ - _qyy_arg1, _qyy_arg2, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL3, \ - _qyy_fn, \ - _qyy_arg1, _qyy_arg2, \ - _qyy_arg3, 0); \ - _qyy_res; \ - }) - - -/* Counts the number of errors that have been recorded by a tool. Nb: - the tool must record the errors with VG_(maybe_record_error)() or - VG_(unique_error)() for them to be counted. */ -#define VALGRIND_COUNT_ERRORS \ - __extension__ \ - ({unsigned int _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__COUNT_ERRORS, \ - 0, 0, 0, 0, 0); \ - _qyy_res; \ - }) - -/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing - when heap blocks are allocated in order to give accurate results. This - happens automatically for the standard allocator functions such as - malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete, - delete[], etc. - - But if your program uses a custom allocator, this doesn't automatically - happen, and Valgrind will not do as well. For example, if you allocate - superblocks with mmap() and then allocates chunks of the superblocks, all - Valgrind's observations will be at the mmap() level and it won't know that - the chunks should be considered separate entities. In Memcheck's case, - that means you probably won't get heap block overrun detection (because - there won't be redzones marked as unaddressable) and you definitely won't - get any leak detection. - - The following client requests allow a custom allocator to be annotated so - that it can be handled accurately by Valgrind. - - VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated - by a malloc()-like function. For Memcheck (an illustrative case), this - does two things: - - - It records that the block has been allocated. This means any addresses - within the block mentioned in error messages will be - identified as belonging to the block. It also means that if the block - isn't freed it will be detected by the leak checker. - - - It marks the block as being addressable and undefined (if 'is_zeroed' is - not set), or addressable and defined (if 'is_zeroed' is set). This - controls how accesses to the block by the program are handled. - - 'addr' is the start of the usable block (ie. after any - redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator - can apply redzones -- these are blocks of padding at the start and end of - each block. Adding redzones is recommended as it makes it much more likely - Valgrind will spot block overruns. `is_zeroed' indicates if the memory is - zeroed (or filled with another predictable value), as is the case for - calloc(). - - VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a - heap block -- that will be used by the client program -- is allocated. - It's best to put it at the outermost level of the allocator if possible; - for example, if you have a function my_alloc() which calls - internal_alloc(), and the client request is put inside internal_alloc(), - stack traces relating to the heap block will contain entries for both - my_alloc() and internal_alloc(), which is probably not what you want. - - For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out - custom blocks from within a heap block, B, that has been allocated with - malloc/calloc/new/etc, then block B will be *ignored* during leak-checking - -- the custom blocks will take precedence. - - VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For - Memcheck, it does two things: - - - It records that the block has been deallocated. This assumes that the - block was annotated as having been allocated via - VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. - - - It marks the block as being unaddressable. - - VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a - heap block is deallocated. - - In many cases, these two client requests will not be enough to get your - allocator working well with Memcheck. More specifically, if your allocator - writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call - will be necessary to mark the memory as addressable just before the zeroing - occurs, otherwise you'll get a lot of invalid write errors. For example, - you'll need to do this if your allocator recycles freed blocks, but it - zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK). - Alternatively, if your allocator reuses freed blocks for allocator-internal - data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary. - - Really, what's happening is a blurring of the lines between the client - program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the - memory should be considered unaddressable to the client program, but the - allocator knows more than the rest of the client program and so may be able - to safely access it. Extra client requests are necessary for Valgrind to - understand the distinction between the allocator and the rest of the - program. - - Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it - has to be emulated with MALLOCLIKE/FREELIKE and memory copying. - - Ignored if addr == 0. -*/ -#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MALLOCLIKE_BLOCK, \ - addr, sizeB, rzB, is_zeroed, 0); \ - } - -/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. - Ignored if addr == 0. -*/ -#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__FREELIKE_BLOCK, \ - addr, rzB, 0, 0, 0); \ - } - -/* Create a memory pool. */ -#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__CREATE_MEMPOOL, \ - pool, rzB, is_zeroed, 0, 0); \ - } - -/* Destroy a memory pool. */ -#define VALGRIND_DESTROY_MEMPOOL(pool) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DESTROY_MEMPOOL, \ - pool, 0, 0, 0, 0); \ - } - -/* Associate a piece of memory with a memory pool. */ -#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_ALLOC, \ - pool, addr, size, 0, 0); \ - } - -/* Disassociate a piece of memory from a memory pool. */ -#define VALGRIND_MEMPOOL_FREE(pool, addr) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_FREE, \ - pool, addr, 0, 0, 0); \ - } - -/* Disassociate any pieces outside a particular range. */ -#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_TRIM, \ - pool, addr, size, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MOVE_MEMPOOL, \ - poolA, poolB, 0, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_CHANGE, \ - pool, addrA, addrB, size, 0); \ - } - -/* Return 1 if a mempool exists, else 0. */ -#define VALGRIND_MEMPOOL_EXISTS(pool) \ - __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_EXISTS, \ - pool, 0, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Mark a piece of memory as being a stack. Returns a stack id. */ -#define VALGRIND_STACK_REGISTER(start, end) \ - __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_REGISTER, \ - start, end, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Unmark the piece of memory associated with a stack id as being a - stack. */ -#define VALGRIND_STACK_DEREGISTER(id) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_DEREGISTER, \ - id, 0, 0, 0, 0); \ - } - -/* Change the start and end address of the stack id. */ -#define VALGRIND_STACK_CHANGE(id, start, end) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_CHANGE, \ - id, start, end, 0, 0); \ - } - -/* Load PDB debug info for Wine PE image_map. */ -#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__LOAD_PDB_DEBUGINFO, \ - fd, ptr, total_size, delta, 0); \ - } - -/* Map a code address to a source file name and line number. buf64 - must point to a 64-byte buffer in the caller's address space. The - result will be dumped in there and is guaranteed to be zero - terminated. If no info is found, the first byte is set to zero. */ -#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MAP_IP_TO_SRCLOC, \ - addr, buf64, 0, 0, 0); \ - } - - -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_arm_linux -#undef PLAT_ppc32_aix5 -#undef PLAT_ppc64_aix5 - -#endif /* __VALGRIND_H */ diff --git a/security/sandbox/chromium/base/threading/platform_thread.h b/security/sandbox/chromium/base/threading/platform_thread.h deleted file mode 100644 index e2b09bcb5..000000000 --- a/security/sandbox/chromium/base/threading/platform_thread.h +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// WARNING: You should *NOT* be using this class directly. PlatformThread is -// the low-level platform-specific abstraction to the OS's threading interface. -// You should instead be using a message-loop driven Thread, see thread.h. - -#ifndef BASE_THREADING_PLATFORM_THREAD_H_ -#define BASE_THREADING_PLATFORM_THREAD_H_ - -#include <stddef.h> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/time/time.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#elif defined(OS_POSIX) -#include <pthread.h> -#include <unistd.h> -#endif - -namespace base { - -// Used for logging. Always an integer value. -#if defined(OS_WIN) -typedef DWORD PlatformThreadId; -#elif defined(OS_POSIX) -typedef pid_t PlatformThreadId; -#endif - -// Used for thread checking and debugging. -// Meant to be as fast as possible. -// These are produced by PlatformThread::CurrentRef(), and used to later -// check if we are on the same thread or not by using ==. These are safe -// to copy between threads, but can't be copied to another process as they -// have no meaning there. Also, the internal identifier can be re-used -// after a thread dies, so a PlatformThreadRef cannot be reliably used -// to distinguish a new thread from an old, dead thread. -class PlatformThreadRef { - public: -#if defined(OS_WIN) - typedef DWORD RefType; -#elif defined(OS_POSIX) - typedef pthread_t RefType; -#endif - PlatformThreadRef() - : id_(0) { - } - - explicit PlatformThreadRef(RefType id) - : id_(id) { - } - - bool operator==(PlatformThreadRef other) const { - return id_ == other.id_; - } - - bool is_null() const { - return id_ == 0; - } - private: - RefType id_; -}; - -// Used to operate on threads. -class PlatformThreadHandle { - public: -#if defined(OS_WIN) - typedef void* Handle; -#elif defined(OS_POSIX) - typedef pthread_t Handle; -#endif - - PlatformThreadHandle() : handle_(0) {} - - explicit PlatformThreadHandle(Handle handle) : handle_(handle) {} - - bool is_equal(const PlatformThreadHandle& other) const { - return handle_ == other.handle_; - } - - bool is_null() const { - return !handle_; - } - - Handle platform_handle() const { - return handle_; - } - - private: - Handle handle_; -}; - -const PlatformThreadId kInvalidThreadId(0); - -// Valid values for priority of Thread::Options and SimpleThread::Options, and -// SetCurrentThreadPriority(), listed in increasing order of importance. -enum class ThreadPriority { - // Suitable for threads that shouldn't disrupt high priority work. - BACKGROUND, - // Default priority level. - NORMAL, - // Suitable for threads which generate data for the display (at ~60Hz). - DISPLAY, - // Suitable for low-latency, glitch-resistant audio. - REALTIME_AUDIO, -}; - -// A namespace for low-level thread functions. -class BASE_EXPORT PlatformThread { - public: - // Implement this interface to run code on a background thread. Your - // ThreadMain method will be called on the newly created thread. - class BASE_EXPORT Delegate { - public: - virtual void ThreadMain() = 0; - - protected: - virtual ~Delegate() {} - }; - - // Gets the current thread id, which may be useful for logging purposes. - static PlatformThreadId CurrentId(); - - // Gets the current thread reference, which can be used to check if - // we're on the right thread quickly. - static PlatformThreadRef CurrentRef(); - - // Get the handle representing the current thread. On Windows, this is a - // pseudo handle constant which will always represent the thread using it and - // hence should not be shared with other threads nor be used to differentiate - // the current thread from another. - static PlatformThreadHandle CurrentHandle(); - - // Yield the current thread so another thread can be scheduled. - static void YieldCurrentThread(); - - // Sleeps for the specified duration. - static void Sleep(base::TimeDelta duration); - - // Sets the thread name visible to debuggers/tools. This has no effect - // otherwise. - static void SetName(const std::string& name); - - // Gets the thread name, if previously set by SetName. - static const char* GetName(); - - // Creates a new thread. The |stack_size| parameter can be 0 to indicate - // that the default stack size should be used. Upon success, - // |*thread_handle| will be assigned a handle to the newly created thread, - // and |delegate|'s ThreadMain method will be executed on the newly created - // thread. - // NOTE: When you are done with the thread handle, you must call Join to - // release system resources associated with the thread. You must ensure that - // the Delegate object outlives the thread. - static bool Create(size_t stack_size, - Delegate* delegate, - PlatformThreadHandle* thread_handle) { - return CreateWithPriority(stack_size, delegate, thread_handle, - ThreadPriority::NORMAL); - } - - // CreateWithPriority() does the same thing as Create() except the priority of - // the thread is set based on |priority|. - static bool CreateWithPriority(size_t stack_size, Delegate* delegate, - PlatformThreadHandle* thread_handle, - ThreadPriority priority); - - // CreateNonJoinable() does the same thing as Create() except the thread - // cannot be Join()'d. Therefore, it also does not output a - // PlatformThreadHandle. - static bool CreateNonJoinable(size_t stack_size, Delegate* delegate); - - // Joins with a thread created via the Create function. This function blocks - // the caller until the designated thread exits. This will invalidate - // |thread_handle|. - static void Join(PlatformThreadHandle thread_handle); - - // Toggles the current thread's priority at runtime. A thread may not be able - // to raise its priority back up after lowering it if the process does not - // have a proper permission, e.g. CAP_SYS_NICE on Linux. - // Since changing other threads' priority is not permitted in favor of - // security, this interface is restricted to change only the current thread - // priority (https://crbug.com/399473). - static void SetCurrentThreadPriority(ThreadPriority priority); - - static ThreadPriority GetCurrentThreadPriority(); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); -}; - -} // namespace base - -#endif // BASE_THREADING_PLATFORM_THREAD_H_ diff --git a/security/sandbox/chromium/base/threading/platform_thread_internal_posix.cc b/security/sandbox/chromium/base/threading/platform_thread_internal_posix.cc deleted file mode 100644 index 9af02044f..000000000 --- a/security/sandbox/chromium/base/threading/platform_thread_internal_posix.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread_internal_posix.h" - -#include "base/logging.h" - -namespace base { - -namespace internal { - -int ThreadPriorityToNiceValue(ThreadPriority priority) { - for (const ThreadPriorityToNiceValuePair& pair : - kThreadPriorityToNiceValueMap) { - if (pair.priority == priority) - return pair.nice_value; - } - NOTREACHED() << "Unknown ThreadPriority"; - return 0; -} - -ThreadPriority NiceValueToThreadPriority(int nice_value) { - for (const ThreadPriorityToNiceValuePair& pair : - kThreadPriorityToNiceValueMap) { - if (pair.nice_value == nice_value) - return pair.priority; - } - NOTREACHED() << "Unknown nice value"; - return ThreadPriority::NORMAL; -} - -} // namespace internal - -} // namespace base diff --git a/security/sandbox/chromium/base/threading/platform_thread_internal_posix.h b/security/sandbox/chromium/base/threading/platform_thread_internal_posix.h deleted file mode 100644 index 05a8d1e26..000000000 --- a/security/sandbox/chromium/base/threading/platform_thread_internal_posix.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_ -#define BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_ - -#include "base/threading/platform_thread.h" - -namespace base { - -namespace internal { - -struct ThreadPriorityToNiceValuePair { - ThreadPriority priority; - int nice_value; -}; -extern const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4]; - -// Returns the nice value matching |priority| based on the platform-specific -// implementation of kThreadPriorityToNiceValueMap. -int ThreadPriorityToNiceValue(ThreadPriority priority); - -// Returns the ThreadPrioirty matching |nice_value| based on the platform- -// specific implementation of kThreadPriorityToNiceValueMap. -ThreadPriority NiceValueToThreadPriority(int nice_value); - -// Allows platform specific tweaks to the generic POSIX solution for -// SetCurrentThreadPriority. Returns true if the platform-specific -// implementation handled this |priority| change, false if the generic -// implementation should instead proceed. -bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority); - -// Returns true if there is a platform-specific ThreadPriority set on the -// current thread (and returns the actual ThreadPriority via |priority|). -// Returns false otherwise, leaving |priority| untouched. -bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority); - -} // namespace internal - -} // namespace base - -#endif // BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_ diff --git a/security/sandbox/chromium/base/threading/platform_thread_linux.cc b/security/sandbox/chromium/base/threading/platform_thread_linux.cc deleted file mode 100644 index 4057ede94..000000000 --- a/security/sandbox/chromium/base/threading/platform_thread_linux.cc +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread.h" - -#include <errno.h> -#include <sched.h> -#include <stddef.h> - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/threading/platform_thread_internal_posix.h" -#include "base/threading/thread_id_name_manager.h" -#include "base/tracked_objects.h" -#include "build/build_config.h" - -#if !defined(OS_NACL) -#include <pthread.h> -#include <sys/prctl.h> -#include <sys/types.h> -#include <unistd.h> -#endif - -namespace base { - -namespace internal { - -namespace { -#if !defined(OS_NACL) -const struct sched_param kRealTimePrio = {8}; -const struct sched_param kResetPrio = {0}; -#endif -} // namespace - -const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { - {ThreadPriority::BACKGROUND, 10}, - {ThreadPriority::NORMAL, 0}, - {ThreadPriority::DISPLAY, -6}, - {ThreadPriority::REALTIME_AUDIO, -10}, -}; - -bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { -#if !defined(OS_NACL) - ThreadPriority current_priority; - if (priority != ThreadPriority::REALTIME_AUDIO && - GetCurrentThreadPriorityForPlatform(¤t_priority) && - current_priority == ThreadPriority::REALTIME_AUDIO) { - // If the pthread's round-robin scheduler is already enabled, and the new - // priority will use setpriority() instead, the pthread scheduler should be - // reset to use SCHED_OTHER so that setpriority() just works. - pthread_setschedparam(pthread_self(), SCHED_OTHER, &kResetPrio); - return false; - } - return priority == ThreadPriority::REALTIME_AUDIO && - pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; -#else - return false; -#endif -} - -bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { -#if !defined(OS_NACL) - int maybe_sched_rr = 0; - struct sched_param maybe_realtime_prio = {0}; - if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, - &maybe_realtime_prio) == 0 && - maybe_sched_rr == SCHED_RR && - maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) { - *priority = ThreadPriority::REALTIME_AUDIO; - return true; - } -#endif - return false; -} - -} // namespace internal - -// static -void PlatformThread::SetName(const std::string& name) { - ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name); - tracked_objects::ThreadData::InitializeThreadContext(name); - -#if !defined(OS_NACL) - // On linux we can get the thread names to show up in the debugger by setting - // the process name for the LWP. We don't want to do this for the main - // thread because that would rename the process, causing tools like killall - // to stop working. - if (PlatformThread::CurrentId() == getpid()) - return; - - // http://0pointer.de/blog/projects/name-your-threads.html - // Set the name for the LWP (which gets truncated to 15 characters). - // Note that glibc also has a 'pthread_setname_np' api, but it may not be - // available everywhere and it's only benefit over using prctl directly is - // that it can set the name of threads other than the current thread. - int err = prctl(PR_SET_NAME, name.c_str()); - // We expect EPERM failures in sandboxed processes, just ignore those. - if (err < 0 && errno != EPERM) - DPLOG(ERROR) << "prctl(PR_SET_NAME)"; -#endif // !defined(OS_NACL) -} - -void InitThreading() {} - -void InitOnThread() {} - -void TerminateOnThread() {} - -size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { -#if !defined(THREAD_SANITIZER) - return 0; -#else - // ThreadSanitizer bloats the stack heavily. Evidence has been that the - // default stack size isn't enough for some browser tests. - return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). -#endif -} - -} // namespace base diff --git a/security/sandbox/chromium/base/threading/platform_thread_posix.cc b/security/sandbox/chromium/base/threading/platform_thread_posix.cc deleted file mode 100644 index 39a007316..000000000 --- a/security/sandbox/chromium/base/threading/platform_thread_posix.cc +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread.h" - -#include <errno.h> -#include <pthread.h> -#include <sched.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/resource.h> -#include <sys/time.h> - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/platform_thread_internal_posix.h" -#include "base/threading/thread_id_name_manager.h" -#include "base/threading/thread_restrictions.h" -#include "build/build_config.h" - -#if defined(OS_LINUX) -#include <sys/syscall.h> -#elif defined(OS_ANDROID) -#include <sys/types.h> -#endif - -namespace base { - -void InitThreading(); -void InitOnThread(); -void TerminateOnThread(); -size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes); - -namespace { - -struct ThreadParams { - ThreadParams() - : delegate(NULL), joinable(false), priority(ThreadPriority::NORMAL) {} - - PlatformThread::Delegate* delegate; - bool joinable; - ThreadPriority priority; -}; - -void* ThreadFunc(void* params) { - base::InitOnThread(); - - PlatformThread::Delegate* delegate = nullptr; - - { - scoped_ptr<ThreadParams> thread_params(static_cast<ThreadParams*>(params)); - - delegate = thread_params->delegate; - if (!thread_params->joinable) - base::ThreadRestrictions::SetSingletonAllowed(false); - - if (thread_params->priority != ThreadPriority::NORMAL) - PlatformThread::SetCurrentThreadPriority(thread_params->priority); - } - - ThreadIdNameManager::GetInstance()->RegisterThread( - PlatformThread::CurrentHandle().platform_handle(), - PlatformThread::CurrentId()); - - delegate->ThreadMain(); - - ThreadIdNameManager::GetInstance()->RemoveName( - PlatformThread::CurrentHandle().platform_handle(), - PlatformThread::CurrentId()); - - base::TerminateOnThread(); - return NULL; -} - -bool CreateThread(size_t stack_size, - bool joinable, - PlatformThread::Delegate* delegate, - PlatformThreadHandle* thread_handle, - ThreadPriority priority) { - DCHECK(thread_handle); - base::InitThreading(); - - pthread_attr_t attributes; - pthread_attr_init(&attributes); - - // Pthreads are joinable by default, so only specify the detached - // attribute if the thread should be non-joinable. - if (!joinable) - pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED); - - // Get a better default if available. - if (stack_size == 0) - stack_size = base::GetDefaultThreadStackSize(attributes); - - if (stack_size > 0) - pthread_attr_setstacksize(&attributes, stack_size); - - scoped_ptr<ThreadParams> params(new ThreadParams); - params->delegate = delegate; - params->joinable = joinable; - params->priority = priority; - - pthread_t handle; - int err = pthread_create(&handle, &attributes, ThreadFunc, params.get()); - bool success = !err; - if (success) { - // ThreadParams should be deleted on the created thread after used. - ignore_result(params.release()); - } else { - // Value of |handle| is undefined if pthread_create fails. - handle = 0; - errno = err; - PLOG(ERROR) << "pthread_create"; - } - *thread_handle = PlatformThreadHandle(handle); - - pthread_attr_destroy(&attributes); - - return success; -} - -} // namespace - -// static -PlatformThreadId PlatformThread::CurrentId() { - // Pthreads doesn't have the concept of a thread ID, so we have to reach down - // into the kernel. -#if defined(OS_MACOSX) - return pthread_mach_thread_np(pthread_self()); -#elif defined(OS_LINUX) - return syscall(__NR_gettid); -#elif defined(OS_ANDROID) - return gettid(); -#elif defined(OS_SOLARIS) || defined(OS_QNX) - return pthread_self(); -#elif defined(OS_NACL) && defined(__GLIBC__) - return pthread_self(); -#elif defined(OS_NACL) && !defined(__GLIBC__) - // Pointers are 32-bits in NaCl. - return reinterpret_cast<int32_t>(pthread_self()); -#elif defined(OS_POSIX) - return reinterpret_cast<int64_t>(pthread_self()); -#endif -} - -// static -PlatformThreadRef PlatformThread::CurrentRef() { - return PlatformThreadRef(pthread_self()); -} - -// static -PlatformThreadHandle PlatformThread::CurrentHandle() { - return PlatformThreadHandle(pthread_self()); -} - -// static -void PlatformThread::YieldCurrentThread() { - sched_yield(); -} - -// static -void PlatformThread::Sleep(TimeDelta duration) { - struct timespec sleep_time, remaining; - - // Break the duration into seconds and nanoseconds. - // NOTE: TimeDelta's microseconds are int64s while timespec's - // nanoseconds are longs, so this unpacking must prevent overflow. - sleep_time.tv_sec = duration.InSeconds(); - duration -= TimeDelta::FromSeconds(sleep_time.tv_sec); - sleep_time.tv_nsec = duration.InMicroseconds() * 1000; // nanoseconds - - while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR) - sleep_time = remaining; -} - -// static -const char* PlatformThread::GetName() { - return ThreadIdNameManager::GetInstance()->GetName(CurrentId()); -} - -// static -bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate, - PlatformThreadHandle* thread_handle, - ThreadPriority priority) { - return CreateThread(stack_size, true, // joinable thread - delegate, thread_handle, priority); -} - -// static -bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { - PlatformThreadHandle unused; - - bool result = CreateThread(stack_size, false /* non-joinable thread */, - delegate, &unused, ThreadPriority::NORMAL); - return result; -} - -// static -void PlatformThread::Join(PlatformThreadHandle thread_handle) { - // Joining another thread may block the current thread for a long time, since - // the thread referred to by |thread_handle| may still be running long-lived / - // blocking tasks. - base::ThreadRestrictions::AssertIOAllowed(); - CHECK_EQ(0, pthread_join(thread_handle.platform_handle(), NULL)); -} - -// Mac has its own Set/GetCurrentThreadPriority() implementations. -#if !defined(OS_MACOSX) - -// static -void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { -#if defined(OS_NACL) - NOTIMPLEMENTED(); -#else - if (internal::SetCurrentThreadPriorityForPlatform(priority)) - return; - - // setpriority(2) should change the whole thread group's (i.e. process) - // priority. However, as stated in the bugs section of - // http://man7.org/linux/man-pages/man2/getpriority.2.html: "under the current - // Linux/NPTL implementation of POSIX threads, the nice value is a per-thread - // attribute". Also, 0 is prefered to the current thread id since it is - // equivalent but makes sandboxing easier (https://crbug.com/399473). - const int nice_setting = internal::ThreadPriorityToNiceValue(priority); - if (setpriority(PRIO_PROCESS, 0, nice_setting)) { - DVPLOG(1) << "Failed to set nice value of thread (" - << PlatformThread::CurrentId() << ") to " << nice_setting; - } -#endif // defined(OS_NACL) -} - -// static -ThreadPriority PlatformThread::GetCurrentThreadPriority() { -#if defined(OS_NACL) - NOTIMPLEMENTED(); - return ThreadPriority::NORMAL; -#else - // Mirrors SetCurrentThreadPriority()'s implementation. - ThreadPriority platform_specific_priority; - if (internal::GetCurrentThreadPriorityForPlatform( - &platform_specific_priority)) { - return platform_specific_priority; - } - - // Need to clear errno before calling getpriority(): - // http://man7.org/linux/man-pages/man2/getpriority.2.html - errno = 0; - int nice_value = getpriority(PRIO_PROCESS, 0); - if (errno != 0) { - DVPLOG(1) << "Failed to get nice value of thread (" - << PlatformThread::CurrentId() << ")"; - return ThreadPriority::NORMAL; - } - - return internal::NiceValueToThreadPriority(nice_value); -#endif // !defined(OS_NACL) -} - -#endif // !defined(OS_MACOSX) - -} // namespace base diff --git a/security/sandbox/chromium/base/threading/platform_thread_win.cc b/security/sandbox/chromium/base/threading/platform_thread_win.cc deleted file mode 100644 index d5bd9bed0..000000000 --- a/security/sandbox/chromium/base/threading/platform_thread_win.cc +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread.h" - -#include <stddef.h> - -#include "base/debug/alias.h" -#include "base/debug/profiler.h" -#include "base/logging.h" -#include "base/threading/thread_id_name_manager.h" -#include "base/threading/thread_restrictions.h" -#include "base/tracked_objects.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" - -namespace base { - -namespace { - -// The information on how to set the thread name comes from -// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx -const DWORD kVCThreadNameException = 0x406D1388; - -typedef struct tagTHREADNAME_INFO { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. -} THREADNAME_INFO; - -// This function has try handling, so it is separated out of its caller. -void SetNameInternal(PlatformThreadId thread_id, const char* name) { - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = thread_id; - info.dwFlags = 0; - - __try { - RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD), - reinterpret_cast<DWORD_PTR*>(&info)); - } __except(EXCEPTION_CONTINUE_EXECUTION) { - } -} - -struct ThreadParams { - PlatformThread::Delegate* delegate; - bool joinable; - ThreadPriority priority; -}; - -DWORD __stdcall ThreadFunc(void* params) { - ThreadParams* thread_params = static_cast<ThreadParams*>(params); - PlatformThread::Delegate* delegate = thread_params->delegate; - if (!thread_params->joinable) - base::ThreadRestrictions::SetSingletonAllowed(false); - - if (thread_params->priority != ThreadPriority::NORMAL) - PlatformThread::SetCurrentThreadPriority(thread_params->priority); - - // Retrieve a copy of the thread handle to use as the key in the - // thread name mapping. - PlatformThreadHandle::Handle platform_handle; - BOOL did_dup = DuplicateHandle(GetCurrentProcess(), - GetCurrentThread(), - GetCurrentProcess(), - &platform_handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS); - - win::ScopedHandle scoped_platform_handle; - - if (did_dup) { - scoped_platform_handle.Set(platform_handle); - ThreadIdNameManager::GetInstance()->RegisterThread( - scoped_platform_handle.Get(), - PlatformThread::CurrentId()); - } - - delete thread_params; - delegate->ThreadMain(); - - if (did_dup) { - ThreadIdNameManager::GetInstance()->RemoveName( - scoped_platform_handle.Get(), - PlatformThread::CurrentId()); - } - - return 0; -} - -// CreateThreadInternal() matches PlatformThread::CreateWithPriority(), except -// that |out_thread_handle| may be nullptr, in which case a non-joinable thread -// is created. -bool CreateThreadInternal(size_t stack_size, - PlatformThread::Delegate* delegate, - PlatformThreadHandle* out_thread_handle, - ThreadPriority priority) { - unsigned int flags = 0; - if (stack_size > 0 && base::win::GetVersion() >= base::win::VERSION_XP) { - flags = STACK_SIZE_PARAM_IS_A_RESERVATION; - } else { - stack_size = 0; - } - - ThreadParams* params = new ThreadParams; - params->delegate = delegate; - params->joinable = out_thread_handle != nullptr; - params->priority = priority; - - // Using CreateThread here vs _beginthreadex makes thread creation a bit - // faster and doesn't require the loader lock to be available. Our code will - // have to work running on CreateThread() threads anyway, since we run code - // on the Windows thread pool, etc. For some background on the difference: - // http://www.microsoft.com/msj/1099/win32/win321099.aspx - void* thread_handle = - ::CreateThread(nullptr, stack_size, ThreadFunc, params, flags, nullptr); - if (!thread_handle) { - delete params; - return false; - } - - if (out_thread_handle) - *out_thread_handle = PlatformThreadHandle(thread_handle); - else - CloseHandle(thread_handle); - return true; -} - -} // namespace - -// static -PlatformThreadId PlatformThread::CurrentId() { - return ::GetCurrentThreadId(); -} - -// static -PlatformThreadRef PlatformThread::CurrentRef() { - return PlatformThreadRef(::GetCurrentThreadId()); -} - -// static -PlatformThreadHandle PlatformThread::CurrentHandle() { - return PlatformThreadHandle(::GetCurrentThread()); -} - -// static -void PlatformThread::YieldCurrentThread() { - ::Sleep(0); -} - -// static -void PlatformThread::Sleep(TimeDelta duration) { - // When measured with a high resolution clock, Sleep() sometimes returns much - // too early. We may need to call it repeatedly to get the desired duration. - TimeTicks end = TimeTicks::Now() + duration; - for (TimeTicks now = TimeTicks::Now(); now < end; now = TimeTicks::Now()) - ::Sleep(static_cast<DWORD>((end - now).InMillisecondsRoundedUp())); -} - -// static -void PlatformThread::SetName(const std::string& name) { - ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name); - - // On Windows only, we don't need to tell the profiler about the "BrokerEvent" - // thread, as it exists only in the chrome.exe image, and never spawns or runs - // tasks (items which could be profiled). This test avoids the notification, - // which would also (as a side effect) initialize the profiler in this unused - // context, including setting up thread local storage, etc. The performance - // impact is not terrible, but there is no reason to do initialize it. - if (name != "BrokerEvent") - tracked_objects::ThreadData::InitializeThreadContext(name); - - // The debugger needs to be around to catch the name in the exception. If - // there isn't a debugger, we are just needlessly throwing an exception. - // If this image file is instrumented, we raise the exception anyway - // to provide the profiler with human-readable thread names. - if (!::IsDebuggerPresent() && !base::debug::IsBinaryInstrumented()) - return; - - SetNameInternal(CurrentId(), name.c_str()); -} - -// static -const char* PlatformThread::GetName() { - return ThreadIdNameManager::GetInstance()->GetName(CurrentId()); -} - -// static -bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate, - PlatformThreadHandle* thread_handle, - ThreadPriority priority) { - DCHECK(thread_handle); - return CreateThreadInternal(stack_size, delegate, thread_handle, priority); -} - -// static -bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { - return CreateThreadInternal(stack_size, delegate, nullptr, - ThreadPriority::NORMAL); -} - -// static -void PlatformThread::Join(PlatformThreadHandle thread_handle) { - DCHECK(thread_handle.platform_handle()); - // TODO(willchan): Enable this check once I can get it to work for Windows - // shutdown. - // Joining another thread may block the current thread for a long time, since - // the thread referred to by |thread_handle| may still be running long-lived / - // blocking tasks. -#if 0 - base::ThreadRestrictions::AssertIOAllowed(); -#endif - - // Wait for the thread to exit. It should already have terminated but make - // sure this assumption is valid. - DWORD result = WaitForSingleObject(thread_handle.platform_handle(), INFINITE); - if (result != WAIT_OBJECT_0) { - // Debug info for bug 127931. - DWORD error = GetLastError(); - debug::Alias(&error); - debug::Alias(&result); - CHECK(false); - } - - CloseHandle(thread_handle.platform_handle()); -} - -// static -void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { - int desired_priority = THREAD_PRIORITY_ERROR_RETURN; - switch (priority) { - case ThreadPriority::BACKGROUND: - desired_priority = THREAD_PRIORITY_LOWEST; - break; - case ThreadPriority::NORMAL: - desired_priority = THREAD_PRIORITY_NORMAL; - break; - case ThreadPriority::DISPLAY: - desired_priority = THREAD_PRIORITY_ABOVE_NORMAL; - break; - case ThreadPriority::REALTIME_AUDIO: - desired_priority = THREAD_PRIORITY_TIME_CRITICAL; - break; - default: - NOTREACHED() << "Unknown priority."; - break; - } - DCHECK_NE(desired_priority, THREAD_PRIORITY_ERROR_RETURN); - -#ifndef NDEBUG - const BOOL success = -#endif - ::SetThreadPriority(PlatformThread::CurrentHandle().platform_handle(), - desired_priority); - DPLOG_IF(ERROR, !success) << "Failed to set thread priority to " - << desired_priority; -} - -// static -ThreadPriority PlatformThread::GetCurrentThreadPriority() { - int priority = - ::GetThreadPriority(PlatformThread::CurrentHandle().platform_handle()); - switch (priority) { - case THREAD_PRIORITY_LOWEST: - return ThreadPriority::BACKGROUND; - case THREAD_PRIORITY_NORMAL: - return ThreadPriority::NORMAL; - case THREAD_PRIORITY_ABOVE_NORMAL: - return ThreadPriority::DISPLAY; - case THREAD_PRIORITY_TIME_CRITICAL: - return ThreadPriority::REALTIME_AUDIO; - case THREAD_PRIORITY_ERROR_RETURN: - DPCHECK(false) << "GetThreadPriority error"; // Falls through. - default: - NOTREACHED() << "Unexpected priority: " << priority; - return ThreadPriority::NORMAL; - } -} - -} // namespace base diff --git a/security/sandbox/chromium/base/threading/sequenced_worker_pool.h b/security/sandbox/chromium/base/threading/sequenced_worker_pool.h deleted file mode 100644 index ba0e44421..000000000 --- a/security/sandbox/chromium/base/threading/sequenced_worker_pool.h +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_THREADING_SEQUENCED_WORKER_POOL_H_ -#define BASE_THREADING_SEQUENCED_WORKER_POOL_H_ - -#include <stddef.h> - -#include <cstddef> -#include <string> - -#include "base/base_export.h" -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/single_thread_task_runner.h" -#include "base/task_runner.h" - -namespace tracked_objects { -class Location; -} // namespace tracked_objects - -namespace base { - -class SingleThreadTaskRunner; - -template <class T> class DeleteHelper; - -class SequencedTaskRunner; - -// A worker thread pool that enforces ordering between sets of tasks. It also -// allows you to specify what should happen to your tasks on shutdown. -// -// To enforce ordering, get a unique sequence token from the pool and post all -// tasks you want to order with the token. All tasks with the same token are -// guaranteed to execute serially, though not necessarily on the same thread. -// This means that: -// -// - No two tasks with the same token will run at the same time. -// -// - Given two tasks T1 and T2 with the same token such that T2 will -// run after T1, then T2 will start after T1 is destroyed. -// -// - If T2 will run after T1, then all memory changes in T1 and T1's -// destruction will be visible to T2. -// -// Example: -// SequencedWorkerPool::SequenceToken token = -// SequencedWorkerPool::GetSequenceToken(); -// pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN, -// FROM_HERE, base::Bind(...)); -// pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN, -// FROM_HERE, base::Bind(...)); -// -// You can make named sequence tokens to make it easier to share a token -// across different components. -// -// You can also post tasks to the pool without ordering using PostWorkerTask. -// These will be executed in an unspecified order. The order of execution -// between tasks with different sequence tokens is also unspecified. -// -// This class may be leaked on shutdown to facilitate fast shutdown. The -// expected usage, however, is to call Shutdown(), which correctly accounts -// for CONTINUE_ON_SHUTDOWN behavior and is required for BLOCK_SHUTDOWN -// behavior. -// -// Implementation note: This does not use a base::WorkerPool since that does -// not enforce shutdown semantics or allow us to specify how many worker -// threads to run. For the typical use case of random background work, we don't -// necessarily want to be super aggressive about creating threads. -// -// Note that SequencedWorkerPool is RefCountedThreadSafe (inherited -// from TaskRunner). -// -// Test-only code should wrap this in a base::SequencedWorkerPoolOwner to avoid -// memory leaks. See http://crbug.com/273800 -class BASE_EXPORT SequencedWorkerPool : public TaskRunner { - public: - // Defines what should happen to a task posted to the worker pool on - // shutdown. - enum WorkerShutdown { - // Tasks posted with this mode which have not run at shutdown will be - // deleted rather than run, and any tasks with this mode running at - // shutdown will be ignored (the worker thread will not be joined). - // - // This option provides a nice way to post stuff you don't want blocking - // shutdown. For example, you might be doing a slow DNS lookup and if it's - // blocked on the OS, you may not want to stop shutdown, since the result - // doesn't really matter at that point. - // - // However, you need to be very careful what you do in your callback when - // you use this option. Since the thread will continue to run until the OS - // terminates the process, the app can be in the process of tearing down - // when you're running. This means any singletons or global objects you - // use may suddenly become invalid out from under you. For this reason, - // it's best to use this only for slow but simple operations like the DNS - // example. - CONTINUE_ON_SHUTDOWN, - - // Tasks posted with this mode that have not started executing at - // shutdown will be deleted rather than executed. However, any tasks that - // have already begun executing when shutdown is called will be allowed - // to continue, and will block shutdown until completion. - // - // Note: Because Shutdown() may block while these tasks are executing, - // care must be taken to ensure that they do not block on the thread that - // called Shutdown(), as this may lead to deadlock. - SKIP_ON_SHUTDOWN, - - // Tasks posted with this mode will block shutdown until they're - // executed. Since this can have significant performance implications, - // use sparingly. - // - // Generally, this should be used only for user data, for example, a task - // writing a preference file. - // - // If a task is posted during shutdown, it will not get run since the - // workers may already be stopped. In this case, the post operation will - // fail (return false) and the task will be deleted. - BLOCK_SHUTDOWN, - }; - - // Opaque identifier that defines sequencing of tasks posted to the worker - // pool. - class BASE_EXPORT SequenceToken { - public: - SequenceToken() : id_(0) {} - ~SequenceToken() {} - - bool Equals(const SequenceToken& other) const { - return id_ == other.id_; - } - - // Returns false if current thread is executing an unsequenced task. - bool IsValid() const { - return id_ != 0; - } - - // Returns a string representation of this token. This method should only be - // used for debugging. - std::string ToString() const; - - private: - friend class SequencedWorkerPool; - - explicit SequenceToken(int id) : id_(id) {} - - int id_; - }; - - // Allows tests to perform certain actions. - class TestingObserver { - public: - virtual ~TestingObserver() {} - virtual void OnHasWork() = 0; - virtual void WillWaitForShutdown() = 0; - virtual void OnDestruct() = 0; - }; - - // Gets the SequencedToken of the current thread. - // If current thread is not a SequencedWorkerPool worker thread or is running - // an unsequenced task, returns an invalid SequenceToken. - static SequenceToken GetSequenceTokenForCurrentThread(); - - // Gets a SequencedTaskRunner for the current thread. If the current thread is - // running an unsequenced task, a new SequenceToken will be generated and set, - // so that the returned SequencedTaskRunner is guaranteed to run tasks after - // the current task has finished running. - static scoped_refptr<SequencedTaskRunner> - GetSequencedTaskRunnerForCurrentThread(); - - // Returns a unique token that can be used to sequence tasks posted to - // PostSequencedWorkerTask(). Valid tokens are always nonzero. - // TODO(bauerb): Rename this to better differentiate from - // GetSequenceTokenForCurrentThread(). - static SequenceToken GetSequenceToken(); - - // Returns the SequencedWorkerPool that owns this thread, or null if the - // current thread is not a SequencedWorkerPool worker thread. - static scoped_refptr<SequencedWorkerPool> GetWorkerPoolForCurrentThread(); - - // When constructing a SequencedWorkerPool, there must be a - // ThreadTaskRunnerHandle on the current thread unless you plan to - // deliberately leak it. - - // Pass the maximum number of threads (they will be lazily created as needed) - // and a prefix for the thread name to aid in debugging. - SequencedWorkerPool(size_t max_threads, - const std::string& thread_name_prefix); - - // Like above, but with |observer| for testing. Does not take ownership of - // |observer|. - SequencedWorkerPool(size_t max_threads, - const std::string& thread_name_prefix, - TestingObserver* observer); - - // Returns the sequence token associated with the given name. Calling this - // function multiple times with the same string will always produce the - // same sequence token. If the name has not been used before, a new token - // will be created. - SequenceToken GetNamedSequenceToken(const std::string& name); - - // Returns a SequencedTaskRunner wrapper which posts to this - // SequencedWorkerPool using the given sequence token. Tasks with nonzero - // delay are posted with SKIP_ON_SHUTDOWN behavior and tasks with zero delay - // are posted with BLOCK_SHUTDOWN behavior. - scoped_refptr<SequencedTaskRunner> GetSequencedTaskRunner( - SequenceToken token); - - // Returns a SequencedTaskRunner wrapper which posts to this - // SequencedWorkerPool using the given sequence token. Tasks with nonzero - // delay are posted with SKIP_ON_SHUTDOWN behavior and tasks with zero delay - // are posted with the given shutdown behavior. - scoped_refptr<SequencedTaskRunner> GetSequencedTaskRunnerWithShutdownBehavior( - SequenceToken token, - WorkerShutdown shutdown_behavior); - - // Returns a TaskRunner wrapper which posts to this SequencedWorkerPool using - // the given shutdown behavior. Tasks with nonzero delay are posted with - // SKIP_ON_SHUTDOWN behavior and tasks with zero delay are posted with the - // given shutdown behavior. - scoped_refptr<TaskRunner> GetTaskRunnerWithShutdownBehavior( - WorkerShutdown shutdown_behavior); - - // Posts the given task for execution in the worker pool. Tasks posted with - // this function will execute in an unspecified order on a background thread. - // Returns true if the task was posted. If your tasks have ordering - // requirements, see PostSequencedWorkerTask(). - // - // This class will attempt to delete tasks that aren't run - // (non-block-shutdown semantics) but can't guarantee that this happens. If - // all worker threads are busy running CONTINUE_ON_SHUTDOWN tasks, there - // will be no workers available to delete these tasks. And there may be - // tasks with the same sequence token behind those CONTINUE_ON_SHUTDOWN - // tasks. Deleting those tasks before the previous one has completed could - // cause nondeterministic crashes because the task could be keeping some - // objects alive which do work in their destructor, which could voilate the - // assumptions of the running task. - // - // The task will be guaranteed to run to completion before shutdown - // (BLOCK_SHUTDOWN semantics). - // - // Returns true if the task was posted successfully. This may fail during - // shutdown regardless of the specified ShutdownBehavior. - bool PostWorkerTask(const tracked_objects::Location& from_here, - const Closure& task); - - // Same as PostWorkerTask but allows a delay to be specified (although doing - // so changes the shutdown behavior). The task will be run after the given - // delay has elapsed. - // - // If the delay is nonzero, the task won't be guaranteed to run to completion - // before shutdown (SKIP_ON_SHUTDOWN semantics) to avoid shutdown hangs. - // If the delay is zero, this behaves exactly like PostWorkerTask, i.e. the - // task will be guaranteed to run to completion before shutdown - // (BLOCK_SHUTDOWN semantics). - bool PostDelayedWorkerTask(const tracked_objects::Location& from_here, - const Closure& task, - TimeDelta delay); - - // Same as PostWorkerTask but allows specification of the shutdown behavior. - bool PostWorkerTaskWithShutdownBehavior( - const tracked_objects::Location& from_here, - const Closure& task, - WorkerShutdown shutdown_behavior); - - // Like PostWorkerTask above, but provides sequencing semantics. This means - // that tasks posted with the same sequence token (see GetSequenceToken()) - // are guaranteed to execute in order. This is useful in cases where you're - // doing operations that may depend on previous ones, like appending to a - // file. - // - // The task will be guaranteed to run to completion before shutdown - // (BLOCK_SHUTDOWN semantics). - // - // Returns true if the task was posted successfully. This may fail during - // shutdown regardless of the specified ShutdownBehavior. - bool PostSequencedWorkerTask(SequenceToken sequence_token, - const tracked_objects::Location& from_here, - const Closure& task); - - // Like PostSequencedWorkerTask above, but allows you to specify a named - // token, which saves an extra call to GetNamedSequenceToken. - bool PostNamedSequencedWorkerTask(const std::string& token_name, - const tracked_objects::Location& from_here, - const Closure& task); - - // Same as PostSequencedWorkerTask but allows a delay to be specified - // (although doing so changes the shutdown behavior). The task will be run - // after the given delay has elapsed. - // - // If the delay is nonzero, the task won't be guaranteed to run to completion - // before shutdown (SKIP_ON_SHUTDOWN semantics) to avoid shutdown hangs. - // If the delay is zero, this behaves exactly like PostSequencedWorkerTask, - // i.e. the task will be guaranteed to run to completion before shutdown - // (BLOCK_SHUTDOWN semantics). - bool PostDelayedSequencedWorkerTask( - SequenceToken sequence_token, - const tracked_objects::Location& from_here, - const Closure& task, - TimeDelta delay); - - // Same as PostSequencedWorkerTask but allows specification of the shutdown - // behavior. - bool PostSequencedWorkerTaskWithShutdownBehavior( - SequenceToken sequence_token, - const tracked_objects::Location& from_here, - const Closure& task, - WorkerShutdown shutdown_behavior); - - // TaskRunner implementation. Forwards to PostDelayedWorkerTask(). - bool PostDelayedTask(const tracked_objects::Location& from_here, - const Closure& task, - TimeDelta delay) override; - bool RunsTasksOnCurrentThread() const override; - - // Returns true if the current thread is processing a task with the given - // sequence_token. - bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; - - // Returns true if any thread is currently processing a task with the given - // sequence token. Should only be called with a valid sequence token. - bool IsRunningSequence(SequenceToken sequence_token) const; - - // Blocks until all pending tasks are complete. This should only be called in - // unit tests when you want to validate something that should have happened. - // This will not flush delayed tasks; delayed tasks get deleted. - // - // Note that calling this will not prevent other threads from posting work to - // the queue while the calling thread is waiting on Flush(). In this case, - // Flush will return only when there's no more work in the queue. Normally, - // this doesn't come up since in a test, all the work is being posted from - // the main thread. - void FlushForTesting(); - - // Spuriously signal that there is work to be done. - void SignalHasWorkForTesting(); - - // Implements the worker pool shutdown. This should be called during app - // shutdown, and will discard/join with appropriate tasks before returning. - // After this call, subsequent calls to post tasks will fail. - // - // Must be called from the same thread this object was constructed on. - void Shutdown() { Shutdown(0); } - - // A variant that allows an arbitrary number of new blocking tasks to be - // posted during shutdown. The tasks cannot be posted within the execution - // context of tasks whose shutdown behavior is not BLOCKING_SHUTDOWN. Once - // the limit is reached, subsequent calls to post task fail in all cases. - // Must be called from the same thread this object was constructed on. - void Shutdown(int max_new_blocking_tasks_after_shutdown); - - // Check if Shutdown was called for given threading pool. This method is used - // for aborting time consuming operation to avoid blocking shutdown. - // - // Can be called from any thread. - bool IsShutdownInProgress(); - - protected: - ~SequencedWorkerPool() override; - - void OnDestruct() const override; - - private: - friend class RefCountedThreadSafe<SequencedWorkerPool>; - friend class DeleteHelper<SequencedWorkerPool>; - - class Inner; - class Worker; - - const scoped_refptr<SingleThreadTaskRunner> constructor_task_runner_; - - // Avoid pulling in too many headers by putting (almost) everything - // into |inner_|. - const scoped_ptr<Inner> inner_; - - DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool); -}; - -} // namespace base - -#endif // BASE_THREADING_SEQUENCED_WORKER_POOL_H_ diff --git a/security/sandbox/chromium/base/threading/thread_checker_impl.h b/security/sandbox/chromium/base/threading/thread_checker_impl.h deleted file mode 100644 index c92e143db..000000000 --- a/security/sandbox/chromium/base/threading/thread_checker_impl.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_THREADING_THREAD_CHECKER_IMPL_H_ -#define BASE_THREADING_THREAD_CHECKER_IMPL_H_ - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/synchronization/lock.h" -#include "base/threading/platform_thread.h" - -namespace base { - -// Real implementation of ThreadChecker, for use in debug mode, or -// for temporary use in release mode (e.g. to CHECK on a threading issue -// seen only in the wild). -// -// Note: You should almost always use the ThreadChecker class to get the -// right version for your build configuration. -class BASE_EXPORT ThreadCheckerImpl { - public: - ThreadCheckerImpl(); - ~ThreadCheckerImpl(); - - bool CalledOnValidThread() const WARN_UNUSED_RESULT; - - // Changes the thread that is checked for in CalledOnValidThread. This may - // be useful when an object may be created on one thread and then used - // exclusively on another thread. - void DetachFromThread(); - - private: - void EnsureThreadIdAssigned() const; - - mutable base::Lock lock_; - // This is mutable so that CalledOnValidThread can set it. - // It's guarded by |lock_|. - mutable PlatformThreadRef valid_thread_id_; -}; - -} // namespace base - -#endif // BASE_THREADING_THREAD_CHECKER_IMPL_H_ diff --git a/security/sandbox/chromium/base/threading/thread_collision_warner.cc b/security/sandbox/chromium/base/threading/thread_collision_warner.cc deleted file mode 100644 index 547e11ca6..000000000 --- a/security/sandbox/chromium/base/threading/thread_collision_warner.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/thread_collision_warner.h" - -#include "base/logging.h" -#include "base/threading/platform_thread.h" - -namespace base { - -void DCheckAsserter::warn() { - NOTREACHED() << "Thread Collision"; -} - -static subtle::Atomic32 CurrentThread() { - const PlatformThreadId current_thread_id = PlatformThread::CurrentId(); - // We need to get the thread id into an atomic data type. This might be a - // truncating conversion, but any loss-of-information just increases the - // chance of a fault negative, not a false positive. - const subtle::Atomic32 atomic_thread_id = - static_cast<subtle::Atomic32>(current_thread_id); - - return atomic_thread_id; -} - -void ThreadCollisionWarner::EnterSelf() { - // If the active thread is 0 then I'll write the current thread ID - // if two or more threads arrive here only one will succeed to - // write on valid_thread_id_ the current thread ID. - subtle::Atomic32 current_thread_id = CurrentThread(); - - int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_, - 0, - current_thread_id); - if (previous_value != 0 && previous_value != current_thread_id) { - // gotcha! a thread is trying to use the same class and that is - // not current thread. - asserter_->warn(); - } - - subtle::NoBarrier_AtomicIncrement(&counter_, 1); -} - -void ThreadCollisionWarner::Enter() { - subtle::Atomic32 current_thread_id = CurrentThread(); - - if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_, - 0, - current_thread_id) != 0) { - // gotcha! another thread is trying to use the same class. - asserter_->warn(); - } - - subtle::NoBarrier_AtomicIncrement(&counter_, 1); -} - -void ThreadCollisionWarner::Leave() { - if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) { - subtle::NoBarrier_Store(&valid_thread_id_, 0); - } -} - -} // namespace base diff --git a/security/sandbox/chromium/base/threading/thread_collision_warner.h b/security/sandbox/chromium/base/threading/thread_collision_warner.h deleted file mode 100644 index 4699a910d..000000000 --- a/security/sandbox/chromium/base/threading/thread_collision_warner.h +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_THREADING_THREAD_COLLISION_WARNER_H_ -#define BASE_THREADING_THREAD_COLLISION_WARNER_H_ - -#include <memory> - -#include "base/atomicops.h" -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/macros.h" - -// A helper class alongside macros to be used to verify assumptions about thread -// safety of a class. -// -// Example: Queue implementation non thread-safe but still usable if clients -// are synchronized somehow. -// -// In this case the macro DFAKE_SCOPED_LOCK has to be -// used, it checks that if a thread is inside the push/pop then -// noone else is still inside the pop/push -// -// class NonThreadSafeQueue { -// public: -// ... -// void push(int) { DFAKE_SCOPED_LOCK(push_pop_); ... } -// int pop() { DFAKE_SCOPED_LOCK(push_pop_); ... } -// ... -// private: -// DFAKE_MUTEX(push_pop_); -// }; -// -// -// Example: Queue implementation non thread-safe but still usable if clients -// are synchronized somehow, it calls a method to "protect" from -// a "protected" method -// -// In this case the macro DFAKE_SCOPED_RECURSIVE_LOCK -// has to be used, it checks that if a thread is inside the push/pop -// then noone else is still inside the pop/push -// -// class NonThreadSafeQueue { -// public: -// void push(int) { -// DFAKE_SCOPED_LOCK(push_pop_); -// ... -// } -// int pop() { -// DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); -// bar(); -// ... -// } -// void bar() { DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); ... } -// ... -// private: -// DFAKE_MUTEX(push_pop_); -// }; -// -// -// Example: Queue implementation not usable even if clients are synchronized, -// so only one thread in the class life cycle can use the two members -// push/pop. -// -// In this case the macro DFAKE_SCOPED_LOCK_THREAD_LOCKED pins the -// specified -// critical section the first time a thread enters push or pop, from -// that time on only that thread is allowed to execute push or pop. -// -// class NonThreadSafeQueue { -// public: -// ... -// void push(int) { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... } -// int pop() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... } -// ... -// private: -// DFAKE_MUTEX(push_pop_); -// }; -// -// -// Example: Class that has to be contructed/destroyed on same thread, it has -// a "shareable" method (with external synchronization) and a not -// shareable method (even with external synchronization). -// -// In this case 3 Critical sections have to be defined -// -// class ExoticClass { -// public: -// ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... } -// ~ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... } -// -// void Shareable() { DFAKE_SCOPED_LOCK(shareable_section_); ... } -// void NotShareable() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... } -// ... -// private: -// DFAKE_MUTEX(ctor_dtor_); -// DFAKE_MUTEX(shareable_section_); -// }; - - -#if !defined(NDEBUG) - -// Defines a class member that acts like a mutex. It is used only as a -// verification tool. -#define DFAKE_MUTEX(obj) \ - mutable base::ThreadCollisionWarner obj -// Asserts the call is never called simultaneously in two threads. Used at -// member function scope. -#define DFAKE_SCOPED_LOCK(obj) \ - base::ThreadCollisionWarner::ScopedCheck s_check_##obj(&obj) -// Asserts the call is never called simultaneously in two threads. Used at -// member function scope. Same as DFAKE_SCOPED_LOCK but allows recursive locks. -#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \ - base::ThreadCollisionWarner::ScopedRecursiveCheck sr_check_##obj(&obj) -// Asserts the code is always executed in the same thread. -#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) \ - base::ThreadCollisionWarner::Check check_##obj(&obj) - -#else - -#define DFAKE_MUTEX(obj) typedef void InternalFakeMutexType##obj -#define DFAKE_SCOPED_LOCK(obj) ((void)0) -#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) ((void)0) -#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) ((void)0) - -#endif - -namespace base { - -// The class ThreadCollisionWarner uses an Asserter to notify the collision -// AsserterBase is the interfaces and DCheckAsserter is the default asserter -// used. During the unit tests is used another class that doesn't "DCHECK" -// in case of collision (check thread_collision_warner_unittests.cc) -struct BASE_EXPORT AsserterBase { - virtual ~AsserterBase() {} - virtual void warn() = 0; -}; - -struct BASE_EXPORT DCheckAsserter : public AsserterBase { - ~DCheckAsserter() override {} - void warn() override; -}; - -class BASE_EXPORT ThreadCollisionWarner { - public: - // The parameter asserter is there only for test purpose - explicit ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter()) - : valid_thread_id_(0), - counter_(0), - asserter_(asserter) {} - - ~ThreadCollisionWarner() { - delete asserter_; - } - - // This class is meant to be used through the macro - // DFAKE_SCOPED_LOCK_THREAD_LOCKED - // it doesn't leave the critical section, as opposed to ScopedCheck, - // because the critical section being pinned is allowed to be used only - // from one thread - class BASE_EXPORT Check { - public: - explicit Check(ThreadCollisionWarner* warner) - : warner_(warner) { - warner_->EnterSelf(); - } - - ~Check() {} - - private: - ThreadCollisionWarner* warner_; - - DISALLOW_COPY_AND_ASSIGN(Check); - }; - - // This class is meant to be used through the macro - // DFAKE_SCOPED_LOCK - class BASE_EXPORT ScopedCheck { - public: - explicit ScopedCheck(ThreadCollisionWarner* warner) - : warner_(warner) { - warner_->Enter(); - } - - ~ScopedCheck() { - warner_->Leave(); - } - - private: - ThreadCollisionWarner* warner_; - - DISALLOW_COPY_AND_ASSIGN(ScopedCheck); - }; - - // This class is meant to be used through the macro - // DFAKE_SCOPED_RECURSIVE_LOCK - class BASE_EXPORT ScopedRecursiveCheck { - public: - explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner) - : warner_(warner) { - warner_->EnterSelf(); - } - - ~ScopedRecursiveCheck() { - warner_->Leave(); - } - - private: - ThreadCollisionWarner* warner_; - - DISALLOW_COPY_AND_ASSIGN(ScopedRecursiveCheck); - }; - - private: - // This method stores the current thread identifier and does a DCHECK - // if a another thread has already done it, it is safe if same thread - // calls this multiple time (recursion allowed). - void EnterSelf(); - - // Same as EnterSelf but recursion is not allowed. - void Enter(); - - // Removes the thread_id stored in order to allow other threads to - // call EnterSelf or Enter. - void Leave(); - - // This stores the thread id that is inside the critical section, if the - // value is 0 then no thread is inside. - volatile subtle::Atomic32 valid_thread_id_; - - // Counter to trace how many time a critical section was "pinned" - // (when allowed) in order to unpin it when counter_ reaches 0. - volatile subtle::Atomic32 counter_; - - // Here only for class unit tests purpose, during the test I need to not - // DCHECK but notify the collision with something else. - AsserterBase* asserter_; - - DISALLOW_COPY_AND_ASSIGN(ThreadCollisionWarner); -}; - -} // namespace base - -#endif // BASE_THREADING_THREAD_COLLISION_WARNER_H_ diff --git a/security/sandbox/chromium/base/threading/thread_id_name_manager.cc b/security/sandbox/chromium/base/threading/thread_id_name_manager.cc deleted file mode 100644 index 56cfa273a..000000000 --- a/security/sandbox/chromium/base/threading/thread_id_name_manager.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/thread_id_name_manager.h" - -#include <stdlib.h> -#include <string.h> - -#include "base/logging.h" -#include "base/memory/singleton.h" -#include "base/strings/string_util.h" - -namespace base { -namespace { - -static const char kDefaultName[] = ""; -static std::string* g_default_name; - -} - -ThreadIdNameManager::ThreadIdNameManager() - : main_process_name_(NULL), - main_process_id_(kInvalidThreadId) { - g_default_name = new std::string(kDefaultName); - - AutoLock locked(lock_); - name_to_interned_name_[kDefaultName] = g_default_name; -} - -ThreadIdNameManager::~ThreadIdNameManager() { -} - -ThreadIdNameManager* ThreadIdNameManager::GetInstance() { - return Singleton<ThreadIdNameManager, - LeakySingletonTraits<ThreadIdNameManager> >::get(); -} - -const char* ThreadIdNameManager::GetDefaultInternedString() { - return g_default_name->c_str(); -} - -void ThreadIdNameManager::RegisterThread(PlatformThreadHandle::Handle handle, - PlatformThreadId id) { - AutoLock locked(lock_); - thread_id_to_handle_[id] = handle; - thread_handle_to_interned_name_[handle] = - name_to_interned_name_[kDefaultName]; -} - -void ThreadIdNameManager::SetName(PlatformThreadId id, - const std::string& name) { - AutoLock locked(lock_); - NameToInternedNameMap::iterator iter = name_to_interned_name_.find(name); - std::string* leaked_str = NULL; - if (iter != name_to_interned_name_.end()) { - leaked_str = iter->second; - } else { - leaked_str = new std::string(name); - name_to_interned_name_[name] = leaked_str; - } - - ThreadIdToHandleMap::iterator id_to_handle_iter = - thread_id_to_handle_.find(id); - - // The main thread of a process will not be created as a Thread object which - // means there is no PlatformThreadHandler registered. - if (id_to_handle_iter == thread_id_to_handle_.end()) { - main_process_name_ = leaked_str; - main_process_id_ = id; - return; - } - thread_handle_to_interned_name_[id_to_handle_iter->second] = leaked_str; -} - -const char* ThreadIdNameManager::GetName(PlatformThreadId id) { - AutoLock locked(lock_); - - if (id == main_process_id_) - return main_process_name_->c_str(); - - ThreadIdToHandleMap::iterator id_to_handle_iter = - thread_id_to_handle_.find(id); - if (id_to_handle_iter == thread_id_to_handle_.end()) - return name_to_interned_name_[kDefaultName]->c_str(); - - ThreadHandleToInternedNameMap::iterator handle_to_name_iter = - thread_handle_to_interned_name_.find(id_to_handle_iter->second); - return handle_to_name_iter->second->c_str(); -} - -void ThreadIdNameManager::RemoveName(PlatformThreadHandle::Handle handle, - PlatformThreadId id) { - AutoLock locked(lock_); - ThreadHandleToInternedNameMap::iterator handle_to_name_iter = - thread_handle_to_interned_name_.find(handle); - - DCHECK(handle_to_name_iter != thread_handle_to_interned_name_.end()); - thread_handle_to_interned_name_.erase(handle_to_name_iter); - - ThreadIdToHandleMap::iterator id_to_handle_iter = - thread_id_to_handle_.find(id); - DCHECK((id_to_handle_iter!= thread_id_to_handle_.end())); - // The given |id| may have been re-used by the system. Make sure the - // mapping points to the provided |handle| before removal. - if (id_to_handle_iter->second != handle) - return; - - thread_id_to_handle_.erase(id_to_handle_iter); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/threading/thread_id_name_manager.h b/security/sandbox/chromium/base/threading/thread_id_name_manager.h deleted file mode 100644 index f469b605e..000000000 --- a/security/sandbox/chromium/base/threading/thread_id_name_manager.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_THREADING_THREAD_ID_NAME_MANAGER_H_ -#define BASE_THREADING_THREAD_ID_NAME_MANAGER_H_ - -#include <map> -#include <string> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "base/threading/platform_thread.h" - -namespace base { - -template <typename T> -struct DefaultSingletonTraits; - -class BASE_EXPORT ThreadIdNameManager { - public: - static ThreadIdNameManager* GetInstance(); - - static const char* GetDefaultInternedString(); - - // Register the mapping between a thread |id| and |handle|. - void RegisterThread(PlatformThreadHandle::Handle handle, PlatformThreadId id); - - // Set the name for the given id. - void SetName(PlatformThreadId id, const std::string& name); - - // Get the name for the given id. - const char* GetName(PlatformThreadId id); - - // Remove the name for the given id. - void RemoveName(PlatformThreadHandle::Handle handle, PlatformThreadId id); - - private: - friend struct DefaultSingletonTraits<ThreadIdNameManager>; - - typedef std::map<PlatformThreadId, PlatformThreadHandle::Handle> - ThreadIdToHandleMap; - typedef std::map<PlatformThreadHandle::Handle, std::string*> - ThreadHandleToInternedNameMap; - typedef std::map<std::string, std::string*> NameToInternedNameMap; - - ThreadIdNameManager(); - ~ThreadIdNameManager(); - - // lock_ protects the name_to_interned_name_, thread_id_to_handle_ and - // thread_handle_to_interned_name_ maps. - Lock lock_; - - NameToInternedNameMap name_to_interned_name_; - ThreadIdToHandleMap thread_id_to_handle_; - ThreadHandleToInternedNameMap thread_handle_to_interned_name_; - - // Treat the main process specially as there is no PlatformThreadHandle. - std::string* main_process_name_; - PlatformThreadId main_process_id_; - - DISALLOW_COPY_AND_ASSIGN(ThreadIdNameManager); -}; - -} // namespace base - -#endif // BASE_THREADING_THREAD_ID_NAME_MANAGER_H_ diff --git a/security/sandbox/chromium/base/threading/thread_local.h b/security/sandbox/chromium/base/threading/thread_local.h deleted file mode 100644 index f40420cd2..000000000 --- a/security/sandbox/chromium/base/threading/thread_local.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// WARNING: Thread local storage is a bit tricky to get right. Please make -// sure that this is really the proper solution for what you're trying to -// achieve. Don't prematurely optimize, most likely you can just use a Lock. -// -// These classes implement a wrapper around the platform's TLS storage -// mechanism. On construction, they will allocate a TLS slot, and free the -// TLS slot on destruction. No memory management (creation or destruction) is -// handled. This means for uses of ThreadLocalPointer, you must correctly -// manage the memory yourself, these classes will not destroy the pointer for -// you. There are no at-thread-exit actions taken by these classes. -// -// ThreadLocalPointer<Type> wraps a Type*. It performs no creation or -// destruction, so memory management must be handled elsewhere. The first call -// to Get() on a thread will return NULL. You can update the pointer with a -// call to Set(). -// -// ThreadLocalBoolean wraps a bool. It will default to false if it has never -// been set otherwise with Set(). -// -// Thread Safety: An instance of ThreadLocalStorage is completely thread safe -// once it has been created. If you want to dynamically create an instance, -// you must of course properly deal with safety and race conditions. This -// means a function-level static initializer is generally inappropiate. -// -// In Android, the system TLS is limited, the implementation is backed with -// ThreadLocalStorage. -// -// Example usage: -// // My class is logically attached to a single thread. We cache a pointer -// // on the thread it was created on, so we can implement current(). -// MyClass::MyClass() { -// DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL); -// Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this); -// } -// -// MyClass::~MyClass() { -// DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL); -// Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL); -// } -// -// // Return the current MyClass associated with the calling thread, can be -// // NULL if there isn't a MyClass associated. -// MyClass* MyClass::current() { -// return Singleton<ThreadLocalPointer<MyClass> >::get()->Get(); -// } - -#ifndef BASE_THREADING_THREAD_LOCAL_H_ -#define BASE_THREADING_THREAD_LOCAL_H_ - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/threading/thread_local_storage.h" -#include "build/build_config.h" - -#if defined(OS_POSIX) -#include <pthread.h> -#endif - -namespace base { -namespace internal { - -// Helper functions that abstract the cross-platform APIs. Do not use directly. -struct BASE_EXPORT ThreadLocalPlatform { -#if defined(OS_WIN) - typedef unsigned long SlotType; -#elif defined(OS_ANDROID) - typedef ThreadLocalStorage::StaticSlot SlotType; -#elif defined(OS_POSIX) - typedef pthread_key_t SlotType; -#endif - - static void AllocateSlot(SlotType* slot); - static void FreeSlot(SlotType slot); - static void* GetValueFromSlot(SlotType slot); - static void SetValueInSlot(SlotType slot, void* value); -}; - -} // namespace internal - -template <typename Type> -class ThreadLocalPointer { - public: - ThreadLocalPointer() : slot_() { - internal::ThreadLocalPlatform::AllocateSlot(&slot_); - } - - ~ThreadLocalPointer() { - internal::ThreadLocalPlatform::FreeSlot(slot_); - } - - Type* Get() { - return static_cast<Type*>( - internal::ThreadLocalPlatform::GetValueFromSlot(slot_)); - } - - void Set(Type* ptr) { - internal::ThreadLocalPlatform::SetValueInSlot( - slot_, const_cast<void*>(static_cast<const void*>(ptr))); - } - - private: - typedef internal::ThreadLocalPlatform::SlotType SlotType; - - SlotType slot_; - - DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>); -}; - -class ThreadLocalBoolean { - public: - ThreadLocalBoolean() {} - ~ThreadLocalBoolean() {} - - bool Get() { - return tlp_.Get() != NULL; - } - - void Set(bool val) { - tlp_.Set(val ? this : NULL); - } - - private: - ThreadLocalPointer<void> tlp_; - - DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean); -}; - -} // namespace base - -#endif // BASE_THREADING_THREAD_LOCAL_H_ diff --git a/security/sandbox/chromium/base/threading/thread_local_posix.cc b/security/sandbox/chromium/base/threading/thread_local_posix.cc deleted file mode 100644 index 8bc46ad19..000000000 --- a/security/sandbox/chromium/base/threading/thread_local_posix.cc +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/thread_local.h" - -#include <pthread.h> - -#include "base/logging.h" -#include "build/build_config.h" - -#if !defined(OS_ANDROID) - -namespace base { -namespace internal { - -// static -void ThreadLocalPlatform::AllocateSlot(SlotType* slot) { - int error = pthread_key_create(slot, NULL); - CHECK_EQ(error, 0); -} - -// static -void ThreadLocalPlatform::FreeSlot(SlotType slot) { - int error = pthread_key_delete(slot); - DCHECK_EQ(0, error); -} - -// static -void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) { - return pthread_getspecific(slot); -} - -// static -void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) { - int error = pthread_setspecific(slot, value); - DCHECK_EQ(error, 0); -} - -} // namespace internal -} // namespace base - -#endif // !defined(OS_ANDROID) diff --git a/security/sandbox/chromium/base/threading/thread_local_storage.h b/security/sandbox/chromium/base/threading/thread_local_storage.h deleted file mode 100644 index 013b0aeff..000000000 --- a/security/sandbox/chromium/base/threading/thread_local_storage.h +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_THREADING_THREAD_LOCAL_STORAGE_H_ -#define BASE_THREADING_THREAD_LOCAL_STORAGE_H_ - -#include "base/atomicops.h" -#include "base/base_export.h" -#include "base/macros.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#elif defined(OS_POSIX) -#include <pthread.h> -#endif - -namespace base { - -namespace internal { - -// WARNING: You should *NOT* be using this class directly. -// PlatformThreadLocalStorage is low-level abstraction to the OS's TLS -// interface, you should instead be using ThreadLocalStorage::StaticSlot/Slot. -class BASE_EXPORT PlatformThreadLocalStorage { - public: - -#if defined(OS_WIN) - typedef unsigned long TLSKey; - enum : unsigned { TLS_KEY_OUT_OF_INDEXES = TLS_OUT_OF_INDEXES }; -#elif defined(OS_POSIX) - typedef pthread_key_t TLSKey; - // The following is a "reserved key" which is used in our generic Chromium - // ThreadLocalStorage implementation. We expect that an OS will not return - // such a key, but if it is returned (i.e., the OS tries to allocate it) we - // will just request another key. - enum { TLS_KEY_OUT_OF_INDEXES = 0x7FFFFFFF }; -#endif - - // The following methods need to be supported on each OS platform, so that - // the Chromium ThreadLocalStore functionality can be constructed. - // Chromium will use these methods to acquire a single OS slot, and then use - // that to support a much larger number of Chromium slots (independent of the - // OS restrictions). - // The following returns true if it successfully is able to return an OS - // key in |key|. - static bool AllocTLS(TLSKey* key); - // Note: FreeTLS() doesn't have to be called, it is fine with this leak, OS - // might not reuse released slot, you might just reset the TLS value with - // SetTLSValue(). - static void FreeTLS(TLSKey key); - static void SetTLSValue(TLSKey key, void* value); - static void* GetTLSValue(TLSKey key); - - // Each platform (OS implementation) is required to call this method on each - // terminating thread when the thread is about to terminate. This method - // will then call all registered destructors for slots in Chromium - // ThreadLocalStorage, until there are no slot values remaining as having - // been set on this thread. - // Destructors may end up being called multiple times on a terminating - // thread, as other destructors may re-set slots that were previously - // destroyed. -#if defined(OS_WIN) - // Since Windows which doesn't support TLS destructor, the implementation - // should use GetTLSValue() to retrieve the value of TLS slot. - static void OnThreadExit(); -#elif defined(OS_POSIX) - // |Value| is the data stored in TLS slot, The implementation can't use - // GetTLSValue() to retrieve the value of slot as it has already been reset - // in Posix. - static void OnThreadExit(void* value); -#endif -}; - -} // namespace internal - -// Wrapper for thread local storage. This class doesn't do much except provide -// an API for portability. -class BASE_EXPORT ThreadLocalStorage { - public: - - // Prototype for the TLS destructor function, which can be optionally used to - // cleanup thread local storage on thread exit. 'value' is the data that is - // stored in thread local storage. - typedef void (*TLSDestructorFunc)(void* value); - - // StaticSlot uses its own struct initializer-list style static - // initialization, as base's LINKER_INITIALIZED requires a constructor and on - // some compilers (notably gcc 4.4) this still ends up needing runtime - // initialization. - #define TLS_INITIALIZER {0} - - // A key representing one value stored in TLS. - // Initialize like - // ThreadLocalStorage::StaticSlot my_slot = TLS_INITIALIZER; - // If you're not using a static variable, use the convenience class - // ThreadLocalStorage::Slot (below) instead. - struct BASE_EXPORT StaticSlot { - // Set up the TLS slot. Called by the constructor. - // 'destructor' is a pointer to a function to perform per-thread cleanup of - // this object. If set to NULL, no cleanup is done for this TLS slot. - void Initialize(TLSDestructorFunc destructor); - - // Free a previously allocated TLS 'slot'. - // If a destructor was set for this slot, removes - // the destructor so that remaining threads exiting - // will not free data. - void Free(); - - // Get the thread-local value stored in slot 'slot'. - // Values are guaranteed to initially be zero. - void* Get() const; - - // Set the thread-local value stored in slot 'slot' to - // value 'value'. - void Set(void* value); - - bool initialized() const { - return base::subtle::Acquire_Load(&initialized_) != 0; - } - - // The internals of this struct should be considered private. - base::subtle::Atomic32 initialized_; - int slot_; - }; - - // A convenience wrapper around StaticSlot with a constructor. Can be used - // as a member variable. - class BASE_EXPORT Slot : public StaticSlot { - public: - // Calls StaticSlot::Initialize(). - explicit Slot(TLSDestructorFunc destructor = NULL); - - private: - using StaticSlot::initialized_; - using StaticSlot::slot_; - - DISALLOW_COPY_AND_ASSIGN(Slot); - }; - - private: - DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorage); -}; - -} // namespace base - -#endif // BASE_THREADING_THREAD_LOCAL_STORAGE_H_ diff --git a/security/sandbox/chromium/base/threading/thread_local_win.cc b/security/sandbox/chromium/base/threading/thread_local_win.cc deleted file mode 100644 index 1c74e4213..000000000 --- a/security/sandbox/chromium/base/threading/thread_local_win.cc +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/thread_local.h" - -#include <windows.h> - -#include "base/logging.h" - -namespace base { -namespace internal { - -// static -void ThreadLocalPlatform::AllocateSlot(SlotType* slot) { - *slot = TlsAlloc(); - CHECK_NE(*slot, TLS_OUT_OF_INDEXES); -} - -// static -void ThreadLocalPlatform::FreeSlot(SlotType slot) { - if (!TlsFree(slot)) { - NOTREACHED() << "Failed to deallocate tls slot with TlsFree()."; - } -} - -// static -void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) { - return TlsGetValue(slot); -} - -// static -void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) { - if (!TlsSetValue(slot, value)) { - LOG(FATAL) << "Failed to TlsSetValue()."; - } -} - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/threading/thread_restrictions.cc b/security/sandbox/chromium/base/threading/thread_restrictions.cc deleted file mode 100644 index 00306c5ae..000000000 --- a/security/sandbox/chromium/base/threading/thread_restrictions.cc +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/thread_restrictions.h" - -#if ENABLE_THREAD_RESTRICTIONS - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/threading/thread_local.h" - -namespace base { - -namespace { - -LazyInstance<ThreadLocalBoolean>::Leaky - g_io_disallowed = LAZY_INSTANCE_INITIALIZER; - -LazyInstance<ThreadLocalBoolean>::Leaky - g_singleton_disallowed = LAZY_INSTANCE_INITIALIZER; - -LazyInstance<ThreadLocalBoolean>::Leaky - g_wait_disallowed = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// static -bool ThreadRestrictions::SetIOAllowed(bool allowed) { - bool previous_disallowed = g_io_disallowed.Get().Get(); - g_io_disallowed.Get().Set(!allowed); - return !previous_disallowed; -} - -// static -void ThreadRestrictions::AssertIOAllowed() { - if (g_io_disallowed.Get().Get()) { - LOG(FATAL) << - "Function marked as IO-only was called from a thread that " - "disallows IO! If this thread really should be allowed to " - "make IO calls, adjust the call to " - "base::ThreadRestrictions::SetIOAllowed() in this thread's " - "startup."; - } -} - -// static -bool ThreadRestrictions::SetSingletonAllowed(bool allowed) { - bool previous_disallowed = g_singleton_disallowed.Get().Get(); - g_singleton_disallowed.Get().Set(!allowed); - return !previous_disallowed; -} - -// static -void ThreadRestrictions::AssertSingletonAllowed() { - if (g_singleton_disallowed.Get().Get()) { - LOG(FATAL) << "LazyInstance/Singleton is not allowed to be used on this " - << "thread. Most likely it's because this thread is not " - << "joinable, so AtExitManager may have deleted the object " - << "on shutdown, leading to a potential shutdown crash."; - } -} - -// static -void ThreadRestrictions::DisallowWaiting() { - g_wait_disallowed.Get().Set(true); -} - -// static -void ThreadRestrictions::AssertWaitAllowed() { - if (g_wait_disallowed.Get().Get()) { - LOG(FATAL) << "Waiting is not allowed to be used on this thread to prevent " - << "jank and deadlock."; - } -} - -bool ThreadRestrictions::SetWaitAllowed(bool allowed) { - bool previous_disallowed = g_wait_disallowed.Get().Get(); - g_wait_disallowed.Get().Set(!allowed); - return !previous_disallowed; -} - -} // namespace base - -#endif // ENABLE_THREAD_RESTRICTIONS diff --git a/security/sandbox/chromium/base/threading/thread_restrictions.h b/security/sandbox/chromium/base/threading/thread_restrictions.h deleted file mode 100644 index eec00fbb7..000000000 --- a/security/sandbox/chromium/base/threading/thread_restrictions.h +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_THREADING_THREAD_RESTRICTIONS_H_ -#define BASE_THREADING_THREAD_RESTRICTIONS_H_ - -#include "base/base_export.h" -#include "base/macros.h" - -// See comment at top of thread_checker.h -#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) -#define ENABLE_THREAD_RESTRICTIONS 1 -#else -#define ENABLE_THREAD_RESTRICTIONS 0 -#endif - -class BrowserProcessImpl; -class HistogramSynchronizer; -class NativeBackendKWallet; -class ScopedAllowWaitForLegacyWebViewApi; - -namespace cc { -class CompletionEvent; -class SingleThreadTaskGraphRunner; -} -namespace chromeos { -class BlockingMethodCaller; -namespace system { -class StatisticsProviderImpl; -} -} -namespace chrome_browser_net { -class Predictor; -} -namespace content { -class BrowserGpuChannelHostFactory; -class BrowserGpuMemoryBufferManager; -class BrowserShutdownProfileDumper; -class BrowserTestBase; -class GpuChannelHost; -class NestedMessagePumpAndroid; -class ScopedAllowWaitForAndroidLayoutTests; -class ScopedAllowWaitForDebugURL; -class SoftwareOutputDeviceMus; -class TextInputClientMac; -class RasterWorkerPool; -} // namespace content -namespace dbus { -class Bus; -} -namespace disk_cache { -class BackendImpl; -class InFlightIO; -} -namespace gles2 { -class CommandBufferClientImpl; -} -namespace mojo { -namespace common { -class MessagePumpMojo; -} -} -namespace mus { -class CommandBufferLocal; -class GpuState; -} -namespace net { -class NetworkChangeNotifierMac; -namespace internal { -class AddressTrackerLinux; -} -} - -namespace remoting { -class AutoThread; -} - -namespace ui { -class WindowResizeHelperMac; -} - -namespace views { -class WindowManagerConnection; -} - -namespace base { - -namespace android { -class JavaHandlerThread; -} - -class SequencedWorkerPool; -class SimpleThread; -class Thread; -class ThreadTestHelper; - -// Certain behavior is disallowed on certain threads. ThreadRestrictions helps -// enforce these rules. Examples of such rules: -// -// * Do not do blocking IO (makes the thread janky) -// * Do not access Singleton/LazyInstance (may lead to shutdown crashes) -// -// Here's more about how the protection works: -// -// 1) If a thread should not be allowed to make IO calls, mark it: -// base::ThreadRestrictions::SetIOAllowed(false); -// By default, threads *are* allowed to make IO calls. -// In Chrome browser code, IO calls should be proxied to the File thread. -// -// 2) If a function makes a call that will go out to disk, check whether the -// current thread is allowed: -// base::ThreadRestrictions::AssertIOAllowed(); -// -// -// Style tip: where should you put AssertIOAllowed checks? It's best -// if you put them as close to the disk access as possible, at the -// lowest level. This rule is simple to follow and helps catch all -// callers. For example, if your function GoDoSomeBlockingDiskCall() -// only calls other functions in Chrome and not fopen(), you should go -// add the AssertIOAllowed checks in the helper functions. - -class BASE_EXPORT ThreadRestrictions { - public: - // Constructing a ScopedAllowIO temporarily allows IO for the current - // thread. Doing this is almost certainly always incorrect. - class BASE_EXPORT ScopedAllowIO { - public: - ScopedAllowIO() { previous_value_ = SetIOAllowed(true); } - ~ScopedAllowIO() { SetIOAllowed(previous_value_); } - private: - // Whether IO is allowed when the ScopedAllowIO was constructed. - bool previous_value_; - - DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO); - }; - - // Constructing a ScopedAllowSingleton temporarily allows accessing for the - // current thread. Doing this is almost always incorrect. - class BASE_EXPORT ScopedAllowSingleton { - public: - ScopedAllowSingleton() { previous_value_ = SetSingletonAllowed(true); } - ~ScopedAllowSingleton() { SetSingletonAllowed(previous_value_); } - private: - // Whether singleton use is allowed when the ScopedAllowSingleton was - // constructed. - bool previous_value_; - - DISALLOW_COPY_AND_ASSIGN(ScopedAllowSingleton); - }; - -#if ENABLE_THREAD_RESTRICTIONS - // Set whether the current thread to make IO calls. - // Threads start out in the *allowed* state. - // Returns the previous value. - static bool SetIOAllowed(bool allowed); - - // Check whether the current thread is allowed to make IO calls, - // and DCHECK if not. See the block comment above the class for - // a discussion of where to add these checks. - static void AssertIOAllowed(); - - // Set whether the current thread can use singletons. Returns the previous - // value. - static bool SetSingletonAllowed(bool allowed); - - // Check whether the current thread is allowed to use singletons (Singleton / - // LazyInstance). DCHECKs if not. - static void AssertSingletonAllowed(); - - // Disable waiting on the current thread. Threads start out in the *allowed* - // state. Returns the previous value. - static void DisallowWaiting(); - - // Check whether the current thread is allowed to wait, and DCHECK if not. - static void AssertWaitAllowed(); -#else - // Inline the empty definitions of these functions so that they can be - // compiled out. - static bool SetIOAllowed(bool allowed) { return true; } - static void AssertIOAllowed() {} - static bool SetSingletonAllowed(bool allowed) { return true; } - static void AssertSingletonAllowed() {} - static void DisallowWaiting() {} - static void AssertWaitAllowed() {} -#endif - - private: - // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to jam or brettw first. - // BEGIN ALLOWED USAGE. - friend class content::BrowserShutdownProfileDumper; - friend class content::BrowserTestBase; - friend class content::NestedMessagePumpAndroid; - friend class content::ScopedAllowWaitForAndroidLayoutTests; - friend class content::ScopedAllowWaitForDebugURL; - friend class ::HistogramSynchronizer; - friend class ::ScopedAllowWaitForLegacyWebViewApi; - friend class cc::CompletionEvent; - friend class cc::SingleThreadTaskGraphRunner; - friend class content::RasterWorkerPool; - friend class remoting::AutoThread; - friend class ui::WindowResizeHelperMac; - friend class MessagePumpDefault; - friend class SequencedWorkerPool; - friend class SimpleThread; - friend class Thread; - friend class ThreadTestHelper; - friend class PlatformThread; - friend class android::JavaHandlerThread; - friend class gles2::CommandBufferClientImpl; - friend class mojo::common::MessagePumpMojo; - friend class mus::CommandBufferLocal; - friend class mus::GpuState; - - // END ALLOWED USAGE. - // BEGIN USAGE THAT NEEDS TO BE FIXED. - friend class ::chromeos::BlockingMethodCaller; // http://crbug.com/125360 - friend class ::chromeos::system::StatisticsProviderImpl; // http://crbug.com/125385 - friend class chrome_browser_net::Predictor; // http://crbug.com/78451 - friend class - content::BrowserGpuChannelHostFactory; // http://crbug.com/125248 - friend class - content::BrowserGpuMemoryBufferManager; // http://crbug.com/420368 - friend class content::GpuChannelHost; // http://crbug.com/125264 - friend class content::TextInputClientMac; // http://crbug.com/121917 - friend class dbus::Bus; // http://crbug.com/125222 - friend class disk_cache::BackendImpl; // http://crbug.com/74623 - friend class disk_cache::InFlightIO; // http://crbug.com/74623 - friend class net::internal::AddressTrackerLinux; // http://crbug.com/125097 - friend class net::NetworkChangeNotifierMac; // http://crbug.com/125097 - friend class ::BrowserProcessImpl; // http://crbug.com/125207 - friend class ::NativeBackendKWallet; // http://crbug.com/125331 -#if !defined(OFFICIAL_BUILD) - friend class content::SoftwareOutputDeviceMus; // Interim non-production code -#endif - friend class views::WindowManagerConnection; -// END USAGE THAT NEEDS TO BE FIXED. - -#if ENABLE_THREAD_RESTRICTIONS - static bool SetWaitAllowed(bool allowed); -#else - static bool SetWaitAllowed(bool allowed) { return true; } -#endif - - // Constructing a ScopedAllowWait temporarily allows waiting on the current - // thread. Doing this is almost always incorrect, which is why we limit who - // can use this through friend. If you find yourself needing to use this, find - // another way. Talk to jam or brettw. - class BASE_EXPORT ScopedAllowWait { - public: - ScopedAllowWait() { previous_value_ = SetWaitAllowed(true); } - ~ScopedAllowWait() { SetWaitAllowed(previous_value_); } - private: - // Whether singleton use is allowed when the ScopedAllowWait was - // constructed. - bool previous_value_; - - DISALLOW_COPY_AND_ASSIGN(ScopedAllowWait); - }; - - DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions); -}; - -} // namespace base - -#endif // BASE_THREADING_THREAD_RESTRICTIONS_H_ diff --git a/security/sandbox/chromium/base/time/time.cc b/security/sandbox/chromium/base/time/time.cc deleted file mode 100644 index 9188887e2..000000000 --- a/security/sandbox/chromium/base/time/time.cc +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/time/time.h" - -#include <cmath> -#include <ios> -#include <limits> -#include <ostream> -#include <sstream> - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/strings/stringprintf.h" -#include "base/third_party/nspr/prtime.h" -#include "build/build_config.h" - -namespace base { - -// TimeDelta ------------------------------------------------------------------ - -// static -TimeDelta TimeDelta::Max() { - return TimeDelta(std::numeric_limits<int64_t>::max()); -} - -int TimeDelta::InDays() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int>::max(); - } - return static_cast<int>(delta_ / Time::kMicrosecondsPerDay); -} - -int TimeDelta::InHours() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int>::max(); - } - return static_cast<int>(delta_ / Time::kMicrosecondsPerHour); -} - -int TimeDelta::InMinutes() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int>::max(); - } - return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute); -} - -double TimeDelta::InSecondsF() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond; -} - -int64_t TimeDelta::InSeconds() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return delta_ / Time::kMicrosecondsPerSecond; -} - -double TimeDelta::InMillisecondsF() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond; -} - -int64_t TimeDelta::InMilliseconds() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return delta_ / Time::kMicrosecondsPerMillisecond; -} - -int64_t TimeDelta::InMillisecondsRoundedUp() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / - Time::kMicrosecondsPerMillisecond; -} - -int64_t TimeDelta::InMicroseconds() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return delta_; -} - -namespace time_internal { - -int64_t SaturatedAdd(TimeDelta delta, int64_t value) { - CheckedNumeric<int64_t> rv(delta.delta_); - rv += value; - return FromCheckedNumeric(rv); -} - -int64_t SaturatedSub(TimeDelta delta, int64_t value) { - CheckedNumeric<int64_t> rv(delta.delta_); - rv -= value; - return FromCheckedNumeric(rv); -} - -int64_t FromCheckedNumeric(const CheckedNumeric<int64_t> value) { - if (value.IsValid()) - return value.ValueUnsafe(); - - // We could return max/min but we don't really expose what the maximum delta - // is. Instead, return max/(-max), which is something that clients can reason - // about. - // TODO(rvargas) crbug.com/332611: don't use internal values. - int64_t limit = std::numeric_limits<int64_t>::max(); - if (value.validity() == internal::RANGE_UNDERFLOW) - limit = -limit; - return value.ValueOrDefault(limit); -} - -} // namespace time_internal - -std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) { - return os << time_delta.InSecondsF() << "s"; -} - -// Time ----------------------------------------------------------------------- - -// static -Time Time::Max() { - return Time(std::numeric_limits<int64_t>::max()); -} - -// static -Time Time::FromTimeT(time_t tt) { - if (tt == 0) - return Time(); // Preserve 0 so we can tell it doesn't exist. - if (tt == std::numeric_limits<time_t>::max()) - return Max(); - return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt); -} - -time_t Time::ToTimeT() const { - if (is_null()) - return 0; // Preserve 0 so we can tell it doesn't exist. - if (is_max()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits<time_t>::max(); - } - if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) { - DLOG(WARNING) << "Overflow when converting base::Time with internal " << - "value " << us_ << " to time_t."; - return std::numeric_limits<time_t>::max(); - } - return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond; -} - -// static -Time Time::FromDoubleT(double dt) { - if (dt == 0 || std::isnan(dt)) - return Time(); // Preserve 0 so we can tell it doesn't exist. - return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt); -} - -double Time::ToDoubleT() const { - if (is_null()) - return 0; // Preserve 0 so we can tell it doesn't exist. - if (is_max()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / - static_cast<double>(kMicrosecondsPerSecond)); -} - -#if defined(OS_POSIX) -// static -Time Time::FromTimeSpec(const timespec& ts) { - return FromDoubleT(ts.tv_sec + - static_cast<double>(ts.tv_nsec) / - base::Time::kNanosecondsPerSecond); -} -#endif - -// static -Time Time::FromJsTime(double ms_since_epoch) { - // The epoch is a valid time, so this constructor doesn't interpret - // 0 as the null time. - return Time(kTimeTToMicrosecondsOffset) + - TimeDelta::FromMillisecondsD(ms_since_epoch); -} - -double Time::ToJsTime() const { - if (is_null()) { - // Preserve 0 so the invalid result doesn't depend on the platform. - return 0; - } - if (is_max()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / - kMicrosecondsPerMillisecond); -} - -int64_t Time::ToJavaTime() const { - if (is_null()) { - // Preserve 0 so the invalid result doesn't depend on the platform. - return 0; - } - if (is_max()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return ((us_ - kTimeTToMicrosecondsOffset) / - kMicrosecondsPerMillisecond); -} - -// static -Time Time::UnixEpoch() { - Time time; - time.us_ = kTimeTToMicrosecondsOffset; - return time; -} - -Time Time::LocalMidnight() const { - Exploded exploded; - LocalExplode(&exploded); - exploded.hour = 0; - exploded.minute = 0; - exploded.second = 0; - exploded.millisecond = 0; - return FromLocalExploded(exploded); -} - -#if !defined(MOZ_SANDBOX) -// static -bool Time::FromStringInternal(const char* time_string, - bool is_local, - Time* parsed_time) { - DCHECK((time_string != NULL) && (parsed_time != NULL)); - - if (time_string[0] == '\0') - return false; - - PRTime result_time = 0; - PRStatus result = PR_ParseTimeString(time_string, - is_local ? PR_FALSE : PR_TRUE, - &result_time); - if (PR_SUCCESS != result) - return false; - - result_time += kTimeTToMicrosecondsOffset; - *parsed_time = Time(result_time); - return true; -} -#endif - -std::ostream& operator<<(std::ostream& os, Time time) { - Time::Exploded exploded; - time.UTCExplode(&exploded); - // Use StringPrintf because iostreams formatting is painful. - return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC", - exploded.year, - exploded.month, - exploded.day_of_month, - exploded.hour, - exploded.minute, - exploded.second, - exploded.millisecond); -} - -// Local helper class to hold the conversion from Time to TickTime at the -// time of the Unix epoch. -class UnixEpochSingleton { - public: - UnixEpochSingleton() - : unix_epoch_(TimeTicks::Now() - (Time::Now() - Time::UnixEpoch())) {} - - TimeTicks unix_epoch() const { return unix_epoch_; } - - private: - const TimeTicks unix_epoch_; - - DISALLOW_COPY_AND_ASSIGN(UnixEpochSingleton); -}; - -static LazyInstance<UnixEpochSingleton>::Leaky - leaky_unix_epoch_singleton_instance = LAZY_INSTANCE_INITIALIZER; - -// Static -TimeTicks TimeTicks::UnixEpoch() { - return leaky_unix_epoch_singleton_instance.Get().unix_epoch(); -} - -TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase, - TimeDelta tick_interval) const { - // |interval_offset| is the offset from |this| to the next multiple of - // |tick_interval| after |tick_phase|, possibly negative if in the past. - TimeDelta interval_offset = (tick_phase - *this) % tick_interval; - // If |this| is exactly on the interval (i.e. offset==0), don't adjust. - // Otherwise, if |tick_phase| was in the past, adjust forward to the next - // tick after |this|. - if (!interval_offset.is_zero() && tick_phase < *this) - interval_offset += tick_interval; - return *this + interval_offset; -} - -std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) { - // This function formats a TimeTicks object as "bogo-microseconds". - // The origin and granularity of the count are platform-specific, and may very - // from run to run. Although bogo-microseconds usually roughly correspond to - // real microseconds, the only real guarantee is that the number never goes - // down during a single run. - const TimeDelta as_time_delta = time_ticks - TimeTicks(); - return os << as_time_delta.InMicroseconds() << " bogo-microseconds"; -} - -std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) { - const TimeDelta as_time_delta = thread_ticks - ThreadTicks(); - return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds"; -} - -// Time::Exploded ------------------------------------------------------------- - -inline bool is_in_range(int value, int lo, int hi) { - return lo <= value && value <= hi; -} - -bool Time::Exploded::HasValidValues() const { - return is_in_range(month, 1, 12) && - is_in_range(day_of_week, 0, 6) && - is_in_range(day_of_month, 1, 31) && - is_in_range(hour, 0, 23) && - is_in_range(minute, 0, 59) && - is_in_range(second, 0, 60) && - is_in_range(millisecond, 0, 999); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/time/time.h b/security/sandbox/chromium/base/time/time.h deleted file mode 100644 index ea19d7ed9..000000000 --- a/security/sandbox/chromium/base/time/time.h +++ /dev/null @@ -1,768 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Time represents an absolute point in coordinated universal time (UTC), -// internally represented as microseconds (s/1,000,000) since the Windows epoch -// (1601-01-01 00:00:00 UTC). System-dependent clock interface routines are -// defined in time_PLATFORM.cc. Note that values for Time may skew and jump -// around as the operating system makes adjustments to synchronize (e.g., with -// NTP servers). Thus, client code that uses the Time class must account for -// this. -// -// TimeDelta represents a duration of time, internally represented in -// microseconds. -// -// TimeTicks and ThreadTicks represent an abstract time that is most of the time -// incrementing, for use in measuring time durations. Internally, they are -// represented in microseconds. They can not be converted to a human-readable -// time, but are guaranteed not to decrease (unlike the Time class). Note that -// TimeTicks may "stand still" (e.g., if the computer is suspended), and -// ThreadTicks will "stand still" whenever the thread has been de-scheduled by -// the operating system. -// -// All time classes are copyable, assignable, and occupy 64-bits per -// instance. Thus, they can be efficiently passed by-value (as opposed to -// by-reference). -// -// Definitions of operator<< are provided to make these types work with -// DCHECK_EQ() and other log macros. For human-readable formatting, see -// "base/i18n/time_formatting.h". -// -// So many choices! Which time class should you use? Examples: -// -// Time: Interpreting the wall-clock time provided by a remote -// system. Detecting whether cached resources have -// expired. Providing the user with a display of the current date -// and time. Determining the amount of time between events across -// re-boots of the machine. -// -// TimeTicks: Tracking the amount of time a task runs. Executing delayed -// tasks at the right time. Computing presentation timestamps. -// Synchronizing audio and video using TimeTicks as a common -// reference clock (lip-sync). Measuring network round-trip -// latency. -// -// ThreadTicks: Benchmarking how long the current thread has been doing actual -// work. - -#ifndef BASE_TIME_TIME_H_ -#define BASE_TIME_TIME_H_ - -#include <stdint.h> -#include <time.h> - -#include <iosfwd> -#include <limits> - -#include "base/base_export.h" -#include "base/numerics/safe_math.h" -#include "build/build_config.h" - -#if defined(OS_MACOSX) -#include <CoreFoundation/CoreFoundation.h> -// Avoid Mac system header macro leak. -#undef TYPE_BOOL -#endif - -#if defined(OS_POSIX) -#include <unistd.h> -#include <sys/time.h> -#endif - -#if defined(OS_WIN) -// For FILETIME in FromFileTime, until it moves to a new converter class. -// See TODO(iyengar) below. -#include <windows.h> - -#include "base/gtest_prod_util.h" -#endif - -namespace base { - -class TimeDelta; - -// The functions in the time_internal namespace are meant to be used only by the -// time classes and functions. Please use the math operators defined in the -// time classes instead. -namespace time_internal { - -// Add or subtract |value| from a TimeDelta. The int64_t argument and return -// value are in terms of a microsecond timebase. -BASE_EXPORT int64_t SaturatedAdd(TimeDelta delta, int64_t value); -BASE_EXPORT int64_t SaturatedSub(TimeDelta delta, int64_t value); - -// Clamp |value| on overflow and underflow conditions. The int64_t argument and -// return value are in terms of a microsecond timebase. -BASE_EXPORT int64_t FromCheckedNumeric(const CheckedNumeric<int64_t> value); - -} // namespace time_internal - -// TimeDelta ------------------------------------------------------------------ - -class BASE_EXPORT TimeDelta { - public: - TimeDelta() : delta_(0) { - } - - // Converts units of time to TimeDeltas. - static TimeDelta FromDays(int days); - static TimeDelta FromHours(int hours); - static TimeDelta FromMinutes(int minutes); - static TimeDelta FromSeconds(int64_t secs); - static TimeDelta FromMilliseconds(int64_t ms); - static TimeDelta FromSecondsD(double secs); - static TimeDelta FromMillisecondsD(double ms); - static TimeDelta FromMicroseconds(int64_t us); -#if defined(OS_WIN) - static TimeDelta FromQPCValue(LONGLONG qpc_value); -#endif - - // Converts an integer value representing TimeDelta to a class. This is used - // when deserializing a |TimeDelta| structure, using a value known to be - // compatible. It is not provided as a constructor because the integer type - // may be unclear from the perspective of a caller. - static TimeDelta FromInternalValue(int64_t delta) { return TimeDelta(delta); } - - // Returns the maximum time delta, which should be greater than any reasonable - // time delta we might compare it to. Adding or subtracting the maximum time - // delta to a time or another time delta has an undefined result. - static TimeDelta Max(); - - // Returns the internal numeric value of the TimeDelta object. Please don't - // use this and do arithmetic on it, as it is more error prone than using the - // provided operators. - // For serializing, use FromInternalValue to reconstitute. - int64_t ToInternalValue() const { return delta_; } - - // Returns the magnitude (absolute value) of this TimeDelta. - TimeDelta magnitude() const { - // Some toolchains provide an incomplete C++11 implementation and lack an - // int64_t overload for std::abs(). The following is a simple branchless - // implementation: - const int64_t mask = delta_ >> (sizeof(delta_) * 8 - 1); - return TimeDelta((delta_ + mask) ^ mask); - } - - // Returns true if the time delta is zero. - bool is_zero() const { - return delta_ == 0; - } - - // Returns true if the time delta is the maximum time delta. - bool is_max() const { return delta_ == std::numeric_limits<int64_t>::max(); } - -#if defined(OS_POSIX) - struct timespec ToTimeSpec() const; -#endif - - // Returns the time delta in some unit. The F versions return a floating - // point value, the "regular" versions return a rounded-down value. - // - // InMillisecondsRoundedUp() instead returns an integer that is rounded up - // to the next full millisecond. - int InDays() const; - int InHours() const; - int InMinutes() const; - double InSecondsF() const; - int64_t InSeconds() const; - double InMillisecondsF() const; - int64_t InMilliseconds() const; - int64_t InMillisecondsRoundedUp() const; - int64_t InMicroseconds() const; - - TimeDelta& operator=(TimeDelta other) { - delta_ = other.delta_; - return *this; - } - - // Computations with other deltas. - TimeDelta operator+(TimeDelta other) const { - return TimeDelta(time_internal::SaturatedAdd(*this, other.delta_)); - } - TimeDelta operator-(TimeDelta other) const { - return TimeDelta(time_internal::SaturatedSub(*this, other.delta_)); - } - - TimeDelta& operator+=(TimeDelta other) { - return *this = (*this + other); - } - TimeDelta& operator-=(TimeDelta other) { - return *this = (*this - other); - } - TimeDelta operator-() const { - return TimeDelta(-delta_); - } - - // Computations with numeric types. - template<typename T> - TimeDelta operator*(T a) const { - CheckedNumeric<int64_t> rv(delta_); - rv *= a; - return TimeDelta(time_internal::FromCheckedNumeric(rv)); - } - template<typename T> - TimeDelta operator/(T a) const { - CheckedNumeric<int64_t> rv(delta_); - rv /= a; - return TimeDelta(time_internal::FromCheckedNumeric(rv)); - } - template<typename T> - TimeDelta& operator*=(T a) { - return *this = (*this * a); - } - template<typename T> - TimeDelta& operator/=(T a) { - return *this = (*this / a); - } - - int64_t operator/(TimeDelta a) const { return delta_ / a.delta_; } - TimeDelta operator%(TimeDelta a) const { - return TimeDelta(delta_ % a.delta_); - } - - // Comparison operators. - bool operator==(TimeDelta other) const { - return delta_ == other.delta_; - } - bool operator!=(TimeDelta other) const { - return delta_ != other.delta_; - } - bool operator<(TimeDelta other) const { - return delta_ < other.delta_; - } - bool operator<=(TimeDelta other) const { - return delta_ <= other.delta_; - } - bool operator>(TimeDelta other) const { - return delta_ > other.delta_; - } - bool operator>=(TimeDelta other) const { - return delta_ >= other.delta_; - } - - private: - friend int64_t time_internal::SaturatedAdd(TimeDelta delta, int64_t value); - friend int64_t time_internal::SaturatedSub(TimeDelta delta, int64_t value); - - // Constructs a delta given the duration in microseconds. This is private - // to avoid confusion by callers with an integer constructor. Use - // FromSeconds, FromMilliseconds, etc. instead. - explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {} - - // Private method to build a delta from a double. - static TimeDelta FromDouble(double value); - - // Delta in microseconds. - int64_t delta_; -}; - -template<typename T> -inline TimeDelta operator*(T a, TimeDelta td) { - return td * a; -} - -// For logging use only. -BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeDelta time_delta); - -// Do not reference the time_internal::TimeBase template class directly. Please -// use one of the time subclasses instead, and only reference the public -// TimeBase members via those classes. -namespace time_internal { - -// TimeBase-------------------------------------------------------------------- - -// Provides value storage and comparison/math operations common to all time -// classes. Each subclass provides for strong type-checking to ensure -// semantically meaningful comparison/math of time values from the same clock -// source or timeline. -template<class TimeClass> -class TimeBase { - public: - static const int64_t kHoursPerDay = 24; - static const int64_t kMillisecondsPerSecond = 1000; - static const int64_t kMillisecondsPerDay = - kMillisecondsPerSecond * 60 * 60 * kHoursPerDay; - static const int64_t kMicrosecondsPerMillisecond = 1000; - static const int64_t kMicrosecondsPerSecond = - kMicrosecondsPerMillisecond * kMillisecondsPerSecond; - static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; - static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; - static const int64_t kMicrosecondsPerDay = - kMicrosecondsPerHour * kHoursPerDay; - static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; - static const int64_t kNanosecondsPerMicrosecond = 1000; - static const int64_t kNanosecondsPerSecond = - kNanosecondsPerMicrosecond * kMicrosecondsPerSecond; - - // Returns true if this object has not been initialized. - // - // Warning: Be careful when writing code that performs math on time values, - // since it's possible to produce a valid "zero" result that should not be - // interpreted as a "null" value. - bool is_null() const { - return us_ == 0; - } - - // Returns true if this object represents the maximum time. - bool is_max() const { return us_ == std::numeric_limits<int64_t>::max(); } - - // For serializing only. Use FromInternalValue() to reconstitute. Please don't - // use this and do arithmetic on it, as it is more error prone than using the - // provided operators. - int64_t ToInternalValue() const { return us_; } - - TimeClass& operator=(TimeClass other) { - us_ = other.us_; - return *(static_cast<TimeClass*>(this)); - } - - // Compute the difference between two times. - TimeDelta operator-(TimeClass other) const { - return TimeDelta::FromMicroseconds(us_ - other.us_); - } - - // Return a new time modified by some delta. - TimeClass operator+(TimeDelta delta) const { - return TimeClass(time_internal::SaturatedAdd(delta, us_)); - } - TimeClass operator-(TimeDelta delta) const { - return TimeClass(-time_internal::SaturatedSub(delta, us_)); - } - - // Modify by some time delta. - TimeClass& operator+=(TimeDelta delta) { - return static_cast<TimeClass&>(*this = (*this + delta)); - } - TimeClass& operator-=(TimeDelta delta) { - return static_cast<TimeClass&>(*this = (*this - delta)); - } - - // Comparison operators - bool operator==(TimeClass other) const { - return us_ == other.us_; - } - bool operator!=(TimeClass other) const { - return us_ != other.us_; - } - bool operator<(TimeClass other) const { - return us_ < other.us_; - } - bool operator<=(TimeClass other) const { - return us_ <= other.us_; - } - bool operator>(TimeClass other) const { - return us_ > other.us_; - } - bool operator>=(TimeClass other) const { - return us_ >= other.us_; - } - - // Converts an integer value representing TimeClass to a class. This is used - // when deserializing a |TimeClass| structure, using a value known to be - // compatible. It is not provided as a constructor because the integer type - // may be unclear from the perspective of a caller. - static TimeClass FromInternalValue(int64_t us) { return TimeClass(us); } - - protected: - explicit TimeBase(int64_t us) : us_(us) {} - - // Time value in a microsecond timebase. - int64_t us_; -}; - -} // namespace time_internal - -template<class TimeClass> -inline TimeClass operator+(TimeDelta delta, TimeClass t) { - return t + delta; -} - -// Time ----------------------------------------------------------------------- - -// Represents a wall clock time in UTC. Values are not guaranteed to be -// monotonically non-decreasing and are subject to large amounts of skew. -class BASE_EXPORT Time : public time_internal::TimeBase<Time> { - public: - // The representation of Jan 1, 1970 UTC in microseconds since the - // platform-dependent epoch. - static const int64_t kTimeTToMicrosecondsOffset; - -#if !defined(OS_WIN) - // On Mac & Linux, this value is the delta from the Windows epoch of 1601 to - // the Posix delta of 1970. This is used for migrating between the old - // 1970-based epochs to the new 1601-based ones. It should be removed from - // this global header and put in the platform-specific ones when we remove the - // migration code. - static const int64_t kWindowsEpochDeltaMicroseconds; -#else - // To avoid overflow in QPC to Microseconds calculations, since we multiply - // by kMicrosecondsPerSecond, then the QPC value should not exceed - // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. - enum : int64_t{kQPCOverflowThreshold = 0x8637BD05AF7}; -#endif - - // Represents an exploded time that can be formatted nicely. This is kind of - // like the Win32 SYSTEMTIME structure or the Unix "struct tm" with a few - // additions and changes to prevent errors. - struct BASE_EXPORT Exploded { - int year; // Four digit year "2007" - int month; // 1-based month (values 1 = January, etc.) - int day_of_week; // 0-based day of week (0 = Sunday, etc.) - int day_of_month; // 1-based day of month (1-31) - int hour; // Hour within the current day (0-23) - int minute; // Minute within the current hour (0-59) - int second; // Second within the current minute (0-59 plus leap - // seconds which may take it up to 60). - int millisecond; // Milliseconds within the current second (0-999) - - // A cursory test for whether the data members are within their - // respective ranges. A 'true' return value does not guarantee the - // Exploded value can be successfully converted to a Time value. - bool HasValidValues() const; - }; - - // Contains the NULL time. Use Time::Now() to get the current time. - Time() : TimeBase(0) { - } - - // Returns the time for epoch in Unix-like system (Jan 1, 1970). - static Time UnixEpoch(); - - // Returns the current time. Watch out, the system might adjust its clock - // in which case time will actually go backwards. We don't guarantee that - // times are increasing, or that two calls to Now() won't be the same. - static Time Now(); - - // Returns the maximum time, which should be greater than any reasonable time - // with which we might compare it. - static Time Max(); - - // Returns the current time. Same as Now() except that this function always - // uses system time so that there are no discrepancies between the returned - // time and system time even on virtual environments including our test bot. - // For timing sensitive unittests, this function should be used. - static Time NowFromSystemTime(); - - // Converts to/from time_t in UTC and a Time class. - // TODO(brettw) this should be removed once everybody starts using the |Time| - // class. - static Time FromTimeT(time_t tt); - time_t ToTimeT() const; - - // Converts time to/from a double which is the number of seconds since epoch - // (Jan 1, 1970). Webkit uses this format to represent time. - // Because WebKit initializes double time value to 0 to indicate "not - // initialized", we map it to empty Time object that also means "not - // initialized". - static Time FromDoubleT(double dt); - double ToDoubleT() const; - -#if defined(OS_POSIX) - // Converts the timespec structure to time. MacOS X 10.8.3 (and tentatively, - // earlier versions) will have the |ts|'s tv_nsec component zeroed out, - // having a 1 second resolution, which agrees with - // https://developer.apple.com/legacy/library/#technotes/tn/tn1150.html#HFSPlusDates. - static Time FromTimeSpec(const timespec& ts); -#endif - - // Converts to/from the Javascript convention for times, a number of - // milliseconds since the epoch: - // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/getTime. - static Time FromJsTime(double ms_since_epoch); - double ToJsTime() const; - - // Converts to Java convention for times, a number of - // milliseconds since the epoch. - int64_t ToJavaTime() const; - -#if defined(OS_POSIX) - static Time FromTimeVal(struct timeval t); - struct timeval ToTimeVal() const; -#endif - -#if defined(OS_MACOSX) - static Time FromCFAbsoluteTime(CFAbsoluteTime t); - CFAbsoluteTime ToCFAbsoluteTime() const; -#endif - -#if defined(OS_WIN) - static Time FromFileTime(FILETIME ft); - FILETIME ToFileTime() const; - - // The minimum time of a low resolution timer. This is basically a windows - // constant of ~15.6ms. While it does vary on some older OS versions, we'll - // treat it as static across all windows versions. - static const int kMinLowResolutionThresholdMs = 16; - - // Enable or disable Windows high resolution timer. - static void EnableHighResolutionTimer(bool enable); - - // Activates or deactivates the high resolution timer based on the |activate| - // flag. If the HighResolutionTimer is not Enabled (see - // EnableHighResolutionTimer), this function will return false. Otherwise - // returns true. Each successful activate call must be paired with a - // subsequent deactivate call. - // All callers to activate the high resolution timer must eventually call - // this function to deactivate the high resolution timer. - static bool ActivateHighResolutionTimer(bool activate); - - // Returns true if the high resolution timer is both enabled and activated. - // This is provided for testing only, and is not tracked in a thread-safe - // way. - static bool IsHighResolutionTimerInUse(); -#endif - - // Converts an exploded structure representing either the local time or UTC - // into a Time class. - static Time FromUTCExploded(const Exploded& exploded) { - return FromExploded(false, exploded); - } - static Time FromLocalExploded(const Exploded& exploded) { - return FromExploded(true, exploded); - } - -#if !defined(MOZ_SANDBOX) - // Converts a string representation of time to a Time object. - // An example of a time string which is converted is as below:- - // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified - // in the input string, FromString assumes local time and FromUTCString - // assumes UTC. A timezone that cannot be parsed (e.g. "UTC" which is not - // specified in RFC822) is treated as if the timezone is not specified. - // TODO(iyengar) Move the FromString/FromTimeT/ToTimeT/FromFileTime to - // a new time converter class. - static bool FromString(const char* time_string, Time* parsed_time) { - return FromStringInternal(time_string, true, parsed_time); - } - static bool FromUTCString(const char* time_string, Time* parsed_time) { - return FromStringInternal(time_string, false, parsed_time); - } -#endif - - // Fills the given exploded structure with either the local time or UTC from - // this time structure (containing UTC). - void UTCExplode(Exploded* exploded) const { - return Explode(false, exploded); - } - void LocalExplode(Exploded* exploded) const { - return Explode(true, exploded); - } - - // Rounds this time down to the nearest day in local time. It will represent - // midnight on that day. - Time LocalMidnight() const; - - private: - friend class time_internal::TimeBase<Time>; - - explicit Time(int64_t us) : TimeBase(us) {} - - // Explodes the given time to either local time |is_local = true| or UTC - // |is_local = false|. - void Explode(bool is_local, Exploded* exploded) const; - - // Unexplodes a given time assuming the source is either local time - // |is_local = true| or UTC |is_local = false|. - static Time FromExploded(bool is_local, const Exploded& exploded); - -#if !defined(MOZ_SANDBOX) - // Converts a string representation of time to a Time object. - // An example of a time string which is converted is as below:- - // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified - // in the input string, local time |is_local = true| or - // UTC |is_local = false| is assumed. A timezone that cannot be parsed - // (e.g. "UTC" which is not specified in RFC822) is treated as if the - // timezone is not specified. - static bool FromStringInternal(const char* time_string, - bool is_local, - Time* parsed_time); -#endif -}; - -// Inline the TimeDelta factory methods, for fast TimeDelta construction. - -// static -inline TimeDelta TimeDelta::FromDays(int days) { - if (days == std::numeric_limits<int>::max()) - return Max(); - return TimeDelta(days * Time::kMicrosecondsPerDay); -} - -// static -inline TimeDelta TimeDelta::FromHours(int hours) { - if (hours == std::numeric_limits<int>::max()) - return Max(); - return TimeDelta(hours * Time::kMicrosecondsPerHour); -} - -// static -inline TimeDelta TimeDelta::FromMinutes(int minutes) { - if (minutes == std::numeric_limits<int>::max()) - return Max(); - return TimeDelta(minutes * Time::kMicrosecondsPerMinute); -} - -// static -inline TimeDelta TimeDelta::FromSeconds(int64_t secs) { - return TimeDelta(secs) * Time::kMicrosecondsPerSecond; -} - -// static -inline TimeDelta TimeDelta::FromMilliseconds(int64_t ms) { - return TimeDelta(ms) * Time::kMicrosecondsPerMillisecond; -} - -// static -inline TimeDelta TimeDelta::FromSecondsD(double secs) { - return FromDouble(secs * Time::kMicrosecondsPerSecond); -} - -// static -inline TimeDelta TimeDelta::FromMillisecondsD(double ms) { - return FromDouble(ms * Time::kMicrosecondsPerMillisecond); -} - -// static -inline TimeDelta TimeDelta::FromMicroseconds(int64_t us) { - return TimeDelta(us); -} - -// static -inline TimeDelta TimeDelta::FromDouble(double value) { - double max_magnitude = std::numeric_limits<int64_t>::max(); - TimeDelta delta = TimeDelta(static_cast<int64_t>(value)); - if (value > max_magnitude) - delta = Max(); - else if (value < -max_magnitude) - delta = -Max(); - return delta; -} - -// For logging use only. -BASE_EXPORT std::ostream& operator<<(std::ostream& os, Time time); - -// TimeTicks ------------------------------------------------------------------ - -// Represents monotonically non-decreasing clock time. -class BASE_EXPORT TimeTicks : public time_internal::TimeBase<TimeTicks> { - public: - TimeTicks() : TimeBase(0) { - } - - // Platform-dependent tick count representing "right now." When - // IsHighResolution() returns false, the resolution of the clock could be - // as coarse as ~15.6ms. Otherwise, the resolution should be no worse than one - // microsecond. - static TimeTicks Now(); - - // Returns true if the high resolution clock is working on this system and - // Now() will return high resolution values. Note that, on systems where the - // high resolution clock works but is deemed inefficient, the low resolution - // clock will be used instead. - static bool IsHighResolution(); - -#if defined(OS_WIN) - // Translates an absolute QPC timestamp into a TimeTicks value. The returned - // value has the same origin as Now(). Do NOT attempt to use this if - // IsHighResolution() returns false. - static TimeTicks FromQPCValue(LONGLONG qpc_value); -#endif - - // Get an estimate of the TimeTick value at the time of the UnixEpoch. Because - // Time and TimeTicks respond differently to user-set time and NTP - // adjustments, this number is only an estimate. Nevertheless, this can be - // useful when you need to relate the value of TimeTicks to a real time and - // date. Note: Upon first invocation, this function takes a snapshot of the - // realtime clock to establish a reference point. This function will return - // the same value for the duration of the application, but will be different - // in future application runs. - static TimeTicks UnixEpoch(); - - // Returns |this| snapped to the next tick, given a |tick_phase| and - // repeating |tick_interval| in both directions. |this| may be before, - // after, or equal to the |tick_phase|. - TimeTicks SnappedToNextTick(TimeTicks tick_phase, - TimeDelta tick_interval) const; - -#if defined(OS_WIN) - protected: - typedef DWORD (*TickFunctionType)(void); - static TickFunctionType SetMockTickFunction(TickFunctionType ticker); -#endif - - private: - friend class time_internal::TimeBase<TimeTicks>; - - // Please use Now() to create a new object. This is for internal use - // and testing. - explicit TimeTicks(int64_t us) : TimeBase(us) {} -}; - -// For logging use only. -BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks); - -// ThreadTicks ---------------------------------------------------------------- - -// Represents a clock, specific to a particular thread, than runs only while the -// thread is running. -class BASE_EXPORT ThreadTicks : public time_internal::TimeBase<ThreadTicks> { - public: - ThreadTicks() : TimeBase(0) { - } - - // Returns true if ThreadTicks::Now() is supported on this system. - static bool IsSupported() { -#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ - (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_ANDROID) - return true; -#elif defined(OS_WIN) - return IsSupportedWin(); -#else - return false; -#endif - } - - // Waits until the initialization is completed. Needs to be guarded with a - // call to IsSupported(). - static void WaitUntilInitialized() { -#if defined(OS_WIN) - WaitUntilInitializedWin(); -#endif - } - - // Returns thread-specific CPU-time on systems that support this feature. - // Needs to be guarded with a call to IsSupported(). Use this timer - // to (approximately) measure how much time the calling thread spent doing - // actual work vs. being de-scheduled. May return bogus results if the thread - // migrates to another CPU between two calls. Returns an empty ThreadTicks - // object until the initialization is completed. If a clock reading is - // absolutely needed, call WaitUntilInitialized() before this method. - static ThreadTicks Now(); - - private: - friend class time_internal::TimeBase<ThreadTicks>; - - // Please use Now() to create a new object. This is for internal use - // and testing. - explicit ThreadTicks(int64_t us) : TimeBase(us) {} - -#if defined(OS_WIN) - FRIEND_TEST_ALL_PREFIXES(TimeTicks, TSCTicksPerSecond); - - // Returns the frequency of the TSC in ticks per second, or 0 if it hasn't - // been measured yet. Needs to be guarded with a call to IsSupported(). - // This method is declared here rather than in the anonymous namespace to - // allow testing. - static double TSCTicksPerSecond(); - - static bool IsSupportedWin(); - static void WaitUntilInitializedWin(); -#endif -}; - -// For logging use only. -BASE_EXPORT std::ostream& operator<<(std::ostream& os, ThreadTicks time_ticks); - -} // namespace base - -#endif // BASE_TIME_TIME_H_ diff --git a/security/sandbox/chromium/base/time/time_posix.cc b/security/sandbox/chromium/base/time/time_posix.cc deleted file mode 100644 index 4aadee618..000000000 --- a/security/sandbox/chromium/base/time/time_posix.cc +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/time/time.h" - -#include <stdint.h> -#include <sys/time.h> -#include <time.h> -#if defined(OS_ANDROID) && !defined(__LP64__) -#include <time64.h> -#endif -#include <unistd.h> - -#include <limits> -#include <ostream> - -#include "base/logging.h" -#include "build/build_config.h" - -#if defined(OS_ANDROID) -#include "base/os_compat_android.h" -#elif defined(OS_NACL) -#include "base/os_compat_nacl.h" -#endif - -#if !defined(OS_MACOSX) -#include "base/lazy_instance.h" -#include "base/synchronization/lock.h" -#endif - -namespace { - -#if !defined(OS_MACOSX) -// This prevents a crash on traversing the environment global and looking up -// the 'TZ' variable in libc. See: crbug.com/390567. -base::LazyInstance<base::Lock>::Leaky - g_sys_time_to_time_struct_lock = LAZY_INSTANCE_INITIALIZER; - -// Define a system-specific SysTime that wraps either to a time_t or -// a time64_t depending on the host system, and associated convertion. -// See crbug.com/162007 -#if defined(OS_ANDROID) && !defined(__LP64__) -typedef time64_t SysTime; - -SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { - base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); - if (is_local) - return mktime64(timestruct); - else - return timegm64(timestruct); -} - -void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { - base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); - if (is_local) - localtime64_r(&t, timestruct); - else - gmtime64_r(&t, timestruct); -} - -#else // OS_ANDROID && !__LP64__ -typedef time_t SysTime; - -SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { - base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); - if (is_local) - return mktime(timestruct); - else - return timegm(timestruct); -} - -void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { - base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); - if (is_local) - localtime_r(&t, timestruct); - else - gmtime_r(&t, timestruct); -} -#endif // OS_ANDROID - -int64_t ConvertTimespecToMicros(const struct timespec& ts) { - base::CheckedNumeric<int64_t> result(ts.tv_sec); - result *= base::Time::kMicrosecondsPerSecond; - result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); - return result.ValueOrDie(); -} - -// Helper function to get results from clock_gettime() and convert to a -// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported -// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines -// _POSIX_MONOTONIC_CLOCK to -1. -#if (defined(OS_POSIX) && \ - defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \ - defined(OS_BSD) || defined(OS_ANDROID) -int64_t ClockNow(clockid_t clk_id) { - struct timespec ts; - if (clock_gettime(clk_id, &ts) != 0) { - NOTREACHED() << "clock_gettime(" << clk_id << ") failed."; - return 0; - } - return ConvertTimespecToMicros(ts); -} -#else // _POSIX_MONOTONIC_CLOCK -#error No usable tick clock function on this platform. -#endif // _POSIX_MONOTONIC_CLOCK -#endif // !defined(OS_MACOSX) - -} // namespace - -namespace base { - -struct timespec TimeDelta::ToTimeSpec() const { - int64_t microseconds = InMicroseconds(); - time_t seconds = 0; - if (microseconds >= Time::kMicrosecondsPerSecond) { - seconds = InSeconds(); - microseconds -= seconds * Time::kMicrosecondsPerSecond; - } - struct timespec result = - {seconds, - static_cast<long>(microseconds * Time::kNanosecondsPerMicrosecond)}; - return result; -} - -#if !defined(OS_MACOSX) -// The Time routines in this file use standard POSIX routines, or almost- -// standard routines in the case of timegm. We need to use a Mach-specific -// function for TimeTicks::Now() on Mac OS X. - -// Time ----------------------------------------------------------------------- - -// Windows uses a Gregorian epoch of 1601. We need to match this internally -// so that our time representations match across all platforms. See bug 14734. -// irb(main):010:0> Time.at(0).getutc() -// => Thu Jan 01 00:00:00 UTC 1970 -// irb(main):011:0> Time.at(-11644473600).getutc() -// => Mon Jan 01 00:00:00 UTC 1601 -static const int64_t kWindowsEpochDeltaSeconds = INT64_C(11644473600); - -// static -const int64_t Time::kWindowsEpochDeltaMicroseconds = - kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond; - -// Some functions in time.cc use time_t directly, so we provide an offset -// to convert from time_t (Unix epoch) and internal (Windows epoch). -// static -const int64_t Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; - -// static -Time Time::Now() { - struct timeval tv; - struct timezone tz = { 0, 0 }; // UTC - if (gettimeofday(&tv, &tz) != 0) { - DCHECK(0) << "Could not determine time of day"; - PLOG(ERROR) << "Call to gettimeofday failed."; - // Return null instead of uninitialized |tv| value, which contains random - // garbage data. This may result in the crash seen in crbug.com/147570. - return Time(); - } - // Combine seconds and microseconds in a 64-bit field containing microseconds - // since the epoch. That's enough for nearly 600 centuries. Adjust from - // Unix (1970) to Windows (1601) epoch. - return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) + - kWindowsEpochDeltaMicroseconds); -} - -// static -Time Time::NowFromSystemTime() { - // Just use Now() because Now() returns the system time. - return Now(); -} - -void Time::Explode(bool is_local, Exploded* exploded) const { - // Time stores times with microsecond resolution, but Exploded only carries - // millisecond resolution, so begin by being lossy. Adjust from Windows - // epoch (1601) to Unix epoch (1970); - int64_t microseconds = us_ - kWindowsEpochDeltaMicroseconds; - // The following values are all rounded towards -infinity. - int64_t milliseconds; // Milliseconds since epoch. - SysTime seconds; // Seconds since epoch. - int millisecond; // Exploded millisecond value (0-999). - if (microseconds >= 0) { - // Rounding towards -infinity <=> rounding towards 0, in this case. - milliseconds = microseconds / kMicrosecondsPerMillisecond; - seconds = milliseconds / kMillisecondsPerSecond; - millisecond = milliseconds % kMillisecondsPerSecond; - } else { - // Round these *down* (towards -infinity). - milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) / - kMicrosecondsPerMillisecond; - seconds = (milliseconds - kMillisecondsPerSecond + 1) / - kMillisecondsPerSecond; - // Make this nonnegative (and between 0 and 999 inclusive). - millisecond = milliseconds % kMillisecondsPerSecond; - if (millisecond < 0) - millisecond += kMillisecondsPerSecond; - } - - struct tm timestruct; - SysTimeToTimeStruct(seconds, ×truct, is_local); - - exploded->year = timestruct.tm_year + 1900; - exploded->month = timestruct.tm_mon + 1; - exploded->day_of_week = timestruct.tm_wday; - exploded->day_of_month = timestruct.tm_mday; - exploded->hour = timestruct.tm_hour; - exploded->minute = timestruct.tm_min; - exploded->second = timestruct.tm_sec; - exploded->millisecond = millisecond; -} - -// static -Time Time::FromExploded(bool is_local, const Exploded& exploded) { - struct tm timestruct; - timestruct.tm_sec = exploded.second; - timestruct.tm_min = exploded.minute; - timestruct.tm_hour = exploded.hour; - timestruct.tm_mday = exploded.day_of_month; - timestruct.tm_mon = exploded.month - 1; - timestruct.tm_year = exploded.year - 1900; - timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this - timestruct.tm_yday = 0; // mktime/timegm ignore this - timestruct.tm_isdst = -1; // attempt to figure it out -#if !defined(OS_NACL) && !defined(OS_SOLARIS) - timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore - timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore -#endif - - int64_t milliseconds; - SysTime seconds; - - // Certain exploded dates do not really exist due to daylight saving times, - // and this causes mktime() to return implementation-defined values when - // tm_isdst is set to -1. On Android, the function will return -1, while the - // C libraries of other platforms typically return a liberally-chosen value. - // Handling this requires the special code below. - - // SysTimeFromTimeStruct() modifies the input structure, save current value. - struct tm timestruct0 = timestruct; - - seconds = SysTimeFromTimeStruct(×truct, is_local); - if (seconds == -1) { - // Get the time values with tm_isdst == 0 and 1, then select the closest one - // to UTC 00:00:00 that isn't -1. - timestruct = timestruct0; - timestruct.tm_isdst = 0; - int64_t seconds_isdst0 = SysTimeFromTimeStruct(×truct, is_local); - - timestruct = timestruct0; - timestruct.tm_isdst = 1; - int64_t seconds_isdst1 = SysTimeFromTimeStruct(×truct, is_local); - - // seconds_isdst0 or seconds_isdst1 can be -1 for some timezones. - // E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'. - if (seconds_isdst0 < 0) - seconds = seconds_isdst1; - else if (seconds_isdst1 < 0) - seconds = seconds_isdst0; - else - seconds = std::min(seconds_isdst0, seconds_isdst1); - } - - // Handle overflow. Clamping the range to what mktime and timegm might - // return is the best that can be done here. It's not ideal, but it's better - // than failing here or ignoring the overflow case and treating each time - // overflow as one second prior to the epoch. - if (seconds == -1 && - (exploded.year < 1969 || exploded.year > 1970)) { - // If exploded.year is 1969 or 1970, take -1 as correct, with the - // time indicating 1 second prior to the epoch. (1970 is allowed to handle - // time zone and DST offsets.) Otherwise, return the most future or past - // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. - // - // The minimum and maximum representible times that mktime and timegm could - // return are used here instead of values outside that range to allow for - // proper round-tripping between exploded and counter-type time - // representations in the presence of possible truncation to time_t by - // division and use with other functions that accept time_t. - // - // When representing the most distant time in the future, add in an extra - // 999ms to avoid the time being less than any other possible value that - // this function can return. - - // On Android, SysTime is int64_t, special care must be taken to avoid - // overflows. - const int64_t min_seconds = (sizeof(SysTime) < sizeof(int64_t)) - ? std::numeric_limits<SysTime>::min() - : std::numeric_limits<int32_t>::min(); - const int64_t max_seconds = (sizeof(SysTime) < sizeof(int64_t)) - ? std::numeric_limits<SysTime>::max() - : std::numeric_limits<int32_t>::max(); - if (exploded.year < 1969) { - milliseconds = min_seconds * kMillisecondsPerSecond; - } else { - milliseconds = max_seconds * kMillisecondsPerSecond; - milliseconds += (kMillisecondsPerSecond - 1); - } - } else { - milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; - } - - // Adjust from Unix (1970) to Windows (1601) epoch. - return Time((milliseconds * kMicrosecondsPerMillisecond) + - kWindowsEpochDeltaMicroseconds); -} - -// TimeTicks ------------------------------------------------------------------ -// static -TimeTicks TimeTicks::Now() { - return TimeTicks(ClockNow(CLOCK_MONOTONIC)); -} - -// static -bool TimeTicks::IsHighResolution() { - return true; -} - -// static -ThreadTicks ThreadTicks::Now() { -#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ - defined(OS_ANDROID) - return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID)); -#else - NOTREACHED(); - return ThreadTicks(); -#endif -} - -#endif // !OS_MACOSX - -// static -Time Time::FromTimeVal(struct timeval t) { - DCHECK_LT(t.tv_usec, static_cast<int>(Time::kMicrosecondsPerSecond)); - DCHECK_GE(t.tv_usec, 0); - if (t.tv_usec == 0 && t.tv_sec == 0) - return Time(); - if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 && - t.tv_sec == std::numeric_limits<time_t>::max()) - return Max(); - return Time((static_cast<int64_t>(t.tv_sec) * Time::kMicrosecondsPerSecond) + - t.tv_usec + kTimeTToMicrosecondsOffset); -} - -struct timeval Time::ToTimeVal() const { - struct timeval result; - if (is_null()) { - result.tv_sec = 0; - result.tv_usec = 0; - return result; - } - if (is_max()) { - result.tv_sec = std::numeric_limits<time_t>::max(); - result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; - return result; - } - int64_t us = us_ - kTimeTToMicrosecondsOffset; - result.tv_sec = us / Time::kMicrosecondsPerSecond; - result.tv_usec = us % Time::kMicrosecondsPerSecond; - return result; -} - -} // namespace base diff --git a/security/sandbox/chromium/base/time/time_win.cc b/security/sandbox/chromium/base/time/time_win.cc deleted file mode 100644 index dc968ad63..000000000 --- a/security/sandbox/chromium/base/time/time_win.cc +++ /dev/null @@ -1,616 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -// Windows Timer Primer -// -// A good article: http://www.ddj.com/windows/184416651 -// A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 -// -// The default windows timer, GetSystemTimeAsFileTime is not very precise. -// It is only good to ~15.5ms. -// -// QueryPerformanceCounter is the logical choice for a high-precision timer. -// However, it is known to be buggy on some hardware. Specifically, it can -// sometimes "jump". On laptops, QPC can also be very expensive to call. -// It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower -// on laptops. A unittest exists which will show the relative cost of various -// timers on any system. -// -// The next logical choice is timeGetTime(). timeGetTime has a precision of -// 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other -// applications on the system. By default, precision is only 15.5ms. -// Unfortunately, we don't want to call timeBeginPeriod because we don't -// want to affect other applications. Further, on mobile platforms, use of -// faster multimedia timers can hurt battery life. See the intel -// article about this here: -// http://softwarecommunity.intel.com/articles/eng/1086.htm -// -// To work around all this, we're going to generally use timeGetTime(). We -// will only increase the system-wide timer if we're not running on battery -// power. - -#include "base/time/time.h" - -#pragma comment(lib, "winmm.lib") -#include <windows.h> -#include <mmsystem.h> -#include <stdint.h> - -#include "base/bit_cast.h" -#include "base/cpu.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/synchronization/lock.h" - -using base::ThreadTicks; -using base::Time; -using base::TimeDelta; -using base::TimeTicks; - -namespace { - -// From MSDN, FILETIME "Contains a 64-bit value representing the number of -// 100-nanosecond intervals since January 1, 1601 (UTC)." -int64_t FileTimeToMicroseconds(const FILETIME& ft) { - // Need to bit_cast to fix alignment, then divide by 10 to convert - // 100-nanoseconds to microseconds. This only works on little-endian - // machines. - return bit_cast<int64_t, FILETIME>(ft) / 10; -} - -void MicrosecondsToFileTime(int64_t us, FILETIME* ft) { - DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not " - "representable in FILETIME"; - - // Multiply by 10 to convert microseconds to 100-nanoseconds. Bit_cast will - // handle alignment problems. This only works on little-endian machines. - *ft = bit_cast<FILETIME, int64_t>(us * 10); -} - -int64_t CurrentWallclockMicroseconds() { - FILETIME ft; - ::GetSystemTimeAsFileTime(&ft); - return FileTimeToMicroseconds(ft); -} - -// Time between resampling the un-granular clock for this API. 60 seconds. -const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; - -int64_t initial_time = 0; -TimeTicks initial_ticks; - -void InitializeClock() { - initial_ticks = TimeTicks::Now(); - initial_time = CurrentWallclockMicroseconds(); -} - -// The two values that ActivateHighResolutionTimer uses to set the systemwide -// timer interrupt frequency on Windows. It controls how precise timers are -// but also has a big impact on battery life. -const int kMinTimerIntervalHighResMs = 1; -const int kMinTimerIntervalLowResMs = 4; -// Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. -bool g_high_res_timer_enabled = false; -// How many times the high resolution timer has been called. -uint32_t g_high_res_timer_count = 0; -// The lock to control access to the above two variables. -base::LazyInstance<base::Lock>::Leaky g_high_res_lock = - LAZY_INSTANCE_INITIALIZER; - -// Returns a pointer to the QueryThreadCycleTime() function from Windows. -// Can't statically link to it because it is not available on XP. -using QueryThreadCycleTimePtr = decltype(::QueryThreadCycleTime)*; -QueryThreadCycleTimePtr GetQueryThreadCycleTimeFunction() { - static const QueryThreadCycleTimePtr query_thread_cycle_time_fn = - reinterpret_cast<QueryThreadCycleTimePtr>(::GetProcAddress( - ::GetModuleHandle(L"kernel32.dll"), "QueryThreadCycleTime")); - return query_thread_cycle_time_fn; -} - -// Returns the current value of the performance counter. -uint64_t QPCNowRaw() { - LARGE_INTEGER perf_counter_now = {}; - // According to the MSDN documentation for QueryPerformanceCounter(), this - // will never fail on systems that run XP or later. - // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx - ::QueryPerformanceCounter(&perf_counter_now); - return perf_counter_now.QuadPart; -} - -} // namespace - -// Time ----------------------------------------------------------------------- - -// The internal representation of Time uses FILETIME, whose epoch is 1601-01-01 -// 00:00:00 UTC. ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the -// number of leap year days between 1601 and 1970: (1970-1601)/4 excluding -// 1700, 1800, and 1900. -// static -const int64_t Time::kTimeTToMicrosecondsOffset = INT64_C(11644473600000000); - -// static -Time Time::Now() { - if (initial_time == 0) - InitializeClock(); - - // We implement time using the high-resolution timers so that we can get - // timeouts which are smaller than 10-15ms. If we just used - // CurrentWallclockMicroseconds(), we'd have the less-granular timer. - // - // To make this work, we initialize the clock (initial_time) and the - // counter (initial_ctr). To compute the initial time, we can check - // the number of ticks that have elapsed, and compute the delta. - // - // To avoid any drift, we periodically resync the counters to the system - // clock. - while (true) { - TimeTicks ticks = TimeTicks::Now(); - - // Calculate the time elapsed since we started our timer - TimeDelta elapsed = ticks - initial_ticks; - - // Check if enough time has elapsed that we need to resync the clock. - if (elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) { - InitializeClock(); - continue; - } - - return Time(elapsed + Time(initial_time)); - } -} - -// static -Time Time::NowFromSystemTime() { - // Force resync. - InitializeClock(); - return Time(initial_time); -} - -// static -Time Time::FromFileTime(FILETIME ft) { - if (bit_cast<int64_t, FILETIME>(ft) == 0) - return Time(); - if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() && - ft.dwLowDateTime == std::numeric_limits<DWORD>::max()) - return Max(); - return Time(FileTimeToMicroseconds(ft)); -} - -FILETIME Time::ToFileTime() const { - if (is_null()) - return bit_cast<FILETIME, int64_t>(0); - if (is_max()) { - FILETIME result; - result.dwHighDateTime = std::numeric_limits<DWORD>::max(); - result.dwLowDateTime = std::numeric_limits<DWORD>::max(); - return result; - } - FILETIME utc_ft; - MicrosecondsToFileTime(us_, &utc_ft); - return utc_ft; -} - -// static -void Time::EnableHighResolutionTimer(bool enable) { - base::AutoLock lock(g_high_res_lock.Get()); - if (g_high_res_timer_enabled == enable) - return; - g_high_res_timer_enabled = enable; - if (!g_high_res_timer_count) - return; - // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true) - // was called which called timeBeginPeriod with g_high_res_timer_enabled - // with a value which is the opposite of |enable|. With that information we - // call timeEndPeriod with the same value used in timeBeginPeriod and - // therefore undo the period effect. - if (enable) { - timeEndPeriod(kMinTimerIntervalLowResMs); - timeBeginPeriod(kMinTimerIntervalHighResMs); - } else { - timeEndPeriod(kMinTimerIntervalHighResMs); - timeBeginPeriod(kMinTimerIntervalLowResMs); - } -} - -// static -bool Time::ActivateHighResolutionTimer(bool activating) { - // We only do work on the transition from zero to one or one to zero so we - // can easily undo the effect (if necessary) when EnableHighResolutionTimer is - // called. - const uint32_t max = std::numeric_limits<uint32_t>::max(); - - base::AutoLock lock(g_high_res_lock.Get()); - UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs - : kMinTimerIntervalLowResMs; - if (activating) { - DCHECK_NE(g_high_res_timer_count, max); - ++g_high_res_timer_count; - if (g_high_res_timer_count == 1) - timeBeginPeriod(period); - } else { - DCHECK_NE(g_high_res_timer_count, 0u); - --g_high_res_timer_count; - if (g_high_res_timer_count == 0) - timeEndPeriod(period); - } - return (period == kMinTimerIntervalHighResMs); -} - -// static -bool Time::IsHighResolutionTimerInUse() { - base::AutoLock lock(g_high_res_lock.Get()); - return g_high_res_timer_enabled && g_high_res_timer_count > 0; -} - -// static -Time Time::FromExploded(bool is_local, const Exploded& exploded) { - // Create the system struct representing our exploded time. It will either be - // in local time or UTC. - SYSTEMTIME st; - st.wYear = static_cast<WORD>(exploded.year); - st.wMonth = static_cast<WORD>(exploded.month); - st.wDayOfWeek = static_cast<WORD>(exploded.day_of_week); - st.wDay = static_cast<WORD>(exploded.day_of_month); - st.wHour = static_cast<WORD>(exploded.hour); - st.wMinute = static_cast<WORD>(exploded.minute); - st.wSecond = static_cast<WORD>(exploded.second); - st.wMilliseconds = static_cast<WORD>(exploded.millisecond); - - FILETIME ft; - bool success = true; - // Ensure that it's in UTC. - if (is_local) { - SYSTEMTIME utc_st; - success = TzSpecificLocalTimeToSystemTime(NULL, &st, &utc_st) && - SystemTimeToFileTime(&utc_st, &ft); - } else { - success = !!SystemTimeToFileTime(&st, &ft); - } - - if (!success) { - NOTREACHED() << "Unable to convert time"; - return Time(0); - } - return Time(FileTimeToMicroseconds(ft)); -} - -void Time::Explode(bool is_local, Exploded* exploded) const { - if (us_ < 0LL) { - // We are not able to convert it to FILETIME. - ZeroMemory(exploded, sizeof(*exploded)); - return; - } - - // FILETIME in UTC. - FILETIME utc_ft; - MicrosecondsToFileTime(us_, &utc_ft); - - // FILETIME in local time if necessary. - bool success = true; - // FILETIME in SYSTEMTIME (exploded). - SYSTEMTIME st = {0}; - if (is_local) { - SYSTEMTIME utc_st; - // We don't use FileTimeToLocalFileTime here, since it uses the current - // settings for the time zone and daylight saving time. Therefore, if it is - // daylight saving time, it will take daylight saving time into account, - // even if the time you are converting is in standard time. - success = FileTimeToSystemTime(&utc_ft, &utc_st) && - SystemTimeToTzSpecificLocalTime(NULL, &utc_st, &st); - } else { - success = !!FileTimeToSystemTime(&utc_ft, &st); - } - - if (!success) { - NOTREACHED() << "Unable to convert time, don't know why"; - ZeroMemory(exploded, sizeof(*exploded)); - return; - } - - exploded->year = st.wYear; - exploded->month = st.wMonth; - exploded->day_of_week = st.wDayOfWeek; - exploded->day_of_month = st.wDay; - exploded->hour = st.wHour; - exploded->minute = st.wMinute; - exploded->second = st.wSecond; - exploded->millisecond = st.wMilliseconds; -} - -// TimeTicks ------------------------------------------------------------------ -namespace { - -// We define a wrapper to adapt between the __stdcall and __cdecl call of the -// mock function, and to avoid a static constructor. Assigning an import to a -// function pointer directly would require setup code to fetch from the IAT. -DWORD timeGetTimeWrapper() { - return timeGetTime(); -} - -DWORD (*g_tick_function)(void) = &timeGetTimeWrapper; - -// Accumulation of time lost due to rollover (in milliseconds). -int64_t g_rollover_ms = 0; - -// The last timeGetTime value we saw, to detect rollover. -DWORD g_last_seen_now = 0; - -// Lock protecting rollover_ms and last_seen_now. -// Note: this is a global object, and we usually avoid these. However, the time -// code is low-level, and we don't want to use Singletons here (it would be too -// easy to use a Singleton without even knowing it, and that may lead to many -// gotchas). Its impact on startup time should be negligible due to low-level -// nature of time code. -base::Lock g_rollover_lock; - -// We use timeGetTime() to implement TimeTicks::Now(). This can be problematic -// because it returns the number of milliseconds since Windows has started, -// which will roll over the 32-bit value every ~49 days. We try to track -// rollover ourselves, which works if TimeTicks::Now() is called at least every -// 49 days. -TimeDelta RolloverProtectedNow() { - base::AutoLock locked(g_rollover_lock); - // We should hold the lock while calling tick_function to make sure that - // we keep last_seen_now stay correctly in sync. - DWORD now = g_tick_function(); - if (now < g_last_seen_now) - g_rollover_ms += 0x100000000I64; // ~49.7 days. - g_last_seen_now = now; - return TimeDelta::FromMilliseconds(now + g_rollover_ms); -} - -// Discussion of tick counter options on Windows: -// -// (1) CPU cycle counter. (Retrieved via RDTSC) -// The CPU counter provides the highest resolution time stamp and is the least -// expensive to retrieve. However, on older CPUs, two issues can affect its -// reliability: First it is maintained per processor and not synchronized -// between processors. Also, the counters will change frequency due to thermal -// and power changes, and stop in some states. -// -// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- -// resolution (<1 microsecond) time stamp. On most hardware running today, it -// auto-detects and uses the constant-rate RDTSC counter to provide extremely -// efficient and reliable time stamps. -// -// On older CPUs where RDTSC is unreliable, it falls back to using more -// expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI -// PM timer, and can involve system calls; and all this is up to the HAL (with -// some help from ACPI). According to -// http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the -// worst case, it gets the counter from the rollover interrupt on the -// programmable interrupt timer. In best cases, the HAL may conclude that the -// RDTSC counter runs at a constant frequency, then it uses that instead. On -// multiprocessor machines, it will try to verify the values returned from -// RDTSC on each processor are consistent with each other, and apply a handful -// of workarounds for known buggy hardware. In other words, QPC is supposed to -// give consistent results on a multiprocessor computer, but for older CPUs it -// can be unreliable due bugs in BIOS or HAL. -// -// (3) System time. The system time provides a low-resolution (from ~1 to ~15.6 -// milliseconds) time stamp but is comparatively less expensive to retrieve and -// more reliable. Time::EnableHighResolutionTimer() and -// Time::ActivateHighResolutionTimer() can be called to alter the resolution of -// this timer; and also other Windows applications can alter it, affecting this -// one. - -using NowFunction = TimeDelta (*)(void); - -TimeDelta InitialNowFunction(); - -// See "threading notes" in InitializeNowFunctionPointer() for details on how -// concurrent reads/writes to these globals has been made safe. -NowFunction g_now_function = &InitialNowFunction; -int64_t g_qpc_ticks_per_second = 0; - -// As of January 2015, use of <atomic> is forbidden in Chromium code. This is -// what std::atomic_thread_fence does on Windows on all Intel architectures when -// the memory_order argument is anything but std::memory_order_seq_cst: -#define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier(); - -TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) { - // Ensure that the assignment to |g_qpc_ticks_per_second|, made in - // InitializeNowFunctionPointer(), has happened by this point. - ATOMIC_THREAD_FENCE(memory_order_acquire); - - DCHECK_GT(g_qpc_ticks_per_second, 0); - - // If the QPC Value is below the overflow threshold, we proceed with - // simple multiply and divide. - if (qpc_value < Time::kQPCOverflowThreshold) { - return TimeDelta::FromMicroseconds( - qpc_value * Time::kMicrosecondsPerSecond / g_qpc_ticks_per_second); - } - // Otherwise, calculate microseconds in a round about manner to avoid - // overflow and precision issues. - int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second; - int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second); - return TimeDelta::FromMicroseconds( - (whole_seconds * Time::kMicrosecondsPerSecond) + - ((leftover_ticks * Time::kMicrosecondsPerSecond) / - g_qpc_ticks_per_second)); -} - -TimeDelta QPCNow() { - return QPCValueToTimeDelta(QPCNowRaw()); -} - -bool IsBuggyAthlon(const base::CPU& cpu) { - // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable. - return cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15; -} - -void InitializeNowFunctionPointer() { - LARGE_INTEGER ticks_per_sec = {}; - if (!QueryPerformanceFrequency(&ticks_per_sec)) - ticks_per_sec.QuadPart = 0; - - // If Windows cannot provide a QPC implementation, TimeTicks::Now() must use - // the low-resolution clock. - // - // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now() - // will still use the low-resolution clock. A CPU lacking a non-stop time - // counter will cause Windows to provide an alternate QPC implementation that - // works, but is expensive to use. Certain Athlon CPUs are known to make the - // QPC implementation unreliable. - // - // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015, - // ~72% of users fall within this category. - NowFunction now_function; - base::CPU cpu; - if (ticks_per_sec.QuadPart <= 0 || - !cpu.has_non_stop_time_stamp_counter() || IsBuggyAthlon(cpu)) { - now_function = &RolloverProtectedNow; - } else { - now_function = &QPCNow; - } - - // Threading note 1: In an unlikely race condition, it's possible for two or - // more threads to enter InitializeNowFunctionPointer() in parallel. This is - // not a problem since all threads should end up writing out the same values - // to the global variables. - // - // Threading note 2: A release fence is placed here to ensure, from the - // perspective of other threads using the function pointers, that the - // assignment to |g_qpc_ticks_per_second| happens before the function pointers - // are changed. - g_qpc_ticks_per_second = ticks_per_sec.QuadPart; - ATOMIC_THREAD_FENCE(memory_order_release); - g_now_function = now_function; -} - -TimeDelta InitialNowFunction() { - InitializeNowFunctionPointer(); - return g_now_function(); -} - -} // namespace - -// static -TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction( - TickFunctionType ticker) { - base::AutoLock locked(g_rollover_lock); - TickFunctionType old = g_tick_function; - g_tick_function = ticker; - g_rollover_ms = 0; - g_last_seen_now = 0; - return old; -} - -// static -TimeTicks TimeTicks::Now() { - return TimeTicks() + g_now_function(); -} - -// static -bool TimeTicks::IsHighResolution() { - if (g_now_function == &InitialNowFunction) - InitializeNowFunctionPointer(); - return g_now_function == &QPCNow; -} - -// static -ThreadTicks ThreadTicks::Now() { - DCHECK(IsSupported()); - - // Get the number of TSC ticks used by the current thread. - ULONG64 thread_cycle_time = 0; - GetQueryThreadCycleTimeFunction()(::GetCurrentThread(), &thread_cycle_time); - - // Get the frequency of the TSC. - double tsc_ticks_per_second = TSCTicksPerSecond(); - if (tsc_ticks_per_second == 0) - return ThreadTicks(); - - // Return the CPU time of the current thread. - double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second; - return ThreadTicks( - static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond)); -} - -// static -bool ThreadTicks::IsSupportedWin() { - static bool is_supported = GetQueryThreadCycleTimeFunction() && - base::CPU().has_non_stop_time_stamp_counter() && - !IsBuggyAthlon(base::CPU()); - return is_supported; -} - -// static -void ThreadTicks::WaitUntilInitializedWin() { - while (TSCTicksPerSecond() == 0) - ::Sleep(10); -} - -double ThreadTicks::TSCTicksPerSecond() { - DCHECK(IsSupported()); - - // The value returned by QueryPerformanceFrequency() cannot be used as the TSC - // frequency, because there is no guarantee that the TSC frequency is equal to - // the performance counter frequency. - - // The TSC frequency is cached in a static variable because it takes some time - // to compute it. - static double tsc_ticks_per_second = 0; - if (tsc_ticks_per_second != 0) - return tsc_ticks_per_second; - - // Increase the thread priority to reduces the chances of having a context - // switch during a reading of the TSC and the performance counter. - int previous_priority = ::GetThreadPriority(::GetCurrentThread()); - ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST); - - // The first time that this function is called, make an initial reading of the - // TSC and the performance counter. - static const uint64_t tsc_initial = __rdtsc(); - static const uint64_t perf_counter_initial = QPCNowRaw(); - - // Make a another reading of the TSC and the performance counter every time - // that this function is called. - uint64_t tsc_now = __rdtsc(); - uint64_t perf_counter_now = QPCNowRaw(); - - // Reset the thread priority. - ::SetThreadPriority(::GetCurrentThread(), previous_priority); - - // Make sure that at least 50 ms elapsed between the 2 readings. The first - // time that this function is called, we don't expect this to be the case. - // Note: The longer the elapsed time between the 2 readings is, the more - // accurate the computed TSC frequency will be. The 50 ms value was - // chosen because local benchmarks show that it allows us to get a - // stddev of less than 1 tick/us between multiple runs. - // Note: According to the MSDN documentation for QueryPerformanceFrequency(), - // this will never fail on systems that run XP or later. - // https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx - LARGE_INTEGER perf_counter_frequency = {}; - ::QueryPerformanceFrequency(&perf_counter_frequency); - DCHECK_GE(perf_counter_now, perf_counter_initial); - uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial; - double elapsed_time_seconds = - perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart); - - const double kMinimumEvaluationPeriodSeconds = 0.05; - if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds) - return 0; - - // Compute the frequency of the TSC. - DCHECK_GE(tsc_now, tsc_initial); - uint64_t tsc_ticks = tsc_now - tsc_initial; - tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds; - - return tsc_ticks_per_second; -} - -// static -TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { - return TimeTicks() + QPCValueToTimeDelta(qpc_value); -} - -// TimeDelta ------------------------------------------------------------------ - -// static -TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { - return QPCValueToTimeDelta(qpc_value); -} diff --git a/security/sandbox/chromium/base/tuple.h b/security/sandbox/chromium/base/tuple.h deleted file mode 100644 index e5872cc4f..000000000 --- a/security/sandbox/chromium/base/tuple.h +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// A Tuple is a generic templatized container, similar in concept to std::pair -// and std::tuple. The convenient MakeTuple() function takes any number of -// arguments and will construct and return the appropriate Tuple object. The -// functions DispatchToMethod and DispatchToFunction take a function pointer or -// instance and method pointer, and unpack a tuple into arguments to the call. -// -// Tuple elements are copied by value, and stored in the tuple. See the unit -// tests for more details of how/when the values are copied. -// -// Example usage: -// // These two methods of creating a Tuple are identical. -// Tuple<int, const char*> tuple_a(1, "wee"); -// Tuple<int, const char*> tuple_b = MakeTuple(1, "wee"); -// -// void SomeFunc(int a, const char* b) { } -// DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee") -// DispatchToFunction( -// &SomeFunc, MakeTuple(10, "foo")); // SomeFunc(10, "foo") -// -// struct { void SomeMeth(int a, int b, int c) { } } foo; -// DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3)); -// // foo->SomeMeth(1, 2, 3); - -#ifndef BASE_TUPLE_H_ -#define BASE_TUPLE_H_ - -#include <stddef.h> - -#include "base/bind_helpers.h" -#include "build/build_config.h" - -namespace base { - -// Index sequences -// -// Minimal clone of the similarly-named C++14 functionality. - -template <size_t...> -struct IndexSequence {}; - -template <size_t... Ns> -struct MakeIndexSequenceImpl; - -#if defined(_PREFAST_) && defined(OS_WIN) - -// Work around VC++ 2013 /analyze internal compiler error: -// https://connect.microsoft.com/VisualStudio/feedback/details/1053626 - -template <> struct MakeIndexSequenceImpl<0> { - using Type = IndexSequence<>; -}; -template <> struct MakeIndexSequenceImpl<1> { - using Type = IndexSequence<0>; -}; -template <> struct MakeIndexSequenceImpl<2> { - using Type = IndexSequence<0,1>; -}; -template <> struct MakeIndexSequenceImpl<3> { - using Type = IndexSequence<0,1,2>; -}; -template <> struct MakeIndexSequenceImpl<4> { - using Type = IndexSequence<0,1,2,3>; -}; -template <> struct MakeIndexSequenceImpl<5> { - using Type = IndexSequence<0,1,2,3,4>; -}; -template <> struct MakeIndexSequenceImpl<6> { - using Type = IndexSequence<0,1,2,3,4,5>; -}; -template <> struct MakeIndexSequenceImpl<7> { - using Type = IndexSequence<0,1,2,3,4,5,6>; -}; -template <> struct MakeIndexSequenceImpl<8> { - using Type = IndexSequence<0,1,2,3,4,5,6,7>; -}; -template <> struct MakeIndexSequenceImpl<9> { - using Type = IndexSequence<0,1,2,3,4,5,6,7,8>; -}; -template <> struct MakeIndexSequenceImpl<10> { - using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9>; -}; -template <> struct MakeIndexSequenceImpl<11> { - using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10>; -}; -template <> struct MakeIndexSequenceImpl<12> { - using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10,11>; -}; -template <> struct MakeIndexSequenceImpl<13> { - using Type = IndexSequence<0,1,2,3,4,5,6,7,8,9,10,11,12>; -}; - -#else // defined(WIN) && defined(_PREFAST_) - -template <size_t... Ns> -struct MakeIndexSequenceImpl<0, Ns...> { - using Type = IndexSequence<Ns...>; -}; - -template <size_t N, size_t... Ns> -struct MakeIndexSequenceImpl<N, Ns...> - : MakeIndexSequenceImpl<N - 1, N - 1, Ns...> {}; - -#endif // defined(WIN) && defined(_PREFAST_) - -template <size_t N> -using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::Type; - -// Traits ---------------------------------------------------------------------- -// -// A simple traits class for tuple arguments. -// -// ValueType: the bare, nonref version of a type (same as the type for nonrefs). -// RefType: the ref version of a type (same as the type for refs). -// ParamType: what type to pass to functions (refs should not be constified). - -template <class P> -struct TupleTraits { - typedef P ValueType; - typedef P& RefType; - typedef const P& ParamType; -}; - -template <class P> -struct TupleTraits<P&> { - typedef P ValueType; - typedef P& RefType; - typedef P& ParamType; -}; - -// Tuple ----------------------------------------------------------------------- -// -// This set of classes is useful for bundling 0 or more heterogeneous data types -// into a single variable. The advantage of this is that it greatly simplifies -// function objects that need to take an arbitrary number of parameters; see -// RunnableMethod and IPC::MessageWithTuple. -// -// Tuple<> is supplied to act as a 'void' type. It can be used, for example, -// when dispatching to a function that accepts no arguments (see the -// Dispatchers below). -// Tuple<A> is rarely useful. One such use is when A is non-const ref that you -// want filled by the dispatchee, and the tuple is merely a container for that -// output (a "tier"). See MakeRefTuple and its usages. - -template <typename IxSeq, typename... Ts> -struct TupleBaseImpl; -template <typename... Ts> -using TupleBase = TupleBaseImpl<MakeIndexSequence<sizeof...(Ts)>, Ts...>; -template <size_t N, typename T> -struct TupleLeaf; - -template <typename... Ts> -struct Tuple final : TupleBase<Ts...> { - Tuple() : TupleBase<Ts...>() {} - explicit Tuple(typename TupleTraits<Ts>::ParamType... args) - : TupleBase<Ts...>(args...) {} -}; - -// Avoids ambiguity between Tuple's two constructors. -template <> -struct Tuple<> final {}; - -template <size_t... Ns, typename... Ts> -struct TupleBaseImpl<IndexSequence<Ns...>, Ts...> : TupleLeaf<Ns, Ts>... { - TupleBaseImpl() : TupleLeaf<Ns, Ts>()... {} - explicit TupleBaseImpl(typename TupleTraits<Ts>::ParamType... args) - : TupleLeaf<Ns, Ts>(args)... {} -}; - -template <size_t N, typename T> -struct TupleLeaf { - TupleLeaf() {} - explicit TupleLeaf(typename TupleTraits<T>::ParamType x) : x(x) {} - - T& get() { return x; } - const T& get() const { return x; } - - T x; -}; - -// Tuple getters -------------------------------------------------------------- -// -// Allows accessing an arbitrary tuple element by index. -// -// Example usage: -// base::Tuple<int, double> t2; -// base::get<0>(t2) = 42; -// base::get<1>(t2) = 3.14; - -template <size_t I, typename T> -T& get(TupleLeaf<I, T>& leaf) { - return leaf.get(); -} - -template <size_t I, typename T> -const T& get(const TupleLeaf<I, T>& leaf) { - return leaf.get(); -} - -// Tuple types ---------------------------------------------------------------- -// -// Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the -// definitions of class types the tuple takes as parameters. - -template <typename T> -struct TupleTypes; - -template <typename... Ts> -struct TupleTypes<Tuple<Ts...>> { - using ValueTuple = Tuple<typename TupleTraits<Ts>::ValueType...>; - using RefTuple = Tuple<typename TupleTraits<Ts>::RefType...>; - using ParamTuple = Tuple<typename TupleTraits<Ts>::ParamType...>; -}; - -// Tuple creators ------------------------------------------------------------- -// -// Helper functions for constructing tuples while inferring the template -// argument types. - -template <typename... Ts> -inline Tuple<Ts...> MakeTuple(const Ts&... arg) { - return Tuple<Ts...>(arg...); -} - -// The following set of helpers make what Boost refers to as "Tiers" - a tuple -// of references. - -template <typename... Ts> -inline Tuple<Ts&...> MakeRefTuple(Ts&... arg) { - return Tuple<Ts&...>(arg...); -} - -// Dispatchers ---------------------------------------------------------------- -// -// Helper functions that call the given method on an object, with the unpacked -// tuple arguments. Notice that they all have the same number of arguments, -// so you need only write: -// DispatchToMethod(object, &Object::method, args); -// This is very useful for templated dispatchers, since they don't need to know -// what type |args| is. - -// Non-Static Dispatchers with no out params. - -template <typename ObjT, typename Method, typename... Ts, size_t... Ns> -inline void DispatchToMethodImpl(ObjT* obj, - Method method, - const Tuple<Ts...>& arg, - IndexSequence<Ns...>) { - (obj->*method)(base::internal::UnwrapTraits<Ts>::Unwrap(get<Ns>(arg))...); -} - -template <typename ObjT, typename Method, typename... Ts> -inline void DispatchToMethod(ObjT* obj, - Method method, - const Tuple<Ts...>& arg) { - DispatchToMethodImpl(obj, method, arg, MakeIndexSequence<sizeof...(Ts)>()); -} - -// Static Dispatchers with no out params. - -template <typename Function, typename... Ts, size_t... Ns> -inline void DispatchToFunctionImpl(Function function, - const Tuple<Ts...>& arg, - IndexSequence<Ns...>) { - (*function)(base::internal::UnwrapTraits<Ts>::Unwrap(get<Ns>(arg))...); -} - -template <typename Function, typename... Ts> -inline void DispatchToFunction(Function function, const Tuple<Ts...>& arg) { - DispatchToFunctionImpl(function, arg, MakeIndexSequence<sizeof...(Ts)>()); -} - -// Dispatchers with out parameters. - -template <typename ObjT, - typename Method, - typename... InTs, - typename... OutTs, - size_t... InNs, - size_t... OutNs> -inline void DispatchToMethodImpl(ObjT* obj, - Method method, - const Tuple<InTs...>& in, - Tuple<OutTs...>* out, - IndexSequence<InNs...>, - IndexSequence<OutNs...>) { - (obj->*method)(base::internal::UnwrapTraits<InTs>::Unwrap(get<InNs>(in))..., - &get<OutNs>(*out)...); -} - -template <typename ObjT, typename Method, typename... InTs, typename... OutTs> -inline void DispatchToMethod(ObjT* obj, - Method method, - const Tuple<InTs...>& in, - Tuple<OutTs...>* out) { - DispatchToMethodImpl(obj, method, in, out, - MakeIndexSequence<sizeof...(InTs)>(), - MakeIndexSequence<sizeof...(OutTs)>()); -} - -} // namespace base - -#endif // BASE_TUPLE_H_ diff --git a/security/sandbox/chromium/base/values.h b/security/sandbox/chromium/base/values.h deleted file mode 100644 index 07e5b6c83..000000000 --- a/security/sandbox/chromium/base/values.h +++ /dev/null @@ -1,567 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file specifies a recursive data storage class called Value intended for -// storing settings and other persistable data. -// -// A Value represents something that can be stored in JSON or passed to/from -// JavaScript. As such, it is NOT a generalized variant type, since only the -// types supported by JavaScript/JSON are supported. -// -// IN PARTICULAR this means that there is no support for int64_t or unsigned -// numbers. Writing JSON with such types would violate the spec. If you need -// something like this, either use a double or make a string value containing -// the number you want. - -#ifndef BASE_VALUES_H_ -#define BASE_VALUES_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <iosfwd> -#include <map> -#include <string> -#include <utility> -#include <vector> - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "base/strings/string_piece.h" - -namespace base { - -class BinaryValue; -class DictionaryValue; -class FundamentalValue; -class ListValue; -class StringValue; -class Value; - -typedef std::vector<Value*> ValueVector; -typedef std::map<std::string, Value*> ValueMap; - -// The Value class is the base class for Values. A Value can be instantiated -// via the Create*Value() factory methods, or by directly creating instances of -// the subclasses. -// -// See the file-level comment above for more information. -class BASE_EXPORT Value { - public: - enum Type { - TYPE_NULL = 0, - TYPE_BOOLEAN, - TYPE_INTEGER, - TYPE_DOUBLE, - TYPE_STRING, - TYPE_BINARY, - TYPE_DICTIONARY, - TYPE_LIST - // Note: Do not add more types. See the file-level comment above for why. - }; - - virtual ~Value(); - - static scoped_ptr<Value> CreateNullValue(); - - // Returns the type of the value stored by the current Value object. - // Each type will be implemented by only one subclass of Value, so it's - // safe to use the Type to determine whether you can cast from - // Value* to (Implementing Class)*. Also, a Value object never changes - // its type after construction. - Type GetType() const { return type_; } - - // Returns true if the current object represents a given type. - bool IsType(Type type) const { return type == type_; } - - // These methods allow the convenient retrieval of the contents of the Value. - // If the current object can be converted into the given type, the value is - // returned through the |out_value| parameter and true is returned; - // otherwise, false is returned and |out_value| is unchanged. - virtual bool GetAsBoolean(bool* out_value) const; - virtual bool GetAsInteger(int* out_value) const; - virtual bool GetAsDouble(double* out_value) const; - virtual bool GetAsString(std::string* out_value) const; - virtual bool GetAsString(string16* out_value) const; - virtual bool GetAsString(const StringValue** out_value) const; - virtual bool GetAsBinary(const BinaryValue** out_value) const; - virtual bool GetAsList(ListValue** out_value); - virtual bool GetAsList(const ListValue** out_value) const; - virtual bool GetAsDictionary(DictionaryValue** out_value); - virtual bool GetAsDictionary(const DictionaryValue** out_value) const; - // Note: Do not add more types. See the file-level comment above for why. - - // This creates a deep copy of the entire Value tree, and returns a pointer - // to the copy. The caller gets ownership of the copy, of course. - // - // Subclasses return their own type directly in their overrides; - // this works because C++ supports covariant return types. - virtual Value* DeepCopy() const; - // Preferred version of DeepCopy. TODO(estade): remove the above. - scoped_ptr<Value> CreateDeepCopy() const; - - // Compares if two Value objects have equal contents. - virtual bool Equals(const Value* other) const; - - // Compares if two Value objects have equal contents. Can handle NULLs. - // NULLs are considered equal but different from Value::CreateNullValue(). - static bool Equals(const Value* a, const Value* b); - - protected: - // These aren't safe for end-users, but they are useful for subclasses. - explicit Value(Type type); - Value(const Value& that); - Value& operator=(const Value& that); - - private: - Type type_; -}; - -// FundamentalValue represents the simple fundamental types of values. -class BASE_EXPORT FundamentalValue : public Value { - public: - explicit FundamentalValue(bool in_value); - explicit FundamentalValue(int in_value); - explicit FundamentalValue(double in_value); - ~FundamentalValue() override; - - // Overridden from Value: - bool GetAsBoolean(bool* out_value) const override; - bool GetAsInteger(int* out_value) const override; - // Values of both type TYPE_INTEGER and TYPE_DOUBLE can be obtained as - // doubles. - bool GetAsDouble(double* out_value) const override; - FundamentalValue* DeepCopy() const override; - bool Equals(const Value* other) const override; - - private: - union { - bool boolean_value_; - int integer_value_; - double double_value_; - }; -}; - -class BASE_EXPORT StringValue : public Value { - public: - // Initializes a StringValue with a UTF-8 narrow character string. - explicit StringValue(const std::string& in_value); - - // Initializes a StringValue with a string16. - explicit StringValue(const string16& in_value); - - ~StringValue() override; - - // Returns |value_| as a pointer or reference. - std::string* GetString(); - const std::string& GetString() const; - - // Overridden from Value: - bool GetAsString(std::string* out_value) const override; - bool GetAsString(string16* out_value) const override; - bool GetAsString(const StringValue** out_value) const override; - StringValue* DeepCopy() const override; - bool Equals(const Value* other) const override; - - private: - std::string value_; -}; - -class BASE_EXPORT BinaryValue: public Value { - public: - // Creates a BinaryValue with a null buffer and size of 0. - BinaryValue(); - - // Creates a BinaryValue, taking ownership of the bytes pointed to by - // |buffer|. - BinaryValue(scoped_ptr<char[]> buffer, size_t size); - - ~BinaryValue() override; - - // For situations where you want to keep ownership of your buffer, this - // factory method creates a new BinaryValue by copying the contents of the - // buffer that's passed in. - static BinaryValue* CreateWithCopiedBuffer(const char* buffer, size_t size); - - size_t GetSize() const { return size_; } - - // May return NULL. - char* GetBuffer() { return buffer_.get(); } - const char* GetBuffer() const { return buffer_.get(); } - - // Overridden from Value: - bool GetAsBinary(const BinaryValue** out_value) const override; - BinaryValue* DeepCopy() const override; - bool Equals(const Value* other) const override; - - private: - scoped_ptr<char[]> buffer_; - size_t size_; - - DISALLOW_COPY_AND_ASSIGN(BinaryValue); -}; - -// DictionaryValue provides a key-value dictionary with (optional) "path" -// parsing for recursive access; see the comment at the top of the file. Keys -// are |std::string|s and should be UTF-8 encoded. -class BASE_EXPORT DictionaryValue : public Value { - public: - // Returns |value| if it is a dictionary, nullptr otherwise. - static scoped_ptr<DictionaryValue> From(scoped_ptr<Value> value); - - DictionaryValue(); - ~DictionaryValue() override; - - // Overridden from Value: - bool GetAsDictionary(DictionaryValue** out_value) override; - bool GetAsDictionary(const DictionaryValue** out_value) const override; - - // Returns true if the current dictionary has a value for the given key. - bool HasKey(const std::string& key) const; - - // Returns the number of Values in this dictionary. - size_t size() const { return dictionary_.size(); } - - // Returns whether the dictionary is empty. - bool empty() const { return dictionary_.empty(); } - - // Clears any current contents of this dictionary. - void Clear(); - - // Sets the Value associated with the given path starting from this object. - // A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes - // into the next DictionaryValue down. Obviously, "." can't be used - // within a key, but there are no other restrictions on keys. - // If the key at any step of the way doesn't exist, or exists but isn't - // a DictionaryValue, a new DictionaryValue will be created and attached - // to the path in that location. |in_value| must be non-null. - void Set(const std::string& path, scoped_ptr<Value> in_value); - // Deprecated version of the above. TODO(estade): remove. - void Set(const std::string& path, Value* in_value); - - // Convenience forms of Set(). These methods will replace any existing - // value at that path, even if it has a different type. - void SetBoolean(const std::string& path, bool in_value); - void SetInteger(const std::string& path, int in_value); - void SetDouble(const std::string& path, double in_value); - void SetString(const std::string& path, const std::string& in_value); - void SetString(const std::string& path, const string16& in_value); - - // Like Set(), but without special treatment of '.'. This allows e.g. URLs to - // be used as paths. - void SetWithoutPathExpansion(const std::string& key, - scoped_ptr<Value> in_value); - // Deprecated version of the above. TODO(estade): remove. - void SetWithoutPathExpansion(const std::string& key, Value* in_value); - - // Convenience forms of SetWithoutPathExpansion(). - void SetBooleanWithoutPathExpansion(const std::string& path, bool in_value); - void SetIntegerWithoutPathExpansion(const std::string& path, int in_value); - void SetDoubleWithoutPathExpansion(const std::string& path, double in_value); - void SetStringWithoutPathExpansion(const std::string& path, - const std::string& in_value); - void SetStringWithoutPathExpansion(const std::string& path, - const string16& in_value); - - // Gets the Value associated with the given path starting from this object. - // A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes - // into the next DictionaryValue down. If the path can be resolved - // successfully, the value for the last key in the path will be returned - // through the |out_value| parameter, and the function will return true. - // Otherwise, it will return false and |out_value| will be untouched. - // Note that the dictionary always owns the value that's returned. - // |out_value| is optional and will only be set if non-NULL. - bool Get(StringPiece path, const Value** out_value) const; - bool Get(StringPiece path, Value** out_value); - - // These are convenience forms of Get(). The value will be retrieved - // and the return value will be true if the path is valid and the value at - // the end of the path can be returned in the form specified. - // |out_value| is optional and will only be set if non-NULL. - bool GetBoolean(const std::string& path, bool* out_value) const; - bool GetInteger(const std::string& path, int* out_value) const; - // Values of both type TYPE_INTEGER and TYPE_DOUBLE can be obtained as - // doubles. - bool GetDouble(const std::string& path, double* out_value) const; - bool GetString(const std::string& path, std::string* out_value) const; - bool GetString(const std::string& path, string16* out_value) const; - bool GetStringASCII(const std::string& path, std::string* out_value) const; - bool GetBinary(const std::string& path, const BinaryValue** out_value) const; - bool GetBinary(const std::string& path, BinaryValue** out_value); - bool GetDictionary(StringPiece path, - const DictionaryValue** out_value) const; - bool GetDictionary(StringPiece path, DictionaryValue** out_value); - bool GetList(const std::string& path, const ListValue** out_value) const; - bool GetList(const std::string& path, ListValue** out_value); - - // Like Get(), but without special treatment of '.'. This allows e.g. URLs to - // be used as paths. - bool GetWithoutPathExpansion(const std::string& key, - const Value** out_value) const; - bool GetWithoutPathExpansion(const std::string& key, Value** out_value); - bool GetBooleanWithoutPathExpansion(const std::string& key, - bool* out_value) const; - bool GetIntegerWithoutPathExpansion(const std::string& key, - int* out_value) const; - bool GetDoubleWithoutPathExpansion(const std::string& key, - double* out_value) const; - bool GetStringWithoutPathExpansion(const std::string& key, - std::string* out_value) const; - bool GetStringWithoutPathExpansion(const std::string& key, - string16* out_value) const; - bool GetDictionaryWithoutPathExpansion( - const std::string& key, - const DictionaryValue** out_value) const; - bool GetDictionaryWithoutPathExpansion(const std::string& key, - DictionaryValue** out_value); - bool GetListWithoutPathExpansion(const std::string& key, - const ListValue** out_value) const; - bool GetListWithoutPathExpansion(const std::string& key, - ListValue** out_value); - - // Removes the Value with the specified path from this dictionary (or one - // of its child dictionaries, if the path is more than just a local key). - // If |out_value| is non-NULL, the removed Value will be passed out via - // |out_value|. If |out_value| is NULL, the removed value will be deleted. - // This method returns true if |path| is a valid path; otherwise it will - // return false and the DictionaryValue object will be unchanged. - virtual bool Remove(const std::string& path, scoped_ptr<Value>* out_value); - - // Like Remove(), but without special treatment of '.'. This allows e.g. URLs - // to be used as paths. - virtual bool RemoveWithoutPathExpansion(const std::string& key, - scoped_ptr<Value>* out_value); - - // Removes a path, clearing out all dictionaries on |path| that remain empty - // after removing the value at |path|. - virtual bool RemovePath(const std::string& path, - scoped_ptr<Value>* out_value); - - // Makes a copy of |this| but doesn't include empty dictionaries and lists in - // the copy. This never returns NULL, even if |this| itself is empty. - scoped_ptr<DictionaryValue> DeepCopyWithoutEmptyChildren() const; - - // Merge |dictionary| into this dictionary. This is done recursively, i.e. any - // sub-dictionaries will be merged as well. In case of key collisions, the - // passed in dictionary takes precedence and data already present will be - // replaced. Values within |dictionary| are deep-copied, so |dictionary| may - // be freed any time after this call. - void MergeDictionary(const DictionaryValue* dictionary); - - // Swaps contents with the |other| dictionary. - virtual void Swap(DictionaryValue* other); - - // This class provides an iterator over both keys and values in the - // dictionary. It can't be used to modify the dictionary. - class BASE_EXPORT Iterator { - public: - explicit Iterator(const DictionaryValue& target); - ~Iterator(); - - bool IsAtEnd() const { return it_ == target_.dictionary_.end(); } - void Advance() { ++it_; } - - const std::string& key() const { return it_->first; } - const Value& value() const { return *it_->second; } - - private: - const DictionaryValue& target_; - ValueMap::const_iterator it_; - }; - - // Overridden from Value: - DictionaryValue* DeepCopy() const override; - // Preferred version of DeepCopy. TODO(estade): remove the above. - scoped_ptr<DictionaryValue> CreateDeepCopy() const; - bool Equals(const Value* other) const override; - - private: - ValueMap dictionary_; - - DISALLOW_COPY_AND_ASSIGN(DictionaryValue); -}; - -// This type of Value represents a list of other Value values. -class BASE_EXPORT ListValue : public Value { - public: - typedef ValueVector::iterator iterator; - typedef ValueVector::const_iterator const_iterator; - - // Returns |value| if it is a list, nullptr otherwise. - static scoped_ptr<ListValue> From(scoped_ptr<Value> value); - - ListValue(); - ~ListValue() override; - - // Clears the contents of this ListValue - void Clear(); - - // Returns the number of Values in this list. - size_t GetSize() const { return list_.size(); } - - // Returns whether the list is empty. - bool empty() const { return list_.empty(); } - - // Sets the list item at the given index to be the Value specified by - // the value given. If the index beyond the current end of the list, null - // Values will be used to pad out the list. - // Returns true if successful, or false if the index was negative or - // the value is a null pointer. - bool Set(size_t index, Value* in_value); - // Preferred version of the above. TODO(estade): remove the above. - bool Set(size_t index, scoped_ptr<Value> in_value); - - // Gets the Value at the given index. Modifies |out_value| (and returns true) - // only if the index falls within the current list range. - // Note that the list always owns the Value passed out via |out_value|. - // |out_value| is optional and will only be set if non-NULL. - bool Get(size_t index, const Value** out_value) const; - bool Get(size_t index, Value** out_value); - - // Convenience forms of Get(). Modifies |out_value| (and returns true) - // only if the index is valid and the Value at that index can be returned - // in the specified form. - // |out_value| is optional and will only be set if non-NULL. - bool GetBoolean(size_t index, bool* out_value) const; - bool GetInteger(size_t index, int* out_value) const; - // Values of both type TYPE_INTEGER and TYPE_DOUBLE can be obtained as - // doubles. - bool GetDouble(size_t index, double* out_value) const; - bool GetString(size_t index, std::string* out_value) const; - bool GetString(size_t index, string16* out_value) const; - bool GetBinary(size_t index, const BinaryValue** out_value) const; - bool GetBinary(size_t index, BinaryValue** out_value); - bool GetDictionary(size_t index, const DictionaryValue** out_value) const; - bool GetDictionary(size_t index, DictionaryValue** out_value); - bool GetList(size_t index, const ListValue** out_value) const; - bool GetList(size_t index, ListValue** out_value); - - // Removes the Value with the specified index from this list. - // If |out_value| is non-NULL, the removed Value AND ITS OWNERSHIP will be - // passed out via |out_value|. If |out_value| is NULL, the removed value will - // be deleted. This method returns true if |index| is valid; otherwise - // it will return false and the ListValue object will be unchanged. - virtual bool Remove(size_t index, scoped_ptr<Value>* out_value); - - // Removes the first instance of |value| found in the list, if any, and - // deletes it. |index| is the location where |value| was found. Returns false - // if not found. - bool Remove(const Value& value, size_t* index); - - // Removes the element at |iter|. If |out_value| is NULL, the value will be - // deleted, otherwise ownership of the value is passed back to the caller. - // Returns an iterator pointing to the location of the element that - // followed the erased element. - iterator Erase(iterator iter, scoped_ptr<Value>* out_value); - - // Appends a Value to the end of the list. - void Append(scoped_ptr<Value> in_value); - // Deprecated version of the above. TODO(estade): remove. - void Append(Value* in_value); - - // Convenience forms of Append. - void AppendBoolean(bool in_value); - void AppendInteger(int in_value); - void AppendDouble(double in_value); - void AppendString(const std::string& in_value); - void AppendString(const string16& in_value); - void AppendStrings(const std::vector<std::string>& in_values); - void AppendStrings(const std::vector<string16>& in_values); - - // Appends a Value if it's not already present. Takes ownership of the - // |in_value|. Returns true if successful, or false if the value was already - // present. If the value was already present the |in_value| is deleted. - bool AppendIfNotPresent(Value* in_value); - - // Insert a Value at index. - // Returns true if successful, or false if the index was out of range. - bool Insert(size_t index, Value* in_value); - - // Searches for the first instance of |value| in the list using the Equals - // method of the Value type. - // Returns a const_iterator to the found item or to end() if none exists. - const_iterator Find(const Value& value) const; - - // Swaps contents with the |other| list. - virtual void Swap(ListValue* other); - - // Iteration. - iterator begin() { return list_.begin(); } - iterator end() { return list_.end(); } - - const_iterator begin() const { return list_.begin(); } - const_iterator end() const { return list_.end(); } - - // Overridden from Value: - bool GetAsList(ListValue** out_value) override; - bool GetAsList(const ListValue** out_value) const override; - ListValue* DeepCopy() const override; - bool Equals(const Value* other) const override; - - // Preferred version of DeepCopy. TODO(estade): remove DeepCopy. - scoped_ptr<ListValue> CreateDeepCopy() const; - - private: - ValueVector list_; - - DISALLOW_COPY_AND_ASSIGN(ListValue); -}; - -// This interface is implemented by classes that know how to serialize -// Value objects. -class BASE_EXPORT ValueSerializer { - public: - virtual ~ValueSerializer(); - - virtual bool Serialize(const Value& root) = 0; -}; - -// This interface is implemented by classes that know how to deserialize Value -// objects. -class BASE_EXPORT ValueDeserializer { - public: - virtual ~ValueDeserializer(); - - // This method deserializes the subclass-specific format into a Value object. - // If the return value is non-NULL, the caller takes ownership of returned - // Value. If the return value is NULL, and if error_code is non-NULL, - // error_code will be set with the underlying error. - // If |error_message| is non-null, it will be filled in with a formatted - // error message including the location of the error if appropriate. - virtual scoped_ptr<Value> Deserialize(int* error_code, - std::string* error_str) = 0; -}; - -// Stream operator so Values can be used in assertion statements. In order that -// gtest uses this operator to print readable output on test failures, we must -// override each specific type. Otherwise, the default template implementation -// is preferred over an upcast. -BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value); - -BASE_EXPORT inline std::ostream& operator<<(std::ostream& out, - const FundamentalValue& value) { - return out << static_cast<const Value&>(value); -} - -BASE_EXPORT inline std::ostream& operator<<(std::ostream& out, - const StringValue& value) { - return out << static_cast<const Value&>(value); -} - -BASE_EXPORT inline std::ostream& operator<<(std::ostream& out, - const DictionaryValue& value) { - return out << static_cast<const Value&>(value); -} - -BASE_EXPORT inline std::ostream& operator<<(std::ostream& out, - const ListValue& value) { - return out << static_cast<const Value&>(value); -} - -} // namespace base - -#endif // BASE_VALUES_H_ diff --git a/security/sandbox/chromium/base/version.h b/security/sandbox/chromium/base/version.h deleted file mode 100644 index 85c99a355..000000000 --- a/security/sandbox/chromium/base/version.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_VERSION_H_ -#define BASE_VERSION_H_ - -#include <stdint.h> -#include <string> -#include <vector> - -#include "base/base_export.h" - -namespace base { - -// Version represents a dotted version number, like "1.2.3.4", supporting -// parsing and comparison. -class BASE_EXPORT Version { - public: - // The only thing you can legally do to a default constructed - // Version object is assign to it. - Version(); - - ~Version(); - - // Initializes from a decimal dotted version number, like "0.1.1". - // Each component is limited to a uint16_t. Call IsValid() to learn - // the outcome. - explicit Version(const std::string& version_str); - - // Returns true if the object contains a valid version number. - bool IsValid() const; - - // Returns true if the version wildcard string is valid. The version wildcard - // string may end with ".*" (e.g. 1.2.*, 1.*). Any other arrangement with "*" - // is invalid (e.g. 1.*.3 or 1.2.3*). This functions defaults to standard - // Version behavior (IsValid) if no wildcard is present. - static bool IsValidWildcardString(const std::string& wildcard_string); - - // Commonly used pattern. Given a valid version object, compare if a - // |version_str| results in a newer version. Returns true if the - // string represents valid version and if the version is greater than - // than the version of this object. - bool IsOlderThan(const std::string& version_str) const; - - bool Equals(const Version& other) const; - - // Returns -1, 0, 1 for <, ==, >. - int CompareTo(const Version& other) const; - - // Given a valid version object, compare if a |wildcard_string| results in a - // newer version. This function will default to CompareTo if the string does - // not end in wildcard sequence ".*". IsValidWildcard(wildcard_string) must be - // true before using this function. - int CompareToWildcardString(const std::string& wildcard_string) const; - - // Return the string representation of this version. - const std::string GetString() const; - - const std::vector<uint32_t>& components() const { return components_; } - - private: - std::vector<uint32_t> components_; -}; - -} // namespace base - -// TODO(xhwang) remove this when all users are updated to explicitly use the -// namespace -using base::Version; - -#endif // BASE_VERSION_H_ diff --git a/security/sandbox/chromium/base/win/pe_image.cc b/security/sandbox/chromium/base/win/pe_image.cc deleted file mode 100644 index 4b5d62099..000000000 --- a/security/sandbox/chromium/base/win/pe_image.cc +++ /dev/null @@ -1,580 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file implements PEImage, a generic class to manipulate PE files. -// This file was adapted from GreenBorder's Code. - -#include <stddef.h> - -#include "base/win/pe_image.h" - -namespace base { -namespace win { - -// Structure to perform imports enumerations. -struct EnumAllImportsStorage { - PEImage::EnumImportsFunction callback; - PVOID cookie; -}; - -namespace { - -// PdbInfo Signature -const DWORD kPdbInfoSignature = 'SDSR'; - -// Compare two strings byte by byte on an unsigned basis. -// if s1 == s2, return 0 -// if s1 < s2, return negative -// if s1 > s2, return positive -// Exception if inputs are invalid. -int StrCmpByByte(LPCSTR s1, LPCSTR s2) { - while (*s1 != '\0' && *s1 == *s2) { - ++s1; - ++s2; - } - - return (*reinterpret_cast<const unsigned char*>(s1) - - *reinterpret_cast<const unsigned char*>(s2)); -} - -struct PdbInfo { - DWORD Signature; - GUID Guid; - DWORD Age; - char PdbFileName[1]; -}; - -} // namespace - -// Callback used to enumerate imports. See EnumImportChunksFunction. -bool ProcessImportChunk(const PEImage &image, LPCSTR module, - PIMAGE_THUNK_DATA name_table, - PIMAGE_THUNK_DATA iat, PVOID cookie) { - EnumAllImportsStorage& storage = - *reinterpret_cast<EnumAllImportsStorage*>(cookie); - - return image.EnumOneImportChunk(storage.callback, module, name_table, iat, - storage.cookie); -} - -// Callback used to enumerate delay imports. See EnumDelayImportChunksFunction. -bool ProcessDelayImportChunk(const PEImage& image, - PImgDelayDescr delay_descriptor, - LPCSTR module, - PIMAGE_THUNK_DATA name_table, - PIMAGE_THUNK_DATA iat, - PVOID cookie) { - EnumAllImportsStorage& storage = - *reinterpret_cast<EnumAllImportsStorage*>(cookie); - - return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor, - module, name_table, iat, storage.cookie); -} - -void PEImage::set_module(HMODULE module) { - module_ = module; -} - -PIMAGE_DOS_HEADER PEImage::GetDosHeader() const { - return reinterpret_cast<PIMAGE_DOS_HEADER>(module_); -} - -PIMAGE_NT_HEADERS PEImage::GetNTHeaders() const { - PIMAGE_DOS_HEADER dos_header = GetDosHeader(); - - return reinterpret_cast<PIMAGE_NT_HEADERS>( - reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew); -} - -PIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const { - PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); - PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers); - - if (section < nt_headers->FileHeader.NumberOfSections) - return first_section + section; - else - return NULL; -} - -WORD PEImage::GetNumSections() const { - return GetNTHeaders()->FileHeader.NumberOfSections; -} - -DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const { - PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); - - return nt_headers->OptionalHeader.DataDirectory[directory].Size; -} - -PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const { - PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); - - return RVAToAddr( - nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress); -} - -PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const { - PBYTE target = reinterpret_cast<PBYTE>(address); - PIMAGE_SECTION_HEADER section; - - for (UINT i = 0; NULL != (section = GetSectionHeader(i)); i++) { - // Don't use the virtual RVAToAddr. - PBYTE start = reinterpret_cast<PBYTE>( - PEImage::RVAToAddr(section->VirtualAddress)); - - DWORD size = section->Misc.VirtualSize; - - if ((start <= target) && (start + size > target)) - return section; - } - - return NULL; -} - -PIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName( - LPCSTR section_name) const { - if (NULL == section_name) - return NULL; - - PIMAGE_SECTION_HEADER ret = NULL; - int num_sections = GetNumSections(); - - for (int i = 0; i < num_sections; i++) { - PIMAGE_SECTION_HEADER section = GetSectionHeader(i); - if (0 == _strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name, - sizeof(section->Name))) { - ret = section; - break; - } - } - - return ret; -} - -bool PEImage::GetDebugId(LPGUID guid, LPDWORD age) const { - if (NULL == guid || NULL == age) { - return false; - } - - DWORD debug_directory_size = - GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG); - PIMAGE_DEBUG_DIRECTORY debug_directory = - reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>( - GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DEBUG)); - - size_t directory_count = - debug_directory_size / sizeof(IMAGE_DEBUG_DIRECTORY); - - for (size_t index = 0; index < directory_count; ++index) { - if (debug_directory[index].Type == IMAGE_DEBUG_TYPE_CODEVIEW) { - PdbInfo* pdb_info = reinterpret_cast<PdbInfo*>( - RVAToAddr(debug_directory[index].AddressOfRawData)); - if (pdb_info->Signature != kPdbInfoSignature) { - // Unsupported PdbInfo signature - return false; - } - *guid = pdb_info->Guid; - *age = pdb_info->Age; - return true; - } - } - return false; -} - -PDWORD PEImage::GetExportEntry(LPCSTR name) const { - PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); - - if (NULL == exports) - return NULL; - - WORD ordinal = 0; - if (!GetProcOrdinal(name, &ordinal)) - return NULL; - - PDWORD functions = reinterpret_cast<PDWORD>( - RVAToAddr(exports->AddressOfFunctions)); - - return functions + ordinal - exports->Base; -} - -FARPROC PEImage::GetProcAddress(LPCSTR function_name) const { - PDWORD export_entry = GetExportEntry(function_name); - if (NULL == export_entry) - return NULL; - - PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry)); - - PBYTE exports = reinterpret_cast<PBYTE>( - GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT)); - DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); - - // Check for forwarded exports as a special case. - if (exports <= function && exports + size > function) - return reinterpret_cast<FARPROC>(-1); - - return reinterpret_cast<FARPROC>(function); -} - -bool PEImage::GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const { - if (NULL == ordinal) - return false; - - PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory(); - - if (NULL == exports) - return false; - - if (IsOrdinal(function_name)) { - *ordinal = ToOrdinal(function_name); - } else { - PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames)); - PDWORD lower = names; - PDWORD upper = names + exports->NumberOfNames; - int cmp = -1; - - // Binary Search for the name. - while (lower != upper) { - PDWORD middle = lower + (upper - lower) / 2; - LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle)); - - // This may be called by sandbox before MSVCRT dll loads, so can't use - // CRT function here. - cmp = StrCmpByByte(function_name, name); - - if (cmp == 0) { - lower = middle; - break; - } - - if (cmp > 0) - lower = middle + 1; - else - upper = middle; - } - - if (cmp != 0) - return false; - - - PWORD ordinals = reinterpret_cast<PWORD>( - RVAToAddr(exports->AddressOfNameOrdinals)); - - *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base); - } - - return true; -} - -bool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const { - PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); - UINT num_sections = nt_headers->FileHeader.NumberOfSections; - PIMAGE_SECTION_HEADER section = GetSectionHeader(0); - - for (UINT i = 0; i < num_sections; i++, section++) { - PVOID section_start = RVAToAddr(section->VirtualAddress); - DWORD size = section->Misc.VirtualSize; - - if (!callback(*this, section, section_start, size, cookie)) - return false; - } - - return true; -} - -bool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const { - PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT); - DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); - - // Check if there are any exports at all. - if (NULL == directory || 0 == size) - return true; - - PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>( - directory); - UINT ordinal_base = exports->Base; - UINT num_funcs = exports->NumberOfFunctions; - UINT num_names = exports->NumberOfNames; - PDWORD functions = reinterpret_cast<PDWORD>(RVAToAddr( - exports->AddressOfFunctions)); - PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames)); - PWORD ordinals = reinterpret_cast<PWORD>(RVAToAddr( - exports->AddressOfNameOrdinals)); - - for (UINT count = 0; count < num_funcs; count++) { - PVOID func = RVAToAddr(functions[count]); - if (NULL == func) - continue; - - // Check for a name. - LPCSTR name = NULL; - UINT hint; - for (hint = 0; hint < num_names; hint++) { - if (ordinals[hint] == count) { - name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint])); - break; - } - } - - if (name == NULL) - hint = 0; - - // Check for forwarded exports. - LPCSTR forward = NULL; - if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) && - reinterpret_cast<char*>(func) <= reinterpret_cast<char*>(directory) + - size) { - forward = reinterpret_cast<LPCSTR>(func); - func = 0; - } - - if (!callback(*this, ordinal_base + count, hint, name, func, forward, - cookie)) - return false; - } - - return true; -} - -bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const { - PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC); - DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC); - PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( - directory); - - if (!directory) - return true; - - while (size >= sizeof(IMAGE_BASE_RELOCATION) && base->SizeOfBlock && - size >= base->SizeOfBlock) { - PWORD reloc = reinterpret_cast<PWORD>(base + 1); - UINT num_relocs = (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / - sizeof(WORD); - - for (UINT i = 0; i < num_relocs; i++, reloc++) { - WORD type = *reloc >> 12; - PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF)); - - if (!callback(*this, type, address, cookie)) - return false; - } - - size -= base->SizeOfBlock; - base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( - reinterpret_cast<char*>(base) + base->SizeOfBlock); - } - - return true; -} - -bool PEImage::EnumImportChunks(EnumImportChunksFunction callback, - PVOID cookie) const { - DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT); - PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk(); - - if (import == NULL || size < sizeof(IMAGE_IMPORT_DESCRIPTOR)) - return true; - - for (; import->FirstThunk; import++) { - LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name)); - PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( - RVAToAddr(import->OriginalFirstThunk)); - PIMAGE_THUNK_DATA iat = reinterpret_cast<PIMAGE_THUNK_DATA>( - RVAToAddr(import->FirstThunk)); - - if (!callback(*this, module_name, name_table, iat, cookie)) - return false; - } - - return true; -} - -bool PEImage::EnumOneImportChunk(EnumImportsFunction callback, - LPCSTR module_name, - PIMAGE_THUNK_DATA name_table, - PIMAGE_THUNK_DATA iat, PVOID cookie) const { - if (NULL == name_table) - return false; - - for (; name_table && name_table->u1.Ordinal; name_table++, iat++) { - LPCSTR name = NULL; - WORD ordinal = 0; - WORD hint = 0; - - if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { - ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal)); - } else { - PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( - RVAToAddr(name_table->u1.ForwarderString)); - - hint = import->Hint; - name = reinterpret_cast<LPCSTR>(&import->Name); - } - - if (!callback(*this, module_name, ordinal, name, hint, iat, cookie)) - return false; - } - - return true; -} - -bool PEImage::EnumAllImports(EnumImportsFunction callback, PVOID cookie) const { - EnumAllImportsStorage temp = { callback, cookie }; - return EnumImportChunks(ProcessImportChunk, &temp); -} - -bool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback, - PVOID cookie) const { - PVOID directory = GetImageDirectoryEntryAddr( - IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); - DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); - PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory); - - if (directory == NULL || size == 0) - return true; - - for (; delay_descriptor->rvaHmod; delay_descriptor++) { - PIMAGE_THUNK_DATA name_table; - PIMAGE_THUNK_DATA iat; - LPCSTR module_name; - - // check if VC7-style imports, using RVAs instead of - // VC6-style addresses. - bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0; - - if (rvas) { - module_name = - reinterpret_cast<LPCSTR>(RVAToAddr(delay_descriptor->rvaDLLName)); - name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( - RVAToAddr(delay_descriptor->rvaINT)); - iat = reinterpret_cast<PIMAGE_THUNK_DATA>( - RVAToAddr(delay_descriptor->rvaIAT)); - } else { - // Values in IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT are 32-bit, even on 64-bit - // platforms. See section 4.8 of PECOFF image spec rev 8.3. - module_name = reinterpret_cast<LPCSTR>( - static_cast<uintptr_t>(delay_descriptor->rvaDLLName)); - name_table = reinterpret_cast<PIMAGE_THUNK_DATA>( - static_cast<uintptr_t>(delay_descriptor->rvaINT)); - iat = reinterpret_cast<PIMAGE_THUNK_DATA>( - static_cast<uintptr_t>(delay_descriptor->rvaIAT)); - } - - if (!callback(*this, delay_descriptor, module_name, name_table, iat, - cookie)) - return false; - } - - return true; -} - -bool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback, - PImgDelayDescr delay_descriptor, - LPCSTR module_name, - PIMAGE_THUNK_DATA name_table, - PIMAGE_THUNK_DATA iat, - PVOID cookie) const { - for (; name_table->u1.Ordinal; name_table++, iat++) { - LPCSTR name = NULL; - WORD ordinal = 0; - WORD hint = 0; - - if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) { - ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal)); - } else { - PIMAGE_IMPORT_BY_NAME import; - bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0; - - if (rvas) { - import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( - RVAToAddr(name_table->u1.ForwarderString)); - } else { - import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>( - name_table->u1.ForwarderString); - } - - hint = import->Hint; - name = reinterpret_cast<LPCSTR>(&import->Name); - } - - if (!callback(*this, module_name, ordinal, name, hint, iat, cookie)) - return false; - } - - return true; -} - -bool PEImage::EnumAllDelayImports(EnumImportsFunction callback, - PVOID cookie) const { - EnumAllImportsStorage temp = { callback, cookie }; - return EnumDelayImportChunks(ProcessDelayImportChunk, &temp); -} - -bool PEImage::VerifyMagic() const { - PIMAGE_DOS_HEADER dos_header = GetDosHeader(); - - if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) - return false; - - PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); - - if (nt_headers->Signature != IMAGE_NT_SIGNATURE) - return false; - - if (nt_headers->FileHeader.SizeOfOptionalHeader != - sizeof(IMAGE_OPTIONAL_HEADER)) - return false; - - if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) - return false; - - return true; -} - -bool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD* on_disk_offset) const { - LPVOID address = RVAToAddr(rva); - return ImageAddrToOnDiskOffset(address, on_disk_offset); -} - -bool PEImage::ImageAddrToOnDiskOffset(LPVOID address, - DWORD* on_disk_offset) const { - if (NULL == address) - return false; - - // Get the section that this address belongs to. - PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address); - if (NULL == section_header) - return false; - - // Don't follow the virtual RVAToAddr, use the one on the base. - DWORD offset_within_section = - static_cast<DWORD>(reinterpret_cast<uintptr_t>(address)) - - static_cast<DWORD>(reinterpret_cast<uintptr_t>( - PEImage::RVAToAddr(section_header->VirtualAddress))); - - *on_disk_offset = section_header->PointerToRawData + offset_within_section; - return true; -} - -PVOID PEImage::RVAToAddr(DWORD rva) const { - if (rva == 0) - return NULL; - - return reinterpret_cast<char*>(module_) + rva; -} - -PVOID PEImageAsData::RVAToAddr(DWORD rva) const { - if (rva == 0) - return NULL; - - PVOID in_memory = PEImage::RVAToAddr(rva); - DWORD disk_offset; - - if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset)) - return NULL; - - return PEImage::RVAToAddr(disk_offset); -} - -} // namespace win -} // namespace base diff --git a/security/sandbox/chromium/base/win/pe_image.h b/security/sandbox/chromium/base/win/pe_image.h deleted file mode 100644 index 4c36bcf85..000000000 --- a/security/sandbox/chromium/base/win/pe_image.h +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file was adapted from GreenBorder's Code. -// To understand what this class is about (for other than well known functions -// as GetProcAddress), a good starting point is "An In-Depth Look into the -// Win32 Portable Executable File Format" by Matt Pietrek: -// http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx - -#ifndef BASE_WIN_PE_IMAGE_H_ -#define BASE_WIN_PE_IMAGE_H_ - -#include <windows.h> - -#if defined(_WIN32_WINNT_WIN8) -// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h. -#undef FACILITY_VISUALCPP -#endif -#include <DelayIMP.h> - -namespace base { -namespace win { - -// This class is a wrapper for the Portable Executable File Format (PE). -// Its main purpose is to provide an easy way to work with imports and exports -// from a file, mapped in memory as image. -class PEImage { - public: - // Callback to enumerate sections. - // cookie is the value passed to the enumerate method. - // Returns true to continue the enumeration. - typedef bool (*EnumSectionsFunction)(const PEImage &image, - PIMAGE_SECTION_HEADER header, - PVOID section_start, DWORD section_size, - PVOID cookie); - - // Callback to enumerate exports. - // function is the actual address of the symbol. If forward is not null, it - // contains the dll and symbol to forward this export to. cookie is the value - // passed to the enumerate method. - // Returns true to continue the enumeration. - typedef bool (*EnumExportsFunction)(const PEImage &image, DWORD ordinal, - DWORD hint, LPCSTR name, PVOID function, - LPCSTR forward, PVOID cookie); - - // Callback to enumerate import blocks. - // name_table and iat point to the imports name table and address table for - // this block. cookie is the value passed to the enumerate method. - // Returns true to continue the enumeration. - typedef bool (*EnumImportChunksFunction)(const PEImage &image, LPCSTR module, - PIMAGE_THUNK_DATA name_table, - PIMAGE_THUNK_DATA iat, PVOID cookie); - - // Callback to enumerate imports. - // module is the dll that exports this symbol. cookie is the value passed to - // the enumerate method. - // Returns true to continue the enumeration. - typedef bool (*EnumImportsFunction)(const PEImage &image, LPCSTR module, - DWORD ordinal, LPCSTR name, DWORD hint, - PIMAGE_THUNK_DATA iat, PVOID cookie); - - // Callback to enumerate dalayed import blocks. - // module is the dll that exports this block of symbols. cookie is the value - // passed to the enumerate method. - // Returns true to continue the enumeration. - typedef bool (*EnumDelayImportChunksFunction)(const PEImage &image, - PImgDelayDescr delay_descriptor, - LPCSTR module, - PIMAGE_THUNK_DATA name_table, - PIMAGE_THUNK_DATA iat, - PVOID cookie); - - // Callback to enumerate relocations. - // cookie is the value passed to the enumerate method. - // Returns true to continue the enumeration. - typedef bool (*EnumRelocsFunction)(const PEImage &image, WORD type, - PVOID address, PVOID cookie); - - explicit PEImage(HMODULE module) : module_(module) {} - explicit PEImage(const void* module) { - module_ = reinterpret_cast<HMODULE>(const_cast<void*>(module)); - } - - virtual ~PEImage() {} - - // Gets the HMODULE for this object. - HMODULE module() const; - - // Sets this object's HMODULE. - void set_module(HMODULE module); - - // Checks if this symbol is actually an ordinal. - static bool IsOrdinal(LPCSTR name); - - // Converts a named symbol to the corresponding ordinal. - static WORD ToOrdinal(LPCSTR name); - - // Returns the DOS_HEADER for this PE. - PIMAGE_DOS_HEADER GetDosHeader() const; - - // Returns the NT_HEADER for this PE. - PIMAGE_NT_HEADERS GetNTHeaders() const; - - // Returns number of sections of this PE. - WORD GetNumSections() const; - - // Returns the header for a given section. - // returns NULL if there is no such section. - PIMAGE_SECTION_HEADER GetSectionHeader(UINT section) const; - - // Returns the size of a given directory entry. - DWORD GetImageDirectoryEntrySize(UINT directory) const; - - // Returns the address of a given directory entry. - PVOID GetImageDirectoryEntryAddr(UINT directory) const; - - // Returns the section header for a given address. - // Use: s = image.GetImageSectionFromAddr(a); - // Post: 's' is the section header of the section that contains 'a' - // or NULL if there is no such section. - PIMAGE_SECTION_HEADER GetImageSectionFromAddr(PVOID address) const; - - // Returns the section header for a given section. - PIMAGE_SECTION_HEADER GetImageSectionHeaderByName(LPCSTR section_name) const; - - // Returns the first block of imports. - PIMAGE_IMPORT_DESCRIPTOR GetFirstImportChunk() const; - - // Returns the exports directory. - PIMAGE_EXPORT_DIRECTORY GetExportDirectory() const; - - // Returns the debug id (guid+age). - bool GetDebugId(LPGUID guid, LPDWORD age) const; - - // Returns a given export entry. - // Use: e = image.GetExportEntry(f); - // Pre: 'f' is either a zero terminated string or ordinal - // Post: 'e' is a pointer to the export directory entry - // that contains 'f's export RVA, or NULL if 'f' - // is not exported from this image - PDWORD GetExportEntry(LPCSTR name) const; - - // Returns the address for a given exported symbol. - // Use: p = image.GetProcAddress(f); - // Pre: 'f' is either a zero terminated string or ordinal. - // Post: if 'f' is a non-forwarded export from image, 'p' is - // the exported function. If 'f' is a forwarded export - // then p is the special value -1. In this case - // RVAToAddr(*GetExportEntry) can be used to resolve - // the string that describes the forward. - FARPROC GetProcAddress(LPCSTR function_name) const; - - // Retrieves the ordinal for a given exported symbol. - // Returns true if the symbol was found. - bool GetProcOrdinal(LPCSTR function_name, WORD *ordinal) const; - - // Enumerates PE sections. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumSections(EnumSectionsFunction callback, PVOID cookie) const; - - // Enumerates PE exports. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumExports(EnumExportsFunction callback, PVOID cookie) const; - - // Enumerates PE imports. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumAllImports(EnumImportsFunction callback, PVOID cookie) const; - - // Enumerates PE import blocks. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumImportChunks(EnumImportChunksFunction callback, PVOID cookie) const; - - // Enumerates the imports from a single PE import block. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumOneImportChunk(EnumImportsFunction callback, LPCSTR module_name, - PIMAGE_THUNK_DATA name_table, PIMAGE_THUNK_DATA iat, - PVOID cookie) const; - - - // Enumerates PE delay imports. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumAllDelayImports(EnumImportsFunction callback, PVOID cookie) const; - - // Enumerates PE delay import blocks. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumDelayImportChunks(EnumDelayImportChunksFunction callback, - PVOID cookie) const; - - // Enumerates imports from a single PE delay import block. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumOneDelayImportChunk(EnumImportsFunction callback, - PImgDelayDescr delay_descriptor, - LPCSTR module_name, - PIMAGE_THUNK_DATA name_table, - PIMAGE_THUNK_DATA iat, - PVOID cookie) const; - - // Enumerates PE relocation entries. - // cookie is a generic cookie to pass to the callback. - // Returns true on success. - bool EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const; - - // Verifies the magic values on the PE file. - // Returns true if all values are correct. - bool VerifyMagic() const; - - // Converts an rva value to the appropriate address. - virtual PVOID RVAToAddr(DWORD rva) const; - - // Converts an rva value to an offset on disk. - // Returns true on success. - bool ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const; - - // Converts an address to an offset on disk. - // Returns true on success. - bool ImageAddrToOnDiskOffset(LPVOID address, DWORD *on_disk_offset) const; - - private: - HMODULE module_; -}; - -// This class is an extension to the PEImage class that allows working with PE -// files mapped as data instead of as image file. -class PEImageAsData : public PEImage { - public: - explicit PEImageAsData(HMODULE hModule) : PEImage(hModule) {} - - PVOID RVAToAddr(DWORD rva) const override; -}; - -inline bool PEImage::IsOrdinal(LPCSTR name) { - return reinterpret_cast<uintptr_t>(name) <= 0xFFFF; -} - -inline WORD PEImage::ToOrdinal(LPCSTR name) { - return static_cast<WORD>(reinterpret_cast<intptr_t>(name)); -} - -inline HMODULE PEImage::module() const { - return module_; -} - -inline PIMAGE_IMPORT_DESCRIPTOR PEImage::GetFirstImportChunk() const { - return reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>( - GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_IMPORT)); -} - -inline PIMAGE_EXPORT_DIRECTORY PEImage::GetExportDirectory() const { - return reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>( - GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT)); -} - -} // namespace win -} // namespace base - -#endif // BASE_WIN_PE_IMAGE_H_ diff --git a/security/sandbox/chromium/base/win/scoped_handle.cc b/security/sandbox/chromium/base/win/scoped_handle.cc deleted file mode 100644 index 9c21603a0..000000000 --- a/security/sandbox/chromium/base/win/scoped_handle.cc +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/win/scoped_handle.h" - -#include <stddef.h> - -#include <unordered_map> - -#include "base/debug/alias.h" -#include "base/hash.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/synchronization/lock_impl.h" - -extern "C" { -__declspec(dllexport) void* GetHandleVerifier(); -typedef void* (*GetHandleVerifierFn)(); -} - -namespace { - -struct HandleHash { - size_t operator()(const HANDLE& handle) const { - char buffer[sizeof(handle)]; - memcpy(buffer, &handle, sizeof(handle)); - return base::Hash(buffer, sizeof(buffer)); - } -}; - -struct Info { - const void* owner; - const void* pc1; - const void* pc2; - DWORD thread_id; -}; -typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; - -// g_lock protects the handle map and setting g_active_verifier. -typedef base::internal::LockImpl NativeLock; -base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; - -bool CloseHandleWrapper(HANDLE handle) { - if (!::CloseHandle(handle)) - CHECK(false); - return true; -} - -// Simple automatic locking using a native critical section so it supports -// recursive locking. -class AutoNativeLock { - public: - explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { - lock_.Lock(); - } - - ~AutoNativeLock() { - lock_.Unlock(); - } - - private: - NativeLock& lock_; - DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); -}; - -// Implements the actual object that is verifying handles for this process. -// The active instance is shared across the module boundary but there is no -// way to delete this object from the wrong side of it (or any side, actually). -class ActiveVerifier { - public: - explicit ActiveVerifier(bool enabled) - : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) { - } - - // Retrieves the current verifier. - static ActiveVerifier* Get(); - - // The methods required by HandleTraits. They are virtual because we need to - // forward the call execution to another module, instead of letting the - // compiler call the version that is linked in the current module. - virtual bool CloseHandle(HANDLE handle); - virtual void StartTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2); - virtual void StopTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2); - virtual void Disable(); - virtual void OnHandleBeingClosed(HANDLE handle); - - private: - ~ActiveVerifier(); // Not implemented. - - static void InstallVerifier(); - - bool enabled_; - bool closing_; - NativeLock* lock_; - HandleMap map_; - DISALLOW_COPY_AND_ASSIGN(ActiveVerifier); -}; -ActiveVerifier* g_active_verifier = NULL; - -// static -ActiveVerifier* ActiveVerifier::Get() { - if (!g_active_verifier) - ActiveVerifier::InstallVerifier(); - - return g_active_verifier; -} - -// static -void ActiveVerifier::InstallVerifier() { -#if defined(COMPONENT_BUILD) - AutoNativeLock lock(g_lock.Get()); - g_active_verifier = new ActiveVerifier(true); -#else - // If you are reading this, wondering why your process seems deadlocked, take - // a look at your DllMain code and remove things that should not be done - // there, like doing whatever gave you that nice windows handle you are trying - // to store in a ScopedHandle. - HMODULE main_module = ::GetModuleHandle(NULL); - GetHandleVerifierFn get_handle_verifier = - reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress( - main_module, "GetHandleVerifier")); - - if (!get_handle_verifier) { - g_active_verifier = new ActiveVerifier(false); - return; - } - - ActiveVerifier* verifier = - reinterpret_cast<ActiveVerifier*>(get_handle_verifier()); - - // This lock only protects against races in this module, which is fine. - AutoNativeLock lock(g_lock.Get()); - g_active_verifier = verifier ? verifier : new ActiveVerifier(true); -#endif -} - -bool ActiveVerifier::CloseHandle(HANDLE handle) { - if (!enabled_) - return CloseHandleWrapper(handle); - - AutoNativeLock lock(*lock_); - closing_ = true; - CloseHandleWrapper(handle); - closing_ = false; - - return true; -} - -void ActiveVerifier::StartTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2) { - if (!enabled_) - return; - - // Grab the thread id before the lock. - DWORD thread_id = GetCurrentThreadId(); - - AutoNativeLock lock(*lock_); - - Info handle_info = { owner, pc1, pc2, thread_id }; - std::pair<HANDLE, Info> item(handle, handle_info); - std::pair<HandleMap::iterator, bool> result = map_.insert(item); - if (!result.second) { - Info other = result.first->second; - base::debug::Alias(&other); - CHECK(false); - } -} - -void ActiveVerifier::StopTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2) { - if (!enabled_) - return; - - AutoNativeLock lock(*lock_); - HandleMap::iterator i = map_.find(handle); - if (i == map_.end()) - CHECK(false); - - Info other = i->second; - if (other.owner != owner) { - base::debug::Alias(&other); - CHECK(false); - } - - map_.erase(i); -} - -void ActiveVerifier::Disable() { - enabled_ = false; -} - -void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) { - if (!enabled_) - return; - - AutoNativeLock lock(*lock_); - if (closing_) - return; - - HandleMap::iterator i = map_.find(handle); - if (i == map_.end()) - return; - - Info other = i->second; - base::debug::Alias(&other); - CHECK(false); -} - -} // namespace - -void* GetHandleVerifier() { - return g_active_verifier; -} - -namespace base { -namespace win { - -// Static. -bool HandleTraits::CloseHandle(HANDLE handle) { - return ActiveVerifier::Get()->CloseHandle(handle); -} - -// Static. -void VerifierTraits::StartTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2) { - return ActiveVerifier::Get()->StartTracking(handle, owner, pc1, pc2); -} - -// Static. -void VerifierTraits::StopTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2) { - return ActiveVerifier::Get()->StopTracking(handle, owner, pc1, pc2); -} - -void DisableHandleVerifier() { - return ActiveVerifier::Get()->Disable(); -} - -void OnHandleBeingClosed(HANDLE handle) { - return ActiveVerifier::Get()->OnHandleBeingClosed(handle); -} - -} // namespace win -} // namespace base diff --git a/security/sandbox/chromium/base/win/scoped_handle.h b/security/sandbox/chromium/base/win/scoped_handle.h deleted file mode 100644 index 404ab6693..000000000 --- a/security/sandbox/chromium/base/win/scoped_handle.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_WIN_SCOPED_HANDLE_H_ -#define BASE_WIN_SCOPED_HANDLE_H_ - -#include <windows.h> - -#include "base/base_export.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/move.h" - -// TODO(rvargas): remove this with the rest of the verifier. -#if defined(COMPILER_MSVC) -#include <intrin.h> -#define BASE_WIN_GET_CALLER _ReturnAddress() -#elif defined(COMPILER_GCC) -#define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\ - __builtin_return_address(0)) -#endif - -namespace base { -namespace win { - -// Generic wrapper for raw handles that takes care of closing handles -// automatically. The class interface follows the style of -// the ScopedFILE class with two additions: -// - IsValid() method can tolerate multiple invalid handle values such as NULL -// and INVALID_HANDLE_VALUE (-1) for Win32 handles. -// - Set() (and the constructors and assignment operators that call it) -// preserve the Windows LastError code. This ensures that GetLastError() can -// be called after stashing a handle in a GenericScopedHandle object. Doing -// this explicitly is necessary because of bug 528394 and VC++ 2015. -template <class Traits, class Verifier> -class GenericScopedHandle { - MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle) - - public: - typedef typename Traits::Handle Handle; - - GenericScopedHandle() : handle_(Traits::NullHandle()) {} - - explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { - Set(handle); - } - - GenericScopedHandle(GenericScopedHandle&& other) - : handle_(Traits::NullHandle()) { - Set(other.Take()); - } - - ~GenericScopedHandle() { - Close(); - } - - bool IsValid() const { - return Traits::IsHandleValid(handle_); - } - - GenericScopedHandle& operator=(GenericScopedHandle&& other) { - DCHECK_NE(this, &other); - Set(other.Take()); - return *this; - } - - void Set(Handle handle) { - if (handle_ != handle) { - // Preserve old LastError to avoid bug 528394. - auto last_error = ::GetLastError(); - Close(); - - if (Traits::IsHandleValid(handle)) { - handle_ = handle; - Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER, - tracked_objects::GetProgramCounter()); - } - ::SetLastError(last_error); - } - } - - Handle Get() const { - return handle_; - } - - // Transfers ownership away from this object. - Handle Take() { - Handle temp = handle_; - handle_ = Traits::NullHandle(); - if (Traits::IsHandleValid(temp)) { - Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER, - tracked_objects::GetProgramCounter()); - } - return temp; - } - - // Explicitly closes the owned handle. - void Close() { - if (Traits::IsHandleValid(handle_)) { - Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER, - tracked_objects::GetProgramCounter()); - - Traits::CloseHandle(handle_); - handle_ = Traits::NullHandle(); - } - } - - private: - Handle handle_; -}; - -#undef BASE_WIN_GET_CALLER - -// The traits class for Win32 handles that can be closed via CloseHandle() API. -class HandleTraits { - public: - typedef HANDLE Handle; - - // Closes the handle. - static bool BASE_EXPORT CloseHandle(HANDLE handle); - - // Returns true if the handle value is valid. - static bool IsHandleValid(HANDLE handle) { - return handle != NULL && handle != INVALID_HANDLE_VALUE; - } - - // Returns NULL handle value. - static HANDLE NullHandle() { - return NULL; - } - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits); -}; - -// Do-nothing verifier. -class DummyVerifierTraits { - public: - typedef HANDLE Handle; - - static void StartTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2) {} - static void StopTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2) {} - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits); -}; - -// Performs actual run-time tracking. -class BASE_EXPORT VerifierTraits { - public: - typedef HANDLE Handle; - - static void StartTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2); - static void StopTracking(HANDLE handle, const void* owner, - const void* pc1, const void* pc2); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits); -}; - -typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle; - -// This function may be called by the embedder to disable the use of -// VerifierTraits at runtime. It has no effect if DummyVerifierTraits is used -// for ScopedHandle. -void BASE_EXPORT DisableHandleVerifier(); - -// This should be called whenever the OS is closing a handle, if extended -// verification of improper handle closing is desired. If |handle| is being -// tracked by the handle verifier and ScopedHandle is not the one closing it, -// a CHECK is generated. -void BASE_EXPORT OnHandleBeingClosed(HANDLE handle); - -} // namespace win -} // namespace base - -#endif // BASE_WIN_SCOPED_HANDLE_H_ diff --git a/security/sandbox/chromium/base/win/scoped_process_information.cc b/security/sandbox/chromium/base/win/scoped_process_information.cc deleted file mode 100644 index 634a538ee..000000000 --- a/security/sandbox/chromium/base/win/scoped_process_information.cc +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/win/scoped_process_information.h" - -#include "base/logging.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" - -namespace base { -namespace win { - -namespace { - -// Duplicates source into target, returning true upon success. |target| is -// guaranteed to be untouched in case of failure. Succeeds with no side-effects -// if source is NULL. -bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) { - if (!source) - return true; - - HANDLE temp = NULL; - - // TODO(shrikant): Remove following code as soon as we gather some - // information regarding AppContainer related DuplicateHandle failures that - // only seem to happen on certain machine and only random launches (normally - // renderer launches seem to succeed even on those machines.) - if (base::win::GetVersion() == base::win::VERSION_WIN8 || - base::win::GetVersion() == base::win::VERSION_WIN8_1) { - typedef LONG (WINAPI *NtDuplicateObject)( - IN HANDLE SourceProcess, - IN HANDLE SourceHandle, - IN HANDLE TargetProcess, - OUT PHANDLE TargetHandle, - IN ACCESS_MASK DesiredAccess, - IN ULONG Attributes, - IN ULONG Options); - - typedef ULONG (WINAPI *RtlNtStatusToDosError)(IN LONG Status); - - NtDuplicateObject nt_duplicate_object = - reinterpret_cast<NtDuplicateObject>(::GetProcAddress( - GetModuleHandle(L"ntdll.dll"), "NtDuplicateObject")); - if (nt_duplicate_object != NULL) { - LONG status = nt_duplicate_object(::GetCurrentProcess(), source, - ::GetCurrentProcess(), &temp, - 0, FALSE, DUPLICATE_SAME_ACCESS); - if (status < 0) { - DPLOG(ERROR) << "Failed to duplicate a handle."; - RtlNtStatusToDosError ntstatus_to_doserror = - reinterpret_cast<RtlNtStatusToDosError>(::GetProcAddress( - GetModuleHandle(L"ntdll.dll"), "RtlNtStatusToDosError")); - if (ntstatus_to_doserror != NULL) { - ::SetLastError(ntstatus_to_doserror(status)); - } - return false; - } - } - } else { - if (!::DuplicateHandle(::GetCurrentProcess(), source, - ::GetCurrentProcess(), &temp, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { - DPLOG(ERROR) << "Failed to duplicate a handle."; - return false; - } - } - target->Set(temp); - return true; -} - -} // namespace - -ScopedProcessInformation::ScopedProcessInformation() - : process_id_(0), thread_id_(0) { -} - -ScopedProcessInformation::ScopedProcessInformation( - const PROCESS_INFORMATION& process_info) : process_id_(0), thread_id_(0) { - Set(process_info); -} - -ScopedProcessInformation::~ScopedProcessInformation() { - Close(); -} - -bool ScopedProcessInformation::IsValid() const { - return process_id_ || process_handle_.Get() || - thread_id_ || thread_handle_.Get(); -} - -void ScopedProcessInformation::Close() { - process_handle_.Close(); - thread_handle_.Close(); - process_id_ = 0; - thread_id_ = 0; -} - -void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) { - if (IsValid()) - Close(); - - process_handle_.Set(process_info.hProcess); - thread_handle_.Set(process_info.hThread); - process_id_ = process_info.dwProcessId; - thread_id_ = process_info.dwThreadId; -} - -bool ScopedProcessInformation::DuplicateFrom( - const ScopedProcessInformation& other) { - DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL"; - DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid"; - - if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) && - CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) { - process_id_ = other.process_id(); - thread_id_ = other.thread_id(); - return true; - } - - return false; -} - -PROCESS_INFORMATION ScopedProcessInformation::Take() { - PROCESS_INFORMATION process_information = {}; - process_information.hProcess = process_handle_.Take(); - process_information.hThread = thread_handle_.Take(); - process_information.dwProcessId = process_id(); - process_information.dwThreadId = thread_id(); - process_id_ = 0; - thread_id_ = 0; - - return process_information; -} - -HANDLE ScopedProcessInformation::TakeProcessHandle() { - process_id_ = 0; - return process_handle_.Take(); -} - -HANDLE ScopedProcessInformation::TakeThreadHandle() { - thread_id_ = 0; - return thread_handle_.Take(); -} - -} // namespace win -} // namespace base diff --git a/security/sandbox/chromium/base/win/scoped_process_information.h b/security/sandbox/chromium/base/win/scoped_process_information.h deleted file mode 100644 index 01df861f0..000000000 --- a/security/sandbox/chromium/base/win/scoped_process_information.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_WIN_SCOPED_PROCESS_INFORMATION_H_ -#define BASE_WIN_SCOPED_PROCESS_INFORMATION_H_ - -#include <windows.h> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/win/scoped_handle.h" - -namespace base { -namespace win { - -// Manages the closing of process and thread handles from PROCESS_INFORMATION -// structures. Allows clients to take ownership of either handle independently. -class BASE_EXPORT ScopedProcessInformation { - public: - ScopedProcessInformation(); - explicit ScopedProcessInformation(const PROCESS_INFORMATION& process_info); - ~ScopedProcessInformation(); - - // Returns true iff this instance is holding a thread and/or process handle. - bool IsValid() const; - - // Closes the held thread and process handles, if any. - void Close(); - - // Populates this instance with the provided |process_info|. - void Set(const PROCESS_INFORMATION& process_info); - - // Populates this instance with duplicate handles and the thread/process IDs - // from |other|. Returns false in case of failure, in which case this instance - // will be completely unpopulated. - bool DuplicateFrom(const ScopedProcessInformation& other); - - // Transfers ownership of the held PROCESS_INFORMATION, if any, away from this - // instance. - PROCESS_INFORMATION Take(); - - // Transfers ownership of the held process handle, if any, away from this - // instance. Note that the related process_id will also be cleared. - HANDLE TakeProcessHandle(); - - // Transfers ownership of the held thread handle, if any, away from this - // instance. Note that the related thread_id will also be cleared. - HANDLE TakeThreadHandle(); - - // Returns the held process handle, if any, while retaining ownership. - HANDLE process_handle() const { - return process_handle_.Get(); - } - - // Returns the held thread handle, if any, while retaining ownership. - HANDLE thread_handle() const { - return thread_handle_.Get(); - } - - // Returns the held process id, if any. - DWORD process_id() const { - return process_id_; - } - - // Returns the held thread id, if any. - DWORD thread_id() const { - return thread_id_; - } - - private: - ScopedHandle process_handle_; - ScopedHandle thread_handle_; - DWORD process_id_; - DWORD thread_id_; - - DISALLOW_COPY_AND_ASSIGN(ScopedProcessInformation); -}; - -} // namespace win -} // namespace base - -#endif // BASE_WIN_SCOPED_PROCESS_INFORMATION_H_ diff --git a/security/sandbox/chromium/base/win/startup_information.cc b/security/sandbox/chromium/base/win/startup_information.cc deleted file mode 100644 index aff52eb79..000000000 --- a/security/sandbox/chromium/base/win/startup_information.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/win/startup_information.h" - -#include "base/logging.h" -#include "base/win/windows_version.h" - -namespace { - -typedef BOOL (WINAPI *InitializeProcThreadAttributeListFunction)( - LPPROC_THREAD_ATTRIBUTE_LIST attribute_list, - DWORD attribute_count, - DWORD flags, - PSIZE_T size); -static InitializeProcThreadAttributeListFunction - initialize_proc_thread_attribute_list; - -typedef BOOL (WINAPI *UpdateProcThreadAttributeFunction)( - LPPROC_THREAD_ATTRIBUTE_LIST attribute_list, - DWORD flags, - DWORD_PTR attribute, - PVOID value, - SIZE_T size, - PVOID previous_value, - PSIZE_T return_size); -static UpdateProcThreadAttributeFunction update_proc_thread_attribute_list; - -typedef VOID (WINAPI *DeleteProcThreadAttributeListFunction)( - LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList); -static DeleteProcThreadAttributeListFunction delete_proc_thread_attribute_list; - -} // namespace - -namespace base { -namespace win { - -StartupInformation::StartupInformation() { - memset(&startup_info_, 0, sizeof(startup_info_)); - - // Pre Windows Vista doesn't support STARTUPINFOEX. - if (base::win::GetVersion() < base::win::VERSION_VISTA) { - startup_info_.StartupInfo.cb = sizeof(STARTUPINFO); - return; - } - - startup_info_.StartupInfo.cb = sizeof(startup_info_); - - // Load the attribute API functions. - if (!initialize_proc_thread_attribute_list || - !update_proc_thread_attribute_list || - !delete_proc_thread_attribute_list) { - HMODULE module = ::GetModuleHandleW(L"kernel32.dll"); - initialize_proc_thread_attribute_list = - reinterpret_cast<InitializeProcThreadAttributeListFunction>( - ::GetProcAddress(module, "InitializeProcThreadAttributeList")); - update_proc_thread_attribute_list = - reinterpret_cast<UpdateProcThreadAttributeFunction>( - ::GetProcAddress(module, "UpdateProcThreadAttribute")); - delete_proc_thread_attribute_list = - reinterpret_cast<DeleteProcThreadAttributeListFunction>( - ::GetProcAddress(module, "DeleteProcThreadAttributeList")); - } -} - -StartupInformation::~StartupInformation() { - if (startup_info_.lpAttributeList) { - delete_proc_thread_attribute_list(startup_info_.lpAttributeList); - delete [] reinterpret_cast<BYTE*>(startup_info_.lpAttributeList); - } -} - -bool StartupInformation::InitializeProcThreadAttributeList( - DWORD attribute_count) { - if (startup_info_.StartupInfo.cb != sizeof(startup_info_) || - startup_info_.lpAttributeList) - return false; - - SIZE_T size = 0; - initialize_proc_thread_attribute_list(NULL, attribute_count, 0, &size); - if (size == 0) - return false; - - startup_info_.lpAttributeList = - reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(new BYTE[size]); - if (!initialize_proc_thread_attribute_list(startup_info_.lpAttributeList, - attribute_count, 0, &size)) { - delete [] reinterpret_cast<BYTE*>(startup_info_.lpAttributeList); - startup_info_.lpAttributeList = NULL; - return false; - } - - return true; -} - -bool StartupInformation::UpdateProcThreadAttribute( - DWORD_PTR attribute, - void* value, - size_t size) { - if (!startup_info_.lpAttributeList) - return false; - return !!update_proc_thread_attribute_list(startup_info_.lpAttributeList, 0, - attribute, value, size, NULL, NULL); -} - -} // namespace win -} // namespace base - diff --git a/security/sandbox/chromium/base/win/startup_information.h b/security/sandbox/chromium/base/win/startup_information.h deleted file mode 100644 index 5b777baef..000000000 --- a/security/sandbox/chromium/base/win/startup_information.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_WIN_STARTUP_INFORMATION_H_ -#define BASE_WIN_STARTUP_INFORMATION_H_ - -#include <windows.h> -#include <stddef.h> - -#include "base/base_export.h" -#include "base/macros.h" - -namespace base { -namespace win { - -// Manages the lifetime of additional attributes in STARTUPINFOEX. -class BASE_EXPORT StartupInformation { - public: - StartupInformation(); - - ~StartupInformation(); - - // Initialize the attribute list for the specified number of entries. - bool InitializeProcThreadAttributeList(DWORD attribute_count); - - // Sets one entry in the initialized attribute list. - // |value| needs to live at least as long as the StartupInformation object - // this is called on. - bool UpdateProcThreadAttribute(DWORD_PTR attribute, - void* value, - size_t size); - - LPSTARTUPINFOW startup_info() { return &startup_info_.StartupInfo; } - LPSTARTUPINFOW startup_info() const { - return const_cast<const LPSTARTUPINFOW>(&startup_info_.StartupInfo); - } - - bool has_extended_startup_info() const { - return !!startup_info_.lpAttributeList; - } - - private: - STARTUPINFOEXW startup_info_; - DISALLOW_COPY_AND_ASSIGN(StartupInformation); -}; - -} // namespace win -} // namespace base - -#endif // BASE_WIN_STARTUP_INFORMATION_H_ diff --git a/security/sandbox/chromium/base/win/windows_version.cc b/security/sandbox/chromium/base/win/windows_version.cc deleted file mode 100644 index eb3f4993d..000000000 --- a/security/sandbox/chromium/base/win/windows_version.cc +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/win/windows_version.h" - -#include <windows.h> - -#include "base/file_version_info_win.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/utf_string_conversions.h" -#include "base/win/registry.h" - -namespace { -typedef BOOL (WINAPI *GetProductInfoPtr)(DWORD, DWORD, DWORD, DWORD, PDWORD); -} // namespace - -namespace base { -namespace win { - -namespace { - -// Helper to map a major.minor.x.build version (e.g. 6.1) to a Windows release. -Version MajorMinorBuildToVersion(int major, int minor, int build) { - if ((major == 5) && (minor > 0)) { - // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003. - return (minor == 1) ? VERSION_XP : VERSION_SERVER_2003; - } else if (major == 6) { - switch (minor) { - case 0: - // Treat Windows Server 2008 the same as Windows Vista. - return VERSION_VISTA; - case 1: - // Treat Windows Server 2008 R2 the same as Windows 7. - return VERSION_WIN7; - case 2: - // Treat Windows Server 2012 the same as Windows 8. - return VERSION_WIN8; - default: - DCHECK_EQ(minor, 3); - return VERSION_WIN8_1; - } - } else if (major == 10) { - if (build < 10586) { - return VERSION_WIN10; - } else { - return VERSION_WIN10_TH2; - } - } else if (major > 6) { - NOTREACHED(); - return VERSION_WIN_LAST; - } - - return VERSION_PRE_XP; -} - -// Retrieve a version from kernel32. This is useful because when running in -// compatibility mode for a down-level version of the OS, the file version of -// kernel32 will still be the "real" version. -Version GetVersionFromKernel32() { - scoped_ptr<FileVersionInfoWin> file_version_info( - static_cast<FileVersionInfoWin*>( - FileVersionInfoWin::CreateFileVersionInfo( - base::FilePath(FILE_PATH_LITERAL("kernel32.dll"))))); - if (file_version_info) { - const int major = - HIWORD(file_version_info->fixed_file_info()->dwFileVersionMS); - const int minor = - LOWORD(file_version_info->fixed_file_info()->dwFileVersionMS); - const int build = - HIWORD(file_version_info->fixed_file_info()->dwFileVersionLS); - return MajorMinorBuildToVersion(major, minor, build); - } - - NOTREACHED(); - return VERSION_WIN_LAST; -} - -} // namespace - -// static -OSInfo* OSInfo::GetInstance() { - // Note: we don't use the Singleton class because it depends on AtExitManager, - // and it's convenient for other modules to use this classs without it. This - // pattern is copied from gurl.cc. - static OSInfo* info; - if (!info) { - OSInfo* new_info = new OSInfo(); - if (InterlockedCompareExchangePointer( - reinterpret_cast<PVOID*>(&info), new_info, NULL)) { - delete new_info; - } - } - return info; -} - -OSInfo::OSInfo() - : version_(VERSION_PRE_XP), - kernel32_version_(VERSION_PRE_XP), - got_kernel32_version_(false), - architecture_(OTHER_ARCHITECTURE), - wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) { - OSVERSIONINFOEX version_info = { sizeof version_info }; - ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); - version_number_.major = version_info.dwMajorVersion; - version_number_.minor = version_info.dwMinorVersion; - version_number_.build = version_info.dwBuildNumber; - version_ = MajorMinorBuildToVersion( - version_number_.major, version_number_.minor, version_number_.build); - service_pack_.major = version_info.wServicePackMajor; - service_pack_.minor = version_info.wServicePackMinor; - - SYSTEM_INFO system_info = {}; - ::GetNativeSystemInfo(&system_info); - switch (system_info.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_INTEL: architecture_ = X86_ARCHITECTURE; break; - case PROCESSOR_ARCHITECTURE_AMD64: architecture_ = X64_ARCHITECTURE; break; - case PROCESSOR_ARCHITECTURE_IA64: architecture_ = IA64_ARCHITECTURE; break; - } - processors_ = system_info.dwNumberOfProcessors; - allocation_granularity_ = system_info.dwAllocationGranularity; - - GetProductInfoPtr get_product_info; - DWORD os_type; - - if (version_info.dwMajorVersion == 6 || version_info.dwMajorVersion == 10) { - // Only present on Vista+. - get_product_info = reinterpret_cast<GetProductInfoPtr>( - ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "GetProductInfo")); - - get_product_info(version_info.dwMajorVersion, version_info.dwMinorVersion, - 0, 0, &os_type); - switch (os_type) { - case PRODUCT_CLUSTER_SERVER: - case PRODUCT_DATACENTER_SERVER: - case PRODUCT_DATACENTER_SERVER_CORE: - case PRODUCT_ENTERPRISE_SERVER: - case PRODUCT_ENTERPRISE_SERVER_CORE: - case PRODUCT_ENTERPRISE_SERVER_IA64: - case PRODUCT_SMALLBUSINESS_SERVER: - case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: - case PRODUCT_STANDARD_SERVER: - case PRODUCT_STANDARD_SERVER_CORE: - case PRODUCT_WEB_SERVER: - version_type_ = SUITE_SERVER; - break; - case PRODUCT_PROFESSIONAL: - case PRODUCT_ULTIMATE: - case PRODUCT_ENTERPRISE: - case PRODUCT_BUSINESS: - version_type_ = SUITE_PROFESSIONAL; - break; - case PRODUCT_HOME_BASIC: - case PRODUCT_HOME_PREMIUM: - case PRODUCT_STARTER: - default: - version_type_ = SUITE_HOME; - break; - } - } else if (version_info.dwMajorVersion == 5 && - version_info.dwMinorVersion == 2) { - if (version_info.wProductType == VER_NT_WORKSTATION && - system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { - version_type_ = SUITE_PROFESSIONAL; - } else if (version_info.wSuiteMask & VER_SUITE_WH_SERVER ) { - version_type_ = SUITE_HOME; - } else { - version_type_ = SUITE_SERVER; - } - } else if (version_info.dwMajorVersion == 5 && - version_info.dwMinorVersion == 1) { - if(version_info.wSuiteMask & VER_SUITE_PERSONAL) - version_type_ = SUITE_HOME; - else - version_type_ = SUITE_PROFESSIONAL; - } else { - // Windows is pre XP so we don't care but pick a safe default. - version_type_ = SUITE_HOME; - } -} - -OSInfo::~OSInfo() { -} - -Version OSInfo::Kernel32Version() const { - if (!got_kernel32_version_) { - kernel32_version_ = GetVersionFromKernel32(); - got_kernel32_version_ = true; - } - return kernel32_version_; -} - -std::string OSInfo::processor_model_name() { - if (processor_model_name_.empty()) { - const wchar_t kProcessorNameString[] = - L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"; - base::win::RegKey key(HKEY_LOCAL_MACHINE, kProcessorNameString, KEY_READ); - string16 value; - key.ReadValue(L"ProcessorNameString", &value); - processor_model_name_ = UTF16ToUTF8(value); - } - return processor_model_name_; -} - -// static -OSInfo::WOW64Status OSInfo::GetWOW64StatusForProcess(HANDLE process_handle) { - typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL); - IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>( - GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process")); - if (!is_wow64_process) - return WOW64_DISABLED; - BOOL is_wow64 = FALSE; - if (!(*is_wow64_process)(process_handle, &is_wow64)) - return WOW64_UNKNOWN; - return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED; -} - -Version GetVersion() { - return OSInfo::GetInstance()->version(); -} - -} // namespace win -} // namespace base diff --git a/security/sandbox/chromium/base/win/windows_version.h b/security/sandbox/chromium/base/win/windows_version.h deleted file mode 100644 index 7bc8b6fe5..000000000 --- a/security/sandbox/chromium/base/win/windows_version.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_WIN_WINDOWS_VERSION_H_ -#define BASE_WIN_WINDOWS_VERSION_H_ - -#include <stddef.h> - -#include <string> - -#include "base/base_export.h" -#include "base/macros.h" - -typedef void* HANDLE; - -namespace base { -namespace win { - -// The running version of Windows. This is declared outside OSInfo for -// syntactic sugar reasons; see the declaration of GetVersion() below. -// NOTE: Keep these in order so callers can do things like -// "if (base::win::GetVersion() >= base::win::VERSION_VISTA) ...". -// -// This enum is used in metrics histograms, so they shouldn't be reordered or -// removed. New values can be added before VERSION_WIN_LAST. -enum Version { - VERSION_PRE_XP = 0, // Not supported. - VERSION_XP = 1, - VERSION_SERVER_2003 = 2, // Also includes XP Pro x64 and Server 2003 R2. - VERSION_VISTA = 3, // Also includes Windows Server 2008. - VERSION_WIN7 = 4, // Also includes Windows Server 2008 R2. - VERSION_WIN8 = 5, // Also includes Windows Server 2012. - VERSION_WIN8_1 = 6, // Also includes Windows Server 2012 R2. - VERSION_WIN10 = 7, // Also includes Windows 10 Server. - VERSION_WIN10_TH2 = 8, // Threshold 2: Version 1511, Build 10586. - VERSION_WIN_LAST, // Indicates error condition. -}; - -// A rough bucketing of the available types of versions of Windows. This is used -// to distinguish enterprise enabled versions from home versions and potentially -// server versions. -enum VersionType { - SUITE_HOME, - SUITE_PROFESSIONAL, - SUITE_SERVER, - SUITE_LAST, -}; - -// A singleton that can be used to query various pieces of information about the -// OS and process state. Note that this doesn't use the base Singleton class, so -// it can be used without an AtExitManager. -class BASE_EXPORT OSInfo { - public: - struct VersionNumber { - int major; - int minor; - int build; - }; - - struct ServicePack { - int major; - int minor; - }; - - // The processor architecture this copy of Windows natively uses. For - // example, given an x64-capable processor, we have three possibilities: - // 32-bit Chrome running on 32-bit Windows: X86_ARCHITECTURE - // 32-bit Chrome running on 64-bit Windows via WOW64: X64_ARCHITECTURE - // 64-bit Chrome running on 64-bit Windows: X64_ARCHITECTURE - enum WindowsArchitecture { - X86_ARCHITECTURE, - X64_ARCHITECTURE, - IA64_ARCHITECTURE, - OTHER_ARCHITECTURE, - }; - - // Whether a process is running under WOW64 (the wrapper that allows 32-bit - // processes to run on 64-bit versions of Windows). This will return - // WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit - // Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g. - // the process does not have sufficient access rights to determine this. - enum WOW64Status { - WOW64_DISABLED, - WOW64_ENABLED, - WOW64_UNKNOWN, - }; - - static OSInfo* GetInstance(); - - Version version() const { return version_; } - Version Kernel32Version() const; - // The next two functions return arrays of values, [major, minor(, build)]. - VersionNumber version_number() const { return version_number_; } - VersionType version_type() const { return version_type_; } - ServicePack service_pack() const { return service_pack_; } - WindowsArchitecture architecture() const { return architecture_; } - int processors() const { return processors_; } - size_t allocation_granularity() const { return allocation_granularity_; } - WOW64Status wow64_status() const { return wow64_status_; } - std::string processor_model_name(); - - // Like wow64_status(), but for the supplied handle instead of the current - // process. This doesn't touch member state, so you can bypass the singleton. - static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); - - private: - OSInfo(); - ~OSInfo(); - - Version version_; - mutable Version kernel32_version_; - mutable bool got_kernel32_version_; - VersionNumber version_number_; - VersionType version_type_; - ServicePack service_pack_; - WindowsArchitecture architecture_; - int processors_; - size_t allocation_granularity_; - WOW64Status wow64_status_; - std::string processor_model_name_; - - DISALLOW_COPY_AND_ASSIGN(OSInfo); -}; - -// Because this is by far the most commonly-requested value from the above -// singleton, we add a global-scope accessor here as syntactic sugar. -BASE_EXPORT Version GetVersion(); - -} // namespace win -} // namespace base - -#endif // BASE_WIN_WINDOWS_VERSION_H_ diff --git a/security/sandbox/chromium/build/build_config.h b/security/sandbox/chromium/build/build_config.h deleted file mode 100644 index d8c3db6ed..000000000 --- a/security/sandbox/chromium/build/build_config.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file adds defines about the platform we're currently building on. -// Operating System: -// OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) / -// OS_NACL (NACL_SFI or NACL_NONSFI) / OS_NACL_SFI / OS_NACL_NONSFI -// Compiler: -// COMPILER_MSVC / COMPILER_GCC -// Processor: -// ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64) -// ARCH_CPU_32_BITS / ARCH_CPU_64_BITS - -#ifndef BUILD_BUILD_CONFIG_H_ -#define BUILD_BUILD_CONFIG_H_ - -// A set of macros to use for platform detection. -#if defined(__native_client__) -// __native_client__ must be first, so that other OS_ defines are not set. -#define OS_NACL 1 -// OS_NACL comes in two sandboxing technology flavors, SFI or Non-SFI. -// PNaCl toolchain defines __native_client_nonsfi__ macro in Non-SFI build -// mode, while it does not in SFI build mode. -#if defined(__native_client_nonsfi__) -#define OS_NACL_NONSFI -#else -#define OS_NACL_SFI -#endif -#elif defined(ANDROID) -#define OS_ANDROID 1 -#elif defined(__APPLE__) -// only include TargetConditions after testing ANDROID as some android builds -// on mac don't have this header available and it's not needed unless the target -// is really mac/ios. -#include <TargetConditionals.h> -#define OS_MACOSX 1 -#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE -#define OS_IOS 1 -#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE -#elif defined(__linux__) -#define OS_LINUX 1 -// include a system header to pull in features.h for glibc/uclibc macros. -#include <unistd.h> -#if defined(__GLIBC__) && !defined(__UCLIBC__) -// we really are using glibc, not uClibc pretending to be glibc -#define LIBC_GLIBC 1 -#endif -#elif defined(_WIN32) -#define OS_WIN 1 -#define TOOLKIT_VIEWS 1 -#elif defined(__FreeBSD__) -#define OS_FREEBSD 1 -#elif defined(__OpenBSD__) -#define OS_OPENBSD 1 -#elif defined(__sun) -#define OS_SOLARIS 1 -#elif defined(__QNXNTO__) -#define OS_QNX 1 -#else -#error Please add support for your platform in build/build_config.h -#endif - -#if defined(USE_OPENSSL_CERTS) && defined(USE_NSS_CERTS) -#error Cannot use both OpenSSL and NSS for certificates -#endif - -// For access to standard BSD features, use OS_BSD instead of a -// more specific macro. -#if defined(OS_FREEBSD) || defined(OS_OPENBSD) -#define OS_BSD 1 -#endif - -// For access to standard POSIXish features, use OS_POSIX instead of a -// more specific macro. -#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \ - defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_ANDROID) || \ - defined(OS_NACL) || defined(OS_QNX) -#define OS_POSIX 1 -#endif - -// Use tcmalloc -#if (defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)) && \ - !defined(NO_TCMALLOC) -#define USE_TCMALLOC 1 -#endif - -// Compiler detection. -#if defined(__GNUC__) -#define COMPILER_GCC 1 -#elif defined(_MSC_VER) -#define COMPILER_MSVC 1 -#else -#error Please add support for your compiler in build/build_config.h -#endif - -// Processor architecture detection. For more info on what's defined, see: -// http://msdn.microsoft.com/en-us/library/b0084kay.aspx -// http://www.agner.org/optimize/calling_conventions.pdf -// or with gcc, run: "echo | gcc -E -dM -" -#if defined(_M_X64) || defined(__x86_64__) -#define ARCH_CPU_X86_FAMILY 1 -#define ARCH_CPU_X86_64 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(_M_IX86) || defined(__i386__) -#define ARCH_CPU_X86_FAMILY 1 -#define ARCH_CPU_X86 1 -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__ARMEL__) -#define ARCH_CPU_ARM_FAMILY 1 -#define ARCH_CPU_ARMEL 1 -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__aarch64__) -#define ARCH_CPU_ARM_FAMILY 1 -#define ARCH_CPU_ARM64 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__pnacl__) -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__MIPSEL__) -#if defined(__LP64__) -#define ARCH_CPU_MIPS64_FAMILY 1 -#define ARCH_CPU_MIPS64EL 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#else -#define ARCH_CPU_MIPS_FAMILY 1 -#define ARCH_CPU_MIPSEL 1 -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#endif -#else -#error Please add support for your architecture in build/build_config.h -#endif - -// Type detection for wchar_t. -#if defined(OS_WIN) -#define WCHAR_T_IS_UTF16 -#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \ - defined(__WCHAR_MAX__) && \ - (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) -#define WCHAR_T_IS_UTF32 -#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \ - defined(__WCHAR_MAX__) && \ - (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff) -// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to -// compile in this mode (in particular, Chrome doesn't). This is intended for -// other projects using base who manage their own dependencies and make sure -// short wchar works for them. -#define WCHAR_T_IS_UTF16 -#else -#error Please add support for your compiler in build/build_config.h -#endif - -#if defined(OS_ANDROID) -// The compiler thinks std::string::const_iterator and "const char*" are -// equivalent types. -#define STD_STRING_ITERATOR_IS_CHAR_POINTER -// The compiler thinks base::string16::const_iterator and "char16*" are -// equivalent types. -#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER -#endif - -#endif // BUILD_BUILD_CONFIG_H_ diff --git a/security/sandbox/chromium/build/buildflag.h b/security/sandbox/chromium/build/buildflag.h deleted file mode 100644 index 283f5bce4..000000000 --- a/security/sandbox/chromium/build/buildflag.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BUILD_BUILDFLAG_H_ -#define BUILD_BUILDFLAG_H_ - -// These macros un-mangle the names of the build flags in a way that looks -// natural, and gives errors if the flag is not defined. Normally in the -// preprocessor it's easy to make mistakes that interpret "you haven't done -// the setup to know what the flag is" as "flag is off". Normally you would -// include the generated header rather than include this file directly. -// -// This is for use with generated headers. See build/build_header.gni. - -// This dance of two macros does a concatenation of two preprocessor args using -// ## doubly indirectly because using ## directly prevents macros in that -// parameter from being expanded. -#define BUILDFLAG_CAT_INDIRECT(a, b) a ## b -#define BUILDFLAG_CAT(a, b) BUILDFLAG_CAT_INDIRECT(a, b) - -// Accessor for build flags. -// -// To test for a value, if the build file specifies: -// -// ENABLE_FOO=true -// -// Then you would check at build-time in source code with: -// -// #include "foo_flags.h" // The header the build file specified. -// -// #if BUILDFLAG(ENABLE_FOO) -// ... -// #endif -// -// There will no #define called ENABLE_FOO so if you accidentally test for -// whether that is defined, it will always be negative. You can also use -// the value in expressions: -// -// const char kSpamServerName[] = BUILDFLAG(SPAM_SERVER_NAME); -// -// Because the flag is accessed as a preprocessor macro with (), an error -// will be thrown if the proper header defining the internal flag value has -// not been included. -#define BUILDFLAG(flag) (BUILDFLAG_CAT(BUILDFLAG_INTERNAL_, flag)()) - -#endif // BUILD_BUILDFLAG_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl.cc deleted file mode 100644 index 3330c4774..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl.cc +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/bpf_dsl/bpf_dsl.h" - -#include <stddef.h> -#include <stdint.h> - -#include <limits> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" -#include "sandbox/linux/bpf_dsl/errorcode.h" -#include "sandbox/linux/bpf_dsl/policy_compiler.h" -#include "sandbox/linux/system_headers/linux_seccomp.h" - -namespace sandbox { -namespace bpf_dsl { -namespace { - -class ReturnResultExprImpl : public internal::ResultExprImpl { - public: - explicit ReturnResultExprImpl(uint32_t ret) : ret_(ret) {} - - CodeGen::Node Compile(PolicyCompiler* pc) const override { - return pc->Return(ret_); - } - - bool IsAllow() const override { return IsAction(SECCOMP_RET_ALLOW); } - - bool IsDeny() const override { - return IsAction(SECCOMP_RET_ERRNO) || IsAction(SECCOMP_RET_KILL); - } - - private: - ~ReturnResultExprImpl() override {} - - bool IsAction(uint32_t action) const { - return (ret_ & SECCOMP_RET_ACTION) == action; - } - - uint32_t ret_; - - DISALLOW_COPY_AND_ASSIGN(ReturnResultExprImpl); -}; - -class TrapResultExprImpl : public internal::ResultExprImpl { - public: - TrapResultExprImpl(TrapRegistry::TrapFnc func, const void* arg, bool safe) - : func_(func), arg_(arg), safe_(safe) { - DCHECK(func_); - } - - CodeGen::Node Compile(PolicyCompiler* pc) const override { - return pc->Trap(func_, arg_, safe_); - } - - bool HasUnsafeTraps() const override { return safe_ == false; } - - bool IsDeny() const override { return true; } - - private: - ~TrapResultExprImpl() override {} - - TrapRegistry::TrapFnc func_; - const void* arg_; - bool safe_; - - DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl); -}; - -class IfThenResultExprImpl : public internal::ResultExprImpl { - public: - IfThenResultExprImpl(const BoolExpr& cond, - const ResultExpr& then_result, - const ResultExpr& else_result) - : cond_(cond), then_result_(then_result), else_result_(else_result) {} - - CodeGen::Node Compile(PolicyCompiler* pc) const override { - // We compile the "then" and "else" expressions in separate statements so - // they have a defined sequencing. See https://crbug.com/529480. - CodeGen::Node then_node = then_result_->Compile(pc); - CodeGen::Node else_node = else_result_->Compile(pc); - return cond_->Compile(pc, then_node, else_node); - } - - bool HasUnsafeTraps() const override { - return then_result_->HasUnsafeTraps() || else_result_->HasUnsafeTraps(); - } - - private: - ~IfThenResultExprImpl() override {} - - BoolExpr cond_; - ResultExpr then_result_; - ResultExpr else_result_; - - DISALLOW_COPY_AND_ASSIGN(IfThenResultExprImpl); -}; - -class ConstBoolExprImpl : public internal::BoolExprImpl { - public: - ConstBoolExprImpl(bool value) : value_(value) {} - - CodeGen::Node Compile(PolicyCompiler* pc, - CodeGen::Node then_node, - CodeGen::Node else_node) const override { - return value_ ? then_node : else_node; - } - - private: - ~ConstBoolExprImpl() override {} - - bool value_; - - DISALLOW_COPY_AND_ASSIGN(ConstBoolExprImpl); -}; - -class MaskedEqualBoolExprImpl : public internal::BoolExprImpl { - public: - MaskedEqualBoolExprImpl(int argno, - size_t width, - uint64_t mask, - uint64_t value) - : argno_(argno), width_(width), mask_(mask), value_(value) {} - - CodeGen::Node Compile(PolicyCompiler* pc, - CodeGen::Node then_node, - CodeGen::Node else_node) const override { - return pc->MaskedEqual(argno_, width_, mask_, value_, then_node, else_node); - } - - private: - ~MaskedEqualBoolExprImpl() override {} - - int argno_; - size_t width_; - uint64_t mask_; - uint64_t value_; - - DISALLOW_COPY_AND_ASSIGN(MaskedEqualBoolExprImpl); -}; - -class NegateBoolExprImpl : public internal::BoolExprImpl { - public: - explicit NegateBoolExprImpl(const BoolExpr& cond) : cond_(cond) {} - - CodeGen::Node Compile(PolicyCompiler* pc, - CodeGen::Node then_node, - CodeGen::Node else_node) const override { - return cond_->Compile(pc, else_node, then_node); - } - - private: - ~NegateBoolExprImpl() override {} - - BoolExpr cond_; - - DISALLOW_COPY_AND_ASSIGN(NegateBoolExprImpl); -}; - -class AndBoolExprImpl : public internal::BoolExprImpl { - public: - AndBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs) - : lhs_(lhs), rhs_(rhs) {} - - CodeGen::Node Compile(PolicyCompiler* pc, - CodeGen::Node then_node, - CodeGen::Node else_node) const override { - return lhs_->Compile(pc, rhs_->Compile(pc, then_node, else_node), - else_node); - } - - private: - ~AndBoolExprImpl() override {} - - BoolExpr lhs_; - BoolExpr rhs_; - - DISALLOW_COPY_AND_ASSIGN(AndBoolExprImpl); -}; - -class OrBoolExprImpl : public internal::BoolExprImpl { - public: - OrBoolExprImpl(const BoolExpr& lhs, const BoolExpr& rhs) - : lhs_(lhs), rhs_(rhs) {} - - CodeGen::Node Compile(PolicyCompiler* pc, - CodeGen::Node then_node, - CodeGen::Node else_node) const override { - return lhs_->Compile(pc, then_node, - rhs_->Compile(pc, then_node, else_node)); - } - - private: - ~OrBoolExprImpl() override {} - - BoolExpr lhs_; - BoolExpr rhs_; - - DISALLOW_COPY_AND_ASSIGN(OrBoolExprImpl); -}; - -} // namespace - -namespace internal { - -bool ResultExprImpl::HasUnsafeTraps() const { - return false; -} - -bool ResultExprImpl::IsAllow() const { - return false; -} - -bool ResultExprImpl::IsDeny() const { - return false; -} - -uint64_t DefaultMask(size_t size) { - switch (size) { - case 4: - return std::numeric_limits<uint32_t>::max(); - case 8: - return std::numeric_limits<uint64_t>::max(); - default: - CHECK(false) << "Unimplemented DefaultMask case"; - return 0; - } -} - -BoolExpr ArgEq(int num, size_t size, uint64_t mask, uint64_t val) { - // If this is changed, update Arg<T>::EqualTo's static_cast rules - // accordingly. - CHECK(size == 4 || size == 8); - - return BoolExpr(new const MaskedEqualBoolExprImpl(num, size, mask, val)); -} - -} // namespace internal - -ResultExpr Allow() { - return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_ALLOW)); -} - -ResultExpr Error(int err) { - CHECK(err >= ErrorCode::ERR_MIN_ERRNO && err <= ErrorCode::ERR_MAX_ERRNO); - return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_ERRNO + err)); -} - -ResultExpr Kill() { - return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_KILL)); -} - -ResultExpr Trace(uint16_t aux) { - return ResultExpr(new const ReturnResultExprImpl(SECCOMP_RET_TRACE + aux)); -} - -ResultExpr Trap(TrapRegistry::TrapFnc trap_func, const void* aux) { - return ResultExpr( - new const TrapResultExprImpl(trap_func, aux, true /* safe */)); -} - -ResultExpr UnsafeTrap(TrapRegistry::TrapFnc trap_func, const void* aux) { - return ResultExpr( - new const TrapResultExprImpl(trap_func, aux, false /* unsafe */)); -} - -BoolExpr BoolConst(bool value) { - return BoolExpr(new const ConstBoolExprImpl(value)); -} - -BoolExpr Not(const BoolExpr& cond) { - return BoolExpr(new const NegateBoolExprImpl(cond)); -} - -BoolExpr AllOf() { - return BoolConst(true); -} - -BoolExpr AllOf(const BoolExpr& lhs, const BoolExpr& rhs) { - return BoolExpr(new const AndBoolExprImpl(lhs, rhs)); -} - -BoolExpr AnyOf() { - return BoolConst(false); -} - -BoolExpr AnyOf(const BoolExpr& lhs, const BoolExpr& rhs) { - return BoolExpr(new const OrBoolExprImpl(lhs, rhs)); -} - -Elser If(const BoolExpr& cond, const ResultExpr& then_result) { - return Elser(nullptr).ElseIf(cond, then_result); -} - -Elser::Elser(cons::List<Clause> clause_list) : clause_list_(clause_list) { -} - -Elser::Elser(const Elser& elser) : clause_list_(elser.clause_list_) { -} - -Elser::~Elser() { -} - -Elser Elser::ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const { - return Elser(Cons(std::make_pair(cond, then_result), clause_list_)); -} - -ResultExpr Elser::Else(const ResultExpr& else_result) const { - // We finally have the default result expression for this - // if/then/else sequence. Also, we've already accumulated all - // if/then pairs into a list of reverse order (i.e., lower priority - // conditions are listed before higher priority ones). E.g., an - // expression like - // - // If(b1, e1).ElseIf(b2, e2).ElseIf(b3, e3).Else(e4) - // - // will have built up a list like - // - // [(b3, e3), (b2, e2), (b1, e1)]. - // - // Now that we have e4, we can walk the list and create a ResultExpr - // tree like: - // - // expr = e4 - // expr = (b3 ? e3 : expr) = (b3 ? e3 : e4) - // expr = (b2 ? e2 : expr) = (b2 ? e2 : (b3 ? e3 : e4)) - // expr = (b1 ? e1 : expr) = (b1 ? e1 : (b2 ? e2 : (b3 ? e3 : e4))) - // - // and end up with an appropriately chained tree. - - ResultExpr expr = else_result; - for (const Clause& clause : clause_list_) { - expr = ResultExpr( - new const IfThenResultExprImpl(clause.first, clause.second, expr)); - } - return expr; -} - -} // namespace bpf_dsl -} // namespace sandbox - -template class scoped_refptr<const sandbox::bpf_dsl::internal::BoolExprImpl>; -template class scoped_refptr<const sandbox::bpf_dsl::internal::ResultExprImpl>; diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl.h deleted file mode 100644 index ffd20ff42..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl.h +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_ -#define SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <utility> -#include <vector> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h" -#include "sandbox/linux/bpf_dsl/cons.h" -#include "sandbox/linux/bpf_dsl/trap_registry.h" -#include "sandbox/sandbox_export.h" - -// The sandbox::bpf_dsl namespace provides a domain-specific language -// to make writing BPF policies more expressive. In general, the -// object types all have value semantics (i.e., they can be copied -// around, returned from or passed to function calls, etc. without any -// surprising side effects), though not all support assignment. -// -// An idiomatic and demonstrative (albeit silly) example of this API -// would be: -// -// #include "sandbox/linux/bpf_dsl/bpf_dsl.h" -// -// using namespace sandbox::bpf_dsl; -// -// class SillyPolicy : public Policy { -// public: -// SillyPolicy() {} -// ~SillyPolicy() override {} -// ResultExpr EvaluateSyscall(int sysno) const override { -// if (sysno == __NR_fcntl) { -// Arg<int> fd(0), cmd(1); -// Arg<unsigned long> flags(2); -// const uint64_t kGoodFlags = O_ACCMODE | O_NONBLOCK; -// return If(AllOf(fd == 0, -// cmd == F_SETFL, -// (flags & ~kGoodFlags) == 0), -// Allow()) -// .ElseIf(AnyOf(cmd == F_DUPFD, cmd == F_DUPFD_CLOEXEC), -// Error(EMFILE)) -// .Else(Trap(SetFlagHandler, NULL)); -// } else { -// return Allow(); -// } -// } -// -// private: -// DISALLOW_COPY_AND_ASSIGN(SillyPolicy); -// }; -// -// More generally, the DSL currently supports the following grammar: -// -// result = Allow() | Error(errno) | Kill() | Trace(aux) -// | Trap(trap_func, aux) | UnsafeTrap(trap_func, aux) -// | If(bool, result)[.ElseIf(bool, result)].Else(result) -// | Switch(arg)[.Case(val, result)].Default(result) -// bool = BoolConst(boolean) | Not(bool) | AllOf(bool...) | AnyOf(bool...) -// | arg == val | arg != val -// arg = Arg<T>(num) | arg & mask -// -// The semantics of each function and operator are intended to be -// intuitive, but are described in more detail below. -// -// (Credit to Sean Parent's "Inheritance is the Base Class of Evil" -// talk at Going Native 2013 for promoting value semantics via shared -// pointers to immutable state.) - -namespace sandbox { -namespace bpf_dsl { - -// ResultExpr is an opaque reference to an immutable result expression tree. -typedef scoped_refptr<const internal::ResultExprImpl> ResultExpr; - -// BoolExpr is an opaque reference to an immutable boolean expression tree. -typedef scoped_refptr<const internal::BoolExprImpl> BoolExpr; - -// Allow specifies a result that the system call should be allowed to -// execute normally. -SANDBOX_EXPORT ResultExpr Allow(); - -// Error specifies a result that the system call should fail with -// error number |err|. As a special case, Error(0) will result in the -// system call appearing to have succeeded, but without having any -// side effects. -SANDBOX_EXPORT ResultExpr Error(int err); - -// Kill specifies a result to kill the process (task) immediately. -SANDBOX_EXPORT ResultExpr Kill(); - -// Trace specifies a result to notify a tracing process via the -// PTRACE_EVENT_SECCOMP event and allow it to change or skip the system call. -// The value of |aux| will be available to the tracer via PTRACE_GETEVENTMSG. -SANDBOX_EXPORT ResultExpr Trace(uint16_t aux); - -// Trap specifies a result that the system call should be handled by -// trapping back into userspace and invoking |trap_func|, passing -// |aux| as the second parameter. -SANDBOX_EXPORT ResultExpr - Trap(TrapRegistry::TrapFnc trap_func, const void* aux); - -// UnsafeTrap is like Trap, except the policy is marked as "unsafe" -// and allowed to use SandboxSyscall to invoke any system call. -// -// NOTE: This feature, by definition, disables all security features of -// the sandbox. It should never be used in production, but it can be -// very useful to diagnose code that is incompatible with the sandbox. -// If even a single system call returns "UnsafeTrap", the security of -// entire sandbox should be considered compromised. -SANDBOX_EXPORT ResultExpr - UnsafeTrap(TrapRegistry::TrapFnc trap_func, const void* aux); - -// BoolConst converts a bool value into a BoolExpr. -SANDBOX_EXPORT BoolExpr BoolConst(bool value); - -// Not returns a BoolExpr representing the logical negation of |cond|. -SANDBOX_EXPORT BoolExpr Not(const BoolExpr& cond); - -// AllOf returns a BoolExpr representing the logical conjunction ("and") -// of zero or more BoolExprs. -SANDBOX_EXPORT BoolExpr AllOf(); -SANDBOX_EXPORT BoolExpr AllOf(const BoolExpr& lhs, const BoolExpr& rhs); -template <typename... Rest> -SANDBOX_EXPORT BoolExpr AllOf(const BoolExpr& first, const Rest&... rest); - -// AnyOf returns a BoolExpr representing the logical disjunction ("or") -// of zero or more BoolExprs. -SANDBOX_EXPORT BoolExpr AnyOf(); -SANDBOX_EXPORT BoolExpr AnyOf(const BoolExpr& lhs, const BoolExpr& rhs); -template <typename... Rest> -SANDBOX_EXPORT BoolExpr AnyOf(const BoolExpr& first, const Rest&... rest); - -template <typename T> -class SANDBOX_EXPORT Arg { - public: - // Initializes the Arg to represent the |num|th system call - // argument (indexed from 0), which is of type |T|. - explicit Arg(int num); - - Arg(const Arg& arg) : num_(arg.num_), mask_(arg.mask_) {} - - // Returns an Arg representing the current argument, but after - // bitwise-and'ing it with |rhs|. - friend Arg operator&(const Arg& lhs, uint64_t rhs) { - return Arg(lhs.num_, lhs.mask_ & rhs); - } - - // Returns a boolean expression comparing whether the system call argument - // (after applying any bitmasks, if appropriate) equals |rhs|. - friend BoolExpr operator==(const Arg& lhs, T rhs) { return lhs.EqualTo(rhs); } - - // Returns a boolean expression comparing whether the system call argument - // (after applying any bitmasks, if appropriate) does not equal |rhs|. - friend BoolExpr operator!=(const Arg& lhs, T rhs) { return Not(lhs == rhs); } - - private: - Arg(int num, uint64_t mask) : num_(num), mask_(mask) {} - - BoolExpr EqualTo(T val) const; - - int num_; - uint64_t mask_; - - DISALLOW_ASSIGN(Arg); -}; - -// If begins a conditional result expression predicated on the -// specified boolean expression. -SANDBOX_EXPORT Elser If(const BoolExpr& cond, const ResultExpr& then_result); - -class SANDBOX_EXPORT Elser { - public: - Elser(const Elser& elser); - ~Elser(); - - // ElseIf extends the conditional result expression with another - // "if then" clause, predicated on the specified boolean expression. - Elser ElseIf(const BoolExpr& cond, const ResultExpr& then_result) const; - - // Else terminates a conditional result expression using |else_result| as - // the default fallback result expression. - ResultExpr Else(const ResultExpr& else_result) const; - - private: - typedef std::pair<BoolExpr, ResultExpr> Clause; - - explicit Elser(cons::List<Clause> clause_list); - - cons::List<Clause> clause_list_; - - friend Elser If(const BoolExpr&, const ResultExpr&); - template <typename T> - friend Caser<T> Switch(const Arg<T>&); - DISALLOW_ASSIGN(Elser); -}; - -// Switch begins a switch expression dispatched according to the -// specified argument value. -template <typename T> -SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg); - -template <typename T> -class SANDBOX_EXPORT Caser { - public: - Caser(const Caser<T>& caser) : arg_(caser.arg_), elser_(caser.elser_) {} - ~Caser() {} - - // Case adds a single-value "case" clause to the switch. - Caser<T> Case(T value, const ResultExpr& result) const; - - // Cases adds a multiple-value "case" clause to the switch. - // See also the SANDBOX_BPF_DSL_CASES macro below for a more idiomatic way - // of using this function. - template <typename... Values> - Caser<T> CasesImpl(const ResultExpr& result, const Values&... values) const; - - // Terminate the switch with a "default" clause. - ResultExpr Default(const ResultExpr& result) const; - - private: - Caser(const Arg<T>& arg, Elser elser) : arg_(arg), elser_(elser) {} - - Arg<T> arg_; - Elser elser_; - - template <typename U> - friend Caser<U> Switch(const Arg<U>&); - DISALLOW_ASSIGN(Caser); -}; - -// Recommended usage is to put -// #define CASES SANDBOX_BPF_DSL_CASES -// near the top of the .cc file (e.g., nearby any "using" statements), then -// use like: -// Switch(arg).CASES((3, 5, 7), result)...; -#define SANDBOX_BPF_DSL_CASES(values, result) \ - CasesImpl(result, SANDBOX_BPF_DSL_CASES_HELPER values) - -// Helper macro to strip parentheses. -#define SANDBOX_BPF_DSL_CASES_HELPER(...) __VA_ARGS__ - -// ===================================================================== -// Official API ends here. -// ===================================================================== - -namespace internal { - -// Make argument-dependent lookup work. This is necessary because although -// BoolExpr is defined in bpf_dsl, since it's merely a typedef for -// scoped_refptr<const internal::BoolExplImpl>, argument-dependent lookup only -// searches the "internal" nested namespace. -using bpf_dsl::Not; -using bpf_dsl::AllOf; -using bpf_dsl::AnyOf; - -// Returns a boolean expression that represents whether system call -// argument |num| of size |size| is equal to |val|, when masked -// according to |mask|. Users should use the Arg template class below -// instead of using this API directly. -SANDBOX_EXPORT BoolExpr - ArgEq(int num, size_t size, uint64_t mask, uint64_t val); - -// Returns the default mask for a system call argument of the specified size. -SANDBOX_EXPORT uint64_t DefaultMask(size_t size); - -} // namespace internal - -template <typename T> -Arg<T>::Arg(int num) - : num_(num), mask_(internal::DefaultMask(sizeof(T))) { -} - -// Definition requires ArgEq to have been declared. Moved out-of-line -// to minimize how much internal clutter users have to ignore while -// reading the header documentation. -// -// Additionally, we use this helper member function to avoid linker errors -// caused by defining operator== out-of-line. For a more detailed explanation, -// see http://www.parashift.com/c++-faq-lite/template-friends.html. -template <typename T> -BoolExpr Arg<T>::EqualTo(T val) const { - if (sizeof(T) == 4) { - // Prevent sign-extension of negative int32_t values. - return internal::ArgEq(num_, sizeof(T), mask_, static_cast<uint32_t>(val)); - } - return internal::ArgEq(num_, sizeof(T), mask_, static_cast<uint64_t>(val)); -} - -template <typename T> -SANDBOX_EXPORT Caser<T> Switch(const Arg<T>& arg) { - return Caser<T>(arg, Elser(nullptr)); -} - -template <typename T> -Caser<T> Caser<T>::Case(T value, const ResultExpr& result) const { - return SANDBOX_BPF_DSL_CASES((value), result); -} - -template <typename T> -template <typename... Values> -Caser<T> Caser<T>::CasesImpl(const ResultExpr& result, - const Values&... values) const { - // Theoretically we could evaluate arg_ just once and emit a more efficient - // dispatch table, but for now we simply translate into an equivalent - // If/ElseIf/Else chain. - - return Caser<T>(arg_, elser_.ElseIf(AnyOf((arg_ == values)...), result)); -} - -template <typename T> -ResultExpr Caser<T>::Default(const ResultExpr& result) const { - return elser_.Else(result); -} - -template <typename... Rest> -BoolExpr AllOf(const BoolExpr& first, const Rest&... rest) { - return AllOf(first, AllOf(rest...)); -} - -template <typename... Rest> -BoolExpr AnyOf(const BoolExpr& first, const Rest&... rest) { - return AnyOf(first, AnyOf(rest...)); -} - -} // namespace bpf_dsl -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_BPF_DSL_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl_forward.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl_forward.h deleted file mode 100644 index 183038990..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl_forward.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_BPF_DSL_FORWARD_H_ -#define SANDBOX_LINUX_BPF_DSL_BPF_DSL_FORWARD_H_ - -#include "base/memory/ref_counted.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { -namespace bpf_dsl { - -// The bpf_dsl_forward.h header provides forward declarations for the -// types defined in bpf_dsl.h. It's intended for use in user headers -// that need to reference bpf_dsl types, but don't require definitions. - -namespace internal { -class ResultExprImpl; -class BoolExprImpl; -} - -typedef scoped_refptr<const internal::ResultExprImpl> ResultExpr; -typedef scoped_refptr<const internal::BoolExprImpl> BoolExpr; - -template <typename T> -class Arg; - -class Elser; - -template <typename T> -class Caser; - -} // namespace bpf_dsl -} // namespace sandbox - -extern template class SANDBOX_EXPORT - scoped_refptr<const sandbox::bpf_dsl::internal::BoolExprImpl>; -extern template class SANDBOX_EXPORT - scoped_refptr<const sandbox::bpf_dsl::internal::ResultExprImpl>; - -#endif // SANDBOX_LINUX_BPF_DSL_BPF_DSL_FORWARD_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl_impl.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl_impl.h deleted file mode 100644 index 0064f8a7a..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/bpf_dsl_impl.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_BPF_DSL_IMPL_H_ -#define SANDBOX_LINUX_BPF_DSL_BPF_DSL_IMPL_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "sandbox/linux/bpf_dsl/codegen.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { -namespace bpf_dsl { -class ErrorCode; -class PolicyCompiler; - -namespace internal { - -// Internal interface implemented by BoolExpr implementations. -class BoolExprImpl : public base::RefCounted<BoolExprImpl> { - public: - // Compile uses |pc| to emit a CodeGen::Node that conditionally continues - // to either |then_node| or |false_node|, depending on whether the represented - // boolean expression is true or false. - virtual CodeGen::Node Compile(PolicyCompiler* pc, - CodeGen::Node then_node, - CodeGen::Node else_node) const = 0; - - protected: - BoolExprImpl() {} - virtual ~BoolExprImpl() {} - - private: - friend class base::RefCounted<BoolExprImpl>; - DISALLOW_COPY_AND_ASSIGN(BoolExprImpl); -}; - -// Internal interface implemented by ResultExpr implementations. -class ResultExprImpl : public base::RefCounted<ResultExprImpl> { - public: - // Compile uses |pc| to emit a CodeGen::Node that executes the - // represented result expression. - virtual CodeGen::Node Compile(PolicyCompiler* pc) const = 0; - - // HasUnsafeTraps returns whether the result expression is or recursively - // contains an unsafe trap expression. - virtual bool HasUnsafeTraps() const; - - // IsAllow returns whether the result expression is an "allow" result. - virtual bool IsAllow() const; - - // IsAllow returns whether the result expression is a "deny" result. - virtual bool IsDeny() const; - - protected: - ResultExprImpl() {} - virtual ~ResultExprImpl() {} - - private: - friend class base::RefCounted<ResultExprImpl>; - DISALLOW_COPY_AND_ASSIGN(ResultExprImpl); -}; - -} // namespace internal -} // namespace bpf_dsl -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_BPF_DSL_IMPL_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/codegen.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/codegen.cc deleted file mode 100644 index 647f55aa8..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/codegen.cc +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/bpf_dsl/codegen.h" - -#include <stddef.h> -#include <stdint.h> - -#include <limits> -#include <utility> - -#include "base/logging.h" -#include "sandbox/linux/system_headers/linux_filter.h" - -// This CodeGen implementation strives for simplicity while still -// generating acceptable BPF programs under typical usage patterns -// (e.g., by PolicyCompiler). -// -// The key to its simplicity is that BPF programs only support forward -// jumps/branches, which allows constraining the DAG construction API -// to make instruction nodes immutable. Immutable nodes admits a -// simple greedy approach of emitting new instructions as needed and -// then reusing existing ones that have already been emitted. This -// cleanly avoids any need to compute basic blocks or apply -// topological sorting because the API effectively sorts instructions -// for us (e.g., before MakeInstruction() can be called to emit a -// branch instruction, it must have already been called for each -// branch path). -// -// This greedy algorithm is not without (theoretical) weakness though: -// -// 1. In the general case, we don't eliminate dead code. If needed, -// we could trace back through the program in Compile() and elide -// any unneeded instructions, but in practice we only emit live -// instructions anyway. -// -// 2. By not dividing instructions into basic blocks and sorting, we -// lose an opportunity to move non-branch/non-return instructions -// adjacent to their successor instructions, which means we might -// need to emit additional jumps. But in practice, they'll -// already be nearby as long as callers don't go out of their way -// to interleave MakeInstruction() calls for unrelated code -// sequences. - -namespace sandbox { - -// kBranchRange is the maximum value that can be stored in -// sock_filter's 8-bit jt and jf fields. -const size_t kBranchRange = std::numeric_limits<uint8_t>::max(); - -const CodeGen::Node CodeGen::kNullNode; - -CodeGen::CodeGen() : program_(), equivalent_(), memos_() { -} - -CodeGen::~CodeGen() { -} - -CodeGen::Program CodeGen::Compile(CodeGen::Node head) { - return Program(program_.rbegin() + Offset(head), program_.rend()); -} - -CodeGen::Node CodeGen::MakeInstruction(uint16_t code, - uint32_t k, - Node jt, - Node jf) { - // To avoid generating redundant code sequences, we memoize the - // results from AppendInstruction(). - auto res = memos_.insert(std::make_pair(MemoKey(code, k, jt, jf), kNullNode)); - CodeGen::Node* node = &res.first->second; - if (res.second) { // Newly inserted memo entry. - *node = AppendInstruction(code, k, jt, jf); - } - return *node; -} - -CodeGen::Node CodeGen::AppendInstruction(uint16_t code, - uint32_t k, - Node jt, - Node jf) { - if (BPF_CLASS(code) == BPF_JMP) { - CHECK_NE(BPF_JA, BPF_OP(code)) << "CodeGen inserts JAs as needed"; - - // Optimally adding jumps is rather tricky, so we use a quick - // approximation: by artificially reducing |jt|'s range, |jt| will - // stay within its true range even if we add a jump for |jf|. - jt = WithinRange(jt, kBranchRange - 1); - jf = WithinRange(jf, kBranchRange); - return Append(code, k, Offset(jt), Offset(jf)); - } - - CHECK_EQ(kNullNode, jf) << "Non-branch instructions shouldn't provide jf"; - if (BPF_CLASS(code) == BPF_RET) { - CHECK_EQ(kNullNode, jt) << "Return instructions shouldn't provide jt"; - } else { - // For non-branch/non-return instructions, execution always - // proceeds to the next instruction; so we need to arrange for - // that to be |jt|. - jt = WithinRange(jt, 0); - CHECK_EQ(0U, Offset(jt)) << "ICE: Failed to setup next instruction"; - } - return Append(code, k, 0, 0); -} - -CodeGen::Node CodeGen::WithinRange(Node target, size_t range) { - // Just use |target| if it's already within range. - if (Offset(target) <= range) { - return target; - } - - // Alternatively, look for an equivalent instruction within range. - if (Offset(equivalent_.at(target)) <= range) { - return equivalent_.at(target); - } - - // Otherwise, fall back to emitting a jump instruction. - Node jump = Append(BPF_JMP | BPF_JA, Offset(target), 0, 0); - equivalent_.at(target) = jump; - return jump; -} - -CodeGen::Node CodeGen::Append(uint16_t code, uint32_t k, size_t jt, size_t jf) { - if (BPF_CLASS(code) == BPF_JMP && BPF_OP(code) != BPF_JA) { - CHECK_LE(jt, kBranchRange); - CHECK_LE(jf, kBranchRange); - } else { - CHECK_EQ(0U, jt); - CHECK_EQ(0U, jf); - } - - CHECK_LT(program_.size(), static_cast<size_t>(BPF_MAXINSNS)); - CHECK_EQ(program_.size(), equivalent_.size()); - - Node res = program_.size(); - program_.push_back(sock_filter{ - code, static_cast<uint8_t>(jt), static_cast<uint8_t>(jf), k}); - equivalent_.push_back(res); - return res; -} - -size_t CodeGen::Offset(Node target) const { - CHECK_LT(target, program_.size()) << "Bogus offset target node"; - return (program_.size() - 1) - target; -} - -// TODO(mdempsky): Move into a general base::Tuple helper library. -bool CodeGen::MemoKeyLess::operator()(const MemoKey& lhs, - const MemoKey& rhs) const { - if (base::get<0>(lhs) != base::get<0>(rhs)) - return base::get<0>(lhs) < base::get<0>(rhs); - if (base::get<1>(lhs) != base::get<1>(rhs)) - return base::get<1>(lhs) < base::get<1>(rhs); - if (base::get<2>(lhs) != base::get<2>(rhs)) - return base::get<2>(lhs) < base::get<2>(rhs); - if (base::get<3>(lhs) != base::get<3>(rhs)) - return base::get<3>(lhs) < base::get<3>(rhs); - return false; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/codegen.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/codegen.h deleted file mode 100644 index 03c3b236e..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/codegen.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_CODEGEN_H__ -#define SANDBOX_LINUX_BPF_DSL_CODEGEN_H__ - -#include <stddef.h> -#include <stdint.h> - -#include <map> -#include <vector> - -#include "base/macros.h" -#include "base/tuple.h" -#include "sandbox/sandbox_export.h" - -struct sock_filter; - -namespace sandbox { - -// The code generator implements a basic assembler that can convert a -// graph of BPF instructions into a well-formed array of BPF -// instructions. Most notably, it ensures that jumps are always -// forward and don't exceed the limit of 255 instructions imposed by -// the instruction set. -// -// Callers would typically create a new CodeGen object and then use it -// to build a DAG of instruction nodes. They'll eventually call -// Compile() to convert this DAG to a Program. -// -// CodeGen gen; -// CodeGen::Node allow, branch, dag; -// -// allow = -// gen.MakeInstruction(BPF_RET+BPF_K, -// ErrorCode(ErrorCode::ERR_ALLOWED).err())); -// branch = -// gen.MakeInstruction(BPF_JMP+BPF_EQ+BPF_K, __NR_getpid, -// Trap(GetPidHandler, NULL), allow); -// dag = -// gen.MakeInstruction(BPF_LD+BPF_W+BPF_ABS, -// offsetof(struct arch_seccomp_data, nr), branch); -// -// // Simplified code follows; in practice, it is important to avoid calling -// // any C++ destructors after starting the sandbox. -// CodeGen::Program program = gen.Compile(dag); -// const struct sock_fprog prog = { -// static_cast<unsigned short>(program.size()), &program[0] }; -// prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); -// -class SANDBOX_EXPORT CodeGen { - public: - // A vector of BPF instructions that need to be installed as a filter - // program in the kernel. - typedef std::vector<struct sock_filter> Program; - - // Node represents a node within the instruction DAG being compiled. - using Node = Program::size_type; - - // kNullNode represents the "null" node; i.e., the reserved node - // value guaranteed to not equal any actual nodes. - static const Node kNullNode = -1; - - CodeGen(); - ~CodeGen(); - - // MakeInstruction creates a node representing the specified - // instruction, or returns and existing equivalent node if one - // exists. For details on the possible parameters refer to - // https://www.kernel.org/doc/Documentation/networking/filter.txt. - // TODO(mdempsky): Reconsider using default arguments here. - Node MakeInstruction(uint16_t code, - uint32_t k, - Node jt = kNullNode, - Node jf = kNullNode); - - // Compile linearizes the instruction DAG rooted at |head| into a - // program that can be executed by a BPF virtual machine. - Program Compile(Node head); - - private: - using MemoKey = base::Tuple<uint16_t, uint32_t, Node, Node>; - struct MemoKeyLess { - bool operator()(const MemoKey& lhs, const MemoKey& rhs) const; - }; - - // AppendInstruction adds a new instruction, ensuring that |jt| and - // |jf| are within range as necessary for |code|. - Node AppendInstruction(uint16_t code, uint32_t k, Node jt, Node jf); - - // WithinRange returns a node equivalent to |next| that is at most - // |range| instructions away from the (logical) beginning of the - // program. - Node WithinRange(Node next, size_t range); - - // Append appends a new instruction to the physical end (i.e., - // logical beginning) of |program_|. - Node Append(uint16_t code, uint32_t k, size_t jt, size_t jf); - - // Offset returns how many instructions exist in |program_| after |target|. - size_t Offset(Node target) const; - - // NOTE: program_ is the compiled program in *reverse*, so that - // indices remain stable as we add instructions. - Program program_; - - // equivalent_ stores the most recent semantically-equivalent node for each - // instruction in program_. A node is defined as semantically-equivalent to N - // if it has the same instruction code and constant as N and its successor - // nodes (if any) are semantically-equivalent to N's successor nodes, or - // if it's an unconditional jump to a node semantically-equivalent to N. - std::vector<Node> equivalent_; - - std::map<MemoKey, Node, MemoKeyLess> memos_; - - DISALLOW_COPY_AND_ASSIGN(CodeGen); -}; - -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_CODEGEN_H__ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/cons.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/cons.h deleted file mode 100644 index be050f778..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/cons.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_CONS_H_ -#define SANDBOX_LINUX_BPF_DSL_CONS_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { -namespace cons { - -// Namespace cons provides an abstraction for immutable "cons list" -// data structures as commonly provided in functional programming -// languages like Lisp or Haskell. -// -// A cons list is a linked list consisting of "cells", each of which -// have a "head" and a "tail" element. A cell's head element contains -// a user specified value, while the tail element contains a (possibly -// null) pointer to another cell. -// -// An empty list (idiomatically referred to as "nil") can be -// constructed as "cons::List<Foo>()" or simply as "nullptr" if Foo -// can be inferred from context (e.g., calling a function that has a -// "cons::List<Foo>" parameter). -// -// Existing lists (including empty lists) can be extended by -// prepending new values to the front using the "Cons(head, tail)" -// function, which will allocate a new cons cell. Notably, cons lists -// support creating multiple lists that share a common tail sequence. -// -// Lastly, lists support iteration via C++11's range-based for loop -// construct. -// -// Examples: -// -// // basic construction -// const cons::List<char> kNil = nullptr; -// cons::List<char> ba = Cons('b', Cons('a', kNil)); -// -// // common tail sequence -// cons::List<char> cba = Cons('c', ba); -// cons::List<char> dba = Cons('d', ba); -// -// // iteration -// for (const char& ch : cba) { -// // iterates 'c', 'b', 'a' -// } -// for (const char& ch : dba) { -// // iterates 'd', 'b', 'a' -// } - -// Forward declarations. -template <typename T> -class Cell; -template <typename T> -class ListIterator; - -// List represents a (possibly null) pointer to a cons cell. -template <typename T> -using List = scoped_refptr<const Cell<T>>; - -// Cons extends a cons list by prepending a new value to the front. -template <typename T> -List<T> Cons(const T& head, const List<T>& tail) { - return List<T>(new const Cell<T>(head, tail)); -} - -// Cell represents an individual "cons cell" within a cons list. -template <typename T> -class Cell : public base::RefCounted<Cell<T>> { - public: - Cell(const T& head, const List<T>& tail) : head_(head), tail_(tail) {} - - // Head returns this cell's head element. - const T& head() const { return head_; } - - // Tail returns this cell's tail element. - const List<T>& tail() const { return tail_; } - - private: - virtual ~Cell() {} - - T head_; - List<T> tail_; - - friend class base::RefCounted<Cell<T>>; - DISALLOW_COPY_AND_ASSIGN(Cell); -}; - -// Begin returns a list iterator pointing to the first element of the -// cons list. It's provided to support range-based for loops. -template <typename T> -ListIterator<T> begin(const List<T>& list) { - return ListIterator<T>(list); -} - -// End returns a list iterator pointing to the "past-the-end" element -// of the cons list (i.e., nil). It's provided to support range-based -// for loops. -template <typename T> -ListIterator<T> end(const List<T>& list) { - return ListIterator<T>(); -} - -// ListIterator provides C++ forward iterator semantics for traversing -// a cons list. -template <typename T> -class ListIterator { - public: - ListIterator() : list_() {} - explicit ListIterator(const List<T>& list) : list_(list) {} - - const T& operator*() const { return list_->head(); } - - ListIterator& operator++() { - list_ = list_->tail(); - return *this; - } - - friend bool operator==(const ListIterator& lhs, const ListIterator& rhs) { - return lhs.list_ == rhs.list_; - } - - private: - List<T> list_; -}; - -template <typename T> -bool operator!=(const ListIterator<T>& lhs, const ListIterator<T>& rhs) { - return !(lhs == rhs); -} - -} // namespace cons -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_CONS_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.cc deleted file mode 100644 index 2edf592f6..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.cc +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/bpf_dsl/dump_bpf.h" - -#include <inttypes.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> - -#include <string> - -#include "base/strings/stringprintf.h" -#include "sandbox/linux/bpf_dsl/codegen.h" -#include "sandbox/linux/bpf_dsl/seccomp_macros.h" -#include "sandbox/linux/bpf_dsl/trap_registry.h" -#include "sandbox/linux/system_headers/linux_filter.h" -#include "sandbox/linux/system_headers/linux_seccomp.h" - -namespace sandbox { -namespace bpf_dsl { - -namespace { - -const char* AluOpToken(uint32_t code) { - switch (BPF_OP(code)) { - case BPF_ADD: - return "+"; - case BPF_SUB: - return "-"; - case BPF_MUL: - return "*"; - case BPF_DIV: - return "/"; - case BPF_MOD: - return "%"; - case BPF_OR: - return "|"; - case BPF_XOR: - return "^"; - case BPF_AND: - return "&"; - case BPF_LSH: - return "<<"; - case BPF_RSH: - return ">>"; - default: - return "???"; - } -} - -const char* JmpOpToken(uint32_t code) { - switch (BPF_OP(code)) { - case BPF_JSET: - return "&"; - case BPF_JEQ: - return "=="; - case BPF_JGE: - return ">="; - default: - return "???"; - } -} - -const char* DataOffsetName(size_t off) { - switch (off) { - case SECCOMP_NR_IDX: - return "System call number"; - case SECCOMP_ARCH_IDX: - return "Architecture"; - case SECCOMP_IP_LSB_IDX: - return "Instruction pointer (LSB)"; - case SECCOMP_IP_MSB_IDX: - return "Instruction pointer (MSB)"; - default: - return "???"; - } -} - -void AppendInstruction(std::string* dst, size_t pc, const sock_filter& insn) { - base::StringAppendF(dst, "%3zu) ", pc); - switch (BPF_CLASS(insn.code)) { - case BPF_LD: - if (insn.code == BPF_LD + BPF_W + BPF_ABS) { - base::StringAppendF(dst, "LOAD %" PRIu32 " // ", insn.k); - size_t maybe_argno = - (insn.k - offsetof(struct arch_seccomp_data, args)) / - sizeof(uint64_t); - if (maybe_argno < 6 && insn.k == SECCOMP_ARG_LSB_IDX(maybe_argno)) { - base::StringAppendF(dst, "Argument %zu (LSB)\n", maybe_argno); - } else if (maybe_argno < 6 && - insn.k == SECCOMP_ARG_MSB_IDX(maybe_argno)) { - base::StringAppendF(dst, "Argument %zu (MSB)\n", maybe_argno); - } else { - base::StringAppendF(dst, "%s\n", DataOffsetName(insn.k)); - } - } else { - base::StringAppendF(dst, "Load ???\n"); - } - break; - case BPF_JMP: - if (BPF_OP(insn.code) == BPF_JA) { - base::StringAppendF(dst, "JMP %zu\n", pc + insn.k + 1); - } else { - base::StringAppendF( - dst, "if A %s 0x%" PRIx32 "; then JMP %zu else JMP %zu\n", - JmpOpToken(insn.code), insn.k, pc + insn.jt + 1, pc + insn.jf + 1); - } - break; - case BPF_RET: - base::StringAppendF(dst, "RET 0x%" PRIx32 " // ", insn.k); - if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP) { - base::StringAppendF(dst, "Trap #%" PRIu32 "\n", - insn.k & SECCOMP_RET_DATA); - } else if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { - base::StringAppendF(dst, "errno = %" PRIu32 "\n", - insn.k & SECCOMP_RET_DATA); - } else if ((insn.k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRACE) { - base::StringAppendF(dst, "Trace #%" PRIu32 "\n", - insn.k & SECCOMP_RET_DATA); - } else if (insn.k == SECCOMP_RET_ALLOW) { - base::StringAppendF(dst, "Allowed\n"); - } else if (insn.k == SECCOMP_RET_KILL) { - base::StringAppendF(dst, "Kill\n"); - } else { - base::StringAppendF(dst, "???\n"); - } - break; - case BPF_ALU: - if (BPF_OP(insn.code) == BPF_NEG) { - base::StringAppendF(dst, "A := -A\n"); - } else { - base::StringAppendF(dst, "A := A %s 0x%" PRIx32 "\n", - AluOpToken(insn.code), insn.k); - } - break; - default: - base::StringAppendF(dst, "???\n"); - break; - } -} - -} // namespace - -void DumpBPF::PrintProgram(const CodeGen::Program& program) { - fputs(StringPrintProgram(program).c_str(), stderr); -} - -std::string DumpBPF::StringPrintProgram(const CodeGen::Program& program) { - std::string res; - for (size_t i = 0; i < program.size(); i++) { - AppendInstruction(&res, i + 1, program[i]); - } - return res; -} - -} // namespace bpf_dsl -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.h deleted file mode 100644 index a7db58981..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/dump_bpf.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> - -#include "sandbox/linux/bpf_dsl/codegen.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { -namespace bpf_dsl { - -class SANDBOX_EXPORT DumpBPF { - public: - // PrintProgram writes |program| in a human-readable format to stderr. - static void PrintProgram(const CodeGen::Program& program); - - // StringPrintProgram writes |program| in a human-readable format to - // a std::string. - static std::string StringPrintProgram(const CodeGen::Program& program); -}; - -} // namespace bpf_dsl -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/errorcode.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/errorcode.h deleted file mode 100644 index 611c27dd8..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/errorcode.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_ERRORCODE_H__ -#define SANDBOX_LINUX_BPF_DSL_ERRORCODE_H__ - -#include "base/macros.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { -namespace bpf_dsl { - -// TODO(mdempsky): Find a proper home for ERR_{MIN,MAX}_ERRNO and -// remove this header. -class SANDBOX_EXPORT ErrorCode { - public: - enum { - ERR_MIN_ERRNO = 0, -#if defined(__mips__) - // MIPS only supports errno up to 1133 - ERR_MAX_ERRNO = 1133, -#else - // TODO(markus): Android only supports errno up to 255 - // (crbug.com/181647). - ERR_MAX_ERRNO = 4095, -#endif - }; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(ErrorCode); -}; - -} // namespace bpf_dsl -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_ERRORCODE_H__ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h deleted file mode 100644 index a747770c7..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/linux_syscall_ranges.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_ -#define SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_ - -#if defined(__x86_64__) - -#define MIN_SYSCALL 0u -#define MAX_PUBLIC_SYSCALL 1024u -#define MAX_SYSCALL MAX_PUBLIC_SYSCALL - -#elif defined(__i386__) - -#define MIN_SYSCALL 0u -#define MAX_PUBLIC_SYSCALL 1024u -#define MAX_SYSCALL MAX_PUBLIC_SYSCALL - -#elif defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)) - -// ARM EABI includes "ARM private" system calls starting at |__ARM_NR_BASE|, -// and a "ghost syscall private to the kernel", cmpxchg, -// at |__ARM_NR_BASE+0x00fff0|. -// See </arch/arm/include/asm/unistd.h> in the Linux kernel. - -// __NR_SYSCALL_BASE is 0 in thumb and ARM EABI. -#define MIN_SYSCALL 0u -#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u) -// __ARM_NR_BASE is __NR_SYSCALL_BASE + 0xf0000u -#define MIN_PRIVATE_SYSCALL 0xf0000u -#define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u) -#define MIN_GHOST_SYSCALL (MIN_PRIVATE_SYSCALL + 0xfff0u) -#define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u) - -#elif defined(__mips__) && (_MIPS_SIM == _ABIO32) - -#include <asm/unistd.h> // for __NR_O32_Linux and __NR_Linux_syscalls -#define MIN_SYSCALL __NR_O32_Linux -#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + __NR_Linux_syscalls) -#define MAX_SYSCALL MAX_PUBLIC_SYSCALL - -#elif defined(__mips__) && (_MIPS_SIM == _ABI64) - -#error "Add support to header file" - -#elif defined(__aarch64__) - -#define MIN_SYSCALL 0u -#define MAX_PUBLIC_SYSCALL 279u -#define MAX_SYSCALL MAX_PUBLIC_SYSCALL - -#else -#error "Unsupported architecture" -#endif - -#endif // SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy.cc deleted file mode 100644 index c20edc6da..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/bpf_dsl/policy.h" - -#include <errno.h> - -#include "sandbox/linux/bpf_dsl/bpf_dsl.h" - -namespace sandbox { -namespace bpf_dsl { - -ResultExpr Policy::InvalidSyscall() const { - return Error(ENOSYS); -} - -} // namespace bpf_dsl -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy.h deleted file mode 100644 index 6c6758945..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_POLICY_H_ -#define SANDBOX_LINUX_BPF_DSL_POLICY_H_ - -#include "base/macros.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { -namespace bpf_dsl { - -// Interface to implement to define a BPF sandbox policy. -class SANDBOX_EXPORT Policy { - public: - Policy() {} - virtual ~Policy() {} - - // User extension point for writing custom sandbox policies. - // The returned ResultExpr will control how the kernel responds to the - // specified system call number. - virtual ResultExpr EvaluateSyscall(int sysno) const = 0; - - // Optional overload for specifying alternate behavior for invalid - // system calls. The default is to return ENOSYS. - virtual ResultExpr InvalidSyscall() const; - - private: - DISALLOW_COPY_AND_ASSIGN(Policy); -}; - -} // namespace bpf_dsl -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_POLICY_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc deleted file mode 100644 index 7ce517a5d..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/bpf_dsl/policy_compiler.h" - -#include <errno.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/syscall.h> - -#include <limits> - -#include "base/logging.h" -#include "base/macros.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" -#include "sandbox/linux/bpf_dsl/codegen.h" -#include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/bpf_dsl/seccomp_macros.h" -#include "sandbox/linux/bpf_dsl/syscall_set.h" -#include "sandbox/linux/system_headers/linux_filter.h" -#include "sandbox/linux/system_headers/linux_seccomp.h" -#include "sandbox/linux/system_headers/linux_syscalls.h" - -namespace sandbox { -namespace bpf_dsl { - -namespace { - -#if defined(__i386__) || defined(__x86_64__) -const bool kIsIntel = true; -#else -const bool kIsIntel = false; -#endif -#if defined(__x86_64__) && defined(__ILP32__) -const bool kIsX32 = true; -#else -const bool kIsX32 = false; -#endif - -const int kSyscallsRequiredForUnsafeTraps[] = { - __NR_rt_sigprocmask, - __NR_rt_sigreturn, -#if defined(__NR_sigprocmask) - __NR_sigprocmask, -#endif -#if defined(__NR_sigreturn) - __NR_sigreturn, -#endif -}; - -bool HasExactlyOneBit(uint64_t x) { - // Common trick; e.g., see http://stackoverflow.com/a/108329. - return x != 0 && (x & (x - 1)) == 0; -} - -ResultExpr DefaultPanic(const char* error) { - return Kill(); -} - -// A Trap() handler that returns an "errno" value. The value is encoded -// in the "aux" parameter. -intptr_t ReturnErrno(const struct arch_seccomp_data&, void* aux) { - // TrapFnc functions report error by following the native kernel convention - // of returning an exit code in the range of -1..-4096. They do not try to - // set errno themselves. The glibc wrapper that triggered the SIGSYS will - // ultimately do so for us. - int err = reinterpret_cast<intptr_t>(aux) & SECCOMP_RET_DATA; - return -err; -} - -bool HasUnsafeTraps(const Policy* policy) { - DCHECK(policy); - for (uint32_t sysnum : SyscallSet::ValidOnly()) { - if (policy->EvaluateSyscall(sysnum)->HasUnsafeTraps()) { - return true; - } - } - return policy->InvalidSyscall()->HasUnsafeTraps(); -} - -} // namespace - -struct PolicyCompiler::Range { - uint32_t from; - CodeGen::Node node; -}; - -PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry) - : policy_(policy), - registry_(registry), - escapepc_(0), - panic_func_(DefaultPanic), - gen_(), - has_unsafe_traps_(HasUnsafeTraps(policy_)) { - DCHECK(policy); -} - -PolicyCompiler::~PolicyCompiler() { -} - -CodeGen::Program PolicyCompiler::Compile() { - CHECK(policy_->InvalidSyscall()->IsDeny()) - << "Policies should deny invalid system calls"; - - // If our BPF program has unsafe traps, enable support for them. - if (has_unsafe_traps_) { - CHECK_NE(0U, escapepc_) << "UnsafeTrap() requires a valid escape PC"; - - for (int sysnum : kSyscallsRequiredForUnsafeTraps) { - CHECK(policy_->EvaluateSyscall(sysnum)->IsAllow()) - << "Policies that use UnsafeTrap() must unconditionally allow all " - "required system calls"; - } - - CHECK(registry_->EnableUnsafeTraps()) - << "We'd rather die than enable unsafe traps"; - } - - // Assemble the BPF filter program. - return gen_.Compile(AssemblePolicy()); -} - -void PolicyCompiler::DangerousSetEscapePC(uint64_t escapepc) { - escapepc_ = escapepc; -} - -void PolicyCompiler::SetPanicFunc(PanicFunc panic_func) { - panic_func_ = panic_func; -} - -CodeGen::Node PolicyCompiler::AssemblePolicy() { - // A compiled policy consists of three logical parts: - // 1. Check that the "arch" field matches the expected architecture. - // 2. If the policy involves unsafe traps, check if the syscall was - // invoked by Syscall::Call, and then allow it unconditionally. - // 3. Check the system call number and jump to the appropriate compiled - // system call policy number. - return CheckArch(MaybeAddEscapeHatch(DispatchSyscall())); -} - -CodeGen::Node PolicyCompiler::CheckArch(CodeGen::Node passed) { - // If the architecture doesn't match SECCOMP_ARCH, disallow the - // system call. - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, SECCOMP_ARCH_IDX, - gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, SECCOMP_ARCH, passed, - CompileResult(panic_func_( - "Invalid audit architecture in BPF filter")))); -} - -CodeGen::Node PolicyCompiler::MaybeAddEscapeHatch(CodeGen::Node rest) { - // If no unsafe traps, then simply return |rest|. - if (!has_unsafe_traps_) { - return rest; - } - - // We already enabled unsafe traps in Compile, but enable them again to give - // the trap registry a second chance to complain before we add the backdoor. - CHECK(registry_->EnableUnsafeTraps()); - - // Allow system calls, if they originate from our magic return address. - const uint32_t lopc = static_cast<uint32_t>(escapepc_); - const uint32_t hipc = static_cast<uint32_t>(escapepc_ >> 32); - - // BPF cannot do native 64-bit comparisons, so we have to compare - // both 32-bit halves of the instruction pointer. If they match what - // we expect, we return ERR_ALLOWED. If either or both don't match, - // we continue evalutating the rest of the sandbox policy. - // - // For simplicity, we check the full 64-bit instruction pointer even - // on 32-bit architectures. - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_LSB_IDX, - gen_.MakeInstruction( - BPF_JMP + BPF_JEQ + BPF_K, lopc, - gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_MSB_IDX, - gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hipc, - CompileResult(Allow()), rest)), - rest)); -} - -CodeGen::Node PolicyCompiler::DispatchSyscall() { - // Evaluate all possible system calls and group their Nodes into - // ranges of identical codes. - Ranges ranges; - FindRanges(&ranges); - - // Compile the system call ranges to an optimized BPF jumptable - CodeGen::Node jumptable = AssembleJumpTable(ranges.begin(), ranges.end()); - - // Grab the system call number, so that we can check it and then - // execute the jump table. - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, SECCOMP_NR_IDX, CheckSyscallNumber(jumptable)); -} - -CodeGen::Node PolicyCompiler::CheckSyscallNumber(CodeGen::Node passed) { - if (kIsIntel) { - // On Intel architectures, verify that system call numbers are in the - // expected number range. - CodeGen::Node invalidX32 = - CompileResult(panic_func_("Illegal mixing of system call ABIs")); - if (kIsX32) { - // The newer x32 API always sets bit 30. - return gen_.MakeInstruction( - BPF_JMP + BPF_JSET + BPF_K, 0x40000000, passed, invalidX32); - } else { - // The older i386 and x86-64 APIs clear bit 30 on all system calls. - return gen_.MakeInstruction( - BPF_JMP + BPF_JSET + BPF_K, 0x40000000, invalidX32, passed); - } - } - - // TODO(mdempsky): Similar validation for other architectures? - return passed; -} - -void PolicyCompiler::FindRanges(Ranges* ranges) { - // Please note that "struct seccomp_data" defines system calls as a signed - // int32_t, but BPF instructions always operate on unsigned quantities. We - // deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL, - // and then verifying that the rest of the number range (both positive and - // negative) all return the same Node. - const CodeGen::Node invalid_node = CompileResult(policy_->InvalidSyscall()); - uint32_t old_sysnum = 0; - CodeGen::Node old_node = - SyscallSet::IsValid(old_sysnum) - ? CompileResult(policy_->EvaluateSyscall(old_sysnum)) - : invalid_node; - - for (uint32_t sysnum : SyscallSet::All()) { - CodeGen::Node node = - SyscallSet::IsValid(sysnum) - ? CompileResult(policy_->EvaluateSyscall(static_cast<int>(sysnum))) - : invalid_node; - // N.B., here we rely on CodeGen folding (i.e., returning the same - // node value for) identical code sequences, otherwise our jump - // table will blow up in size. - if (node != old_node) { - ranges->push_back(Range{old_sysnum, old_node}); - old_sysnum = sysnum; - old_node = node; - } - } - ranges->push_back(Range{old_sysnum, old_node}); -} - -CodeGen::Node PolicyCompiler::AssembleJumpTable(Ranges::const_iterator start, - Ranges::const_iterator stop) { - // We convert the list of system call ranges into jump table that performs - // a binary search over the ranges. - // As a sanity check, we need to have at least one distinct ranges for us - // to be able to build a jump table. - CHECK(start < stop) << "Invalid iterator range"; - const auto n = stop - start; - if (n == 1) { - // If we have narrowed things down to a single range object, we can - // return from the BPF filter program. - return start->node; - } - - // Pick the range object that is located at the mid point of our list. - // We compare our system call number against the lowest valid system call - // number in this range object. If our number is lower, it is outside of - // this range object. If it is greater or equal, it might be inside. - Ranges::const_iterator mid = start + n / 2; - - // Sub-divide the list of ranges and continue recursively. - CodeGen::Node jf = AssembleJumpTable(start, mid); - CodeGen::Node jt = AssembleJumpTable(mid, stop); - return gen_.MakeInstruction(BPF_JMP + BPF_JGE + BPF_K, mid->from, jt, jf); -} - -CodeGen::Node PolicyCompiler::CompileResult(const ResultExpr& res) { - return res->Compile(this); -} - -CodeGen::Node PolicyCompiler::MaskedEqual(int argno, - size_t width, - uint64_t mask, - uint64_t value, - CodeGen::Node passed, - CodeGen::Node failed) { - // Sanity check that arguments make sense. - CHECK(argno >= 0 && argno < 6) << "Invalid argument number " << argno; - CHECK(width == 4 || width == 8) << "Invalid argument width " << width; - CHECK_NE(0U, mask) << "Zero mask is invalid"; - CHECK_EQ(value, value & mask) << "Value contains masked out bits"; - if (sizeof(void*) == 4) { - CHECK_EQ(4U, width) << "Invalid width on 32-bit platform"; - } - if (width == 4) { - CHECK_EQ(0U, mask >> 32) << "Mask exceeds argument size"; - CHECK_EQ(0U, value >> 32) << "Value exceeds argument size"; - } - - // We want to emit code to check "(arg & mask) == value" where arg, mask, and - // value are 64-bit values, but the BPF machine is only 32-bit. We implement - // this by independently testing the upper and lower 32-bits and continuing to - // |passed| if both evaluate true, or to |failed| if either evaluate false. - return MaskedEqualHalf(argno, width, mask, value, ArgHalf::UPPER, - MaskedEqualHalf(argno, width, mask, value, - ArgHalf::LOWER, passed, failed), - failed); -} - -CodeGen::Node PolicyCompiler::MaskedEqualHalf(int argno, - size_t width, - uint64_t full_mask, - uint64_t full_value, - ArgHalf half, - CodeGen::Node passed, - CodeGen::Node failed) { - if (width == 4 && half == ArgHalf::UPPER) { - // Special logic for sanity checking the upper 32-bits of 32-bit system - // call arguments. - - // TODO(mdempsky): Compile Unexpected64bitArgument() just per program. - CodeGen::Node invalid_64bit = Unexpected64bitArgument(); - - const uint32_t upper = SECCOMP_ARG_MSB_IDX(argno); - const uint32_t lower = SECCOMP_ARG_LSB_IDX(argno); - - if (sizeof(void*) == 4) { - // On 32-bit platforms, the upper 32-bits should always be 0: - // LDW [upper] - // JEQ 0, passed, invalid - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, - upper, - gen_.MakeInstruction( - BPF_JMP + BPF_JEQ + BPF_K, 0, passed, invalid_64bit)); - } - - // On 64-bit platforms, the upper 32-bits may be 0 or ~0; but we only allow - // ~0 if the sign bit of the lower 32-bits is set too: - // LDW [upper] - // JEQ 0, passed, (next) - // JEQ ~0, (next), invalid - // LDW [lower] - // JSET (1<<31), passed, invalid - // - // TODO(mdempsky): The JSET instruction could perhaps jump to passed->next - // instead, as the first instruction of passed should be "LDW [lower]". - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, - upper, - gen_.MakeInstruction( - BPF_JMP + BPF_JEQ + BPF_K, - 0, - passed, - gen_.MakeInstruction( - BPF_JMP + BPF_JEQ + BPF_K, - std::numeric_limits<uint32_t>::max(), - gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, - lower, - gen_.MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, - 1U << 31, - passed, - invalid_64bit)), - invalid_64bit))); - } - - const uint32_t idx = (half == ArgHalf::UPPER) ? SECCOMP_ARG_MSB_IDX(argno) - : SECCOMP_ARG_LSB_IDX(argno); - const uint32_t mask = (half == ArgHalf::UPPER) ? full_mask >> 32 : full_mask; - const uint32_t value = - (half == ArgHalf::UPPER) ? full_value >> 32 : full_value; - - // Emit a suitable instruction sequence for (arg & mask) == value. - - // For (arg & 0) == 0, just return passed. - if (mask == 0) { - CHECK_EQ(0U, value); - return passed; - } - - // For (arg & ~0) == value, emit: - // LDW [idx] - // JEQ value, passed, failed - if (mask == std::numeric_limits<uint32_t>::max()) { - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, - idx, - gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed)); - } - - // For (arg & mask) == 0, emit: - // LDW [idx] - // JSET mask, failed, passed - // (Note: failed and passed are intentionally swapped.) - if (value == 0) { - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, - idx, - gen_.MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, mask, failed, passed)); - } - - // For (arg & x) == x where x is a single-bit value, emit: - // LDW [idx] - // JSET mask, passed, failed - if (mask == value && HasExactlyOneBit(mask)) { - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, - idx, - gen_.MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, mask, passed, failed)); - } - - // Generic fallback: - // LDW [idx] - // AND mask - // JEQ value, passed, failed - return gen_.MakeInstruction( - BPF_LD + BPF_W + BPF_ABS, - idx, - gen_.MakeInstruction( - BPF_ALU + BPF_AND + BPF_K, - mask, - gen_.MakeInstruction( - BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed))); -} - -CodeGen::Node PolicyCompiler::Unexpected64bitArgument() { - return CompileResult(panic_func_("Unexpected 64bit argument detected")); -} - -CodeGen::Node PolicyCompiler::Return(uint32_t ret) { - if (has_unsafe_traps_ && (ret & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { - // When inside an UnsafeTrap() callback, we want to allow all system calls. - // This means, we must conditionally disable the sandbox -- and that's not - // something that kernel-side BPF filters can do, as they cannot inspect - // any state other than the syscall arguments. - // But if we redirect all error handlers to user-space, then we can easily - // make this decision. - // The performance penalty for this extra round-trip to user-space is not - // actually that bad, as we only ever pay it for denied system calls; and a - // typical program has very few of these. - return Trap(ReturnErrno, reinterpret_cast<void*>(ret & SECCOMP_RET_DATA), - true); - } - - return gen_.MakeInstruction(BPF_RET + BPF_K, ret); -} - -CodeGen::Node PolicyCompiler::Trap(TrapRegistry::TrapFnc fnc, - const void* aux, - bool safe) { - uint16_t trap_id = registry_->Add(fnc, aux, safe); - return gen_.MakeInstruction(BPF_RET + BPF_K, SECCOMP_RET_TRAP + trap_id); -} - -bool PolicyCompiler::IsRequiredForUnsafeTrap(int sysno) { - for (size_t i = 0; i < arraysize(kSyscallsRequiredForUnsafeTraps); ++i) { - if (sysno == kSyscallsRequiredForUnsafeTraps[i]) { - return true; - } - } - return false; -} - -} // namespace bpf_dsl -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h deleted file mode 100644 index 48b1d780d..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_ -#define SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <vector> - -#include "base/macros.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h" -#include "sandbox/linux/bpf_dsl/codegen.h" -#include "sandbox/linux/bpf_dsl/trap_registry.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { -namespace bpf_dsl { -class Policy; - -// PolicyCompiler implements the bpf_dsl compiler, allowing users to -// transform bpf_dsl policies into BPF programs to be executed by the -// Linux kernel. -class SANDBOX_EXPORT PolicyCompiler { - public: - using PanicFunc = bpf_dsl::ResultExpr (*)(const char* error); - - PolicyCompiler(const Policy* policy, TrapRegistry* registry); - ~PolicyCompiler(); - - // Compile registers any trap handlers needed by the policy and - // compiles the policy to a BPF program, which it returns. - CodeGen::Program Compile(); - - // DangerousSetEscapePC sets the "escape PC" that is allowed to issue any - // system calls, regardless of policy. - void DangerousSetEscapePC(uint64_t escapepc); - - // SetPanicFunc sets the callback function used for handling faulty - // system call conditions. The default behavior is to immediately kill - // the process. - // TODO(mdempsky): Move this into Policy? - void SetPanicFunc(PanicFunc panic_func); - - // UnsafeTraps require some syscalls to always be allowed. - // This helper function returns true for these calls. - static bool IsRequiredForUnsafeTrap(int sysno); - - // Functions below are meant for use within bpf_dsl itself. - - // Return returns a CodeGen::Node that returns the specified seccomp - // return value. - CodeGen::Node Return(uint32_t ret); - - // Trap returns a CodeGen::Node to indicate the system call should - // instead invoke a trap handler. - CodeGen::Node Trap(TrapRegistry::TrapFnc fnc, const void* aux, bool safe); - - // MaskedEqual returns a CodeGen::Node that represents a conditional branch. - // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared - // to "value"; if equal, then "passed" will be executed, otherwise "failed". - // If "width" is 4, the argument must in the range of 0x0..(1u << 32 - 1) - // If it is outside this range, the sandbox treats the system call just - // the same as any other ABI violation (i.e., it panics). - CodeGen::Node MaskedEqual(int argno, - size_t width, - uint64_t mask, - uint64_t value, - CodeGen::Node passed, - CodeGen::Node failed); - - private: - struct Range; - typedef std::vector<Range> Ranges; - - // Used by MaskedEqualHalf to track which half of the argument it's - // emitting instructions for. - enum class ArgHalf { - LOWER, - UPPER, - }; - - // Compile the configured policy into a complete instruction sequence. - CodeGen::Node AssemblePolicy(); - - // Return an instruction sequence that checks the - // arch_seccomp_data's "arch" field is valid, and then passes - // control to |passed| if so. - CodeGen::Node CheckArch(CodeGen::Node passed); - - // If |has_unsafe_traps_| is true, returns an instruction sequence - // that allows all system calls from |escapepc_|, and otherwise - // passes control to |rest|. Otherwise, simply returns |rest|. - CodeGen::Node MaybeAddEscapeHatch(CodeGen::Node rest); - - // Return an instruction sequence that loads and checks the system - // call number, performs a binary search, and then dispatches to an - // appropriate instruction sequence compiled from the current - // policy. - CodeGen::Node DispatchSyscall(); - - // Return an instruction sequence that checks the system call number - // (expected to be loaded in register A) and if valid, passes - // control to |passed| (with register A still valid). - CodeGen::Node CheckSyscallNumber(CodeGen::Node passed); - - // Finds all the ranges of system calls that need to be handled. Ranges are - // sorted in ascending order of system call numbers. There are no gaps in the - // ranges. System calls with identical CodeGen::Nodes are coalesced into a - // single - // range. - void FindRanges(Ranges* ranges); - - // Returns a BPF program snippet that implements a jump table for the - // given range of system call numbers. This function runs recursively. - CodeGen::Node AssembleJumpTable(Ranges::const_iterator start, - Ranges::const_iterator stop); - - // CompileResult compiles an individual result expression into a - // CodeGen node. - CodeGen::Node CompileResult(const ResultExpr& res); - - // Returns a BPF program that evaluates half of a conditional expression; - // it should only ever be called from CondExpression(). - CodeGen::Node MaskedEqualHalf(int argno, - size_t width, - uint64_t full_mask, - uint64_t full_value, - ArgHalf half, - CodeGen::Node passed, - CodeGen::Node failed); - - // Returns the fatal CodeGen::Node that is used to indicate that somebody - // attempted to pass a 64bit value in a 32bit system call argument. - CodeGen::Node Unexpected64bitArgument(); - - const Policy* policy_; - TrapRegistry* registry_; - uint64_t escapepc_; - PanicFunc panic_func_; - - CodeGen gen_; - bool has_unsafe_traps_; - - DISALLOW_COPY_AND_ASSIGN(PolicyCompiler); -}; - -} // namespace bpf_dsl -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_POLICY_COMPILER_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/seccomp_macros.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/seccomp_macros.h deleted file mode 100644 index af70f21cd..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/seccomp_macros.h +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_ -#define SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_ - -#include <sys/types.h> // For __BIONIC__. -// Old Bionic versions do not have sys/user.h. The if can be removed once we no -// longer need to support these old Bionic versions. -// All x86_64 builds use a new enough bionic to have sys/user.h. -#if !defined(__BIONIC__) || defined(__x86_64__) -#if !defined(__native_client_nonsfi__) -#include <sys/user.h> -#endif -#if defined(__mips__) -// sys/user.h in eglibc misses size_t definition -#include <stddef.h> -#endif -#endif - -#include "sandbox/linux/system_headers/linux_seccomp.h" // For AUDIT_ARCH_* - -// Impose some reasonable maximum BPF program size. Realistically, the -// kernel probably has much lower limits. But by limiting to less than -// 30 bits, we can ease requirements on some of our data types. -#define SECCOMP_MAX_PROGRAM_SIZE (1<<30) - -#if defined(__i386__) -#define SECCOMP_ARCH AUDIT_ARCH_I386 - -#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)]) -#define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, REG_EAX) -#define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, REG_EAX) -#define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, REG_EIP) -#define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, REG_EBX) -#define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, REG_ECX) -#define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, REG_EDX) -#define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, REG_ESI) -#define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, REG_EDI) -#define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, REG_EBP) -#define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) -#define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) -#define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ - instruction_pointer) + 4) -#define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ - instruction_pointer) + 0) -#define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ - 8*(nr) + 4) -#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ - 8*(nr) + 0) - - -#if defined(__BIONIC__) || defined(__native_client_nonsfi__) -// Old Bionic versions and PNaCl toolchain don't have sys/user.h, so we just -// define regs_struct directly. This can be removed once we no longer need to -// support these old Bionic versions and PNaCl toolchain. -struct regs_struct { - long int ebx; - long int ecx; - long int edx; - long int esi; - long int edi; - long int ebp; - long int eax; - long int xds; - long int xes; - long int xfs; - long int xgs; - long int orig_eax; - long int eip; - long int xcs; - long int eflags; - long int esp; - long int xss; -}; -#else -typedef user_regs_struct regs_struct; -#endif - -#define SECCOMP_PT_RESULT(_regs) (_regs).eax -#define SECCOMP_PT_SYSCALL(_regs) (_regs).orig_eax -#define SECCOMP_PT_IP(_regs) (_regs).eip -#define SECCOMP_PT_PARM1(_regs) (_regs).ebx -#define SECCOMP_PT_PARM2(_regs) (_regs).ecx -#define SECCOMP_PT_PARM3(_regs) (_regs).edx -#define SECCOMP_PT_PARM4(_regs) (_regs).esi -#define SECCOMP_PT_PARM5(_regs) (_regs).edi -#define SECCOMP_PT_PARM6(_regs) (_regs).ebp - -#elif defined(__x86_64__) -#define SECCOMP_ARCH AUDIT_ARCH_X86_64 - -#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)]) -#define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, REG_RAX) -#define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, REG_RAX) -#define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, REG_RIP) -#define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, REG_RDI) -#define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, REG_RSI) -#define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, REG_RDX) -#define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, REG_R10) -#define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, REG_R8) -#define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, REG_R9) -#define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) -#define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) -#define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ - instruction_pointer) + 4) -#define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ - instruction_pointer) + 0) -#define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ - 8*(nr) + 4) -#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ - 8*(nr) + 0) - -typedef user_regs_struct regs_struct; -#define SECCOMP_PT_RESULT(_regs) (_regs).rax -#define SECCOMP_PT_SYSCALL(_regs) (_regs).orig_rax -#define SECCOMP_PT_IP(_regs) (_regs).rip -#define SECCOMP_PT_PARM1(_regs) (_regs).rdi -#define SECCOMP_PT_PARM2(_regs) (_regs).rsi -#define SECCOMP_PT_PARM3(_regs) (_regs).rdx -#define SECCOMP_PT_PARM4(_regs) (_regs).r10 -#define SECCOMP_PT_PARM5(_regs) (_regs).r8 -#define SECCOMP_PT_PARM6(_regs) (_regs).r9 - -#elif defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)) -#define SECCOMP_ARCH AUDIT_ARCH_ARM - -// ARM sigcontext_t is different from i386/x86_64. -// See </arch/arm/include/asm/sigcontext.h> in the Linux kernel. -#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.arm_##_reg) -// ARM EABI syscall convention. -#define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, r0) -#define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, r7) -#define SECCOMP_IP(_ctx) SECCOMP_REG(_ctx, pc) -#define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, r0) -#define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, r1) -#define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, r2) -#define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, r3) -#define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, r4) -#define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, r5) -#define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) -#define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) -#define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ - instruction_pointer) + 4) -#define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ - instruction_pointer) + 0) -#define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ - 8*(nr) + 4) -#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ - 8*(nr) + 0) - -#if defined(__BIONIC__) || defined(__native_client_nonsfi__) -// Old Bionic versions and PNaCl toolchain don't have sys/user.h, so we just -// define regs_struct directly. This can be removed once we no longer need to -// support these old Bionic versions and PNaCl toolchain. -struct regs_struct { - unsigned long uregs[18]; -}; -#else -typedef user_regs regs_struct; -#endif - -#define REG_cpsr uregs[16] -#define REG_pc uregs[15] -#define REG_lr uregs[14] -#define REG_sp uregs[13] -#define REG_ip uregs[12] -#define REG_fp uregs[11] -#define REG_r10 uregs[10] -#define REG_r9 uregs[9] -#define REG_r8 uregs[8] -#define REG_r7 uregs[7] -#define REG_r6 uregs[6] -#define REG_r5 uregs[5] -#define REG_r4 uregs[4] -#define REG_r3 uregs[3] -#define REG_r2 uregs[2] -#define REG_r1 uregs[1] -#define REG_r0 uregs[0] -#define REG_ORIG_r0 uregs[17] - -#define SECCOMP_PT_RESULT(_regs) (_regs).REG_r0 -#define SECCOMP_PT_SYSCALL(_regs) (_regs).REG_r7 -#define SECCOMP_PT_IP(_regs) (_regs).REG_pc -#define SECCOMP_PT_PARM1(_regs) (_regs).REG_r0 -#define SECCOMP_PT_PARM2(_regs) (_regs).REG_r1 -#define SECCOMP_PT_PARM3(_regs) (_regs).REG_r2 -#define SECCOMP_PT_PARM4(_regs) (_regs).REG_r3 -#define SECCOMP_PT_PARM5(_regs) (_regs).REG_r4 -#define SECCOMP_PT_PARM6(_regs) (_regs).REG_r5 - -#elif defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32) -#define SECCOMP_ARCH AUDIT_ARCH_MIPSEL -#define SYSCALL_EIGHT_ARGS -// MIPS sigcontext_t is different from i386/x86_64 and ARM. -// See </arch/mips/include/uapi/asm/sigcontext.h> in the Linux kernel. -#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[_reg]) -// Based on MIPS o32 ABI syscall convention. -// On MIPS, when indirect syscall is being made (syscall(__NR_foo)), -// real identificator (__NR_foo) is not in v0, but in a0 -#define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, 2) -#define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, 2) -#define SECCOMP_IP(_ctx) (_ctx)->uc_mcontext.pc -#define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, 4) -#define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, 5) -#define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, 6) -#define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, 7) -// Only the first 4 arguments of syscall are in registers. -// The rest are on the stack. -#define SECCOMP_STACKPARM(_ctx, n) (((long *)SECCOMP_REG(_ctx, 29))[(n)]) -#define SECCOMP_PARM5(_ctx) SECCOMP_STACKPARM(_ctx, 4) -#define SECCOMP_PARM6(_ctx) SECCOMP_STACKPARM(_ctx, 5) -#define SECCOMP_PARM7(_ctx) SECCOMP_STACKPARM(_ctx, 6) -#define SECCOMP_PARM8(_ctx) SECCOMP_STACKPARM(_ctx, 7) -#define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) -#define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) -#define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ - instruction_pointer) + 4) -#define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ - instruction_pointer) + 0) -#define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ - 8*(nr) + 4) -#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ - 8*(nr) + 0) - -// On Mips we don't have structures like user_regs or user_regs_struct in -// sys/user.h that we could use, so we just define regs_struct directly. -struct regs_struct { - unsigned long long regs[32]; -}; - -#define REG_a3 regs[7] -#define REG_a2 regs[6] -#define REG_a1 regs[5] -#define REG_a0 regs[4] -#define REG_v1 regs[3] -#define REG_v0 regs[2] - -#define SECCOMP_PT_RESULT(_regs) (_regs).REG_v0 -#define SECCOMP_PT_SYSCALL(_regs) (_regs).REG_v0 -#define SECCOMP_PT_PARM1(_regs) (_regs).REG_a0 -#define SECCOMP_PT_PARM2(_regs) (_regs).REG_a1 -#define SECCOMP_PT_PARM3(_regs) (_regs).REG_a2 -#define SECCOMP_PT_PARM4(_regs) (_regs).REG_a3 - -#elif defined(__aarch64__) -struct regs_struct { - unsigned long long regs[31]; - unsigned long long sp; - unsigned long long pc; - unsigned long long pstate; -}; - -#define SECCOMP_ARCH AUDIT_ARCH_AARCH64 - -#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.regs[_reg]) - -#define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, 0) -#define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, 8) -#define SECCOMP_IP(_ctx) (_ctx)->uc_mcontext.pc -#define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, 0) -#define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, 1) -#define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, 2) -#define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, 3) -#define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, 4) -#define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, 5) - -#define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) -#define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) -#define SECCOMP_IP_MSB_IDX \ - (offsetof(struct arch_seccomp_data, instruction_pointer) + 4) -#define SECCOMP_IP_LSB_IDX \ - (offsetof(struct arch_seccomp_data, instruction_pointer) + 0) -#define SECCOMP_ARG_MSB_IDX(nr) \ - (offsetof(struct arch_seccomp_data, args) + 8 * (nr) + 4) -#define SECCOMP_ARG_LSB_IDX(nr) \ - (offsetof(struct arch_seccomp_data, args) + 8 * (nr) + 0) - -#define SECCOMP_PT_RESULT(_regs) (_regs).regs[0] -#define SECCOMP_PT_SYSCALL(_regs) (_regs).regs[8] -#define SECCOMP_PT_IP(_regs) (_regs).pc -#define SECCOMP_PT_PARM1(_regs) (_regs).regs[0] -#define SECCOMP_PT_PARM2(_regs) (_regs).regs[1] -#define SECCOMP_PT_PARM3(_regs) (_regs).regs[2] -#define SECCOMP_PT_PARM4(_regs) (_regs).regs[3] -#define SECCOMP_PT_PARM5(_regs) (_regs).regs[4] -#define SECCOMP_PT_PARM6(_regs) (_regs).regs[5] -#else -#error Unsupported target platform - -#endif - -#endif // SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/syscall_set.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/syscall_set.cc deleted file mode 100644 index 3d61fa31f..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/syscall_set.cc +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/bpf_dsl/syscall_set.h" - -#include <stdint.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h" - -namespace sandbox { - -namespace { - -#if defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32) -// This is true for Mips O32 ABI. -static_assert(MIN_SYSCALL == __NR_Linux, "min syscall number should be 4000"); -#else -// This true for supported architectures (Intel and ARM EABI). -static_assert(MIN_SYSCALL == 0u, - "min syscall should always be zero"); -#endif - -// SyscallRange represents an inclusive range of system call numbers. -struct SyscallRange { - uint32_t first; - uint32_t last; -}; - -const SyscallRange kValidSyscallRanges[] = { - // First we iterate up to MAX_PUBLIC_SYSCALL, which is equal to MAX_SYSCALL - // on Intel architectures, but leaves room for private syscalls on ARM. - {MIN_SYSCALL, MAX_PUBLIC_SYSCALL}, -#if defined(__arm__) - // ARM EABI includes "ARM private" system calls starting at - // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at - // MIN_GHOST_SYSCALL. - {MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL}, - {MIN_GHOST_SYSCALL, MAX_SYSCALL}, -#endif -}; - -} // namespace - -SyscallSet::Iterator SyscallSet::begin() const { - return Iterator(set_, false); -} - -SyscallSet::Iterator SyscallSet::end() const { - return Iterator(set_, true); -} - -bool SyscallSet::IsValid(uint32_t num) { - for (const SyscallRange& range : kValidSyscallRanges) { - if (num >= range.first && num <= range.last) { - return true; - } - } - return false; -} - -bool operator==(const SyscallSet& lhs, const SyscallSet& rhs) { - return (lhs.set_ == rhs.set_); -} - -SyscallSet::Iterator::Iterator(Set set, bool done) - : set_(set), done_(done), num_(0) { - // If the set doesn't contain 0, we need to skip to the next element. - if (!done && set_ == (IsValid(num_) ? Set::INVALID_ONLY : Set::VALID_ONLY)) { - ++*this; - } -} - -uint32_t SyscallSet::Iterator::operator*() const { - DCHECK(!done_); - return num_; -} - -SyscallSet::Iterator& SyscallSet::Iterator::operator++() { - DCHECK(!done_); - - num_ = NextSyscall(); - if (num_ == 0) { - done_ = true; - } - - return *this; -} - -// NextSyscall returns the next system call in the iterated system -// call set after |num_|, or 0 if no such system call exists. -uint32_t SyscallSet::Iterator::NextSyscall() const { - const bool want_valid = (set_ != Set::INVALID_ONLY); - const bool want_invalid = (set_ != Set::VALID_ONLY); - - for (const SyscallRange& range : kValidSyscallRanges) { - if (want_invalid && range.first > 0 && num_ < range.first - 1) { - // Even when iterating invalid syscalls, we only include the end points; - // so skip directly to just before the next (valid) range. - return range.first - 1; - } - if (want_valid && num_ < range.first) { - return range.first; - } - if (want_valid && num_ < range.last) { - return num_ + 1; - } - if (want_invalid && num_ <= range.last) { - return range.last + 1; - } - } - - if (want_invalid) { - // BPF programs only ever operate on unsigned quantities. So, - // that's how we iterate; we return values from - // 0..0xFFFFFFFFu. But there are places, where the kernel might - // interpret system call numbers as signed quantities, so the - // boundaries between signed and unsigned values are potential - // problem cases. We want to explicitly return these values from - // our iterator. - if (num_ < 0x7FFFFFFFu) - return 0x7FFFFFFFu; - if (num_ < 0x80000000u) - return 0x80000000u; - - if (num_ < 0xFFFFFFFFu) - return 0xFFFFFFFFu; - } - - return 0; -} - -bool operator==(const SyscallSet::Iterator& lhs, - const SyscallSet::Iterator& rhs) { - DCHECK(lhs.set_ == rhs.set_); - return (lhs.done_ == rhs.done_) && (lhs.num_ == rhs.num_); -} - -bool operator!=(const SyscallSet::Iterator& lhs, - const SyscallSet::Iterator& rhs) { - return !(lhs == rhs); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/syscall_set.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/syscall_set.h deleted file mode 100644 index b9f076d93..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/syscall_set.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__ -#define SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__ - -#include <stdint.h> - -#include <iterator> - -#include "base/macros.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { - -// Iterates over the entire system call range from 0..0xFFFFFFFFu. This -// iterator is aware of how system calls look like and will skip quickly -// over ranges that can't contain system calls. It iterates more slowly -// whenever it reaches a range that is potentially problematic, returning -// the last invalid value before a valid range of system calls, and the -// first invalid value after a valid range of syscalls. It iterates over -// individual values whenever it is in the normal range for system calls -// (typically MIN_SYSCALL..MAX_SYSCALL). -// -// Example usage: -// for (uint32_t sysnum : SyscallSet::All()) { -// // Do something with sysnum. -// } -class SANDBOX_EXPORT SyscallSet { - public: - class Iterator; - - SyscallSet(const SyscallSet& ss) : set_(ss.set_) {} - ~SyscallSet() {} - - Iterator begin() const; - Iterator end() const; - - // All returns a SyscallSet that contains both valid and invalid - // system call numbers. - static SyscallSet All() { return SyscallSet(Set::ALL); } - - // ValidOnly returns a SyscallSet that contains only valid system - // call numbers. - static SyscallSet ValidOnly() { return SyscallSet(Set::VALID_ONLY); } - - // InvalidOnly returns a SyscallSet that contains only invalid - // system call numbers, but still omits numbers in the middle of a - // range of invalid system call numbers. - static SyscallSet InvalidOnly() { return SyscallSet(Set::INVALID_ONLY); } - - // IsValid returns whether |num| specifies a valid system call - // number. - static bool IsValid(uint32_t num); - - private: - enum class Set { ALL, VALID_ONLY, INVALID_ONLY }; - - explicit SyscallSet(Set set) : set_(set) {} - - Set set_; - - friend bool operator==(const SyscallSet&, const SyscallSet&); - DISALLOW_ASSIGN(SyscallSet); -}; - -SANDBOX_EXPORT bool operator==(const SyscallSet& lhs, const SyscallSet& rhs); - -// Iterator provides C++ input iterator semantics for traversing a -// SyscallSet. -class SyscallSet::Iterator - : public std::iterator<std::input_iterator_tag, uint32_t> { - public: - Iterator(const Iterator& it) - : set_(it.set_), done_(it.done_), num_(it.num_) {} - ~Iterator() {} - - uint32_t operator*() const; - Iterator& operator++(); - - private: - Iterator(Set set, bool done); - - uint32_t NextSyscall() const; - - Set set_; - bool done_; - uint32_t num_; - - friend SyscallSet; - friend bool operator==(const Iterator&, const Iterator&); - DISALLOW_ASSIGN(Iterator); -}; - -SANDBOX_EXPORT bool operator==(const SyscallSet::Iterator& lhs, - const SyscallSet::Iterator& rhs); -SANDBOX_EXPORT bool operator!=(const SyscallSet::Iterator& lhs, - const SyscallSet::Iterator& rhs); - -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_SYSCALL_SET_H__ diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/trap_registry.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/trap_registry.h deleted file mode 100644 index 0a5d2f14c..000000000 --- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/trap_registry.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_BPF_DSL_TRAP_REGISTRY_H_ -#define SANDBOX_LINUX_BPF_DSL_TRAP_REGISTRY_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { - -// This must match the kernel's seccomp_data structure. -struct arch_seccomp_data { - int nr; - uint32_t arch; - uint64_t instruction_pointer; - uint64_t args[6]; -}; - -namespace bpf_dsl { - -// TrapRegistry provides an interface for registering "trap handlers" -// by associating them with non-zero 16-bit trap IDs. Trap IDs should -// remain valid for the lifetime of the trap registry. -class SANDBOX_EXPORT TrapRegistry { - public: - // TrapFnc is a pointer to a function that fulfills the trap handler - // function signature. - // - // Trap handlers follow the calling convention of native system - // calls; e.g., to report an error, they return an exit code in the - // range -1..-4096 instead of directly modifying errno. However, - // modifying errno is harmless, as the original value will be - // restored afterwards. - // - // Trap handlers are executed from signal context and possibly an - // async-signal context, so they must be async-signal safe: - // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html - typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void* aux); - - // Add registers the specified trap handler tuple and returns a - // non-zero trap ID that uniquely identifies the tuple for the life - // time of the trap registry. If the same tuple is registered - // multiple times, the same value will be returned each time. - virtual uint16_t Add(TrapFnc fnc, const void* aux, bool safe) = 0; - - // EnableUnsafeTraps tries to enable unsafe traps and returns - // whether it was successful. This is a one-way operation. - // - // CAUTION: Enabling unsafe traps effectively defeats the security - // guarantees provided by the sandbox policy. TrapRegistry - // implementations should ensure unsafe traps are only enabled - // during testing. - virtual bool EnableUnsafeTraps() = 0; - - protected: - TrapRegistry() {} - - // TrapRegistry's destructor is intentionally non-virtual so that - // implementations can omit their destructor. Instead we protect against - // misuse by marking it protected. - ~TrapRegistry() {} - - DISALLOW_COPY_AND_ASSIGN(TrapRegistry); -}; - -} // namespace bpf_dsl -} // namespace sandbox - -#endif // SANDBOX_LINUX_BPF_DSL_TRAP_REGISTRY_H_ diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h deleted file mode 100644 index 00d415c3f..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_ -#define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h" - -namespace sandbox { - -// This templated class allows building a BPFTesterDelegate from a -// deprecated-style BPF policy (that is a SyscallEvaluator function pointer, -// instead of a SandboxBPFPolicy class), specified in |policy_function| and a -// function pointer to a test in |test_function|. -// This allows both the policy and the test function to take a pointer to an -// object of type "Aux" as a parameter. This is used to implement the BPF_TEST -// macro and should generally not be used directly. -template <class Policy, class Aux> -class BPFTesterCompatibilityDelegate : public BPFTesterDelegate { - public: - typedef void (*TestFunction)(Aux*); - - explicit BPFTesterCompatibilityDelegate(TestFunction test_function) - : aux_(), test_function_(test_function) {} - - ~BPFTesterCompatibilityDelegate() override {} - - scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override { - // The current method is guaranteed to only run in the child process - // running the test. In this process, the current object is guaranteed - // to live forever. So it's ok to pass aux_pointer_for_policy_ to - // the policy, which could in turn pass it to the kernel via Trap(). - return scoped_ptr<bpf_dsl::Policy>(new Policy(&aux_)); - } - - void RunTestFunction() override { - // Run the actual test. - // The current object is guaranteed to live forever in the child process - // where this will run. - test_function_(&aux_); - } - - private: - Aux aux_; - TestFunction test_function_; - - DISALLOW_COPY_AND_ASSIGN(BPFTesterCompatibilityDelegate); -}; - -} // namespace sandbox - -#endif // SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTER_COMPATIBILITY_DELEGATE_H_ diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tests.h b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tests.h deleted file mode 100644 index cc4debd4c..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tests.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ -#define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ - -#include "base/logging.h" -#include "base/macros.h" -#include "build/build_config.h" -#include "sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h" -#include "sandbox/linux/tests/unit_tests.h" - -namespace sandbox { - -// BPF_TEST_C() is a special version of SANDBOX_TEST(). It runs a test function -// in a sub-process, under a seccomp-bpf policy specified in -// |bpf_policy_class_name| without failing on configurations that are allowed -// to not support seccomp-bpf in their kernels. -// This is the preferred format for new BPF tests. |bpf_policy_class_name| is a -// class name (which will be default-constructed) that implements the -// Policy interface. -// The test function's body can simply follow. Test functions should use -// the BPF_ASSERT macros defined below, not GTEST's macros. The use of -// CHECK* macros is supported but less robust. -#define BPF_TEST_C(test_case_name, test_name, bpf_policy_class_name) \ - BPF_DEATH_TEST_C( \ - test_case_name, test_name, DEATH_SUCCESS(), bpf_policy_class_name) - -// Identical to BPF_TEST_C but allows to specify the nature of death. -#define BPF_DEATH_TEST_C( \ - test_case_name, test_name, death, bpf_policy_class_name) \ - void BPF_TEST_C_##test_name(); \ - TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \ - sandbox::SandboxBPFTestRunner bpf_test_runner( \ - new sandbox::BPFTesterSimpleDelegate<bpf_policy_class_name>( \ - BPF_TEST_C_##test_name)); \ - sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \ - } \ - void BPF_TEST_C_##test_name() - -// This form of BPF_TEST is a little verbose and should be reserved for complex -// tests where a lot of control is required. -// |bpf_tester_delegate_class| must be a classname implementing the -// BPFTesterDelegate interface. -#define BPF_TEST_D(test_case_name, test_name, bpf_tester_delegate_class) \ - BPF_DEATH_TEST_D( \ - test_case_name, test_name, DEATH_SUCCESS(), bpf_tester_delegate_class) - -// Identical to BPF_TEST_D but allows to specify the nature of death. -#define BPF_DEATH_TEST_D( \ - test_case_name, test_name, death, bpf_tester_delegate_class) \ - TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \ - sandbox::SandboxBPFTestRunner bpf_test_runner( \ - new bpf_tester_delegate_class()); \ - sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \ - } - -// Assertions are handled exactly the same as with a normal SANDBOX_TEST() -#define BPF_ASSERT SANDBOX_ASSERT -#define BPF_ASSERT_EQ(x, y) BPF_ASSERT((x) == (y)) -#define BPF_ASSERT_NE(x, y) BPF_ASSERT((x) != (y)) -#define BPF_ASSERT_LT(x, y) BPF_ASSERT((x) < (y)) -#define BPF_ASSERT_GT(x, y) BPF_ASSERT((x) > (y)) -#define BPF_ASSERT_LE(x, y) BPF_ASSERT((x) <= (y)) -#define BPF_ASSERT_GE(x, y) BPF_ASSERT((x) >= (y)) - -// This form of BPF_TEST is now discouraged (but still allowed) in favor of -// BPF_TEST_D and BPF_TEST_C. -// The |policy| parameter should be a Policy subclass. -// BPF_TEST() takes a C++ data type as an fourth parameter. A variable -// of this type will be allocated and a pointer to it will be -// available within the test function as "BPF_AUX". The pointer will -// also be passed as an argument to the policy's constructor. Policies -// would typically use it as an argument to SandboxBPF::Trap(), if -// they want to communicate data between the BPF_TEST() and a Trap() -// function. The life-time of this object is the same as the life-time -// of the process running under the seccomp-bpf policy. -// |aux| must not be void. -#define BPF_TEST(test_case_name, test_name, policy, aux) \ - BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux) - -// A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the -// test will fail with a particular known error condition. Use the DEATH_XXX() -// macros from unit_tests.h to specify the expected error condition. -#define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux) \ - void BPF_TEST_##test_name(aux* BPF_AUX); \ - TEST(test_case_name, DISABLE_ON_TSAN(test_name)) { \ - sandbox::SandboxBPFTestRunner bpf_test_runner( \ - new sandbox::BPFTesterCompatibilityDelegate<policy, aux>( \ - BPF_TEST_##test_name)); \ - sandbox::UnitTests::RunTestInProcess(&bpf_test_runner, death); \ - } \ - void BPF_TEST_##test_name(aux* BPF_AUX) - -// This class takes a simple function pointer as a constructor parameter and a -// class name as a template parameter to implement the BPFTesterDelegate -// interface which can be used to build BPF unittests with -// the SandboxBPFTestRunner class. -template <class PolicyClass> -class BPFTesterSimpleDelegate : public BPFTesterDelegate { - public: - explicit BPFTesterSimpleDelegate(void (*test_function)(void)) - : test_function_(test_function) {} - ~BPFTesterSimpleDelegate() override {} - - scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override { - return scoped_ptr<bpf_dsl::Policy>(new PolicyClass()); - } - void RunTestFunction() override { - DCHECK(test_function_); - test_function_(); - } - - private: - void (*test_function_)(void); - DISALLOW_COPY_AND_ASSIGN(BPFTesterSimpleDelegate); -}; - -} // namespace sandbox - -#endif // SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__ diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc deleted file mode 100644 index e300baf9b..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/seccomp-bpf/bpf_tests.h" - -#include <errno.h> -#include <sys/ptrace.h> -#include <sys/syscall.h> -#include <sys/types.h> -#include <unistd.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "build/build_config.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl.h" -#include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" -#include "sandbox/linux/services/syscall_wrappers.h" -#include "sandbox/linux/system_headers/linux_syscalls.h" -#include "sandbox/linux/tests/unit_tests.h" -#include "testing/gtest/include/gtest/gtest.h" - -using sandbox::bpf_dsl::Allow; -using sandbox::bpf_dsl::Error; -using sandbox::bpf_dsl::ResultExpr; - -namespace sandbox { - -namespace { - -class FourtyTwo { - public: - static const int kMagicValue = 42; - FourtyTwo() : value_(kMagicValue) {} - int value() { return value_; } - - private: - int value_; - DISALLOW_COPY_AND_ASSIGN(FourtyTwo); -}; - -class EmptyClassTakingPolicy : public bpf_dsl::Policy { - public: - explicit EmptyClassTakingPolicy(FourtyTwo* fourty_two) { - BPF_ASSERT(fourty_two); - BPF_ASSERT(FourtyTwo::kMagicValue == fourty_two->value()); - } - ~EmptyClassTakingPolicy() override {} - - ResultExpr EvaluateSyscall(int sysno) const override { - DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); - return Allow(); - } -}; - -BPF_TEST(BPFTest, - BPFAUXPointsToClass, - EmptyClassTakingPolicy, - FourtyTwo /* *BPF_AUX */) { - // BPF_AUX should point to an instance of FourtyTwo. - BPF_ASSERT(BPF_AUX); - BPF_ASSERT(FourtyTwo::kMagicValue == BPF_AUX->value()); -} - -void DummyTestFunction(FourtyTwo *fourty_two) { -} - -TEST(BPFTest, BPFTesterCompatibilityDelegateLeakTest) { - // Don't do anything, simply gives dynamic tools an opportunity to detect - // leaks. - { - BPFTesterCompatibilityDelegate<EmptyClassTakingPolicy, FourtyTwo> - simple_delegate(DummyTestFunction); - } - { - // Test polymorphism. - scoped_ptr<BPFTesterDelegate> simple_delegate( - new BPFTesterCompatibilityDelegate<EmptyClassTakingPolicy, FourtyTwo>( - DummyTestFunction)); - } -} - -class EnosysPtracePolicy : public bpf_dsl::Policy { - public: - EnosysPtracePolicy() { my_pid_ = sys_getpid(); } - ~EnosysPtracePolicy() override { - // Policies should be able to bind with the process on which they are - // created. They should never be created in a parent process. - BPF_ASSERT_EQ(my_pid_, sys_getpid()); - } - - ResultExpr EvaluateSyscall(int system_call_number) const override { - CHECK(SandboxBPF::IsValidSyscallNumber(system_call_number)); - if (system_call_number == __NR_ptrace) { - // The EvaluateSyscall function should run in the process that created - // the current object. - BPF_ASSERT_EQ(my_pid_, sys_getpid()); - return Error(ENOSYS); - } else { - return Allow(); - } - } - - private: - pid_t my_pid_; - DISALLOW_COPY_AND_ASSIGN(EnosysPtracePolicy); -}; - -class BasicBPFTesterDelegate : public BPFTesterDelegate { - public: - BasicBPFTesterDelegate() {} - ~BasicBPFTesterDelegate() override {} - - scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override { - return scoped_ptr<bpf_dsl::Policy>(new EnosysPtracePolicy()); - } - void RunTestFunction() override { - errno = 0; - int ret = ptrace(PTRACE_TRACEME, -1, NULL, NULL); - BPF_ASSERT(-1 == ret); - BPF_ASSERT(ENOSYS == errno); - } - - private: - DISALLOW_COPY_AND_ASSIGN(BasicBPFTesterDelegate); -}; - -// This is the most powerful and complex way to create a BPF test, but it -// requires a full class definition (BasicBPFTesterDelegate). -BPF_TEST_D(BPFTest, BPFTestWithDelegateClass, BasicBPFTesterDelegate); - -// This is the simplest form of BPF tests. -BPF_TEST_C(BPFTest, BPFTestWithInlineTest, EnosysPtracePolicy) { - errno = 0; - int ret = ptrace(PTRACE_TRACEME, -1, NULL, NULL); - BPF_ASSERT(-1 == ret); - BPF_ASSERT(ENOSYS == errno); -} - -const char kHelloMessage[] = "Hello"; - -BPF_DEATH_TEST_C(BPFTest, - BPFDeathTestWithInlineTest, - DEATH_MESSAGE(kHelloMessage), - EnosysPtracePolicy) { - LOG(ERROR) << kHelloMessage; - _exit(1); -} - -} // namespace - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/die.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/die.cc deleted file mode 100644 index 3baf1f13d..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/die.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/seccomp-bpf/die.h" - -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <sys/prctl.h> -#include <sys/syscall.h> -#include <unistd.h> - -#include <string> - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "sandbox/linux/seccomp-bpf/syscall.h" -#include "sandbox/linux/services/syscall_wrappers.h" -#include "sandbox/linux/system_headers/linux_signal.h" - -namespace sandbox { - -void Die::ExitGroup() { - // exit_group() should exit our program. After all, it is defined as a - // function that doesn't return. But things can theoretically go wrong. - // Especially, since we are dealing with system call filters. Continuing - // execution would be very bad in most cases where ExitGroup() gets called. - // So, we'll try a few other strategies too. - Syscall::Call(__NR_exit_group, 1); - - // We have no idea what our run-time environment looks like. So, signal - // handlers might or might not do the right thing. Try to reset settings - // to a defined state; but we have not way to verify whether we actually - // succeeded in doing so. Nonetheless, triggering a fatal signal could help - // us terminate. - struct sigaction sa = {}; - sa.sa_handler = LINUX_SIG_DFL; - sa.sa_flags = LINUX_SA_RESTART; - sys_sigaction(LINUX_SIGSEGV, &sa, nullptr); - Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0); - if (*(volatile char*)0) { - } - - // If there is no way for us to ask for the program to exit, the next - // best thing we can do is to loop indefinitely. Maybe, somebody will notice - // and file a bug... - // We in fact retry the system call inside of our loop so that it will - // stand out when somebody tries to diagnose the problem by using "strace". - for (;;) { - Syscall::Call(__NR_exit_group, 1); - } -} - -void Die::SandboxDie(const char* msg, const char* file, int line) { - if (simple_exit_) { - LogToStderr(msg, file, line); - } else { - logging::LogMessage(file, line, logging::LOG_FATAL).stream() << msg; - } - ExitGroup(); -} - -void Die::RawSandboxDie(const char* msg) { - if (!msg) - msg = ""; - RAW_LOG(FATAL, msg); - ExitGroup(); -} - -void Die::SandboxInfo(const char* msg, const char* file, int line) { - if (!suppress_info_) { - logging::LogMessage(file, line, logging::LOG_INFO).stream() << msg; - } -} - -void Die::LogToStderr(const char* msg, const char* file, int line) { - if (msg) { - char buf[40]; - snprintf(buf, sizeof(buf), "%d", line); - std::string s = std::string(file) + ":" + buf + ":" + msg + "\n"; - - // No need to loop. Short write()s are unlikely and if they happen we - // probably prefer them over a loop that blocks. - ignore_result( - HANDLE_EINTR(Syscall::Call(__NR_write, 2, s.c_str(), s.length()))); - } -} - -bool Die::simple_exit_ = false; -bool Die::suppress_info_ = false; - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/die.h b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/die.h deleted file mode 100644 index b3f3f72c2..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/die.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SECCOMP_BPF_DIE_H__ -#define SANDBOX_LINUX_SECCOMP_BPF_DIE_H__ - -#include "base/macros.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { - -// This is the main API for using this file. Prints a error message and -// exits with a fatal error. This is not async-signal safe. -#define SANDBOX_DIE(m) sandbox::Die::SandboxDie(m, __FILE__, __LINE__) - -// An async signal safe version of the same API. Won't print the filename -// and line numbers. -#define RAW_SANDBOX_DIE(m) sandbox::Die::RawSandboxDie(m) - -// Adds an informational message to the log file or stderr as appropriate. -#define SANDBOX_INFO(m) sandbox::Die::SandboxInfo(m, __FILE__, __LINE__) - -class SANDBOX_EXPORT Die { - public: - // Terminate the program, even if the current sandbox policy prevents some - // of the more commonly used functions used for exiting. - // Most users would want to call SANDBOX_DIE() instead, as it logs extra - // information. But calling ExitGroup() is correct and in some rare cases - // preferable. So, we make it part of the public API. - static void ExitGroup() __attribute__((noreturn)); - - // This method gets called by SANDBOX_DIE(). There is normally no reason - // to call it directly unless you are defining your own exiting macro. - static void SandboxDie(const char* msg, const char* file, int line) - __attribute__((noreturn)); - - static void RawSandboxDie(const char* msg) __attribute__((noreturn)); - - // This method gets called by SANDBOX_INFO(). There is normally no reason - // to call it directly unless you are defining your own logging macro. - static void SandboxInfo(const char* msg, const char* file, int line); - - // Writes a message to stderr. Used as a fall-back choice, if we don't have - // any other way to report an error. - static void LogToStderr(const char* msg, const char* file, int line); - - // We generally want to run all exit handlers. This means, on SANDBOX_DIE() - // we should be calling LOG(FATAL). But there are some situations where - // we just need to print a message and then terminate. This would typically - // happen in cases where we consume the error message internally (e.g. in - // unit tests or in the supportsSeccompSandbox() method). - static void EnableSimpleExit() { simple_exit_ = true; } - - // Sometimes we need to disable all informational messages (e.g. from within - // unittests). - static void SuppressInfoMessages(bool flag) { suppress_info_ = flag; } - - private: - static bool simple_exit_; - static bool suppress_info_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(Die); -}; - -} // namespace sandbox - -#endif // SANDBOX_LINUX_SECCOMP_BPF_DIE_H__ diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc deleted file mode 100644 index b48682ba9..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" - -#include <errno.h> -#include <stdint.h> -#include <sys/prctl.h> -#include <sys/types.h> -#include <unistd.h> - -#include "base/compiler_specific.h" -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/posix/eintr_wrapper.h" -#include "base/third_party/valgrind/valgrind.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl.h" -#include "sandbox/linux/bpf_dsl/codegen.h" -#include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/bpf_dsl/policy_compiler.h" -#include "sandbox/linux/bpf_dsl/seccomp_macros.h" -#include "sandbox/linux/bpf_dsl/syscall_set.h" -#include "sandbox/linux/seccomp-bpf/die.h" -#include "sandbox/linux/seccomp-bpf/syscall.h" -#include "sandbox/linux/seccomp-bpf/trap.h" -#include "sandbox/linux/services/proc_util.h" -#include "sandbox/linux/services/syscall_wrappers.h" -#include "sandbox/linux/services/thread_helpers.h" -#include "sandbox/linux/system_headers/linux_filter.h" -#include "sandbox/linux/system_headers/linux_seccomp.h" -#include "sandbox/linux/system_headers/linux_syscalls.h" - -namespace sandbox { - -namespace { - -bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; } - -bool IsSingleThreaded(int proc_fd) { - return ThreadHelpers::IsSingleThreaded(proc_fd); -} - -// Check if the kernel supports seccomp-filter (a.k.a. seccomp mode 2) via -// prctl(). -bool KernelSupportsSeccompBPF() { - errno = 0; - const int rv = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, nullptr); - - if (rv == -1 && EFAULT == errno) { - return true; - } - return false; -} - -// LG introduced a buggy syscall, sys_set_media_ext, with the same number as -// seccomp. Return true if the current kernel has this buggy syscall. -// -// We want this to work with upcoming versions of seccomp, so we pass bogus -// flags that are unlikely to ever be used by the kernel. A normal kernel would -// return -EINVAL, but a buggy LG kernel would return 1. -bool KernelHasLGBug() { -#if defined(OS_ANDROID) - // sys_set_media will see this as NULL, which should be a safe (non-crashing) - // way to invoke it. A genuine seccomp syscall will see it as - // SECCOMP_SET_MODE_STRICT. - const unsigned int operation = 0; - // Chosen by fair dice roll. Guaranteed to be random. - const unsigned int flags = 0xf7a46a5c; - const int rv = sys_seccomp(operation, flags, nullptr); - // A genuine kernel would return -EINVAL (which would set rv to -1 and errno - // to EINVAL), or at the very least return some kind of error (which would - // set rv to -1). Any other behavior indicates that whatever code received - // our syscall was not the real seccomp. - if (rv != -1) { - return true; - } -#endif // defined(OS_ANDROID) - - return false; -} - -// Check if the kernel supports seccomp-filter via the seccomp system call -// and the TSYNC feature to enable seccomp on all threads. -bool KernelSupportsSeccompTsync() { - if (KernelHasLGBug()) { - return false; - } - - errno = 0; - const int rv = - sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, nullptr); - - if (rv == -1 && errno == EFAULT) { - return true; - } else { - // TODO(jln): turn these into DCHECK after 417888 is considered fixed. - CHECK_EQ(-1, rv); - CHECK(ENOSYS == errno || EINVAL == errno); - return false; - } -} - -uint64_t EscapePC() { - intptr_t rv = Syscall::Call(-1); - if (rv == -1 && errno == ENOSYS) { - return 0; - } - return static_cast<uint64_t>(static_cast<uintptr_t>(rv)); -} - -intptr_t SandboxPanicTrap(const struct arch_seccomp_data&, void* aux) { - SANDBOX_DIE(static_cast<const char*>(aux)); -} - -bpf_dsl::ResultExpr SandboxPanic(const char* error) { - return bpf_dsl::Trap(SandboxPanicTrap, error); -} - -} // namespace - -SandboxBPF::SandboxBPF(bpf_dsl::Policy* policy) - : proc_fd_(), sandbox_has_started_(false), policy_(policy) { -} - -SandboxBPF::~SandboxBPF() { -} - -// static -bool SandboxBPF::SupportsSeccompSandbox(SeccompLevel level) { - // Never pretend to support seccomp with Valgrind, as it - // throws the tool off. - if (IsRunningOnValgrind()) { - return false; - } - - switch (level) { - case SeccompLevel::SINGLE_THREADED: - return KernelSupportsSeccompBPF(); - case SeccompLevel::MULTI_THREADED: - return KernelSupportsSeccompTsync(); - } - NOTREACHED(); - return false; -} - -bool SandboxBPF::StartSandbox(SeccompLevel seccomp_level) { - DCHECK(policy_); - CHECK(seccomp_level == SeccompLevel::SINGLE_THREADED || - seccomp_level == SeccompLevel::MULTI_THREADED); - - if (sandbox_has_started_) { - SANDBOX_DIE( - "Cannot repeatedly start sandbox. Create a separate Sandbox " - "object instead."); - return false; - } - - if (!proc_fd_.is_valid()) { - SetProcFd(ProcUtil::OpenProc()); - } - - const bool supports_tsync = KernelSupportsSeccompTsync(); - - if (seccomp_level == SeccompLevel::SINGLE_THREADED) { - // Wait for /proc/self/task/ to update if needed and assert the - // process is single threaded. - ThreadHelpers::AssertSingleThreaded(proc_fd_.get()); - } else if (seccomp_level == SeccompLevel::MULTI_THREADED) { - if (IsSingleThreaded(proc_fd_.get())) { - SANDBOX_DIE("Cannot start sandbox; " - "process may be single-threaded when reported as not"); - return false; - } - if (!supports_tsync) { - SANDBOX_DIE("Cannot start sandbox; kernel does not support synchronizing " - "filters for a threadgroup"); - return false; - } - } - - // We no longer need access to any files in /proc. We want to do this - // before installing the filters, just in case that our policy denies - // close(). - if (proc_fd_.is_valid()) { - proc_fd_.reset(); - } - - // Install the filters. - InstallFilter(supports_tsync || - seccomp_level == SeccompLevel::MULTI_THREADED); - - return true; -} - -void SandboxBPF::SetProcFd(base::ScopedFD proc_fd) { - proc_fd_.swap(proc_fd); -} - -// static -bool SandboxBPF::IsValidSyscallNumber(int sysnum) { - return SyscallSet::IsValid(sysnum); -} - -// static -bool SandboxBPF::IsRequiredForUnsafeTrap(int sysno) { - return bpf_dsl::PolicyCompiler::IsRequiredForUnsafeTrap(sysno); -} - -// static -intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) { - return Syscall::Call( - args.nr, static_cast<intptr_t>(args.args[0]), - static_cast<intptr_t>(args.args[1]), static_cast<intptr_t>(args.args[2]), - static_cast<intptr_t>(args.args[3]), static_cast<intptr_t>(args.args[4]), - static_cast<intptr_t>(args.args[5])); -} - -CodeGen::Program SandboxBPF::AssembleFilter() { - DCHECK(policy_); - - bpf_dsl::PolicyCompiler compiler(policy_.get(), Trap::Registry()); - if (Trap::SandboxDebuggingAllowedByUser()) { - compiler.DangerousSetEscapePC(EscapePC()); - } - compiler.SetPanicFunc(SandboxPanic); - return compiler.Compile(); -} - -void SandboxBPF::InstallFilter(bool must_sync_threads) { - // We want to be very careful in not imposing any requirements on the - // policies that are set with SetSandboxPolicy(). This means, as soon as - // the sandbox is active, we shouldn't be relying on libraries that could - // be making system calls. This, for example, means we should avoid - // using the heap and we should avoid using STL functions. - // Temporarily copy the contents of the "program" vector into a - // stack-allocated array; and then explicitly destroy that object. - // This makes sure we don't ex- or implicitly call new/delete after we - // installed the BPF filter program in the kernel. Depending on the - // system memory allocator that is in effect, these operators can result - // in system calls to things like munmap() or brk(). - CodeGen::Program program = AssembleFilter(); - - struct sock_filter bpf[program.size()]; - const struct sock_fprog prog = {static_cast<unsigned short>(program.size()), - bpf}; - memcpy(bpf, &program[0], sizeof(bpf)); - CodeGen::Program().swap(program); // vector swap trick - - // Make an attempt to release memory that is no longer needed here, rather - // than in the destructor. Try to avoid as much as possible to presume of - // what will be possible to do in the new (sandboxed) execution environment. - policy_.reset(); - - if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { - SANDBOX_DIE("Kernel refuses to enable no-new-privs"); - } - - // Install BPF filter program. If the thread state indicates multi-threading - // support, then the kernel hass the seccomp system call. Otherwise, fall - // back on prctl, which requires the process to be single-threaded. - if (must_sync_threads) { - int rv = - sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, &prog); - if (rv) { - SANDBOX_DIE( - "Kernel refuses to turn on and synchronize threads for BPF filters"); - } - } else { - if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { - SANDBOX_DIE("Kernel refuses to turn on BPF filters"); - } - } - - sandbox_has_started_ = true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h deleted file mode 100644 index e758e0312..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_ -#define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_ - -#include <stdint.h> - -#include "base/files/scoped_file.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/linux/bpf_dsl/codegen.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { -struct arch_seccomp_data; -namespace bpf_dsl { -class Policy; -} - -// This class can be used to apply a syscall sandboxing policy expressed in a -// bpf_dsl::Policy object to the current process. -// Syscall sandboxing policies get inherited by subprocesses and, once applied, -// can never be removed for the lifetime of the process. -class SANDBOX_EXPORT SandboxBPF { - public: - enum class SeccompLevel { - SINGLE_THREADED, - MULTI_THREADED, - }; - - // Ownership of |policy| is transfered here to the sandbox object. - // nullptr is allowed for unit tests. - explicit SandboxBPF(bpf_dsl::Policy* policy); - // NOTE: Setting a policy and starting the sandbox is a one-way operation. - // The kernel does not provide any option for unloading a loaded sandbox. The - // sandbox remains engaged even when the object is destructed. - ~SandboxBPF(); - - // Detect if the kernel supports the specified seccomp level. - // See StartSandbox() for a description of these. - static bool SupportsSeccompSandbox(SeccompLevel level); - - // This is the main public entry point. It sets up the resources needed by - // the sandbox, and enters Seccomp mode. - // The calling process must provide a |level| to tell the sandbox which type - // of kernel support it should engage. - // SINGLE_THREADED will only sandbox the calling thread. Since it would be a - // security risk, the sandbox will also check that the current process is - // single threaded and crash if it isn't the case. - // MULTI_THREADED requires more recent kernel support and allows to sandbox - // all the threads of the current process. Be mindful of potential races, - // with other threads using disallowed system calls either before or after - // the sandbox is engaged. - // - // It is possible to stack multiple sandboxes by creating separate "Sandbox" - // objects and calling "StartSandbox()" on each of them. Please note, that - // this requires special care, though, as newly stacked sandboxes can never - // relax restrictions imposed by earlier sandboxes. Furthermore, installing - // a new policy requires making system calls, that might already be - // disallowed. - // Finally, stacking does add more kernel overhead than having a single - // combined policy. So, it should only be used if there are no alternatives. - bool StartSandbox(SeccompLevel level) WARN_UNUSED_RESULT; - - // The sandbox needs to be able to access files in "/proc/self/". If - // this directory is not accessible when "StartSandbox()" gets called, the - // caller must provide an already opened file descriptor by calling - // "SetProcFd()". - // The sandbox becomes the new owner of this file descriptor and will - // close it when "StartSandbox()" executes or when the sandbox object - // disappears. - void SetProcFd(base::ScopedFD proc_fd); - - // Checks whether a particular system call number is valid on the current - // architecture. - static bool IsValidSyscallNumber(int sysnum); - - // UnsafeTraps require some syscalls to always be allowed. - // This helper function returns true for these calls. - static bool IsRequiredForUnsafeTrap(int sysno); - - // From within an UnsafeTrap() it is often useful to be able to execute - // the system call that triggered the trap. The ForwardSyscall() method - // makes this easy. It is more efficient than calling glibc's syscall() - // function, as it avoid the extra round-trip to the signal handler. And - // it automatically does the correct thing to report kernel-style error - // conditions, rather than setting errno. See the comments for TrapFnc for - // details. In other words, the return value from ForwardSyscall() is - // directly suitable as a return value for a trap handler. - static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); - - private: - friend class SandboxBPFTestRunner; - - // Assembles a BPF filter program from the current policy. After calling this - // function, you must not call any other sandboxing function. - CodeGen::Program AssembleFilter(); - - // Assembles and installs a filter based on the policy that has previously - // been configured with SetSandboxPolicy(). - void InstallFilter(bool must_sync_threads); - - base::ScopedFD proc_fd_; - bool sandbox_has_started_; - scoped_ptr<bpf_dsl::Policy> policy_; - - DISALLOW_COPY_AND_ASSIGN(SandboxBPF); -}; - -} // namespace sandbox - -#endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_ diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc deleted file mode 100644 index c0193f956..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h" - -#include <fcntl.h> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/seccomp-bpf/die.h" -#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" -#include "sandbox/linux/system_headers/linux_filter.h" -#include "sandbox/linux/tests/unit_tests.h" - -namespace sandbox { - -SandboxBPFTestRunner::SandboxBPFTestRunner( - BPFTesterDelegate* bpf_tester_delegate) - : bpf_tester_delegate_(bpf_tester_delegate) { -} - -SandboxBPFTestRunner::~SandboxBPFTestRunner() { -} - -void SandboxBPFTestRunner::Run() { - DCHECK(bpf_tester_delegate_); - sandbox::Die::EnableSimpleExit(); - - scoped_ptr<bpf_dsl::Policy> policy = - bpf_tester_delegate_->GetSandboxBPFPolicy(); - - if (sandbox::SandboxBPF::SupportsSeccompSandbox( - SandboxBPF::SeccompLevel::SINGLE_THREADED)) { - // Initialize and then start the sandbox with our custom policy - sandbox::SandboxBPF sandbox(policy.release()); - SANDBOX_ASSERT(sandbox.StartSandbox( - sandbox::SandboxBPF::SeccompLevel::SINGLE_THREADED)); - - // Run the actual test. - bpf_tester_delegate_->RunTestFunction(); - } else { - printf("This BPF test is not fully running in this configuration!\n"); - // Android and Valgrind are the only configurations where we accept not - // having kernel BPF support. - if (!IsAndroid() && !IsRunningOnValgrind()) { - const bool seccomp_bpf_is_supported = false; - SANDBOX_ASSERT(seccomp_bpf_is_supported); - } - // Call the compiler and verify the policy. That's the least we can do, - // if we don't have kernel support. - sandbox::SandboxBPF sandbox(policy.release()); - sandbox.AssembleFilter(); - sandbox::UnitTests::IgnoreThisTest(); - } -} - -bool SandboxBPFTestRunner::ShouldCheckForLeaks() const { - // LSAN requires being able to use ptrace() and other system calls that could - // be denied. - return false; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h deleted file mode 100644 index fef6240d7..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_test_runner.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_TEST_RUNNER_H_ -#define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_TEST_RUNNER_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/linux/tests/sandbox_test_runner.h" - -namespace sandbox { -namespace bpf_dsl { -class Policy; -} - -// To create a SandboxBPFTestRunner object, one needs to implement this -// interface and pass an instance to the SandboxBPFTestRunner constructor. -// In the child process running the test, the BPFTesterDelegate object is -// guaranteed to not be destroyed until the child process terminates. -class BPFTesterDelegate { - public: - BPFTesterDelegate() {} - virtual ~BPFTesterDelegate() {} - - // This will instanciate a policy suitable for the test we want to run. It is - // guaranteed to only be called from the child process that will run the - // test. - virtual scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() = 0; - // This will be called from a child process with the BPF sandbox turned on. - virtual void RunTestFunction() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(BPFTesterDelegate); -}; - -// This class implements the SandboxTestRunner interface and Run() will -// initialize a seccomp-bpf sandbox (specified by |bpf_tester_delegate|) and -// run a test function (via |bpf_tester_delegate|) if the current kernel -// configuration allows it. If it can not run the test under seccomp-bpf, -// Run() will still compile the policy which should allow to get some coverage -// under tools such as Valgrind. -class SandboxBPFTestRunner : public SandboxTestRunner { - public: - // This constructor takes ownership of the |bpf_tester_delegate| object. - // (It doesn't take a scoped_ptr since they make polymorphism verbose). - explicit SandboxBPFTestRunner(BPFTesterDelegate* bpf_tester_delegate); - ~SandboxBPFTestRunner() override; - - void Run() override; - - bool ShouldCheckForLeaks() const override; - - private: - scoped_ptr<BPFTesterDelegate> bpf_tester_delegate_; - DISALLOW_COPY_AND_ASSIGN(SandboxBPFTestRunner); -}; - -} // namespace sandbox - -#endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_TEST_RUNNER_H_ diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall.cc deleted file mode 100644 index bc6461f11..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall.cc +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/seccomp-bpf/syscall.h" - -#include <errno.h> -#include <stdint.h> - -#include "base/logging.h" -#include "sandbox/linux/bpf_dsl/seccomp_macros.h" - -namespace sandbox { - -namespace { - -#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \ - defined(ARCH_CPU_MIPS_FAMILY) -// Number that's not currently used by any Linux kernel ABIs. -const int kInvalidSyscallNumber = 0x351d3; -#else -#error Unrecognized architecture -#endif - -asm(// We need to be able to tell the kernel exactly where we made a - // system call. The C++ compiler likes to sometimes clone or - // inline code, which would inadvertently end up duplicating - // the entry point. - // "gcc" can suppress code duplication with suitable function - // attributes, but "clang" doesn't have this ability. - // The "clang" developer mailing list suggested that the correct - // and portable solution is a file-scope assembly block. - // N.B. We do mark our code as a proper function so that backtraces - // work correctly. But we make absolutely no attempt to use the - // ABI's calling conventions for passing arguments. We will only - // ever be called from assembly code and thus can pick more - // suitable calling conventions. -#if defined(__i386__) - ".text\n" - ".align 16, 0x90\n" - ".type SyscallAsm, @function\n" - "SyscallAsm:.cfi_startproc\n" - // Check if "%eax" is negative. If so, do not attempt to make a - // system call. Instead, compute the return address that is visible - // to the kernel after we execute "int $0x80". This address can be - // used as a marker that BPF code inspects. - "test %eax, %eax\n" - "jge 1f\n" - // Always, make sure that our code is position-independent, or - // address space randomization might not work on i386. This means, - // we can't use "lea", but instead have to rely on "call/pop". - "call 0f; .cfi_adjust_cfa_offset 4\n" - "0:pop %eax; .cfi_adjust_cfa_offset -4\n" - "addl $2f-0b, %eax\n" - "ret\n" - // Save register that we don't want to clobber. On i386, we need to - // save relatively aggressively, as there are a couple or registers - // that are used internally (e.g. %ebx for position-independent - // code, and %ebp for the frame pointer), and as we need to keep at - // least a few registers available for the register allocator. - "1:push %esi; .cfi_adjust_cfa_offset 4; .cfi_rel_offset esi, 0\n" - "push %edi; .cfi_adjust_cfa_offset 4; .cfi_rel_offset edi, 0\n" - "push %ebx; .cfi_adjust_cfa_offset 4; .cfi_rel_offset ebx, 0\n" - "push %ebp; .cfi_adjust_cfa_offset 4; .cfi_rel_offset ebp, 0\n" - // Copy entries from the array holding the arguments into the - // correct CPU registers. - "movl 0(%edi), %ebx\n" - "movl 4(%edi), %ecx\n" - "movl 8(%edi), %edx\n" - "movl 12(%edi), %esi\n" - "movl 20(%edi), %ebp\n" - "movl 16(%edi), %edi\n" - // Enter the kernel. - "int $0x80\n" - // This is our "magic" return address that the BPF filter sees. - "2:" - // Restore any clobbered registers that we didn't declare to the - // compiler. - "pop %ebp; .cfi_restore ebp; .cfi_adjust_cfa_offset -4\n" - "pop %ebx; .cfi_restore ebx; .cfi_adjust_cfa_offset -4\n" - "pop %edi; .cfi_restore edi; .cfi_adjust_cfa_offset -4\n" - "pop %esi; .cfi_restore esi; .cfi_adjust_cfa_offset -4\n" - "ret\n" - ".cfi_endproc\n" - "9:.size SyscallAsm, 9b-SyscallAsm\n" -#elif defined(__x86_64__) - ".text\n" - ".align 16, 0x90\n" - ".type SyscallAsm, @function\n" - "SyscallAsm:.cfi_startproc\n" - // Check if "%rdi" is negative. If so, do not attempt to make a - // system call. Instead, compute the return address that is visible - // to the kernel after we execute "syscall". This address can be - // used as a marker that BPF code inspects. - "test %rdi, %rdi\n" - "jge 1f\n" - // Always make sure that our code is position-independent, or the - // linker will throw a hissy fit on x86-64. - "lea 2f(%rip), %rax\n" - "ret\n" - // Now we load the registers used to pass arguments to the system - // call: system call number in %rax, and arguments in %rdi, %rsi, - // %rdx, %r10, %r8, %r9. Note: These are all caller-save registers - // (only %rbx, %rbp, %rsp, and %r12-%r15 are callee-save), so no - // need to worry here about spilling registers or CFI directives. - "1:movq %rdi, %rax\n" - "movq 0(%rsi), %rdi\n" - "movq 16(%rsi), %rdx\n" - "movq 24(%rsi), %r10\n" - "movq 32(%rsi), %r8\n" - "movq 40(%rsi), %r9\n" - "movq 8(%rsi), %rsi\n" - // Enter the kernel. - "syscall\n" - // This is our "magic" return address that the BPF filter sees. - "2:ret\n" - ".cfi_endproc\n" - "9:.size SyscallAsm, 9b-SyscallAsm\n" -#elif defined(__arm__) - // Throughout this file, we use the same mode (ARM vs. thumb) - // that the C++ compiler uses. This means, when transfering control - // from C++ to assembly code, we do not need to switch modes (e.g. - // by using the "bx" instruction). It also means that our assembly - // code should not be invoked directly from code that lives in - // other compilation units, as we don't bother implementing thumb - // interworking. That's OK, as we don't make any of the assembly - // symbols public. They are all local to this file. - ".text\n" - ".align 2\n" - ".type SyscallAsm, %function\n" -#if defined(__thumb__) - ".thumb_func\n" -#else - ".arm\n" -#endif - "SyscallAsm:\n" -#if !defined(__native_client_nonsfi__) - // .fnstart and .fnend pseudo operations creates unwind table. - // It also creates a reference to the symbol __aeabi_unwind_cpp_pr0, which - // is not provided by PNaCl toolchain. Disable it. - ".fnstart\n" -#endif - "@ args = 0, pretend = 0, frame = 8\n" - "@ frame_needed = 1, uses_anonymous_args = 0\n" -#if defined(__thumb__) - ".cfi_startproc\n" - "push {r7, lr}\n" - ".save {r7, lr}\n" - ".cfi_offset 14, -4\n" - ".cfi_offset 7, -8\n" - ".cfi_def_cfa_offset 8\n" -#else - "stmfd sp!, {fp, lr}\n" - "add fp, sp, #4\n" -#endif - // Check if "r0" is negative. If so, do not attempt to make a - // system call. Instead, compute the return address that is visible - // to the kernel after we execute "swi 0". This address can be - // used as a marker that BPF code inspects. - "cmp r0, #0\n" - "bge 1f\n" - "adr r0, 2f\n" - "b 2f\n" - // We declared (almost) all clobbered registers to the compiler. On - // ARM there is no particular register pressure. So, we can go - // ahead and directly copy the entries from the arguments array - // into the appropriate CPU registers. - "1:ldr r5, [r6, #20]\n" - "ldr r4, [r6, #16]\n" - "ldr r3, [r6, #12]\n" - "ldr r2, [r6, #8]\n" - "ldr r1, [r6, #4]\n" - "mov r7, r0\n" - "ldr r0, [r6, #0]\n" - // Enter the kernel - "swi 0\n" -// Restore the frame pointer. Also restore the program counter from -// the link register; this makes us return to the caller. -#if defined(__thumb__) - "2:pop {r7, pc}\n" - ".cfi_endproc\n" -#else - "2:ldmfd sp!, {fp, pc}\n" -#endif -#if !defined(__native_client_nonsfi__) - // Do not use .fnstart and .fnend for PNaCl toolchain. See above comment, - // for more details. - ".fnend\n" -#endif - "9:.size SyscallAsm, 9b-SyscallAsm\n" -#elif defined(__mips__) - ".text\n" - ".align 4\n" - ".type SyscallAsm, @function\n" - "SyscallAsm:.ent SyscallAsm\n" - ".frame $sp, 40, $ra\n" - ".set push\n" - ".set noreorder\n" - "addiu $sp, $sp, -40\n" - "sw $ra, 36($sp)\n" - // Check if "v0" is negative. If so, do not attempt to make a - // system call. Instead, compute the return address that is visible - // to the kernel after we execute "syscall". This address can be - // used as a marker that BPF code inspects. - "bgez $v0, 1f\n" - " nop\n" - "la $v0, 2f\n" - "b 2f\n" - " nop\n" - // On MIPS first four arguments go to registers a0 - a3 and any - // argument after that goes to stack. We can go ahead and directly - // copy the entries from the arguments array into the appropriate - // CPU registers and on the stack. - "1:lw $a3, 28($a0)\n" - "lw $a2, 24($a0)\n" - "lw $a1, 20($a0)\n" - "lw $t0, 16($a0)\n" - "sw $a3, 28($sp)\n" - "sw $a2, 24($sp)\n" - "sw $a1, 20($sp)\n" - "sw $t0, 16($sp)\n" - "lw $a3, 12($a0)\n" - "lw $a2, 8($a0)\n" - "lw $a1, 4($a0)\n" - "lw $a0, 0($a0)\n" - // Enter the kernel - "syscall\n" - // This is our "magic" return address that the BPF filter sees. - // Restore the return address from the stack. - "2:lw $ra, 36($sp)\n" - "jr $ra\n" - " addiu $sp, $sp, 40\n" - ".set pop\n" - ".end SyscallAsm\n" - ".size SyscallAsm,.-SyscallAsm\n" -#elif defined(__aarch64__) - ".text\n" - ".align 2\n" - ".type SyscallAsm, %function\n" - "SyscallAsm:\n" - ".cfi_startproc\n" - "cmp x0, #0\n" - "b.ge 1f\n" - "adr x0,2f\n" - "b 2f\n" - "1:ldr x5, [x6, #40]\n" - "ldr x4, [x6, #32]\n" - "ldr x3, [x6, #24]\n" - "ldr x2, [x6, #16]\n" - "ldr x1, [x6, #8]\n" - "mov x8, x0\n" - "ldr x0, [x6, #0]\n" - // Enter the kernel - "svc 0\n" - "2:ret\n" - ".cfi_endproc\n" - ".size SyscallAsm, .-SyscallAsm\n" -#endif - ); // asm - -#if defined(__x86_64__) -extern "C" { -intptr_t SyscallAsm(intptr_t nr, const intptr_t args[6]); -} -#endif - -} // namespace - -intptr_t Syscall::InvalidCall() { - // Explicitly pass eight zero arguments just in case. - return Call(kInvalidSyscallNumber, 0, 0, 0, 0, 0, 0, 0, 0); -} - -intptr_t Syscall::Call(int nr, - intptr_t p0, - intptr_t p1, - intptr_t p2, - intptr_t p3, - intptr_t p4, - intptr_t p5, - intptr_t p6, - intptr_t p7) { - // We rely on "intptr_t" to be the exact size as a "void *". This is - // typically true, but just in case, we add a check. The language - // specification allows platforms some leeway in cases, where - // "sizeof(void *)" is not the same as "sizeof(void (*)())". We expect - // that this would only be an issue for IA64, which we are currently not - // planning on supporting. And it is even possible that this would work - // on IA64, but for lack of actual hardware, I cannot test. - static_assert(sizeof(void*) == sizeof(intptr_t), - "pointer types and intptr_t must be exactly the same size"); - - // TODO(nedeljko): Enable use of more than six parameters on architectures - // where that makes sense. -#if defined(__mips__) - const intptr_t args[8] = {p0, p1, p2, p3, p4, p5, p6, p7}; -#else - DCHECK_EQ(p6, 0) << " Support for syscalls with more than six arguments not " - "added for this architecture"; - DCHECK_EQ(p7, 0) << " Support for syscalls with more than six arguments not " - "added for this architecture"; - const intptr_t args[6] = {p0, p1, p2, p3, p4, p5}; -#endif // defined(__mips__) - -// Invoke our file-scope assembly code. The constraints have been picked -// carefully to match what the rest of the assembly code expects in input, -// output, and clobbered registers. -#if defined(__i386__) - intptr_t ret = nr; - asm volatile( - "call SyscallAsm\n" - // N.B. These are not the calling conventions normally used by the ABI. - : "=a"(ret) - : "0"(ret), "D"(args) - : "cc", "esp", "memory", "ecx", "edx"); -#elif defined(__x86_64__) - intptr_t ret = SyscallAsm(nr, args); -#elif defined(__arm__) - intptr_t ret; - { - register intptr_t inout __asm__("r0") = nr; - register const intptr_t* data __asm__("r6") = args; - asm volatile( - "bl SyscallAsm\n" - // N.B. These are not the calling conventions normally used by the ABI. - : "=r"(inout) - : "0"(inout), "r"(data) - : "cc", - "lr", - "memory", - "r1", - "r2", - "r3", - "r4", - "r5" -#if !defined(__thumb__) - // In thumb mode, we cannot use "r7" as a general purpose register, as - // it is our frame pointer. We have to manually manage and preserve - // it. - // In ARM mode, we have a dedicated frame pointer register and "r7" is - // thus available as a general purpose register. We don't preserve it, - // but instead mark it as clobbered. - , - "r7" -#endif // !defined(__thumb__) - ); - ret = inout; - } -#elif defined(__mips__) - int err_status; - intptr_t ret = Syscall::SandboxSyscallRaw(nr, args, &err_status); - - if (err_status) { - // On error, MIPS returns errno from syscall instead of -errno. - // The purpose of this negation is for SandboxSyscall() to behave - // more like it would on other architectures. - ret = -ret; - } -#elif defined(__aarch64__) - intptr_t ret; - { - register intptr_t inout __asm__("x0") = nr; - register const intptr_t* data __asm__("x6") = args; - asm volatile("bl SyscallAsm\n" - : "=r"(inout) - : "0"(inout), "r"(data) - : "memory", "x1", "x2", "x3", "x4", "x5", "x8", "x30"); - ret = inout; - } - -#else -#error "Unimplemented architecture" -#endif - return ret; -} - -void Syscall::PutValueInUcontext(intptr_t ret_val, ucontext_t* ctx) { -#if defined(__mips__) - // Mips ABI states that on error a3 CPU register has non zero value and if - // there is no error, it should be zero. - if (ret_val <= -1 && ret_val >= -4095) { - // |ret_val| followes the Syscall::Call() convention of being -errno on - // errors. In order to write correct value to return register this sign - // needs to be changed back. - ret_val = -ret_val; - SECCOMP_PARM4(ctx) = 1; - } else - SECCOMP_PARM4(ctx) = 0; -#endif - SECCOMP_RESULT(ctx) = static_cast<greg_t>(ret_val); -} - -#if defined(__mips__) -intptr_t Syscall::SandboxSyscallRaw(int nr, - const intptr_t* args, - intptr_t* err_ret) { - register intptr_t ret __asm__("v0") = nr; - // a3 register becomes non zero on error. - register intptr_t err_stat __asm__("a3") = 0; - { - register const intptr_t* data __asm__("a0") = args; - asm volatile( - "la $t9, SyscallAsm\n" - "jalr $t9\n" - " nop\n" - : "=r"(ret), "=r"(err_stat) - : "0"(ret), - "r"(data) - // a2 is in the clober list so inline assembly can not change its - // value. - : "memory", "ra", "t9", "a2"); - } - - // Set an error status so it can be used outside of this function - *err_ret = err_stat; - - return ret; -} -#endif // defined(__mips__) - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall.h b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall.h deleted file mode 100644 index ccfc88dcb..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall.h +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ -#define SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ - -#include <signal.h> -#include <stdint.h> - -#include "base/macros.h" -#include "sandbox/linux/system_headers/linux_signal.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { - -// This purely static class can be used to perform system calls with some -// low-level control. -class SANDBOX_EXPORT Syscall { - public: - // InvalidCall() invokes Call() with a platform-appropriate syscall - // number that is guaranteed to not be implemented (i.e., normally - // returns -ENOSYS). - // This is primarily meant to be useful for writing sandbox policy - // unit tests. - static intptr_t InvalidCall(); - - // System calls can take up to six parameters (up to eight on some - // architectures). Traditionally, glibc - // implements this property by using variadic argument lists. This works, but - // confuses modern tools such as valgrind, because we are nominally passing - // uninitialized data whenever we call through this function and pass less - // than the full six arguments. - // So, instead, we use C++'s template system to achieve a very similar - // effect. C++ automatically sets the unused parameters to zero for us, and - // it also does the correct type expansion (e.g. from 32bit to 64bit) where - // necessary. - // We have to use C-style cast operators as we want to be able to accept both - // integer and pointer types. - template <class T0, - class T1, - class T2, - class T3, - class T4, - class T5, - class T6, - class T7> - static inline intptr_t - Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7) { - return Call(nr, - (intptr_t)p0, - (intptr_t)p1, - (intptr_t)p2, - (intptr_t)p3, - (intptr_t)p4, - (intptr_t)p5, - (intptr_t)p6, - (intptr_t)p7); - } - - template <class T0, - class T1, - class T2, - class T3, - class T4, - class T5, - class T6> - static inline intptr_t - Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6) { - return Call(nr, - (intptr_t)p0, - (intptr_t)p1, - (intptr_t)p2, - (intptr_t)p3, - (intptr_t)p4, - (intptr_t)p5, - (intptr_t)p6, - 0); - } - - template <class T0, class T1, class T2, class T3, class T4, class T5> - static inline intptr_t - Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) { - return Call(nr, - (intptr_t)p0, - (intptr_t)p1, - (intptr_t)p2, - (intptr_t)p3, - (intptr_t)p4, - (intptr_t)p5, - 0, - 0); - } - - template <class T0, class T1, class T2, class T3, class T4> - static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4) { - return Call(nr, p0, p1, p2, p3, p4, 0, 0, 0); - } - - template <class T0, class T1, class T2, class T3> - static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3) { - return Call(nr, p0, p1, p2, p3, 0, 0, 0, 0); - } - - template <class T0, class T1, class T2> - static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2) { - return Call(nr, p0, p1, p2, 0, 0, 0, 0, 0); - } - - template <class T0, class T1> - static inline intptr_t Call(int nr, T0 p0, T1 p1) { - return Call(nr, p0, p1, 0, 0, 0, 0, 0, 0); - } - - template <class T0> - static inline intptr_t Call(int nr, T0 p0) { - return Call(nr, p0, 0, 0, 0, 0, 0, 0, 0); - } - - static inline intptr_t Call(int nr) { - return Call(nr, 0, 0, 0, 0, 0, 0, 0, 0); - } - - // Set the registers in |ctx| to match what they would be after a system call - // returning |ret_val|. |ret_val| must follow the Syscall::Call() convention - // of being -errno on errors. - static void PutValueInUcontext(intptr_t ret_val, ucontext_t* ctx); - - private: - // This performs system call |nr| with the arguments p0 to p7 from a constant - // userland address, which is for instance observable by seccomp-bpf filters. - // The constant userland address from which these system calls are made will - // be returned if |nr| is passed as -1. - // On error, this function will return a value between -1 and -4095 which - // should be interpreted as -errno. - static intptr_t Call(int nr, - intptr_t p0, - intptr_t p1, - intptr_t p2, - intptr_t p3, - intptr_t p4, - intptr_t p5, - intptr_t p6, - intptr_t p7); - -#if defined(__mips__) - // This function basically does on MIPS what SandboxSyscall() is doing on - // other architectures. However, because of specificity of MIPS regarding - // handling syscall errors, SandboxSyscall() is made as a wrapper for this - // function in order for SandboxSyscall() to behave more like on other - // architectures on places where return value from SandboxSyscall() is used - // directly (like in most tests). - // The syscall "nr" is called with arguments that are set in an array on which - // pointer "args" points to and an information weather there is an error or no - // is returned to SandboxSyscall() by err_stat. - static intptr_t SandboxSyscallRaw(int nr, - const intptr_t* args, - intptr_t* err_stat); -#endif // defined(__mips__) - - DISALLOW_IMPLICIT_CONSTRUCTORS(Syscall); -}; - -} // namespace sandbox - -#endif // SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__ diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall_unittest.cc deleted file mode 100644 index 01336f9b6..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/syscall_unittest.cc +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/seccomp-bpf/syscall.h" - -#include <asm/unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/mman.h> -#include <sys/syscall.h> -#include <sys/types.h> -#include <unistd.h> - -#include <vector> - -#include "base/macros.h" -#include "base/posix/eintr_wrapper.h" -#include "build/build_config.h" -#include "sandbox/linux/bpf_dsl/bpf_dsl.h" -#include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/seccomp-bpf/bpf_tests.h" -#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" -#include "sandbox/linux/tests/unit_tests.h" -#include "testing/gtest/include/gtest/gtest.h" - -using sandbox::bpf_dsl::Allow; -using sandbox::bpf_dsl::ResultExpr; -using sandbox::bpf_dsl::Trap; - -namespace sandbox { - -namespace { - -// Different platforms use different symbols for the six-argument version -// of the mmap() system call. Test for the correct symbol at compile time. -#ifdef __NR_mmap2 -const int kMMapNr = __NR_mmap2; -#else -const int kMMapNr = __NR_mmap; -#endif - -TEST(Syscall, InvalidCallReturnsENOSYS) { - EXPECT_EQ(-ENOSYS, Syscall::InvalidCall()); -} - -TEST(Syscall, WellKnownEntryPoint) { -// Test that Syscall::Call(-1) is handled specially. Don't do this on ARM, -// where syscall(-1) crashes with SIGILL. Not running the test is fine, as we -// are still testing ARM code in the next set of tests. -#if !defined(__arm__) && !defined(__aarch64__) - EXPECT_NE(Syscall::Call(-1), syscall(-1)); -#endif - -// If possible, test that Syscall::Call(-1) returns the address right -// after -// a kernel entry point. -#if defined(__i386__) - EXPECT_EQ(0x80CDu, ((uint16_t*)Syscall::Call(-1))[-1]); // INT 0x80 -#elif defined(__x86_64__) - EXPECT_EQ(0x050Fu, ((uint16_t*)Syscall::Call(-1))[-1]); // SYSCALL -#elif defined(__arm__) -#if defined(__thumb__) - EXPECT_EQ(0xDF00u, ((uint16_t*)Syscall::Call(-1))[-1]); // SWI 0 -#else - EXPECT_EQ(0xEF000000u, ((uint32_t*)Syscall::Call(-1))[-1]); // SVC 0 -#endif -#elif defined(__mips__) - // Opcode for MIPS sycall is in the lower 16-bits - EXPECT_EQ(0x0cu, (((uint32_t*)Syscall::Call(-1))[-1]) & 0x0000FFFF); -#elif defined(__aarch64__) - EXPECT_EQ(0xD4000001u, ((uint32_t*)Syscall::Call(-1))[-1]); // SVC 0 -#else -#warning Incomplete test case; need port for target platform -#endif -} - -TEST(Syscall, TrivialSyscallNoArgs) { - // Test that we can do basic system calls - EXPECT_EQ(Syscall::Call(__NR_getpid), syscall(__NR_getpid)); -} - -TEST(Syscall, TrivialSyscallOneArg) { - int new_fd; - // Duplicate standard error and close it. - ASSERT_GE(new_fd = Syscall::Call(__NR_dup, 2), 0); - int close_return_value = IGNORE_EINTR(Syscall::Call(__NR_close, new_fd)); - ASSERT_EQ(close_return_value, 0); -} - -TEST(Syscall, TrivialFailingSyscall) { - errno = -42; - int ret = Syscall::Call(__NR_dup, -1); - ASSERT_EQ(-EBADF, ret); - // Verify that Syscall::Call does not touch errno. - ASSERT_EQ(-42, errno); -} - -// SIGSYS trap handler that will be called on __NR_uname. -intptr_t CopySyscallArgsToAux(const struct arch_seccomp_data& args, void* aux) { - // |aux| is our BPF_AUX pointer. - std::vector<uint64_t>* const seen_syscall_args = - static_cast<std::vector<uint64_t>*>(aux); - BPF_ASSERT(arraysize(args.args) == 6); - seen_syscall_args->assign(args.args, args.args + arraysize(args.args)); - return -ENOMEM; -} - -class CopyAllArgsOnUnamePolicy : public bpf_dsl::Policy { - public: - explicit CopyAllArgsOnUnamePolicy(std::vector<uint64_t>* aux) : aux_(aux) {} - ~CopyAllArgsOnUnamePolicy() override {} - - ResultExpr EvaluateSyscall(int sysno) const override { - DCHECK(SandboxBPF::IsValidSyscallNumber(sysno)); - if (sysno == __NR_uname) { - return Trap(CopySyscallArgsToAux, aux_); - } else { - return Allow(); - } - } - - private: - std::vector<uint64_t>* aux_; - - DISALLOW_COPY_AND_ASSIGN(CopyAllArgsOnUnamePolicy); -}; - -// We are testing Syscall::Call() by making use of a BPF filter that -// allows us -// to inspect the system call arguments that the kernel saw. -BPF_TEST(Syscall, - SyntheticSixArgs, - CopyAllArgsOnUnamePolicy, - std::vector<uint64_t> /* (*BPF_AUX) */) { - const int kExpectedValue = 42; - // In this test we only pass integers to the kernel. We might want to make - // additional tests to try other types. What we will see depends on - // implementation details of kernel BPF filters and we will need to document - // the expected behavior very clearly. - int syscall_args[6]; - for (size_t i = 0; i < arraysize(syscall_args); ++i) { - syscall_args[i] = kExpectedValue + i; - } - - // We could use pretty much any system call we don't need here. uname() is - // nice because it doesn't have any dangerous side effects. - BPF_ASSERT(Syscall::Call(__NR_uname, - syscall_args[0], - syscall_args[1], - syscall_args[2], - syscall_args[3], - syscall_args[4], - syscall_args[5]) == -ENOMEM); - - // We expect the trap handler to have copied the 6 arguments. - BPF_ASSERT(BPF_AUX->size() == 6); - - // Don't loop here so that we can see which argument does cause the failure - // easily from the failing line. - // uint64_t is the type passed to our SIGSYS handler. - BPF_ASSERT((*BPF_AUX)[0] == static_cast<uint64_t>(syscall_args[0])); - BPF_ASSERT((*BPF_AUX)[1] == static_cast<uint64_t>(syscall_args[1])); - BPF_ASSERT((*BPF_AUX)[2] == static_cast<uint64_t>(syscall_args[2])); - BPF_ASSERT((*BPF_AUX)[3] == static_cast<uint64_t>(syscall_args[3])); - BPF_ASSERT((*BPF_AUX)[4] == static_cast<uint64_t>(syscall_args[4])); - BPF_ASSERT((*BPF_AUX)[5] == static_cast<uint64_t>(syscall_args[5])); -} - -TEST(Syscall, ComplexSyscallSixArgs) { - int fd; - ASSERT_LE(0, - fd = Syscall::Call(__NR_openat, AT_FDCWD, "/dev/null", O_RDWR, 0L)); - - // Use mmap() to allocate some read-only memory - char* addr0; - ASSERT_NE( - (char*)NULL, - addr0 = reinterpret_cast<char*>(Syscall::Call(kMMapNr, - (void*)NULL, - 4096, - PROT_READ, - MAP_PRIVATE | MAP_ANONYMOUS, - fd, - 0L))); - - // Try to replace the existing mapping with a read-write mapping - char* addr1; - ASSERT_EQ(addr0, - addr1 = reinterpret_cast<char*>( - Syscall::Call(kMMapNr, - addr0, - 4096L, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, - fd, - 0L))); - ++*addr1; // This should not seg fault - - // Clean up - EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr1, 4096L)); - EXPECT_EQ(0, IGNORE_EINTR(Syscall::Call(__NR_close, fd))); - - // Check that the offset argument (i.e. the sixth argument) is processed - // correctly. - ASSERT_GE( - fd = Syscall::Call(__NR_openat, AT_FDCWD, "/proc/self/exe", O_RDONLY, 0L), - 0); - char* addr2, *addr3; - ASSERT_NE((char*)NULL, - addr2 = reinterpret_cast<char*>(Syscall::Call( - kMMapNr, (void*)NULL, 8192L, PROT_READ, MAP_PRIVATE, fd, 0L))); - ASSERT_NE((char*)NULL, - addr3 = reinterpret_cast<char*>(Syscall::Call(kMMapNr, - (void*)NULL, - 4096L, - PROT_READ, - MAP_PRIVATE, - fd, -#if defined(__NR_mmap2) - 1L -#else - 4096L -#endif - ))); - EXPECT_EQ(0, memcmp(addr2 + 4096, addr3, 4096)); - - // Just to be absolutely on the safe side, also verify that the file - // contents matches what we are getting from a read() operation. - char buf[8192]; - EXPECT_EQ(8192, Syscall::Call(__NR_read, fd, buf, 8192L)); - EXPECT_EQ(0, memcmp(addr2, buf, 8192)); - - // Clean up - EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr2, 8192L)); - EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr3, 4096L)); - EXPECT_EQ(0, IGNORE_EINTR(Syscall::Call(__NR_close, fd))); -} - -} // namespace - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc deleted file mode 100644 index 003708d2c..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc +++ /dev/null @@ -1,387 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/seccomp-bpf/trap.h" - -#include <errno.h> -#include <signal.h> -#include <stddef.h> -#include <stdint.h> -#include <string.h> -#include <sys/syscall.h> - -#include <algorithm> -#include <limits> -#include <tuple> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "build/build_config.h" -#include "sandbox/linux/bpf_dsl/seccomp_macros.h" -#include "sandbox/linux/seccomp-bpf/die.h" -#include "sandbox/linux/seccomp-bpf/syscall.h" -#include "sandbox/linux/services/syscall_wrappers.h" -#include "sandbox/linux/system_headers/linux_seccomp.h" -#include "sandbox/linux/system_headers/linux_signal.h" - -namespace { - -struct arch_sigsys { - void* ip; - int nr; - unsigned int arch; -}; - -const int kCapacityIncrement = 20; - -// Unsafe traps can only be turned on, if the user explicitly allowed them -// by setting the CHROME_SANDBOX_DEBUGGING environment variable. -const char kSandboxDebuggingEnv[] = "CHROME_SANDBOX_DEBUGGING"; - -// We need to tell whether we are performing a "normal" callback, or -// whether we were called recursively from within a UnsafeTrap() callback. -// This is a little tricky to do, because we need to somehow get access to -// per-thread data from within a signal context. Normal TLS storage is not -// safely accessible at this time. We could roll our own, but that involves -// a lot of complexity. Instead, we co-opt one bit in the signal mask. -// If BUS is blocked, we assume that we have been called recursively. -// There is a possibility for collision with other code that needs to do -// this, but in practice the risks are low. -// If SIGBUS turns out to be a problem, we could instead co-opt one of the -// realtime signals. There are plenty of them. Unfortunately, there is no -// way to mark a signal as allocated. So, the potential for collision is -// possibly even worse. -bool GetIsInSigHandler(const ucontext_t* ctx) { - // Note: on Android, sigismember does not take a pointer to const. - return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), LINUX_SIGBUS); -} - -void SetIsInSigHandler() { - sigset_t mask; - if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGBUS) || - sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, NULL)) { - SANDBOX_DIE("Failed to block SIGBUS"); - } -} - -bool IsDefaultSignalAction(const struct sigaction& sa) { - if (sa.sa_flags & SA_SIGINFO || sa.sa_handler != SIG_DFL) { - return false; - } - return true; -} - -} // namespace - -namespace sandbox { - -Trap::Trap() - : trap_array_(NULL), - trap_array_size_(0), - trap_array_capacity_(0), - has_unsafe_traps_(false) { - // Set new SIGSYS handler - struct sigaction sa = {}; - // In some toolchain, sa_sigaction is not declared in struct sigaction. - // So, here cast the pointer to the sa_handler's type. This works because - // |sa_handler| and |sa_sigaction| shares the same memory. - sa.sa_handler = reinterpret_cast<void (*)(int)>(SigSysAction); - sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER; - struct sigaction old_sa = {}; - if (sys_sigaction(LINUX_SIGSYS, &sa, &old_sa) < 0) { - SANDBOX_DIE("Failed to configure SIGSYS handler"); - } - - if (!IsDefaultSignalAction(old_sa)) { - static const char kExistingSIGSYSMsg[] = - "Existing signal handler when trying to install SIGSYS. SIGSYS needs " - "to be reserved for seccomp-bpf."; - DLOG(FATAL) << kExistingSIGSYSMsg; - LOG(ERROR) << kExistingSIGSYSMsg; - } - - // Unmask SIGSYS - sigset_t mask; - if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGSYS) || - sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL)) { - SANDBOX_DIE("Failed to configure SIGSYS handler"); - } -} - -bpf_dsl::TrapRegistry* Trap::Registry() { - // Note: This class is not thread safe. It is the caller's responsibility - // to avoid race conditions. Normally, this is a non-issue as the sandbox - // can only be initialized if there are no other threads present. - // Also, this is not a normal singleton. Once created, the global trap - // object must never be destroyed again. - if (!global_trap_) { - global_trap_ = new Trap(); - if (!global_trap_) { - SANDBOX_DIE("Failed to allocate global trap handler"); - } - } - return global_trap_; -} - -void Trap::SigSysAction(int nr, LinuxSigInfo* info, void* void_context) { - if (info) { - MSAN_UNPOISON(info, sizeof(*info)); - } - - // Obtain the signal context. This, most notably, gives us access to - // all CPU registers at the time of the signal. - ucontext_t* ctx = reinterpret_cast<ucontext_t*>(void_context); - if (ctx) { - MSAN_UNPOISON(ctx, sizeof(*ctx)); - } - - if (!global_trap_) { - RAW_SANDBOX_DIE( - "This can't happen. Found no global singleton instance " - "for Trap() handling."); - } - global_trap_->SigSys(nr, info, ctx); -} - -void Trap::SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx) { - // Signal handlers should always preserve "errno". Otherwise, we could - // trigger really subtle bugs. - const int old_errno = errno; - - // Various sanity checks to make sure we actually received a signal - // triggered by a BPF filter. If something else triggered SIGSYS - // (e.g. kill()), there is really nothing we can do with this signal. - if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !ctx || - info->si_errno <= 0 || - static_cast<size_t>(info->si_errno) > trap_array_size_) { - // ATI drivers seem to send SIGSYS, so this cannot be FATAL. - // See crbug.com/178166. - // TODO(jln): add a DCHECK or move back to FATAL. - RAW_LOG(ERROR, "Unexpected SIGSYS received."); - errno = old_errno; - return; - } - - - // Obtain the siginfo information that is specific to SIGSYS. Unfortunately, - // most versions of glibc don't include this information in siginfo_t. So, - // we need to explicitly copy it into a arch_sigsys structure. - struct arch_sigsys sigsys; - memcpy(&sigsys, &info->_sifields, sizeof(sigsys)); - -#if defined(__mips__) - // When indirect syscall (syscall(__NR_foo, ...)) is made on Mips, the - // number in register SECCOMP_SYSCALL(ctx) is always __NR_syscall and the - // real number of a syscall (__NR_foo) is in SECCOMP_PARM1(ctx) - bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) && - sigsys.nr != static_cast<int>(SECCOMP_PARM1(ctx)); -#else - bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)); -#endif - - // Some more sanity checks. - if (sigsys.ip != reinterpret_cast<void*>(SECCOMP_IP(ctx)) || - sigsys_nr_is_bad || sigsys.arch != SECCOMP_ARCH) { - // TODO(markus): - // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal - // safe and can lead to bugs. We should eventually implement a different - // logging and reporting mechanism that is safe to be called from - // the sigSys() handler. - RAW_SANDBOX_DIE("Sanity checks are failing after receiving SIGSYS."); - } - - intptr_t rc; - if (has_unsafe_traps_ && GetIsInSigHandler(ctx)) { - errno = old_errno; - if (sigsys.nr == __NR_clone) { - RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler."); - } -#if defined(__mips__) - // Mips supports up to eight arguments for syscall. - // However, seccomp bpf can filter only up to six arguments, so using eight - // arguments has sense only when using UnsafeTrap() handler. - rc = Syscall::Call(SECCOMP_SYSCALL(ctx), - SECCOMP_PARM1(ctx), - SECCOMP_PARM2(ctx), - SECCOMP_PARM3(ctx), - SECCOMP_PARM4(ctx), - SECCOMP_PARM5(ctx), - SECCOMP_PARM6(ctx), - SECCOMP_PARM7(ctx), - SECCOMP_PARM8(ctx)); -#else - rc = Syscall::Call(SECCOMP_SYSCALL(ctx), - SECCOMP_PARM1(ctx), - SECCOMP_PARM2(ctx), - SECCOMP_PARM3(ctx), - SECCOMP_PARM4(ctx), - SECCOMP_PARM5(ctx), - SECCOMP_PARM6(ctx)); -#endif // defined(__mips__) - } else { - const TrapKey& trap = trap_array_[info->si_errno - 1]; - if (!trap.safe) { - SetIsInSigHandler(); - } - - // Copy the seccomp-specific data into a arch_seccomp_data structure. This - // is what we are showing to TrapFnc callbacks that the system call - // evaluator registered with the sandbox. - struct arch_seccomp_data data = { - static_cast<int>(SECCOMP_SYSCALL(ctx)), - SECCOMP_ARCH, - reinterpret_cast<uint64_t>(sigsys.ip), - {static_cast<uint64_t>(SECCOMP_PARM1(ctx)), - static_cast<uint64_t>(SECCOMP_PARM2(ctx)), - static_cast<uint64_t>(SECCOMP_PARM3(ctx)), - static_cast<uint64_t>(SECCOMP_PARM4(ctx)), - static_cast<uint64_t>(SECCOMP_PARM5(ctx)), - static_cast<uint64_t>(SECCOMP_PARM6(ctx))}}; - - // Now call the TrapFnc callback associated with this particular instance - // of SECCOMP_RET_TRAP. - rc = trap.fnc(data, const_cast<void*>(trap.aux)); - } - - // Update the CPU register that stores the return code of the system call - // that we just handled, and restore "errno" to the value that it had - // before entering the signal handler. - Syscall::PutValueInUcontext(rc, ctx); - errno = old_errno; - - return; -} - -bool Trap::TrapKey::operator<(const TrapKey& o) const { - return std::tie(fnc, aux, safe) < std::tie(o.fnc, o.aux, o.safe); -} - -uint16_t Trap::Add(TrapFnc fnc, const void* aux, bool safe) { - if (!safe && !SandboxDebuggingAllowedByUser()) { - // Unless the user set the CHROME_SANDBOX_DEBUGGING environment variable, - // we never return an ErrorCode that is marked as "unsafe". This also - // means, the BPF compiler will never emit code that allow unsafe system - // calls to by-pass the filter (because they use the magic return address - // from Syscall::Call(-1)). - - // This SANDBOX_DIE() can optionally be removed. It won't break security, - // but it might make error messages from the BPF compiler a little harder - // to understand. Removing the SANDBOX_DIE() allows callers to easily check - // whether unsafe traps are supported (by checking whether the returned - // ErrorCode is ET_INVALID). - SANDBOX_DIE( - "Cannot use unsafe traps unless CHROME_SANDBOX_DEBUGGING " - "is enabled"); - - return 0; - } - - // Each unique pair of TrapFnc and auxiliary data make up a distinct instance - // of a SECCOMP_RET_TRAP. - TrapKey key(fnc, aux, safe); - - // We return unique identifiers together with SECCOMP_RET_TRAP. This allows - // us to associate trap with the appropriate handler. The kernel allows us - // identifiers in the range from 0 to SECCOMP_RET_DATA (0xFFFF). We want to - // avoid 0, as it could be confused for a trap without any specific id. - // The nice thing about sequentially numbered identifiers is that we can also - // trivially look them up from our signal handler without making any system - // calls that might be async-signal-unsafe. - // In order to do so, we store all of our traps in a C-style trap_array_. - - TrapIds::const_iterator iter = trap_ids_.find(key); - if (iter != trap_ids_.end()) { - // We have seen this pair before. Return the same id that we assigned - // earlier. - return iter->second; - } - - // This is a new pair. Remember it and assign a new id. - if (trap_array_size_ >= SECCOMP_RET_DATA /* 0xFFFF */ || - trap_array_size_ >= std::numeric_limits<uint16_t>::max()) { - // In practice, this is pretty much impossible to trigger, as there - // are other kernel limitations that restrict overall BPF program sizes. - SANDBOX_DIE("Too many SECCOMP_RET_TRAP callback instances"); - } - - // Our callers ensure that there are no other threads accessing trap_array_ - // concurrently (typically this is done by ensuring that we are single- - // threaded while the sandbox is being set up). But we nonetheless are - // modifying a live data structure that could be accessed any time a - // system call is made; as system calls could be triggering SIGSYS. - // So, we have to be extra careful that we update trap_array_ atomically. - // In particular, this means we shouldn't be using realloc() to resize it. - // Instead, we allocate a new array, copy the values, and then switch the - // pointer. We only really care about the pointer being updated atomically - // and the data that is pointed to being valid, as these are the only - // values accessed from the signal handler. It is OK if trap_array_size_ - // is inconsistent with the pointer, as it is monotonously increasing. - // Also, we only care about compiler barriers, as the signal handler is - // triggered synchronously from a system call. We don't have to protect - // against issues with the memory model or with completely asynchronous - // events. - if (trap_array_size_ >= trap_array_capacity_) { - trap_array_capacity_ += kCapacityIncrement; - TrapKey* old_trap_array = trap_array_; - TrapKey* new_trap_array = new TrapKey[trap_array_capacity_]; - std::copy_n(old_trap_array, trap_array_size_, new_trap_array); - - // Language specs are unclear on whether the compiler is allowed to move - // the "delete[]" above our preceding assignments and/or memory moves, - // iff the compiler believes that "delete[]" doesn't have any other - // global side-effects. - // We insert optimization barriers to prevent this from happening. - // The first barrier is probably not needed, but better be explicit in - // what we want to tell the compiler. - // The clang developer mailing list couldn't answer whether this is a - // legitimate worry; but they at least thought that the barrier is - // sufficient to prevent the (so far hypothetical) problem of re-ordering - // of instructions by the compiler. - // - // TODO(mdempsky): Try to clean this up using base/atomicops or C++11 - // atomics; see crbug.com/414363. - asm volatile("" : "=r"(new_trap_array) : "0"(new_trap_array) : "memory"); - trap_array_ = new_trap_array; - asm volatile("" : "=r"(trap_array_) : "0"(trap_array_) : "memory"); - - delete[] old_trap_array; - } - - uint16_t id = trap_array_size_ + 1; - trap_ids_[key] = id; - trap_array_[trap_array_size_] = key; - trap_array_size_++; - return id; -} - -bool Trap::SandboxDebuggingAllowedByUser() { - const char* debug_flag = getenv(kSandboxDebuggingEnv); - return debug_flag && *debug_flag; -} - -bool Trap::EnableUnsafeTraps() { - if (!has_unsafe_traps_) { - // Unsafe traps are a one-way fuse. Once enabled, they can never be turned - // off again. - // We only allow enabling unsafe traps, if the user explicitly set an - // appropriate environment variable. This prevents bugs that accidentally - // disable all sandboxing for all users. - if (SandboxDebuggingAllowedByUser()) { - // We only ever print this message once, when we enable unsafe traps the - // first time. - SANDBOX_INFO("WARNING! Disabling sandbox for debugging purposes"); - has_unsafe_traps_ = true; - } else { - SANDBOX_INFO( - "Cannot disable sandbox and use unsafe traps unless " - "CHROME_SANDBOX_DEBUGGING is turned on first"); - } - } - // Returns the, possibly updated, value of has_unsafe_traps_. - return has_unsafe_traps_; -} - -Trap* Trap::global_trap_; - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.h b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.h deleted file mode 100644 index a73d2064b..000000000 --- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ -#define SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ - -#include <stddef.h> -#include <stdint.h> - -#include <map> - -#include "base/macros.h" -#include "sandbox/linux/bpf_dsl/trap_registry.h" -#include "sandbox/linux/system_headers/linux_signal.h" -#include "sandbox/sandbox_export.h" - -namespace sandbox { - -// The Trap class allows a BPF filter program to branch out to user space by -// raising a SIGSYS signal. -// N.B.: This class does not perform any synchronization operations. If -// modifications are made to any of the traps, it is the caller's -// responsibility to ensure that this happens in a thread-safe fashion. -// Preferably, that means that no other threads should be running at that -// time. For the purposes of our sandbox, this assertion should always be -// true. Threads are incompatible with the seccomp sandbox anyway. -class SANDBOX_EXPORT Trap : public bpf_dsl::TrapRegistry { - public: - uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override; - - bool EnableUnsafeTraps() override; - - // Registry returns the trap registry used by Trap's SIGSYS handler, - // creating it if necessary. - static bpf_dsl::TrapRegistry* Registry(); - - // SandboxDebuggingAllowedByUser returns whether the - // "CHROME_SANDBOX_DEBUGGING" environment variable is set. - static bool SandboxDebuggingAllowedByUser(); - - private: - struct TrapKey { - TrapKey() : fnc(NULL), aux(NULL), safe(false) {} - TrapKey(TrapFnc f, const void* a, bool s) : fnc(f), aux(a), safe(s) {} - TrapFnc fnc; - const void* aux; - bool safe; - bool operator<(const TrapKey&) const; - }; - typedef std::map<TrapKey, uint16_t> TrapIds; - - // Our constructor is private. A shared global instance is created - // automatically as needed. - Trap(); - - // The destructor is unimplemented as destroying this object would - // break subsequent system calls that trigger a SIGSYS. - ~Trap() = delete; - - static void SigSysAction(int nr, LinuxSigInfo* info, void* void_context); - - // Make sure that SigSys is not inlined in order to get slightly better crash - // dumps. - void SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx) - __attribute__((noinline)); - // We have a global singleton that handles all of our SIGSYS traps. This - // variable must never be deallocated after it has been set up initially, as - // there is no way to reset in-kernel BPF filters that generate SIGSYS - // events. - static Trap* global_trap_; - - TrapIds trap_ids_; // Maps from TrapKeys to numeric ids - TrapKey* trap_array_; // Array of TrapKeys indexed by ids - size_t trap_array_size_; // Currently used size of array - size_t trap_array_capacity_; // Currently allocated capacity of array - bool has_unsafe_traps_; // Whether unsafe traps have been enabled - - // Copying and assigning is unimplemented. It doesn't make sense for a - // singleton. - DISALLOW_COPY_AND_ASSIGN(Trap); -}; - -} // namespace sandbox - -#endif // SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ diff --git a/security/sandbox/chromium/sandbox/linux/services/syscall_wrappers.cc b/security/sandbox/chromium/sandbox/linux/services/syscall_wrappers.cc deleted file mode 100644 index 9d5a6ada0..000000000 --- a/security/sandbox/chromium/sandbox/linux/services/syscall_wrappers.cc +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/linux/services/syscall_wrappers.h" - -#include <pthread.h> -#include <sched.h> -#include <setjmp.h> -#include <sys/resource.h> -#include <sys/syscall.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <cstring> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/third_party/valgrind/valgrind.h" -#include "build/build_config.h" -#include "sandbox/linux/system_headers/capability.h" -#include "sandbox/linux/system_headers/linux_signal.h" -#include "sandbox/linux/system_headers/linux_syscalls.h" - -namespace sandbox { - -pid_t sys_getpid(void) { - return syscall(__NR_getpid); -} - -pid_t sys_gettid(void) { - return syscall(__NR_gettid); -} - -long sys_clone(unsigned long flags, - std::nullptr_t child_stack, - pid_t* ptid, - pid_t* ctid, - std::nullptr_t tls) { - const bool clone_tls_used = flags & CLONE_SETTLS; - const bool invalid_ctid = - (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && !ctid; - const bool invalid_ptid = (flags & CLONE_PARENT_SETTID) && !ptid; - - // We do not support CLONE_VM. - const bool clone_vm_used = flags & CLONE_VM; - if (clone_tls_used || invalid_ctid || invalid_ptid || clone_vm_used) { - RAW_LOG(FATAL, "Invalid usage of sys_clone"); - } - - if (ptid) MSAN_UNPOISON(ptid, sizeof(*ptid)); - if (ctid) MSAN_UNPOISON(ctid, sizeof(*ctid)); - // See kernel/fork.c in Linux. There is different ordering of sys_clone - // parameters depending on CONFIG_CLONE_BACKWARDS* configuration options. -#if defined(ARCH_CPU_X86_64) - return syscall(__NR_clone, flags, child_stack, ptid, ctid, tls); -#elif defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARM_FAMILY) || \ - defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY) - // CONFIG_CLONE_BACKWARDS defined. - return syscall(__NR_clone, flags, child_stack, ptid, tls, ctid); -#endif -} - -long sys_clone(unsigned long flags) { - return sys_clone(flags, nullptr, nullptr, nullptr, nullptr); -} - -void sys_exit_group(int status) { - syscall(__NR_exit_group, status); -} - -int sys_seccomp(unsigned int operation, - unsigned int flags, - const struct sock_fprog* args) { - return syscall(__NR_seccomp, operation, flags, args); -} - -int sys_prlimit64(pid_t pid, - int resource, - const struct rlimit64* new_limit, - struct rlimit64* old_limit) { - int res = syscall(__NR_prlimit64, pid, resource, new_limit, old_limit); - if (res == 0 && old_limit) MSAN_UNPOISON(old_limit, sizeof(*old_limit)); - return res; -} - -int sys_capget(cap_hdr* hdrp, cap_data* datap) { - int res = syscall(__NR_capget, hdrp, datap); - if (res == 0) { - if (hdrp) MSAN_UNPOISON(hdrp, sizeof(*hdrp)); - if (datap) MSAN_UNPOISON(datap, sizeof(*datap)); - } - return res; -} - -int sys_capset(cap_hdr* hdrp, const cap_data* datap) { - return syscall(__NR_capset, hdrp, datap); -} - -int sys_getresuid(uid_t* ruid, uid_t* euid, uid_t* suid) { - int res; -#if defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARMEL) - // On 32-bit x86 or 32-bit arm, getresuid supports 16bit values only. - // Use getresuid32 instead. - res = syscall(__NR_getresuid32, ruid, euid, suid); -#else - res = syscall(__NR_getresuid, ruid, euid, suid); -#endif - if (res == 0) { - if (ruid) MSAN_UNPOISON(ruid, sizeof(*ruid)); - if (euid) MSAN_UNPOISON(euid, sizeof(*euid)); - if (suid) MSAN_UNPOISON(suid, sizeof(*suid)); - } - return res; -} - -int sys_getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid) { - int res; -#if defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARMEL) - // On 32-bit x86 or 32-bit arm, getresgid supports 16bit values only. - // Use getresgid32 instead. - res = syscall(__NR_getresgid32, rgid, egid, sgid); -#else - res = syscall(__NR_getresgid, rgid, egid, sgid); -#endif - if (res == 0) { - if (rgid) MSAN_UNPOISON(rgid, sizeof(*rgid)); - if (egid) MSAN_UNPOISON(egid, sizeof(*egid)); - if (sgid) MSAN_UNPOISON(sgid, sizeof(*sgid)); - } - return res; -} - -int sys_chroot(const char* path) { - return syscall(__NR_chroot, path); -} - -int sys_unshare(int flags) { - return syscall(__NR_unshare, flags); -} - -int sys_sigprocmask(int how, const sigset_t* set, std::nullptr_t oldset) { - // In some toolchain (in particular Android and PNaCl toolchain), - // sigset_t is 32 bits, but the Linux ABI uses more. - LinuxSigSet linux_value; - std::memset(&linux_value, 0, sizeof(LinuxSigSet)); - std::memcpy(&linux_value, set, std::min(sizeof(sigset_t), - sizeof(LinuxSigSet))); - - return syscall(__NR_rt_sigprocmask, how, &linux_value, nullptr, - sizeof(linux_value)); -} - -// When this is built with PNaCl toolchain, we should always use sys_sigaction -// below, because sigaction() provided by the toolchain is incompatible with -// Linux's ABI. -#if !defined(OS_NACL_NONSFI) -int sys_sigaction(int signum, - const struct sigaction* act, - struct sigaction* oldact) { - return sigaction(signum, act, oldact); -} -#else -#if defined(ARCH_CPU_X86_FAMILY) - -// On x86_64, sa_restorer is required. We specify it on x86 as well in order to -// support kernels with VDSO disabled. -#if !defined(SA_RESTORER) -#define SA_RESTORER 0x04000000 -#endif - -// XSTR(__NR_foo) expands to a string literal containing the value value of -// __NR_foo. -#define STR(x) #x -#define XSTR(x) STR(x) - -// rt_sigreturn is a special system call that interacts with the user land -// stack. Thus, here prologue must not be created, which implies syscall() -// does not work properly, too. Note that rt_sigreturn does not return. -// TODO(rickyz): These assembly functions may still break stack unwinding on -// nonsfi NaCl builds. -#if defined(ARCH_CPU_X86_64) - -extern "C" { - void sys_rt_sigreturn(); -} - -asm( - ".text\n" - "sys_rt_sigreturn:\n" - "mov $" XSTR(__NR_rt_sigreturn) ", %eax\n" - "syscall\n"); - -#elif defined(ARCH_CPU_X86) -extern "C" { - void sys_sigreturn(); - void sys_rt_sigreturn(); -} - -asm( - ".text\n" - "sys_rt_sigreturn:\n" - "mov $" XSTR(__NR_rt_sigreturn) ", %eax\n" - "int $0x80\n" - - "sys_sigreturn:\n" - "pop %eax\n" - "mov $" XSTR(__NR_sigreturn) ", %eax\n" - "int $0x80\n"); -#else -#error "Unsupported architecture." -#endif - -#undef STR -#undef XSTR - -#endif - -int sys_sigaction(int signum, - const struct sigaction* act, - struct sigaction* oldact) { - LinuxSigAction linux_act = {}; - if (act) { - linux_act.kernel_handler = act->sa_handler; - std::memcpy(&linux_act.sa_mask, &act->sa_mask, - std::min(sizeof(linux_act.sa_mask), sizeof(act->sa_mask))); - linux_act.sa_flags = act->sa_flags; - -#if defined(ARCH_CPU_X86_FAMILY) - if (!(linux_act.sa_flags & SA_RESTORER)) { - linux_act.sa_flags |= SA_RESTORER; -#if defined(ARCH_CPU_X86_64) - linux_act.sa_restorer = sys_rt_sigreturn; -#elif defined(ARCH_CPU_X86) - linux_act.sa_restorer = - linux_act.sa_flags & SA_SIGINFO ? sys_rt_sigreturn : sys_sigreturn; -#else -#error "Unsupported architecture." -#endif - } -#endif - } - - LinuxSigAction linux_oldact = {}; - int result = syscall(__NR_rt_sigaction, signum, act ? &linux_act : nullptr, - oldact ? &linux_oldact : nullptr, - sizeof(LinuxSigSet)); - - if (result == 0 && oldact) { - oldact->sa_handler = linux_oldact.kernel_handler; - sigemptyset(&oldact->sa_mask); - std::memcpy(&oldact->sa_mask, &linux_oldact.sa_mask, - std::min(sizeof(linux_act.sa_mask), sizeof(act->sa_mask))); - oldact->sa_flags = linux_oldact.sa_flags; - } - return result; -} - -#endif // defined(MEMORY_SANITIZER) - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/linux/services/syscall_wrappers.h b/security/sandbox/chromium/sandbox/linux/services/syscall_wrappers.h deleted file mode 100644 index 057e4c87f..000000000 --- a/security/sandbox/chromium/sandbox/linux/services/syscall_wrappers.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ -#define SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ - -#include <signal.h> -#include <stdint.h> -#include <sys/types.h> - -#include <cstddef> - -#include "sandbox/sandbox_export.h" - -struct sock_fprog; -struct rlimit64; -struct cap_hdr; -struct cap_data; - -namespace sandbox { - -// Provide direct system call wrappers for a few common system calls. -// These are guaranteed to perform a system call and do not rely on things such -// as caching the current pid (c.f. getpid()) unless otherwise specified. - -SANDBOX_EXPORT pid_t sys_getpid(void); - -SANDBOX_EXPORT pid_t sys_gettid(void); - -SANDBOX_EXPORT long sys_clone(unsigned long flags); - -// |regs| is not supported and must be passed as nullptr. |child_stack| must be -// nullptr, since otherwise this function cannot safely return. As a -// consequence, this function does not support CLONE_VM. -SANDBOX_EXPORT long sys_clone(unsigned long flags, - std::nullptr_t child_stack, - pid_t* ptid, - pid_t* ctid, - std::nullptr_t regs); - -SANDBOX_EXPORT void sys_exit_group(int status); - -// The official system call takes |args| as void* (in order to be extensible), -// but add more typing for the cases that are currently used. -SANDBOX_EXPORT int sys_seccomp(unsigned int operation, - unsigned int flags, - const struct sock_fprog* args); - -// Some libcs do not expose a prlimit64 wrapper. -SANDBOX_EXPORT int sys_prlimit64(pid_t pid, - int resource, - const struct rlimit64* new_limit, - struct rlimit64* old_limit); - -// Some libcs do not expose capget/capset wrappers. We want to use these -// directly in order to avoid pulling in libcap2. -SANDBOX_EXPORT int sys_capget(struct cap_hdr* hdrp, struct cap_data* datap); -SANDBOX_EXPORT int sys_capset(struct cap_hdr* hdrp, - const struct cap_data* datap); - -// Some libcs do not expose getresuid/getresgid wrappers. -SANDBOX_EXPORT int sys_getresuid(uid_t* ruid, uid_t* euid, uid_t* suid); -SANDBOX_EXPORT int sys_getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid); - -// Some libcs do not expose a chroot wrapper. -SANDBOX_EXPORT int sys_chroot(const char* path); - -// Some libcs do not expose a unshare wrapper. -SANDBOX_EXPORT int sys_unshare(int flags); - -// Some libcs do not expose a sigprocmask. Note that oldset must be a nullptr, -// because of some ABI gap between toolchain's and Linux's. -SANDBOX_EXPORT int sys_sigprocmask(int how, - const sigset_t* set, - std::nullptr_t oldset); - -// Some libcs do not expose a sigaction(). -SANDBOX_EXPORT int sys_sigaction(int signum, - const struct sigaction* act, - struct sigaction* oldact); - -} // namespace sandbox - -#endif // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/arm_linux_syscalls.h b/security/sandbox/chromium/sandbox/linux/system_headers/arm_linux_syscalls.h deleted file mode 100644 index 1addd5384..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/arm_linux_syscalls.h +++ /dev/null @@ -1,1418 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Generated from the Linux kernel's calls.S. -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_SYSCALLS_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_SYSCALLS_H_ - -#if !defined(__arm__) || !defined(__ARM_EABI__) -#error "Including header on wrong architecture" -#endif - -#if !defined(__NR_SYSCALL_BASE) -// On ARM EABI arch, __NR_SYSCALL_BASE is 0. -#define __NR_SYSCALL_BASE 0 -#endif - -// This syscall list has holes, because ARM EABI makes some syscalls obsolete. - -#if !defined(__NR_restart_syscall) -#define __NR_restart_syscall (__NR_SYSCALL_BASE+0) -#endif - -#if !defined(__NR_exit) -#define __NR_exit (__NR_SYSCALL_BASE+1) -#endif - -#if !defined(__NR_fork) -#define __NR_fork (__NR_SYSCALL_BASE+2) -#endif - -#if !defined(__NR_read) -#define __NR_read (__NR_SYSCALL_BASE+3) -#endif - -#if !defined(__NR_write) -#define __NR_write (__NR_SYSCALL_BASE+4) -#endif - -#if !defined(__NR_open) -#define __NR_open (__NR_SYSCALL_BASE+5) -#endif - -#if !defined(__NR_close) -#define __NR_close (__NR_SYSCALL_BASE+6) -#endif - -#if !defined(__NR_creat) -#define __NR_creat (__NR_SYSCALL_BASE+8) -#endif - -#if !defined(__NR_link) -#define __NR_link (__NR_SYSCALL_BASE+9) -#endif - -#if !defined(__NR_unlink) -#define __NR_unlink (__NR_SYSCALL_BASE+10) -#endif - -#if !defined(__NR_execve) -#define __NR_execve (__NR_SYSCALL_BASE+11) -#endif - -#if !defined(__NR_chdir) -#define __NR_chdir (__NR_SYSCALL_BASE+12) -#endif - -#if !defined(__NR_mknod) -#define __NR_mknod (__NR_SYSCALL_BASE+14) -#endif - -#if !defined(__NR_chmod) -#define __NR_chmod (__NR_SYSCALL_BASE+15) -#endif - -#if !defined(__NR_lchown) -#define __NR_lchown (__NR_SYSCALL_BASE+16) -#endif - -#if !defined(__NR_lseek) -#define __NR_lseek (__NR_SYSCALL_BASE+19) -#endif - -#if !defined(__NR_getpid) -#define __NR_getpid (__NR_SYSCALL_BASE+20) -#endif - -#if !defined(__NR_mount) -#define __NR_mount (__NR_SYSCALL_BASE+21) -#endif - -#if !defined(__NR_setuid) -#define __NR_setuid (__NR_SYSCALL_BASE+23) -#endif - -#if !defined(__NR_getuid) -#define __NR_getuid (__NR_SYSCALL_BASE+24) -#endif - -#if !defined(__NR_ptrace) -#define __NR_ptrace (__NR_SYSCALL_BASE+26) -#endif - -#if !defined(__NR_pause) -#define __NR_pause (__NR_SYSCALL_BASE+29) -#endif - -#if !defined(__NR_access) -#define __NR_access (__NR_SYSCALL_BASE+33) -#endif - -#if !defined(__NR_nice) -#define __NR_nice (__NR_SYSCALL_BASE+34) -#endif - -#if !defined(__NR_sync) -#define __NR_sync (__NR_SYSCALL_BASE+36) -#endif - -#if !defined(__NR_kill) -#define __NR_kill (__NR_SYSCALL_BASE+37) -#endif - -#if !defined(__NR_rename) -#define __NR_rename (__NR_SYSCALL_BASE+38) -#endif - -#if !defined(__NR_mkdir) -#define __NR_mkdir (__NR_SYSCALL_BASE+39) -#endif - -#if !defined(__NR_rmdir) -#define __NR_rmdir (__NR_SYSCALL_BASE+40) -#endif - -#if !defined(__NR_dup) -#define __NR_dup (__NR_SYSCALL_BASE+41) -#endif - -#if !defined(__NR_pipe) -#define __NR_pipe (__NR_SYSCALL_BASE+42) -#endif - -#if !defined(__NR_times) -#define __NR_times (__NR_SYSCALL_BASE+43) -#endif - -#if !defined(__NR_brk) -#define __NR_brk (__NR_SYSCALL_BASE+45) -#endif - -#if !defined(__NR_setgid) -#define __NR_setgid (__NR_SYSCALL_BASE+46) -#endif - -#if !defined(__NR_getgid) -#define __NR_getgid (__NR_SYSCALL_BASE+47) -#endif - -#if !defined(__NR_geteuid) -#define __NR_geteuid (__NR_SYSCALL_BASE+49) -#endif - -#if !defined(__NR_getegid) -#define __NR_getegid (__NR_SYSCALL_BASE+50) -#endif - -#if !defined(__NR_acct) -#define __NR_acct (__NR_SYSCALL_BASE+51) -#endif - -#if !defined(__NR_umount2) -#define __NR_umount2 (__NR_SYSCALL_BASE+52) -#endif - -#if !defined(__NR_ioctl) -#define __NR_ioctl (__NR_SYSCALL_BASE+54) -#endif - -#if !defined(__NR_fcntl) -#define __NR_fcntl (__NR_SYSCALL_BASE+55) -#endif - -#if !defined(__NR_setpgid) -#define __NR_setpgid (__NR_SYSCALL_BASE+57) -#endif - -#if !defined(__NR_umask) -#define __NR_umask (__NR_SYSCALL_BASE+60) -#endif - -#if !defined(__NR_chroot) -#define __NR_chroot (__NR_SYSCALL_BASE+61) -#endif - -#if !defined(__NR_ustat) -#define __NR_ustat (__NR_SYSCALL_BASE+62) -#endif - -#if !defined(__NR_dup2) -#define __NR_dup2 (__NR_SYSCALL_BASE+63) -#endif - -#if !defined(__NR_getppid) -#define __NR_getppid (__NR_SYSCALL_BASE+64) -#endif - -#if !defined(__NR_getpgrp) -#define __NR_getpgrp (__NR_SYSCALL_BASE+65) -#endif - -#if !defined(__NR_setsid) -#define __NR_setsid (__NR_SYSCALL_BASE+66) -#endif - -#if !defined(__NR_sigaction) -#define __NR_sigaction (__NR_SYSCALL_BASE+67) -#endif - -#if !defined(__NR_setreuid) -#define __NR_setreuid (__NR_SYSCALL_BASE+70) -#endif - -#if !defined(__NR_setregid) -#define __NR_setregid (__NR_SYSCALL_BASE+71) -#endif - -#if !defined(__NR_sigsuspend) -#define __NR_sigsuspend (__NR_SYSCALL_BASE+72) -#endif - -#if !defined(__NR_sigpending) -#define __NR_sigpending (__NR_SYSCALL_BASE+73) -#endif - -#if !defined(__NR_sethostname) -#define __NR_sethostname (__NR_SYSCALL_BASE+74) -#endif - -#if !defined(__NR_setrlimit) -#define __NR_setrlimit (__NR_SYSCALL_BASE+75) -#endif - -#if !defined(__NR_getrusage) -#define __NR_getrusage (__NR_SYSCALL_BASE+77) -#endif - -#if !defined(__NR_gettimeofday) -#define __NR_gettimeofday (__NR_SYSCALL_BASE+78) -#endif - -#if !defined(__NR_settimeofday) -#define __NR_settimeofday (__NR_SYSCALL_BASE+79) -#endif - -#if !defined(__NR_getgroups) -#define __NR_getgroups (__NR_SYSCALL_BASE+80) -#endif - -#if !defined(__NR_setgroups) -#define __NR_setgroups (__NR_SYSCALL_BASE+81) -#endif - -#if !defined(__NR_symlink) -#define __NR_symlink (__NR_SYSCALL_BASE+83) -#endif - -#if !defined(__NR_readlink) -#define __NR_readlink (__NR_SYSCALL_BASE+85) -#endif - -#if !defined(__NR_uselib) -#define __NR_uselib (__NR_SYSCALL_BASE+86) -#endif - -#if !defined(__NR_swapon) -#define __NR_swapon (__NR_SYSCALL_BASE+87) -#endif - -#if !defined(__NR_reboot) -#define __NR_reboot (__NR_SYSCALL_BASE+88) -#endif - -#if !defined(__NR_munmap) -#define __NR_munmap (__NR_SYSCALL_BASE+91) -#endif - -#if !defined(__NR_truncate) -#define __NR_truncate (__NR_SYSCALL_BASE+92) -#endif - -#if !defined(__NR_ftruncate) -#define __NR_ftruncate (__NR_SYSCALL_BASE+93) -#endif - -#if !defined(__NR_fchmod) -#define __NR_fchmod (__NR_SYSCALL_BASE+94) -#endif - -#if !defined(__NR_fchown) -#define __NR_fchown (__NR_SYSCALL_BASE+95) -#endif - -#if !defined(__NR_getpriority) -#define __NR_getpriority (__NR_SYSCALL_BASE+96) -#endif - -#if !defined(__NR_setpriority) -#define __NR_setpriority (__NR_SYSCALL_BASE+97) -#endif - -#if !defined(__NR_statfs) -#define __NR_statfs (__NR_SYSCALL_BASE+99) -#endif - -#if !defined(__NR_fstatfs) -#define __NR_fstatfs (__NR_SYSCALL_BASE+100) -#endif - -#if !defined(__NR_syslog) -#define __NR_syslog (__NR_SYSCALL_BASE+103) -#endif - -#if !defined(__NR_setitimer) -#define __NR_setitimer (__NR_SYSCALL_BASE+104) -#endif - -#if !defined(__NR_getitimer) -#define __NR_getitimer (__NR_SYSCALL_BASE+105) -#endif - -#if !defined(__NR_stat) -#define __NR_stat (__NR_SYSCALL_BASE+106) -#endif - -#if !defined(__NR_lstat) -#define __NR_lstat (__NR_SYSCALL_BASE+107) -#endif - -#if !defined(__NR_fstat) -#define __NR_fstat (__NR_SYSCALL_BASE+108) -#endif - -#if !defined(__NR_vhangup) -#define __NR_vhangup (__NR_SYSCALL_BASE+111) -#endif - -#if !defined(__NR_wait4) -#define __NR_wait4 (__NR_SYSCALL_BASE+114) -#endif - -#if !defined(__NR_swapoff) -#define __NR_swapoff (__NR_SYSCALL_BASE+115) -#endif - -#if !defined(__NR_sysinfo) -#define __NR_sysinfo (__NR_SYSCALL_BASE+116) -#endif - -#if !defined(__NR_fsync) -#define __NR_fsync (__NR_SYSCALL_BASE+118) -#endif - -#if !defined(__NR_sigreturn) -#define __NR_sigreturn (__NR_SYSCALL_BASE+119) -#endif - -#if !defined(__NR_clone) -#define __NR_clone (__NR_SYSCALL_BASE+120) -#endif - -#if !defined(__NR_setdomainname) -#define __NR_setdomainname (__NR_SYSCALL_BASE+121) -#endif - -#if !defined(__NR_uname) -#define __NR_uname (__NR_SYSCALL_BASE+122) -#endif - -#if !defined(__NR_adjtimex) -#define __NR_adjtimex (__NR_SYSCALL_BASE+124) -#endif - -#if !defined(__NR_mprotect) -#define __NR_mprotect (__NR_SYSCALL_BASE+125) -#endif - -#if !defined(__NR_sigprocmask) -#define __NR_sigprocmask (__NR_SYSCALL_BASE+126) -#endif - -#if !defined(__NR_init_module) -#define __NR_init_module (__NR_SYSCALL_BASE+128) -#endif - -#if !defined(__NR_delete_module) -#define __NR_delete_module (__NR_SYSCALL_BASE+129) -#endif - -#if !defined(__NR_quotactl) -#define __NR_quotactl (__NR_SYSCALL_BASE+131) -#endif - -#if !defined(__NR_getpgid) -#define __NR_getpgid (__NR_SYSCALL_BASE+132) -#endif - -#if !defined(__NR_fchdir) -#define __NR_fchdir (__NR_SYSCALL_BASE+133) -#endif - -#if !defined(__NR_bdflush) -#define __NR_bdflush (__NR_SYSCALL_BASE+134) -#endif - -#if !defined(__NR_sysfs) -#define __NR_sysfs (__NR_SYSCALL_BASE+135) -#endif - -#if !defined(__NR_personality) -#define __NR_personality (__NR_SYSCALL_BASE+136) -#endif - -#if !defined(__NR_setfsuid) -#define __NR_setfsuid (__NR_SYSCALL_BASE+138) -#endif - -#if !defined(__NR_setfsgid) -#define __NR_setfsgid (__NR_SYSCALL_BASE+139) -#endif - -#if !defined(__NR__llseek) -#define __NR__llseek (__NR_SYSCALL_BASE+140) -#endif - -#if !defined(__NR_getdents) -#define __NR_getdents (__NR_SYSCALL_BASE+141) -#endif - -#if !defined(__NR__newselect) -#define __NR__newselect (__NR_SYSCALL_BASE+142) -#endif - -#if !defined(__NR_flock) -#define __NR_flock (__NR_SYSCALL_BASE+143) -#endif - -#if !defined(__NR_msync) -#define __NR_msync (__NR_SYSCALL_BASE+144) -#endif - -#if !defined(__NR_readv) -#define __NR_readv (__NR_SYSCALL_BASE+145) -#endif - -#if !defined(__NR_writev) -#define __NR_writev (__NR_SYSCALL_BASE+146) -#endif - -#if !defined(__NR_getsid) -#define __NR_getsid (__NR_SYSCALL_BASE+147) -#endif - -#if !defined(__NR_fdatasync) -#define __NR_fdatasync (__NR_SYSCALL_BASE+148) -#endif - -#if !defined(__NR__sysctl) -#define __NR__sysctl (__NR_SYSCALL_BASE+149) -#endif - -#if !defined(__NR_mlock) -#define __NR_mlock (__NR_SYSCALL_BASE+150) -#endif - -#if !defined(__NR_munlock) -#define __NR_munlock (__NR_SYSCALL_BASE+151) -#endif - -#if !defined(__NR_mlockall) -#define __NR_mlockall (__NR_SYSCALL_BASE+152) -#endif - -#if !defined(__NR_munlockall) -#define __NR_munlockall (__NR_SYSCALL_BASE+153) -#endif - -#if !defined(__NR_sched_setparam) -#define __NR_sched_setparam (__NR_SYSCALL_BASE+154) -#endif - -#if !defined(__NR_sched_getparam) -#define __NR_sched_getparam (__NR_SYSCALL_BASE+155) -#endif - -#if !defined(__NR_sched_setscheduler) -#define __NR_sched_setscheduler (__NR_SYSCALL_BASE+156) -#endif - -#if !defined(__NR_sched_getscheduler) -#define __NR_sched_getscheduler (__NR_SYSCALL_BASE+157) -#endif - -#if !defined(__NR_sched_yield) -#define __NR_sched_yield (__NR_SYSCALL_BASE+158) -#endif - -#if !defined(__NR_sched_get_priority_max) -#define __NR_sched_get_priority_max (__NR_SYSCALL_BASE+159) -#endif - -#if !defined(__NR_sched_get_priority_min) -#define __NR_sched_get_priority_min (__NR_SYSCALL_BASE+160) -#endif - -#if !defined(__NR_sched_rr_get_interval) -#define __NR_sched_rr_get_interval (__NR_SYSCALL_BASE+161) -#endif - -#if !defined(__NR_nanosleep) -#define __NR_nanosleep (__NR_SYSCALL_BASE+162) -#endif - -#if !defined(__NR_mremap) -#define __NR_mremap (__NR_SYSCALL_BASE+163) -#endif - -#if !defined(__NR_setresuid) -#define __NR_setresuid (__NR_SYSCALL_BASE+164) -#endif - -#if !defined(__NR_getresuid) -#define __NR_getresuid (__NR_SYSCALL_BASE+165) -#endif - -#if !defined(__NR_poll) -#define __NR_poll (__NR_SYSCALL_BASE+168) -#endif - -#if !defined(__NR_nfsservctl) -#define __NR_nfsservctl (__NR_SYSCALL_BASE+169) -#endif - -#if !defined(__NR_setresgid) -#define __NR_setresgid (__NR_SYSCALL_BASE+170) -#endif - -#if !defined(__NR_getresgid) -#define __NR_getresgid (__NR_SYSCALL_BASE+171) -#endif - -#if !defined(__NR_prctl) -#define __NR_prctl (__NR_SYSCALL_BASE+172) -#endif - -#if !defined(__NR_rt_sigreturn) -#define __NR_rt_sigreturn (__NR_SYSCALL_BASE+173) -#endif - -#if !defined(__NR_rt_sigaction) -#define __NR_rt_sigaction (__NR_SYSCALL_BASE+174) -#endif - -#if !defined(__NR_rt_sigprocmask) -#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE+175) -#endif - -#if !defined(__NR_rt_sigpending) -#define __NR_rt_sigpending (__NR_SYSCALL_BASE+176) -#endif - -#if !defined(__NR_rt_sigtimedwait) -#define __NR_rt_sigtimedwait (__NR_SYSCALL_BASE+177) -#endif - -#if !defined(__NR_rt_sigqueueinfo) -#define __NR_rt_sigqueueinfo (__NR_SYSCALL_BASE+178) -#endif - -#if !defined(__NR_rt_sigsuspend) -#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE+179) -#endif - -#if !defined(__NR_pread64) -#define __NR_pread64 (__NR_SYSCALL_BASE+180) -#endif - -#if !defined(__NR_pwrite64) -#define __NR_pwrite64 (__NR_SYSCALL_BASE+181) -#endif - -#if !defined(__NR_chown) -#define __NR_chown (__NR_SYSCALL_BASE+182) -#endif - -#if !defined(__NR_getcwd) -#define __NR_getcwd (__NR_SYSCALL_BASE+183) -#endif - -#if !defined(__NR_capget) -#define __NR_capget (__NR_SYSCALL_BASE+184) -#endif - -#if !defined(__NR_capset) -#define __NR_capset (__NR_SYSCALL_BASE+185) -#endif - -#if !defined(__NR_sigaltstack) -#define __NR_sigaltstack (__NR_SYSCALL_BASE+186) -#endif - -#if !defined(__NR_sendfile) -#define __NR_sendfile (__NR_SYSCALL_BASE+187) -#endif - -#if !defined(__NR_vfork) -#define __NR_vfork (__NR_SYSCALL_BASE+190) -#endif - -#if !defined(__NR_ugetrlimit) -#define __NR_ugetrlimit (__NR_SYSCALL_BASE+191) -#endif - -#if !defined(__NR_mmap2) -#define __NR_mmap2 (__NR_SYSCALL_BASE+192) -#endif - -#if !defined(__NR_truncate64) -#define __NR_truncate64 (__NR_SYSCALL_BASE+193) -#endif - -#if !defined(__NR_ftruncate64) -#define __NR_ftruncate64 (__NR_SYSCALL_BASE+194) -#endif - -#if !defined(__NR_stat64) -#define __NR_stat64 (__NR_SYSCALL_BASE+195) -#endif - -#if !defined(__NR_lstat64) -#define __NR_lstat64 (__NR_SYSCALL_BASE+196) -#endif - -#if !defined(__NR_fstat64) -#define __NR_fstat64 (__NR_SYSCALL_BASE+197) -#endif - -#if !defined(__NR_lchown32) -#define __NR_lchown32 (__NR_SYSCALL_BASE+198) -#endif - -#if !defined(__NR_getuid32) -#define __NR_getuid32 (__NR_SYSCALL_BASE+199) -#endif - -#if !defined(__NR_getgid32) -#define __NR_getgid32 (__NR_SYSCALL_BASE+200) -#endif - -#if !defined(__NR_geteuid32) -#define __NR_geteuid32 (__NR_SYSCALL_BASE+201) -#endif - -#if !defined(__NR_getegid32) -#define __NR_getegid32 (__NR_SYSCALL_BASE+202) -#endif - -#if !defined(__NR_setreuid32) -#define __NR_setreuid32 (__NR_SYSCALL_BASE+203) -#endif - -#if !defined(__NR_setregid32) -#define __NR_setregid32 (__NR_SYSCALL_BASE+204) -#endif - -#if !defined(__NR_getgroups32) -#define __NR_getgroups32 (__NR_SYSCALL_BASE+205) -#endif - -#if !defined(__NR_setgroups32) -#define __NR_setgroups32 (__NR_SYSCALL_BASE+206) -#endif - -#if !defined(__NR_fchown32) -#define __NR_fchown32 (__NR_SYSCALL_BASE+207) -#endif - -#if !defined(__NR_setresuid32) -#define __NR_setresuid32 (__NR_SYSCALL_BASE+208) -#endif - -#if !defined(__NR_getresuid32) -#define __NR_getresuid32 (__NR_SYSCALL_BASE+209) -#endif - -#if !defined(__NR_setresgid32) -#define __NR_setresgid32 (__NR_SYSCALL_BASE+210) -#endif - -#if !defined(__NR_getresgid32) -#define __NR_getresgid32 (__NR_SYSCALL_BASE+211) -#endif - -#if !defined(__NR_chown32) -#define __NR_chown32 (__NR_SYSCALL_BASE+212) -#endif - -#if !defined(__NR_setuid32) -#define __NR_setuid32 (__NR_SYSCALL_BASE+213) -#endif - -#if !defined(__NR_setgid32) -#define __NR_setgid32 (__NR_SYSCALL_BASE+214) -#endif - -#if !defined(__NR_setfsuid32) -#define __NR_setfsuid32 (__NR_SYSCALL_BASE+215) -#endif - -#if !defined(__NR_setfsgid32) -#define __NR_setfsgid32 (__NR_SYSCALL_BASE+216) -#endif - -#if !defined(__NR_getdents64) -#define __NR_getdents64 (__NR_SYSCALL_BASE+217) -#endif - -#if !defined(__NR_pivot_root) -#define __NR_pivot_root (__NR_SYSCALL_BASE+218) -#endif - -#if !defined(__NR_mincore) -#define __NR_mincore (__NR_SYSCALL_BASE+219) -#endif - -#if !defined(__NR_madvise) -#define __NR_madvise (__NR_SYSCALL_BASE+220) -#endif - -#if !defined(__NR_fcntl64) -#define __NR_fcntl64 (__NR_SYSCALL_BASE+221) -#endif - -#if !defined(__NR_gettid) -#define __NR_gettid (__NR_SYSCALL_BASE+224) -#endif - -#if !defined(__NR_readahead) -#define __NR_readahead (__NR_SYSCALL_BASE+225) -#endif - -#if !defined(__NR_setxattr) -#define __NR_setxattr (__NR_SYSCALL_BASE+226) -#endif - -#if !defined(__NR_lsetxattr) -#define __NR_lsetxattr (__NR_SYSCALL_BASE+227) -#endif - -#if !defined(__NR_fsetxattr) -#define __NR_fsetxattr (__NR_SYSCALL_BASE+228) -#endif - -#if !defined(__NR_getxattr) -#define __NR_getxattr (__NR_SYSCALL_BASE+229) -#endif - -#if !defined(__NR_lgetxattr) -#define __NR_lgetxattr (__NR_SYSCALL_BASE+230) -#endif - -#if !defined(__NR_fgetxattr) -#define __NR_fgetxattr (__NR_SYSCALL_BASE+231) -#endif - -#if !defined(__NR_listxattr) -#define __NR_listxattr (__NR_SYSCALL_BASE+232) -#endif - -#if !defined(__NR_llistxattr) -#define __NR_llistxattr (__NR_SYSCALL_BASE+233) -#endif - -#if !defined(__NR_flistxattr) -#define __NR_flistxattr (__NR_SYSCALL_BASE+234) -#endif - -#if !defined(__NR_removexattr) -#define __NR_removexattr (__NR_SYSCALL_BASE+235) -#endif - -#if !defined(__NR_lremovexattr) -#define __NR_lremovexattr (__NR_SYSCALL_BASE+236) -#endif - -#if !defined(__NR_fremovexattr) -#define __NR_fremovexattr (__NR_SYSCALL_BASE+237) -#endif - -#if !defined(__NR_tkill) -#define __NR_tkill (__NR_SYSCALL_BASE+238) -#endif - -#if !defined(__NR_sendfile64) -#define __NR_sendfile64 (__NR_SYSCALL_BASE+239) -#endif - -#if !defined(__NR_futex) -#define __NR_futex (__NR_SYSCALL_BASE+240) -#endif - -#if !defined(__NR_sched_setaffinity) -#define __NR_sched_setaffinity (__NR_SYSCALL_BASE+241) -#endif - -#if !defined(__NR_sched_getaffinity) -#define __NR_sched_getaffinity (__NR_SYSCALL_BASE+242) -#endif - -#if !defined(__NR_io_setup) -#define __NR_io_setup (__NR_SYSCALL_BASE+243) -#endif - -#if !defined(__NR_io_destroy) -#define __NR_io_destroy (__NR_SYSCALL_BASE+244) -#endif - -#if !defined(__NR_io_getevents) -#define __NR_io_getevents (__NR_SYSCALL_BASE+245) -#endif - -#if !defined(__NR_io_submit) -#define __NR_io_submit (__NR_SYSCALL_BASE+246) -#endif - -#if !defined(__NR_io_cancel) -#define __NR_io_cancel (__NR_SYSCALL_BASE+247) -#endif - -#if !defined(__NR_exit_group) -#define __NR_exit_group (__NR_SYSCALL_BASE+248) -#endif - -#if !defined(__NR_lookup_dcookie) -#define __NR_lookup_dcookie (__NR_SYSCALL_BASE+249) -#endif - -#if !defined(__NR_epoll_create) -#define __NR_epoll_create (__NR_SYSCALL_BASE+250) -#endif - -#if !defined(__NR_epoll_ctl) -#define __NR_epoll_ctl (__NR_SYSCALL_BASE+251) -#endif - -#if !defined(__NR_epoll_wait) -#define __NR_epoll_wait (__NR_SYSCALL_BASE+252) -#endif - -#if !defined(__NR_remap_file_pages) -#define __NR_remap_file_pages (__NR_SYSCALL_BASE+253) -#endif - -#if !defined(__NR_set_tid_address) -#define __NR_set_tid_address (__NR_SYSCALL_BASE+256) -#endif - -#if !defined(__NR_timer_create) -#define __NR_timer_create (__NR_SYSCALL_BASE+257) -#endif - -#if !defined(__NR_timer_settime) -#define __NR_timer_settime (__NR_SYSCALL_BASE+258) -#endif - -#if !defined(__NR_timer_gettime) -#define __NR_timer_gettime (__NR_SYSCALL_BASE+259) -#endif - -#if !defined(__NR_timer_getoverrun) -#define __NR_timer_getoverrun (__NR_SYSCALL_BASE+260) -#endif - -#if !defined(__NR_timer_delete) -#define __NR_timer_delete (__NR_SYSCALL_BASE+261) -#endif - -#if !defined(__NR_clock_settime) -#define __NR_clock_settime (__NR_SYSCALL_BASE+262) -#endif - -#if !defined(__NR_clock_gettime) -#define __NR_clock_gettime (__NR_SYSCALL_BASE+263) -#endif - -#if !defined(__NR_clock_getres) -#define __NR_clock_getres (__NR_SYSCALL_BASE+264) -#endif - -#if !defined(__NR_clock_nanosleep) -#define __NR_clock_nanosleep (__NR_SYSCALL_BASE+265) -#endif - -#if !defined(__NR_statfs64) -#define __NR_statfs64 (__NR_SYSCALL_BASE+266) -#endif - -#if !defined(__NR_fstatfs64) -#define __NR_fstatfs64 (__NR_SYSCALL_BASE+267) -#endif - -#if !defined(__NR_tgkill) -#define __NR_tgkill (__NR_SYSCALL_BASE+268) -#endif - -#if !defined(__NR_utimes) -#define __NR_utimes (__NR_SYSCALL_BASE+269) -#endif - -#if !defined(__NR_arm_fadvise64_64) -#define __NR_arm_fadvise64_64 (__NR_SYSCALL_BASE+270) -#endif - -#if !defined(__NR_pciconfig_iobase) -#define __NR_pciconfig_iobase (__NR_SYSCALL_BASE+271) -#endif - -#if !defined(__NR_pciconfig_read) -#define __NR_pciconfig_read (__NR_SYSCALL_BASE+272) -#endif - -#if !defined(__NR_pciconfig_write) -#define __NR_pciconfig_write (__NR_SYSCALL_BASE+273) -#endif - -#if !defined(__NR_mq_open) -#define __NR_mq_open (__NR_SYSCALL_BASE+274) -#endif - -#if !defined(__NR_mq_unlink) -#define __NR_mq_unlink (__NR_SYSCALL_BASE+275) -#endif - -#if !defined(__NR_mq_timedsend) -#define __NR_mq_timedsend (__NR_SYSCALL_BASE+276) -#endif - -#if !defined(__NR_mq_timedreceive) -#define __NR_mq_timedreceive (__NR_SYSCALL_BASE+277) -#endif - -#if !defined(__NR_mq_notify) -#define __NR_mq_notify (__NR_SYSCALL_BASE+278) -#endif - -#if !defined(__NR_mq_getsetattr) -#define __NR_mq_getsetattr (__NR_SYSCALL_BASE+279) -#endif - -#if !defined(__NR_waitid) -#define __NR_waitid (__NR_SYSCALL_BASE+280) -#endif - -#if !defined(__NR_socket) -#define __NR_socket (__NR_SYSCALL_BASE+281) -#endif - -#if !defined(__NR_bind) -#define __NR_bind (__NR_SYSCALL_BASE+282) -#endif - -#if !defined(__NR_connect) -#define __NR_connect (__NR_SYSCALL_BASE+283) -#endif - -#if !defined(__NR_listen) -#define __NR_listen (__NR_SYSCALL_BASE+284) -#endif - -#if !defined(__NR_accept) -#define __NR_accept (__NR_SYSCALL_BASE+285) -#endif - -#if !defined(__NR_getsockname) -#define __NR_getsockname (__NR_SYSCALL_BASE+286) -#endif - -#if !defined(__NR_getpeername) -#define __NR_getpeername (__NR_SYSCALL_BASE+287) -#endif - -#if !defined(__NR_socketpair) -#define __NR_socketpair (__NR_SYSCALL_BASE+288) -#endif - -#if !defined(__NR_send) -#define __NR_send (__NR_SYSCALL_BASE+289) -#endif - -#if !defined(__NR_sendto) -#define __NR_sendto (__NR_SYSCALL_BASE+290) -#endif - -#if !defined(__NR_recv) -#define __NR_recv (__NR_SYSCALL_BASE+291) -#endif - -#if !defined(__NR_recvfrom) -#define __NR_recvfrom (__NR_SYSCALL_BASE+292) -#endif - -#if !defined(__NR_shutdown) -#define __NR_shutdown (__NR_SYSCALL_BASE+293) -#endif - -#if !defined(__NR_setsockopt) -#define __NR_setsockopt (__NR_SYSCALL_BASE+294) -#endif - -#if !defined(__NR_getsockopt) -#define __NR_getsockopt (__NR_SYSCALL_BASE+295) -#endif - -#if !defined(__NR_sendmsg) -#define __NR_sendmsg (__NR_SYSCALL_BASE+296) -#endif - -#if !defined(__NR_recvmsg) -#define __NR_recvmsg (__NR_SYSCALL_BASE+297) -#endif - -#if !defined(__NR_semop) -#define __NR_semop (__NR_SYSCALL_BASE+298) -#endif - -#if !defined(__NR_semget) -#define __NR_semget (__NR_SYSCALL_BASE+299) -#endif - -#if !defined(__NR_semctl) -#define __NR_semctl (__NR_SYSCALL_BASE+300) -#endif - -#if !defined(__NR_msgsnd) -#define __NR_msgsnd (__NR_SYSCALL_BASE+301) -#endif - -#if !defined(__NR_msgrcv) -#define __NR_msgrcv (__NR_SYSCALL_BASE+302) -#endif - -#if !defined(__NR_msgget) -#define __NR_msgget (__NR_SYSCALL_BASE+303) -#endif - -#if !defined(__NR_msgctl) -#define __NR_msgctl (__NR_SYSCALL_BASE+304) -#endif - -#if !defined(__NR_shmat) -#define __NR_shmat (__NR_SYSCALL_BASE+305) -#endif - -#if !defined(__NR_shmdt) -#define __NR_shmdt (__NR_SYSCALL_BASE+306) -#endif - -#if !defined(__NR_shmget) -#define __NR_shmget (__NR_SYSCALL_BASE+307) -#endif - -#if !defined(__NR_shmctl) -#define __NR_shmctl (__NR_SYSCALL_BASE+308) -#endif - -#if !defined(__NR_add_key) -#define __NR_add_key (__NR_SYSCALL_BASE+309) -#endif - -#if !defined(__NR_request_key) -#define __NR_request_key (__NR_SYSCALL_BASE+310) -#endif - -#if !defined(__NR_keyctl) -#define __NR_keyctl (__NR_SYSCALL_BASE+311) -#endif - -#if !defined(__NR_semtimedop) -#define __NR_semtimedop (__NR_SYSCALL_BASE+312) -#endif - -#if !defined(__NR_vserver) -#define __NR_vserver (__NR_SYSCALL_BASE+313) -#endif - -#if !defined(__NR_ioprio_set) -#define __NR_ioprio_set (__NR_SYSCALL_BASE+314) -#endif - -#if !defined(__NR_ioprio_get) -#define __NR_ioprio_get (__NR_SYSCALL_BASE+315) -#endif - -#if !defined(__NR_inotify_init) -#define __NR_inotify_init (__NR_SYSCALL_BASE+316) -#endif - -#if !defined(__NR_inotify_add_watch) -#define __NR_inotify_add_watch (__NR_SYSCALL_BASE+317) -#endif - -#if !defined(__NR_inotify_rm_watch) -#define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+318) -#endif - -#if !defined(__NR_mbind) -#define __NR_mbind (__NR_SYSCALL_BASE+319) -#endif - -#if !defined(__NR_get_mempolicy) -#define __NR_get_mempolicy (__NR_SYSCALL_BASE+320) -#endif - -#if !defined(__NR_set_mempolicy) -#define __NR_set_mempolicy (__NR_SYSCALL_BASE+321) -#endif - -#if !defined(__NR_openat) -#define __NR_openat (__NR_SYSCALL_BASE+322) -#endif - -#if !defined(__NR_mkdirat) -#define __NR_mkdirat (__NR_SYSCALL_BASE+323) -#endif - -#if !defined(__NR_mknodat) -#define __NR_mknodat (__NR_SYSCALL_BASE+324) -#endif - -#if !defined(__NR_fchownat) -#define __NR_fchownat (__NR_SYSCALL_BASE+325) -#endif - -#if !defined(__NR_futimesat) -#define __NR_futimesat (__NR_SYSCALL_BASE+326) -#endif - -#if !defined(__NR_fstatat64) -#define __NR_fstatat64 (__NR_SYSCALL_BASE+327) -#endif - -#if !defined(__NR_unlinkat) -#define __NR_unlinkat (__NR_SYSCALL_BASE+328) -#endif - -#if !defined(__NR_renameat) -#define __NR_renameat (__NR_SYSCALL_BASE+329) -#endif - -#if !defined(__NR_linkat) -#define __NR_linkat (__NR_SYSCALL_BASE+330) -#endif - -#if !defined(__NR_symlinkat) -#define __NR_symlinkat (__NR_SYSCALL_BASE+331) -#endif - -#if !defined(__NR_readlinkat) -#define __NR_readlinkat (__NR_SYSCALL_BASE+332) -#endif - -#if !defined(__NR_fchmodat) -#define __NR_fchmodat (__NR_SYSCALL_BASE+333) -#endif - -#if !defined(__NR_faccessat) -#define __NR_faccessat (__NR_SYSCALL_BASE+334) -#endif - -#if !defined(__NR_pselect6) -#define __NR_pselect6 (__NR_SYSCALL_BASE+335) -#endif - -#if !defined(__NR_ppoll) -#define __NR_ppoll (__NR_SYSCALL_BASE+336) -#endif - -#if !defined(__NR_unshare) -#define __NR_unshare (__NR_SYSCALL_BASE+337) -#endif - -#if !defined(__NR_set_robust_list) -#define __NR_set_robust_list (__NR_SYSCALL_BASE+338) -#endif - -#if !defined(__NR_get_robust_list) -#define __NR_get_robust_list (__NR_SYSCALL_BASE+339) -#endif - -#if !defined(__NR_splice) -#define __NR_splice (__NR_SYSCALL_BASE+340) -#endif - -#if !defined(__NR_arm_sync_file_range) -#define __NR_arm_sync_file_range (__NR_SYSCALL_BASE+341) -#endif - -#if !defined(__NR_sync_file_range2) -#define __NR_sync_file_range2 (__NR_SYSCALL_BASE+341) -#endif - -#if !defined(__NR_tee) -#define __NR_tee (__NR_SYSCALL_BASE+342) -#endif - -#if !defined(__NR_vmsplice) -#define __NR_vmsplice (__NR_SYSCALL_BASE+343) -#endif - -#if !defined(__NR_move_pages) -#define __NR_move_pages (__NR_SYSCALL_BASE+344) -#endif - -#if !defined(__NR_getcpu) -#define __NR_getcpu (__NR_SYSCALL_BASE+345) -#endif - -#if !defined(__NR_epoll_pwait) -#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346) -#endif - -#if !defined(__NR_kexec_load) -#define __NR_kexec_load (__NR_SYSCALL_BASE+347) -#endif - -#if !defined(__NR_utimensat) -#define __NR_utimensat (__NR_SYSCALL_BASE+348) -#endif - -#if !defined(__NR_signalfd) -#define __NR_signalfd (__NR_SYSCALL_BASE+349) -#endif - -#if !defined(__NR_timerfd_create) -#define __NR_timerfd_create (__NR_SYSCALL_BASE+350) -#endif - -#if !defined(__NR_eventfd) -#define __NR_eventfd (__NR_SYSCALL_BASE+351) -#endif - -#if !defined(__NR_fallocate) -#define __NR_fallocate (__NR_SYSCALL_BASE+352) -#endif - -#if !defined(__NR_timerfd_settime) -#define __NR_timerfd_settime (__NR_SYSCALL_BASE+353) -#endif - -#if !defined(__NR_timerfd_gettime) -#define __NR_timerfd_gettime (__NR_SYSCALL_BASE+354) -#endif - -#if !defined(__NR_signalfd4) -#define __NR_signalfd4 (__NR_SYSCALL_BASE+355) -#endif - -#if !defined(__NR_eventfd2) -#define __NR_eventfd2 (__NR_SYSCALL_BASE+356) -#endif - -#if !defined(__NR_epoll_create1) -#define __NR_epoll_create1 (__NR_SYSCALL_BASE+357) -#endif - -#if !defined(__NR_dup3) -#define __NR_dup3 (__NR_SYSCALL_BASE+358) -#endif - -#if !defined(__NR_pipe2) -#define __NR_pipe2 (__NR_SYSCALL_BASE+359) -#endif - -#if !defined(__NR_inotify_init1) -#define __NR_inotify_init1 (__NR_SYSCALL_BASE+360) -#endif - -#if !defined(__NR_preadv) -#define __NR_preadv (__NR_SYSCALL_BASE+361) -#endif - -#if !defined(__NR_pwritev) -#define __NR_pwritev (__NR_SYSCALL_BASE+362) -#endif - -#if !defined(__NR_rt_tgsigqueueinfo) -#define __NR_rt_tgsigqueueinfo (__NR_SYSCALL_BASE+363) -#endif - -#if !defined(__NR_perf_event_open) -#define __NR_perf_event_open (__NR_SYSCALL_BASE+364) -#endif - -#if !defined(__NR_recvmmsg) -#define __NR_recvmmsg (__NR_SYSCALL_BASE+365) -#endif - -#if !defined(__NR_accept4) -#define __NR_accept4 (__NR_SYSCALL_BASE+366) -#endif - -#if !defined(__NR_fanotify_init) -#define __NR_fanotify_init (__NR_SYSCALL_BASE+367) -#endif - -#if !defined(__NR_fanotify_mark) -#define __NR_fanotify_mark (__NR_SYSCALL_BASE+368) -#endif - -#if !defined(__NR_prlimit64) -#define __NR_prlimit64 (__NR_SYSCALL_BASE+369) -#endif - -#if !defined(__NR_name_to_handle_at) -#define __NR_name_to_handle_at (__NR_SYSCALL_BASE+370) -#endif - -#if !defined(__NR_open_by_handle_at) -#define __NR_open_by_handle_at (__NR_SYSCALL_BASE+371) -#endif - -#if !defined(__NR_clock_adjtime) -#define __NR_clock_adjtime (__NR_SYSCALL_BASE+372) -#endif - -#if !defined(__NR_syncfs) -#define __NR_syncfs (__NR_SYSCALL_BASE+373) -#endif - -#if !defined(__NR_sendmmsg) -#define __NR_sendmmsg (__NR_SYSCALL_BASE+374) -#endif - -#if !defined(__NR_setns) -#define __NR_setns (__NR_SYSCALL_BASE+375) -#endif - -#if !defined(__NR_process_vm_readv) -#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) -#endif - -#if !defined(__NR_process_vm_writev) -#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) -#endif - -#if !defined(__NR_kcmp) -#define __NR_kcmp (__NR_SYSCALL_BASE+378) -#endif - -#if !defined(__NR_finit_module) -#define __NR_finit_module (__NR_SYSCALL_BASE+379) -#endif - -#if !defined(__NR_sched_setattr) -#define __NR_sched_setattr (__NR_SYSCALL_BASE+380) -#endif - -#if !defined(__NR_sched_getattr) -#define __NR_sched_getattr (__NR_SYSCALL_BASE+381) -#endif - -#if !defined(__NR_renameat2) -#define __NR_renameat2 (__NR_SYSCALL_BASE+382) -#endif - -#if !defined(__NR_seccomp) -#define __NR_seccomp (__NR_SYSCALL_BASE+383) -#endif - -#if !defined(__NR_getrandom) -#define __NR_getrandom (__NR_SYSCALL_BASE+384) -#endif - -#if !defined(__NR_memfd_create) -#define __NR_memfd_create (__NR_SYSCALL_BASE+385) -#endif - -// ARM private syscalls. -#if !defined(__ARM_NR_BASE) -#define __ARM_NR_BASE (__NR_SYSCALL_BASE + 0xF0000) -#endif - -#if !defined(__ARM_NR_breakpoint) -#define __ARM_NR_breakpoint (__ARM_NR_BASE+1) -#endif - -#if !defined(__ARM_NR_cacheflush) -#define __ARM_NR_cacheflush (__ARM_NR_BASE+2) -#endif - -#if !defined(__ARM_NR_usr26) -#define __ARM_NR_usr26 (__ARM_NR_BASE+3) -#endif - -#if !defined(__ARM_NR_usr32) -#define __ARM_NR_usr32 (__ARM_NR_BASE+4) -#endif - -#if !defined(__ARM_NR_set_tls) -#define __ARM_NR_set_tls (__ARM_NR_BASE+5) -#endif - -// ARM kernel private syscall. -#if !defined(__ARM_NR_cmpxchg) -#define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0) -#endif - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_SYSCALLS_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/arm_linux_ucontext.h b/security/sandbox/chromium/sandbox/linux/system_headers/arm_linux_ucontext.h deleted file mode 100644 index 35208fa2a..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/arm_linux_ucontext.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_ - -#include <stddef.h> - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#if !defined(__native_client_nonsfi__) -#include <asm/sigcontext.h> -#else -// In PNaCl toolchain, sigcontext and stack_t is not defined. So here declare -// them. -struct sigcontext { - unsigned long trap_no; - unsigned long error_code; - unsigned long oldmask; - unsigned long arm_r0; - unsigned long arm_r1; - unsigned long arm_r2; - unsigned long arm_r3; - unsigned long arm_r4; - unsigned long arm_r5; - unsigned long arm_r6; - unsigned long arm_r7; - unsigned long arm_r8; - unsigned long arm_r9; - unsigned long arm_r10; - unsigned long arm_fp; - unsigned long arm_ip; - unsigned long arm_sp; - unsigned long arm_lr; - unsigned long arm_pc; - unsigned long arm_cpsr; - unsigned long fault_address; -}; - -typedef struct sigaltstack { - void* ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -#endif - -// We also need greg_t for the sandbox, include it in this header as well. -typedef unsigned long greg_t; - -// typedef unsigned long sigset_t; -typedef struct ucontext { - unsigned long uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; - /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */ - int __not_used[32 - (sizeof(sigset_t) / sizeof(int))]; - /* Last for extensibility. Eight byte aligned because some - coprocessors require eight byte alignment. */ - unsigned long uc_regspace[128] __attribute__((__aligned__(8))); -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/capability.h b/security/sandbox/chromium/sandbox/linux/system_headers/capability.h deleted file mode 100644 index f91fcf78a..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/capability.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_CAPABILITY_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_CAPABILITY_H_ - -#include <stdint.h> - -// The following macros are taken from linux/capability.h. -// We only support capability version 3, which was introduced in Linux 2.6.26. -#ifndef _LINUX_CAPABILITY_VERSION_3 -#define _LINUX_CAPABILITY_VERSION_3 0x20080522 -#endif -#ifndef _LINUX_CAPABILITY_U32S_3 -#define _LINUX_CAPABILITY_U32S_3 2 -#endif -#ifndef CAP_TO_INDEX -#define CAP_TO_INDEX(x) ((x) >> 5) // 1 << 5 == bits in __u32 -#endif -#ifndef CAP_TO_MASK -#define CAP_TO_MASK(x) (1 << ((x) & 31)) // mask for indexed __u32 -#endif -#ifndef CAP_SYS_CHROOT -#define CAP_SYS_CHROOT 18 -#endif -#ifndef CAP_SYS_ADMIN -#define CAP_SYS_ADMIN 21 -#endif - -struct cap_hdr { - uint32_t version; - int pid; -}; - -struct cap_data { - uint32_t effective; - uint32_t permitted; - uint32_t inheritable; -}; - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_CAPABILITY_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/i386_linux_ucontext.h b/security/sandbox/chromium/sandbox/linux/system_headers/i386_linux_ucontext.h deleted file mode 100644 index f4380339d..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/i386_linux_ucontext.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_ - -#include <stddef.h> -#include <stdint.h> - -// We do something compatible with glibc. Hopefully, at some point Android will -// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. -// This is mostly copied from breakpad (common/android/include/sys/ucontext.h), -// except we do use sigset_t for uc_sigmask instead of a custom type. - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#if !defined(__native_client_nonsfi__) -#include <asm/sigcontext.h> -#else -// In PNaCl toolchain, sigcontext is not defined. So here declare it. -typedef struct sigaltstack { - void* ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; -#endif - -/* 80-bit floating-point register */ -struct _libc_fpreg { - unsigned short significand[4]; - unsigned short exponent; -}; - -/* Simple floating-point state, see FNSTENV instruction */ -struct _libc_fpstate { - unsigned long cw; - unsigned long sw; - unsigned long tag; - unsigned long ipoff; - unsigned long cssel; - unsigned long dataoff; - unsigned long datasel; - struct _libc_fpreg _st[8]; - unsigned long status; -}; - -typedef uint32_t greg_t; - -typedef struct { - uint32_t gregs[19]; - struct _libc_fpstate* fpregs; - uint32_t oldmask; - uint32_t cr2; -} mcontext_t; - -enum { - REG_GS = 0, - REG_FS, - REG_ES, - REG_DS, - REG_EDI, - REG_ESI, - REG_EBP, - REG_ESP, - REG_EBX, - REG_EDX, - REG_ECX, - REG_EAX, - REG_TRAPNO, - REG_ERR, - REG_EIP, - REG_CS, - REG_EFL, - REG_UESP, - REG_SS, -}; - -typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - // Android and PNaCl toolchain's sigset_t has only 32 bits, though Linux - // ABI requires 64 bits. - union { - sigset_t uc_sigmask; - uint32_t kernel_sigmask[2]; - }; - struct _libc_fpstate __fpregs_mem; -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/linux_filter.h b/security/sandbox/chromium/sandbox/linux/system_headers/linux_filter.h deleted file mode 100644 index b23b6eb0c..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/linux_filter.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FILTER_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FILTER_H_ - -#include <stdint.h> - -// The following structs and macros are taken from linux/filter.h, -// as some toolchain does not expose them. -struct sock_filter { - uint16_t code; - uint8_t jt; - uint8_t jf; - uint32_t k; -}; - -struct sock_fprog { - uint16_t len; - struct sock_filter *filter; -}; - -#ifndef BPF_CLASS -#define BPF_CLASS(code) ((code) & 0x07) -#endif - -#ifndef BPF_LD -#define BPF_LD 0x00 -#endif - -#ifndef BPF_ALU -#define BPF_ALU 0x04 -#endif - -#ifndef BPF_JMP -#define BPF_JMP 0x05 -#endif - -#ifndef BPF_RET -#define BPF_RET 0x06 -#endif - -#ifndef BPF_SIZE -#define BPF_SIZE(code) ((code) & 0x18) -#endif - -#ifndef BPF_W -#define BPF_W 0x00 -#endif - -#ifndef BPF_MODE -#define BPF_MODE(code) ((code) & 0xe0) -#endif - -#ifndef BPF_ABS -#define BPF_ABS 0x20 -#endif - -#ifndef BPF_OP -#define BPF_OP(code) ((code) & 0xf0) -#endif - -#ifndef BPF_ADD -#define BPF_ADD 0x00 -#endif - -#ifndef BPF_SUB -#define BPF_SUB 0x10 -#endif - -#ifndef BPF_MUL -#define BPF_MUL 0x20 -#endif - -#ifndef BPF_DIV -#define BPF_DIV 0x30 -#endif - -#ifndef BPF_OR -#define BPF_OR 0x40 -#endif - -#ifndef BPF_AND -#define BPF_AND 0x50 -#endif - -#ifndef BPF_LSH -#define BPF_LSH 0x60 -#endif - -#ifndef BPF_RSH -#define BPF_RSH 0x70 -#endif - -#ifndef BPF_NEG -#define BPF_NEG 0x80 -#endif - -#ifndef BPF_MOD -#define BPF_MOD 0x90 -#endif - -#ifndef BPF_XOR -#define BPF_XOR 0xA0 -#endif - -#ifndef BPF_JA -#define BPF_JA 0x00 -#endif - -#ifndef BPF_JEQ -#define BPF_JEQ 0x10 -#endif - -#ifndef BPF_JGT -#define BPF_JGT 0x20 -#endif - -#ifndef BPF_JGE -#define BPF_JGE 0x30 -#endif - -#ifndef BPF_JSET -#define BPF_JSET 0x40 -#endif - -#ifndef BPF_SRC -#define BPF_SRC(code) ((code) & 0x08) -#endif - -#ifndef BPF_K -#define BPF_K 0x00 -#endif - -#ifndef BPF_MAXINSNS -#define BPF_MAXINSNS 4096 -#endif - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FILTER_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/linux_futex.h b/security/sandbox/chromium/sandbox/linux/system_headers/linux_futex.h deleted file mode 100644 index 4e2840333..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/linux_futex.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_ - -#if !defined(__native_client_nonsfi__) -#include <linux/futex.h> -#endif // !defined(__native_client_nonsfi__) - -#if !defined(FUTEX_WAIT) -#define FUTEX_WAIT 0 -#endif - -#if !defined(FUTEX_WAKE) -#define FUTEX_WAKE 1 -#endif - -#if !defined(FUTEX_FD) -#define FUTEX_FD 2 -#endif - -#if !defined(FUTEX_REQUEUE) -#define FUTEX_REQUEUE 3 -#endif - -#if !defined(FUTEX_CMP_REQUEUE) -#define FUTEX_CMP_REQUEUE 4 -#endif - -#if !defined(FUTEX_WAKE_OP) -#define FUTEX_WAKE_OP 5 -#endif - -#if !defined(FUTEX_LOCK_PI) -#define FUTEX_LOCK_PI 6 -#endif - -#if !defined(FUTEX_UNLOCK_PI) -#define FUTEX_UNLOCK_PI 7 -#endif - -#if !defined(FUTEX_TRYLOCK_PI) -#define FUTEX_TRYLOCK_PI 8 -#endif - -#if !defined(FUTEX_WAIT_BITSET) -#define FUTEX_WAIT_BITSET 9 -#endif - -#if !defined(FUTEX_WAKE_BITSET) -#define FUTEX_WAKE_BITSET 10 -#endif - -#if !defined(FUTEX_WAIT_REQUEUE_PI) -#define FUTEX_WAIT_REQUEUE_PI 11 -#endif - -#if !defined(FUTEX_CMP_REQUEUE_PI) -#define FUTEX_CMP_REQUEUE_PI 12 -#endif - -#if !defined(FUTEX_PRIVATE_FLAG) -#define FUTEX_PRIVATE_FLAG 128 -#endif - -#if !defined FUTEX_CLOCK_REALTIME -#define FUTEX_CLOCK_REALTIME 256 -#endif - -#if !defined(FUTEX_CMD_MASK) -#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) -#endif - -#if !defined(FUTEX_CMP_REQUEUE_PI_PRIVATE) -#define FUTEX_CMP_REQUEUE_PI_PRIVATE (FUTEX_CMP_REQUEUE_PI | FUTEX_PRIVATE_FLAG) -#endif - -#if !defined(FUTEX_UNLOCK_PI_PRIVATE) -#define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG) -#endif - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_FUTEX_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/linux_seccomp.h b/security/sandbox/chromium/sandbox/linux/system_headers/linux_seccomp.h deleted file mode 100644 index 3deb3d225..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/linux_seccomp.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_ - -// The Seccomp2 kernel ABI is not part of older versions of glibc. -// As we can't break compilation with these versions of the library, -// we explicitly define all missing symbols. -// If we ever decide that we can now rely on system headers, the following -// include files should be enabled: -// #include <linux/audit.h> -// #include <linux/seccomp.h> - -// For audit.h -#ifndef EM_ARM -#define EM_ARM 40 -#endif -#ifndef EM_386 -#define EM_386 3 -#endif -#ifndef EM_X86_64 -#define EM_X86_64 62 -#endif -#ifndef EM_MIPS -#define EM_MIPS 8 -#endif -#ifndef EM_AARCH64 -#define EM_AARCH64 183 -#endif - -#ifndef __AUDIT_ARCH_64BIT -#define __AUDIT_ARCH_64BIT 0x80000000 -#endif -#ifndef __AUDIT_ARCH_LE -#define __AUDIT_ARCH_LE 0x40000000 -#endif -#ifndef AUDIT_ARCH_ARM -#define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE) -#endif -#ifndef AUDIT_ARCH_I386 -#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE) -#endif -#ifndef AUDIT_ARCH_X86_64 -#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) -#endif -#ifndef AUDIT_ARCH_MIPSEL -#define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE) -#endif -#ifndef AUDIT_ARCH_AARCH64 -#define AUDIT_ARCH_AARCH64 (EM_AARCH64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE) -#endif - -// For prctl.h -#ifndef PR_SET_SECCOMP -#define PR_SET_SECCOMP 22 -#define PR_GET_SECCOMP 21 -#endif -#ifndef PR_SET_NO_NEW_PRIVS -#define PR_SET_NO_NEW_PRIVS 38 -#define PR_GET_NO_NEW_PRIVS 39 -#endif -#ifndef IPC_64 -#define IPC_64 0x0100 -#endif - -// In order to build will older tool chains, we currently have to avoid -// including <linux/seccomp.h>. Until that can be fixed (if ever). Rely on -// our own definitions of the seccomp kernel ABI. -#ifndef SECCOMP_MODE_FILTER -#define SECCOMP_MODE_DISABLED 0 -#define SECCOMP_MODE_STRICT 1 -#define SECCOMP_MODE_FILTER 2 // User user-supplied filter -#endif - -#ifndef SECCOMP_SET_MODE_STRICT -#define SECCOMP_SET_MODE_STRICT 0 -#endif -#ifndef SECCOMP_SET_MODE_FILTER -#define SECCOMP_SET_MODE_FILTER 1 -#endif -#ifndef SECCOMP_FILTER_FLAG_TSYNC -#define SECCOMP_FILTER_FLAG_TSYNC 1 -#endif - -#ifndef SECCOMP_RET_KILL -// Return values supported for BPF filter programs. Please note that the -// "illegal" SECCOMP_RET_INVALID is not supported by the kernel, should only -// ever be used internally, and would result in the kernel killing our process. -#define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately -#define SECCOMP_RET_INVALID 0x00010000U // Illegal return value -#define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS -#define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno -#define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow -#define SECCOMP_RET_ALLOW 0x7fff0000U // Allow -#define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value -#define SECCOMP_RET_DATA 0x0000ffffU // sections -#else -#define SECCOMP_RET_INVALID 0x00010000U // Illegal return value -#endif - -#ifndef SYS_SECCOMP -#define SYS_SECCOMP 1 -#endif - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/linux_signal.h b/security/sandbox/chromium/sandbox/linux/system_headers/linux_signal.h deleted file mode 100644 index fb9a47b8d..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/linux_signal.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_ - -#include <stdint.h> - -// NOTE: On some toolchains, signal related ABI is incompatible with Linux's -// (not undefined, but defined different values and in different memory -// layouts). So, fill the gap here. -#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \ - defined(__aarch64__) - -#define LINUX_SIGHUP 1 -#define LINUX_SIGINT 2 -#define LINUX_SIGQUIT 3 -#define LINUX_SIGABRT 6 -#define LINUX_SIGBUS 7 -#define LINUX_SIGUSR1 10 -#define LINUX_SIGSEGV 11 -#define LINUX_SIGUSR2 12 -#define LINUX_SIGPIPE 13 -#define LINUX_SIGTERM 15 -#define LINUX_SIGCHLD 17 -#define LINUX_SIGSYS 31 - -#define LINUX_SIG_BLOCK 0 -#define LINUX_SIG_UNBLOCK 1 - -#define LINUX_SA_SIGINFO 4 -#define LINUX_SA_NODEFER 0x40000000 -#define LINUX_SA_RESTART 0x10000000 - -#define LINUX_SIG_DFL 0 - -#elif defined(__mips__) - -#define LINUX_SIGHUP 1 -#define LINUX_SIGINT 2 -#define LINUX_SIGQUIT 3 -#define LINUX_SIGABRT 6 -#define LINUX_SIGBUS 10 -#define LINUX_SIGSEGV 11 -#define LINUX_SIGSYS 12 -#define LINUX_SIGPIPE 13 -#define LINUX_SIGTERM 15 -#define LINUX_SIGUSR1 16 -#define LINUX_SIGUSR2 17 -#define LINUX_SIGCHLD 18 - -#define LINUX_SIG_BLOCK 1 -#define LINUX_SIG_UNBLOCK 2 - -#define LINUX_SA_SIGINFO 0x00000008 -#define LINUX_SA_NODEFER 0x40000000 -#define LINUX_SA_RESTART 0x10000000 - -#define LINUX_SIG_DFL 0 - -#else -#error "Unsupported platform" -#endif - -#if defined(__native_client_nonsfi__) -#if !defined(__i386__) && !defined(__arm__) -#error "Unsupported platform" -#endif - -#include <signal.h> - -struct LinuxSigInfo { - int si_signo; - int si_errno; - int si_code; - - // Extra data is followed by the |si_code|. The length depends on the - // signal number. - char _sifields[1]; -}; - -#include "sandbox/linux/system_headers/linux_ucontext.h" - -#else // !defined(__native_client_nonsfi__) - -#include <signal.h> - -static_assert(LINUX_SIGHUP == SIGHUP, "LINUX_SIGHUP == SIGHUP"); -static_assert(LINUX_SIGINT == SIGINT, "LINUX_SIGINT == SIGINT"); -static_assert(LINUX_SIGQUIT == SIGQUIT, "LINUX_SIGQUIT == SIGQUIT"); -static_assert(LINUX_SIGABRT == SIGABRT, "LINUX_SIGABRT == SIGABRT"); -static_assert(LINUX_SIGBUS == SIGBUS, "LINUX_SIGBUS == SIGBUS"); -static_assert(LINUX_SIGUSR1 == SIGUSR1, "LINUX_SIGUSR1 == SIGUSR1"); -static_assert(LINUX_SIGSEGV == SIGSEGV, "LINUX_SIGSEGV == SIGSEGV"); -static_assert(LINUX_SIGUSR2 == SIGUSR2, "LINUX_SIGUSR2 == SIGUSR2"); -static_assert(LINUX_SIGPIPE == SIGPIPE, "LINUX_SIGPIPE == SIGPIPE"); -static_assert(LINUX_SIGTERM == SIGTERM, "LINUX_SIGTERM == SIGTERM"); -static_assert(LINUX_SIGCHLD == SIGCHLD, "LINUX_SIGCHLD == SIGCHLD"); -static_assert(LINUX_SIGSYS == SIGSYS, "LINUX_SIGSYS == SIGSYS"); -static_assert(LINUX_SIG_BLOCK == SIG_BLOCK, "LINUX_SIG_BLOCK == SIG_BLOCK"); -static_assert(LINUX_SIG_UNBLOCK == SIG_UNBLOCK, - "LINUX_SIG_UNBLOCK == SIG_UNBLOCK"); -static_assert(LINUX_SA_SIGINFO == SA_SIGINFO, "LINUX_SA_SIGINFO == SA_SIGINFO"); -static_assert(LINUX_SA_NODEFER == SA_NODEFER, "LINUX_SA_NODEFER == SA_NODEFER"); -static_assert(LINUX_SA_RESTART == SA_RESTART, "LINUX_SA_RESTART == SA_RESTART"); -static_assert(LINUX_SIG_DFL == SIG_DFL, "LINUX_SIG_DFL == SIG_DFL"); - -typedef siginfo_t LinuxSigInfo; - -#if defined(__ANDROID__) -// Android's signal.h doesn't define ucontext etc. -#include "sandbox/linux/system_headers/linux_ucontext.h" -#endif // defined(__ANDROID__) - -#endif // !defined(__native_client_nonsfi__) - -// struct sigset_t is different size in PNaCl from the Linux's. -#if defined(__mips__) -#if !defined(_NSIG_WORDS) -#define _NSIG_WORDS 4 -#endif -struct LinuxSigSet { - unsigned long sig[_NSIG_WORDS]; -}; -#else -typedef uint64_t LinuxSigSet; -#endif - -// struct sigaction is different in PNaCl from the Linux's. -#if defined(__mips__) -struct LinuxSigAction { - unsigned int sa_flags; - void (*kernel_handler)(int); - LinuxSigSet sa_mask; -}; -#else -struct LinuxSigAction { - void (*kernel_handler)(int); - uint32_t sa_flags; - void (*sa_restorer)(void); - LinuxSigSet sa_mask; -}; -#endif - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/linux_syscalls.h b/security/sandbox/chromium/sandbox/linux/system_headers/linux_syscalls.h deleted file mode 100644 index 2b441e47e..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/linux_syscalls.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This header will be kept up to date so that we can compile system-call -// policies even when system headers are old. -// System call numbers are accessible through __NR_syscall_name. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SYSCALLS_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SYSCALLS_H_ - -#if defined(__x86_64__) -#include "sandbox/linux/system_headers/x86_64_linux_syscalls.h" -#endif - -#if defined(__i386__) -#include "sandbox/linux/system_headers/x86_32_linux_syscalls.h" -#endif - -#if defined(__arm__) && defined(__ARM_EABI__) -#include "sandbox/linux/system_headers/arm_linux_syscalls.h" -#endif - -#if defined(__mips__) && (_MIPS_SIM == _ABIO32) -#include "sandbox/linux/system_headers/mips_linux_syscalls.h" -#endif - -#if defined(__mips__) && (_MIPS_SIM == _ABI64) -#include "sandbox/linux/system_headers/mips64_linux_syscalls.h" -#endif - -#if defined(__aarch64__) -#include "sandbox/linux/system_headers/arm64_linux_syscalls.h" -#endif - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SYSCALLS_H_ - diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/linux_ucontext.h b/security/sandbox/chromium/sandbox/linux/system_headers/linux_ucontext.h deleted file mode 100644 index ea4d8a6c1..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/linux_ucontext.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ - -#if defined(__ANDROID__) || defined(__native_client_nonsfi__) - -#if defined(__arm__) -#include "sandbox/linux/system_headers/arm_linux_ucontext.h" -#elif defined(__i386__) -#include "sandbox/linux/system_headers/i386_linux_ucontext.h" -#elif defined(__x86_64__) -#include "sandbox/linux/system_headers/x86_64_linux_ucontext.h" -#elif defined(__mips__) -#include "sandbox/linux/system_headers/mips_linux_ucontext.h" -#elif defined(__aarch64__) -#include "sandbox/linux/system_headers/arm64_linux_ucontext.h" -#else -#error "No support for your architecture in Android or PNaCl header" -#endif - -#else // defined(__ANDROID__) || defined(__native_client_nonsfi__) -#error "The header file included on non Android and non PNaCl." -#endif // defined(__ANDROID__) || defined(__native_client_nonsfi__) - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h b/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h deleted file mode 100644 index d9b7afc9b..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h +++ /dev/null @@ -1,1494 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Generated from the Linux kernel's syscall_32.tbl. -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_ - -#if !defined(__i386__) -#error "Including header on wrong architecture" -#endif - -#if !defined(__NR_restart_syscall) -#define __NR_restart_syscall 0 -#endif - -#if !defined(__NR_exit) -#define __NR_exit 1 -#endif - -#if !defined(__NR_fork) -#define __NR_fork 2 -#endif - -#if !defined(__NR_read) -#define __NR_read 3 -#endif - -#if !defined(__NR_write) -#define __NR_write 4 -#endif - -#if !defined(__NR_open) -#define __NR_open 5 -#endif - -#if !defined(__NR_close) -#define __NR_close 6 -#endif - -#if !defined(__NR_waitpid) -#define __NR_waitpid 7 -#endif - -#if !defined(__NR_creat) -#define __NR_creat 8 -#endif - -#if !defined(__NR_link) -#define __NR_link 9 -#endif - -#if !defined(__NR_unlink) -#define __NR_unlink 10 -#endif - -#if !defined(__NR_execve) -#define __NR_execve 11 -#endif - -#if !defined(__NR_chdir) -#define __NR_chdir 12 -#endif - -#if !defined(__NR_time) -#define __NR_time 13 -#endif - -#if !defined(__NR_mknod) -#define __NR_mknod 14 -#endif - -#if !defined(__NR_chmod) -#define __NR_chmod 15 -#endif - -#if !defined(__NR_lchown) -#define __NR_lchown 16 -#endif - -#if !defined(__NR_break) -#define __NR_break 17 -#endif - -#if !defined(__NR_oldstat) -#define __NR_oldstat 18 -#endif - -#if !defined(__NR_lseek) -#define __NR_lseek 19 -#endif - -#if !defined(__NR_getpid) -#define __NR_getpid 20 -#endif - -#if !defined(__NR_mount) -#define __NR_mount 21 -#endif - -#if !defined(__NR_umount) -#define __NR_umount 22 -#endif - -#if !defined(__NR_setuid) -#define __NR_setuid 23 -#endif - -#if !defined(__NR_getuid) -#define __NR_getuid 24 -#endif - -#if !defined(__NR_stime) -#define __NR_stime 25 -#endif - -#if !defined(__NR_ptrace) -#define __NR_ptrace 26 -#endif - -#if !defined(__NR_alarm) -#define __NR_alarm 27 -#endif - -#if !defined(__NR_oldfstat) -#define __NR_oldfstat 28 -#endif - -#if !defined(__NR_pause) -#define __NR_pause 29 -#endif - -#if !defined(__NR_utime) -#define __NR_utime 30 -#endif - -#if !defined(__NR_stty) -#define __NR_stty 31 -#endif - -#if !defined(__NR_gtty) -#define __NR_gtty 32 -#endif - -#if !defined(__NR_access) -#define __NR_access 33 -#endif - -#if !defined(__NR_nice) -#define __NR_nice 34 -#endif - -#if !defined(__NR_ftime) -#define __NR_ftime 35 -#endif - -#if !defined(__NR_sync) -#define __NR_sync 36 -#endif - -#if !defined(__NR_kill) -#define __NR_kill 37 -#endif - -#if !defined(__NR_rename) -#define __NR_rename 38 -#endif - -#if !defined(__NR_mkdir) -#define __NR_mkdir 39 -#endif - -#if !defined(__NR_rmdir) -#define __NR_rmdir 40 -#endif - -#if !defined(__NR_dup) -#define __NR_dup 41 -#endif - -#if !defined(__NR_pipe) -#define __NR_pipe 42 -#endif - -#if !defined(__NR_times) -#define __NR_times 43 -#endif - -#if !defined(__NR_prof) -#define __NR_prof 44 -#endif - -#if !defined(__NR_brk) -#define __NR_brk 45 -#endif - -#if !defined(__NR_setgid) -#define __NR_setgid 46 -#endif - -#if !defined(__NR_getgid) -#define __NR_getgid 47 -#endif - -#if !defined(__NR_signal) -#define __NR_signal 48 -#endif - -#if !defined(__NR_geteuid) -#define __NR_geteuid 49 -#endif - -#if !defined(__NR_getegid) -#define __NR_getegid 50 -#endif - -#if !defined(__NR_acct) -#define __NR_acct 51 -#endif - -#if !defined(__NR_umount2) -#define __NR_umount2 52 -#endif - -#if !defined(__NR_lock) -#define __NR_lock 53 -#endif - -#if !defined(__NR_ioctl) -#define __NR_ioctl 54 -#endif - -#if !defined(__NR_fcntl) -#define __NR_fcntl 55 -#endif - -#if !defined(__NR_mpx) -#define __NR_mpx 56 -#endif - -#if !defined(__NR_setpgid) -#define __NR_setpgid 57 -#endif - -#if !defined(__NR_ulimit) -#define __NR_ulimit 58 -#endif - -#if !defined(__NR_oldolduname) -#define __NR_oldolduname 59 -#endif - -#if !defined(__NR_umask) -#define __NR_umask 60 -#endif - -#if !defined(__NR_chroot) -#define __NR_chroot 61 -#endif - -#if !defined(__NR_ustat) -#define __NR_ustat 62 -#endif - -#if !defined(__NR_dup2) -#define __NR_dup2 63 -#endif - -#if !defined(__NR_getppid) -#define __NR_getppid 64 -#endif - -#if !defined(__NR_getpgrp) -#define __NR_getpgrp 65 -#endif - -#if !defined(__NR_setsid) -#define __NR_setsid 66 -#endif - -#if !defined(__NR_sigaction) -#define __NR_sigaction 67 -#endif - -#if !defined(__NR_sgetmask) -#define __NR_sgetmask 68 -#endif - -#if !defined(__NR_ssetmask) -#define __NR_ssetmask 69 -#endif - -#if !defined(__NR_setreuid) -#define __NR_setreuid 70 -#endif - -#if !defined(__NR_setregid) -#define __NR_setregid 71 -#endif - -#if !defined(__NR_sigsuspend) -#define __NR_sigsuspend 72 -#endif - -#if !defined(__NR_sigpending) -#define __NR_sigpending 73 -#endif - -#if !defined(__NR_sethostname) -#define __NR_sethostname 74 -#endif - -#if !defined(__NR_setrlimit) -#define __NR_setrlimit 75 -#endif - -#if !defined(__NR_getrlimit) -#define __NR_getrlimit 76 -#endif - -#if !defined(__NR_getrusage) -#define __NR_getrusage 77 -#endif - -#if !defined(__NR_gettimeofday) -#define __NR_gettimeofday 78 -#endif - -#if !defined(__NR_settimeofday) -#define __NR_settimeofday 79 -#endif - -#if !defined(__NR_getgroups) -#define __NR_getgroups 80 -#endif - -#if !defined(__NR_setgroups) -#define __NR_setgroups 81 -#endif - -#if !defined(__NR_select) -#define __NR_select 82 -#endif - -#if !defined(__NR_symlink) -#define __NR_symlink 83 -#endif - -#if !defined(__NR_oldlstat) -#define __NR_oldlstat 84 -#endif - -#if !defined(__NR_readlink) -#define __NR_readlink 85 -#endif - -#if !defined(__NR_uselib) -#define __NR_uselib 86 -#endif - -#if !defined(__NR_swapon) -#define __NR_swapon 87 -#endif - -#if !defined(__NR_reboot) -#define __NR_reboot 88 -#endif - -#if !defined(__NR_readdir) -#define __NR_readdir 89 -#endif - -#if !defined(__NR_mmap) -#define __NR_mmap 90 -#endif - -#if !defined(__NR_munmap) -#define __NR_munmap 91 -#endif - -#if !defined(__NR_truncate) -#define __NR_truncate 92 -#endif - -#if !defined(__NR_ftruncate) -#define __NR_ftruncate 93 -#endif - -#if !defined(__NR_fchmod) -#define __NR_fchmod 94 -#endif - -#if !defined(__NR_fchown) -#define __NR_fchown 95 -#endif - -#if !defined(__NR_getpriority) -#define __NR_getpriority 96 -#endif - -#if !defined(__NR_setpriority) -#define __NR_setpriority 97 -#endif - -#if !defined(__NR_profil) -#define __NR_profil 98 -#endif - -#if !defined(__NR_statfs) -#define __NR_statfs 99 -#endif - -#if !defined(__NR_fstatfs) -#define __NR_fstatfs 100 -#endif - -#if !defined(__NR_ioperm) -#define __NR_ioperm 101 -#endif - -#if !defined(__NR_socketcall) -#define __NR_socketcall 102 -#endif - -#if !defined(__NR_syslog) -#define __NR_syslog 103 -#endif - -#if !defined(__NR_setitimer) -#define __NR_setitimer 104 -#endif - -#if !defined(__NR_getitimer) -#define __NR_getitimer 105 -#endif - -#if !defined(__NR_stat) -#define __NR_stat 106 -#endif - -#if !defined(__NR_lstat) -#define __NR_lstat 107 -#endif - -#if !defined(__NR_fstat) -#define __NR_fstat 108 -#endif - -#if !defined(__NR_olduname) -#define __NR_olduname 109 -#endif - -#if !defined(__NR_iopl) -#define __NR_iopl 110 -#endif - -#if !defined(__NR_vhangup) -#define __NR_vhangup 111 -#endif - -#if !defined(__NR_idle) -#define __NR_idle 112 -#endif - -#if !defined(__NR_vm86old) -#define __NR_vm86old 113 -#endif - -#if !defined(__NR_wait4) -#define __NR_wait4 114 -#endif - -#if !defined(__NR_swapoff) -#define __NR_swapoff 115 -#endif - -#if !defined(__NR_sysinfo) -#define __NR_sysinfo 116 -#endif - -#if !defined(__NR_ipc) -#define __NR_ipc 117 -#endif - -#if !defined(__NR_fsync) -#define __NR_fsync 118 -#endif - -#if !defined(__NR_sigreturn) -#define __NR_sigreturn 119 -#endif - -#if !defined(__NR_clone) -#define __NR_clone 120 -#endif - -#if !defined(__NR_setdomainname) -#define __NR_setdomainname 121 -#endif - -#if !defined(__NR_uname) -#define __NR_uname 122 -#endif - -#if !defined(__NR_modify_ldt) -#define __NR_modify_ldt 123 -#endif - -#if !defined(__NR_adjtimex) -#define __NR_adjtimex 124 -#endif - -#if !defined(__NR_mprotect) -#define __NR_mprotect 125 -#endif - -#if !defined(__NR_sigprocmask) -#define __NR_sigprocmask 126 -#endif - -#if !defined(__NR_create_module) -#define __NR_create_module 127 -#endif - -#if !defined(__NR_init_module) -#define __NR_init_module 128 -#endif - -#if !defined(__NR_delete_module) -#define __NR_delete_module 129 -#endif - -#if !defined(__NR_get_kernel_syms) -#define __NR_get_kernel_syms 130 -#endif - -#if !defined(__NR_quotactl) -#define __NR_quotactl 131 -#endif - -#if !defined(__NR_getpgid) -#define __NR_getpgid 132 -#endif - -#if !defined(__NR_fchdir) -#define __NR_fchdir 133 -#endif - -#if !defined(__NR_bdflush) -#define __NR_bdflush 134 -#endif - -#if !defined(__NR_sysfs) -#define __NR_sysfs 135 -#endif - -#if !defined(__NR_personality) -#define __NR_personality 136 -#endif - -#if !defined(__NR_afs_syscall) -#define __NR_afs_syscall 137 -#endif - -#if !defined(__NR_setfsuid) -#define __NR_setfsuid 138 -#endif - -#if !defined(__NR_setfsgid) -#define __NR_setfsgid 139 -#endif - -#if !defined(__NR__llseek) -#define __NR__llseek 140 -#endif - -#if !defined(__NR_getdents) -#define __NR_getdents 141 -#endif - -#if !defined(__NR__newselect) -#define __NR__newselect 142 -#endif - -#if !defined(__NR_flock) -#define __NR_flock 143 -#endif - -#if !defined(__NR_msync) -#define __NR_msync 144 -#endif - -#if !defined(__NR_readv) -#define __NR_readv 145 -#endif - -#if !defined(__NR_writev) -#define __NR_writev 146 -#endif - -#if !defined(__NR_getsid) -#define __NR_getsid 147 -#endif - -#if !defined(__NR_fdatasync) -#define __NR_fdatasync 148 -#endif - -#if !defined(__NR__sysctl) -#define __NR__sysctl 149 -#endif - -#if !defined(__NR_mlock) -#define __NR_mlock 150 -#endif - -#if !defined(__NR_munlock) -#define __NR_munlock 151 -#endif - -#if !defined(__NR_mlockall) -#define __NR_mlockall 152 -#endif - -#if !defined(__NR_munlockall) -#define __NR_munlockall 153 -#endif - -#if !defined(__NR_sched_setparam) -#define __NR_sched_setparam 154 -#endif - -#if !defined(__NR_sched_getparam) -#define __NR_sched_getparam 155 -#endif - -#if !defined(__NR_sched_setscheduler) -#define __NR_sched_setscheduler 156 -#endif - -#if !defined(__NR_sched_getscheduler) -#define __NR_sched_getscheduler 157 -#endif - -#if !defined(__NR_sched_yield) -#define __NR_sched_yield 158 -#endif - -#if !defined(__NR_sched_get_priority_max) -#define __NR_sched_get_priority_max 159 -#endif - -#if !defined(__NR_sched_get_priority_min) -#define __NR_sched_get_priority_min 160 -#endif - -#if !defined(__NR_sched_rr_get_interval) -#define __NR_sched_rr_get_interval 161 -#endif - -#if !defined(__NR_nanosleep) -#define __NR_nanosleep 162 -#endif - -#if !defined(__NR_mremap) -#define __NR_mremap 163 -#endif - -#if !defined(__NR_setresuid) -#define __NR_setresuid 164 -#endif - -#if !defined(__NR_getresuid) -#define __NR_getresuid 165 -#endif - -#if !defined(__NR_vm86) -#define __NR_vm86 166 -#endif - -#if !defined(__NR_query_module) -#define __NR_query_module 167 -#endif - -#if !defined(__NR_poll) -#define __NR_poll 168 -#endif - -#if !defined(__NR_nfsservctl) -#define __NR_nfsservctl 169 -#endif - -#if !defined(__NR_setresgid) -#define __NR_setresgid 170 -#endif - -#if !defined(__NR_getresgid) -#define __NR_getresgid 171 -#endif - -#if !defined(__NR_prctl) -#define __NR_prctl 172 -#endif - -#if !defined(__NR_rt_sigreturn) -#define __NR_rt_sigreturn 173 -#endif - -#if !defined(__NR_rt_sigaction) -#define __NR_rt_sigaction 174 -#endif - -#if !defined(__NR_rt_sigprocmask) -#define __NR_rt_sigprocmask 175 -#endif - -#if !defined(__NR_rt_sigpending) -#define __NR_rt_sigpending 176 -#endif - -#if !defined(__NR_rt_sigtimedwait) -#define __NR_rt_sigtimedwait 177 -#endif - -#if !defined(__NR_rt_sigqueueinfo) -#define __NR_rt_sigqueueinfo 178 -#endif - -#if !defined(__NR_rt_sigsuspend) -#define __NR_rt_sigsuspend 179 -#endif - -#if !defined(__NR_pread64) -#define __NR_pread64 180 -#endif - -#if !defined(__NR_pwrite64) -#define __NR_pwrite64 181 -#endif - -#if !defined(__NR_chown) -#define __NR_chown 182 -#endif - -#if !defined(__NR_getcwd) -#define __NR_getcwd 183 -#endif - -#if !defined(__NR_capget) -#define __NR_capget 184 -#endif - -#if !defined(__NR_capset) -#define __NR_capset 185 -#endif - -#if !defined(__NR_sigaltstack) -#define __NR_sigaltstack 186 -#endif - -#if !defined(__NR_sendfile) -#define __NR_sendfile 187 -#endif - -#if !defined(__NR_getpmsg) -#define __NR_getpmsg 188 -#endif - -#if !defined(__NR_putpmsg) -#define __NR_putpmsg 189 -#endif - -#if !defined(__NR_vfork) -#define __NR_vfork 190 -#endif - -#if !defined(__NR_ugetrlimit) -#define __NR_ugetrlimit 191 -#endif - -#if !defined(__NR_mmap2) -#define __NR_mmap2 192 -#endif - -#if !defined(__NR_truncate64) -#define __NR_truncate64 193 -#endif - -#if !defined(__NR_ftruncate64) -#define __NR_ftruncate64 194 -#endif - -#if !defined(__NR_stat64) -#define __NR_stat64 195 -#endif - -#if !defined(__NR_lstat64) -#define __NR_lstat64 196 -#endif - -#if !defined(__NR_fstat64) -#define __NR_fstat64 197 -#endif - -#if !defined(__NR_lchown32) -#define __NR_lchown32 198 -#endif - -#if !defined(__NR_getuid32) -#define __NR_getuid32 199 -#endif - -#if !defined(__NR_getgid32) -#define __NR_getgid32 200 -#endif - -#if !defined(__NR_geteuid32) -#define __NR_geteuid32 201 -#endif - -#if !defined(__NR_getegid32) -#define __NR_getegid32 202 -#endif - -#if !defined(__NR_setreuid32) -#define __NR_setreuid32 203 -#endif - -#if !defined(__NR_setregid32) -#define __NR_setregid32 204 -#endif - -#if !defined(__NR_getgroups32) -#define __NR_getgroups32 205 -#endif - -#if !defined(__NR_setgroups32) -#define __NR_setgroups32 206 -#endif - -#if !defined(__NR_fchown32) -#define __NR_fchown32 207 -#endif - -#if !defined(__NR_setresuid32) -#define __NR_setresuid32 208 -#endif - -#if !defined(__NR_getresuid32) -#define __NR_getresuid32 209 -#endif - -#if !defined(__NR_setresgid32) -#define __NR_setresgid32 210 -#endif - -#if !defined(__NR_getresgid32) -#define __NR_getresgid32 211 -#endif - -#if !defined(__NR_chown32) -#define __NR_chown32 212 -#endif - -#if !defined(__NR_setuid32) -#define __NR_setuid32 213 -#endif - -#if !defined(__NR_setgid32) -#define __NR_setgid32 214 -#endif - -#if !defined(__NR_setfsuid32) -#define __NR_setfsuid32 215 -#endif - -#if !defined(__NR_setfsgid32) -#define __NR_setfsgid32 216 -#endif - -#if !defined(__NR_pivot_root) -#define __NR_pivot_root 217 -#endif - -#if !defined(__NR_mincore) -#define __NR_mincore 218 -#endif - -#if !defined(__NR_madvise) -#define __NR_madvise 219 -#endif - -#if !defined(__NR_getdents64) -#define __NR_getdents64 220 -#endif - -#if !defined(__NR_fcntl64) -#define __NR_fcntl64 221 -#endif - -#if !defined(__NR_gettid) -#define __NR_gettid 224 -#endif - -#if !defined(__NR_readahead) -#define __NR_readahead 225 -#endif - -#if !defined(__NR_setxattr) -#define __NR_setxattr 226 -#endif - -#if !defined(__NR_lsetxattr) -#define __NR_lsetxattr 227 -#endif - -#if !defined(__NR_fsetxattr) -#define __NR_fsetxattr 228 -#endif - -#if !defined(__NR_getxattr) -#define __NR_getxattr 229 -#endif - -#if !defined(__NR_lgetxattr) -#define __NR_lgetxattr 230 -#endif - -#if !defined(__NR_fgetxattr) -#define __NR_fgetxattr 231 -#endif - -#if !defined(__NR_listxattr) -#define __NR_listxattr 232 -#endif - -#if !defined(__NR_llistxattr) -#define __NR_llistxattr 233 -#endif - -#if !defined(__NR_flistxattr) -#define __NR_flistxattr 234 -#endif - -#if !defined(__NR_removexattr) -#define __NR_removexattr 235 -#endif - -#if !defined(__NR_lremovexattr) -#define __NR_lremovexattr 236 -#endif - -#if !defined(__NR_fremovexattr) -#define __NR_fremovexattr 237 -#endif - -#if !defined(__NR_tkill) -#define __NR_tkill 238 -#endif - -#if !defined(__NR_sendfile64) -#define __NR_sendfile64 239 -#endif - -#if !defined(__NR_futex) -#define __NR_futex 240 -#endif - -#if !defined(__NR_sched_setaffinity) -#define __NR_sched_setaffinity 241 -#endif - -#if !defined(__NR_sched_getaffinity) -#define __NR_sched_getaffinity 242 -#endif - -#if !defined(__NR_set_thread_area) -#define __NR_set_thread_area 243 -#endif - -#if !defined(__NR_get_thread_area) -#define __NR_get_thread_area 244 -#endif - -#if !defined(__NR_io_setup) -#define __NR_io_setup 245 -#endif - -#if !defined(__NR_io_destroy) -#define __NR_io_destroy 246 -#endif - -#if !defined(__NR_io_getevents) -#define __NR_io_getevents 247 -#endif - -#if !defined(__NR_io_submit) -#define __NR_io_submit 248 -#endif - -#if !defined(__NR_io_cancel) -#define __NR_io_cancel 249 -#endif - -#if !defined(__NR_fadvise64) -#define __NR_fadvise64 250 -#endif - -#if !defined(__NR_exit_group) -#define __NR_exit_group 252 -#endif - -#if !defined(__NR_lookup_dcookie) -#define __NR_lookup_dcookie 253 -#endif - -#if !defined(__NR_epoll_create) -#define __NR_epoll_create 254 -#endif - -#if !defined(__NR_epoll_ctl) -#define __NR_epoll_ctl 255 -#endif - -#if !defined(__NR_epoll_wait) -#define __NR_epoll_wait 256 -#endif - -#if !defined(__NR_remap_file_pages) -#define __NR_remap_file_pages 257 -#endif - -#if !defined(__NR_set_tid_address) -#define __NR_set_tid_address 258 -#endif - -#if !defined(__NR_timer_create) -#define __NR_timer_create 259 -#endif - -#if !defined(__NR_timer_settime) -#define __NR_timer_settime 260 -#endif - -#if !defined(__NR_timer_gettime) -#define __NR_timer_gettime 261 -#endif - -#if !defined(__NR_timer_getoverrun) -#define __NR_timer_getoverrun 262 -#endif - -#if !defined(__NR_timer_delete) -#define __NR_timer_delete 263 -#endif - -#if !defined(__NR_clock_settime) -#define __NR_clock_settime 264 -#endif - -#if !defined(__NR_clock_gettime) -#define __NR_clock_gettime 265 -#endif - -#if !defined(__NR_clock_getres) -#define __NR_clock_getres 266 -#endif - -#if !defined(__NR_clock_nanosleep) -#define __NR_clock_nanosleep 267 -#endif - -#if !defined(__NR_statfs64) -#define __NR_statfs64 268 -#endif - -#if !defined(__NR_fstatfs64) -#define __NR_fstatfs64 269 -#endif - -#if !defined(__NR_tgkill) -#define __NR_tgkill 270 -#endif - -#if !defined(__NR_utimes) -#define __NR_utimes 271 -#endif - -#if !defined(__NR_fadvise64_64) -#define __NR_fadvise64_64 272 -#endif - -#if !defined(__NR_vserver) -#define __NR_vserver 273 -#endif - -#if !defined(__NR_mbind) -#define __NR_mbind 274 -#endif - -#if !defined(__NR_get_mempolicy) -#define __NR_get_mempolicy 275 -#endif - -#if !defined(__NR_set_mempolicy) -#define __NR_set_mempolicy 276 -#endif - -#if !defined(__NR_mq_open) -#define __NR_mq_open 277 -#endif - -#if !defined(__NR_mq_unlink) -#define __NR_mq_unlink 278 -#endif - -#if !defined(__NR_mq_timedsend) -#define __NR_mq_timedsend 279 -#endif - -#if !defined(__NR_mq_timedreceive) -#define __NR_mq_timedreceive 280 -#endif - -#if !defined(__NR_mq_notify) -#define __NR_mq_notify 281 -#endif - -#if !defined(__NR_mq_getsetattr) -#define __NR_mq_getsetattr 282 -#endif - -#if !defined(__NR_kexec_load) -#define __NR_kexec_load 283 -#endif - -#if !defined(__NR_waitid) -#define __NR_waitid 284 -#endif - -#if !defined(__NR_add_key) -#define __NR_add_key 286 -#endif - -#if !defined(__NR_request_key) -#define __NR_request_key 287 -#endif - -#if !defined(__NR_keyctl) -#define __NR_keyctl 288 -#endif - -#if !defined(__NR_ioprio_set) -#define __NR_ioprio_set 289 -#endif - -#if !defined(__NR_ioprio_get) -#define __NR_ioprio_get 290 -#endif - -#if !defined(__NR_inotify_init) -#define __NR_inotify_init 291 -#endif - -#if !defined(__NR_inotify_add_watch) -#define __NR_inotify_add_watch 292 -#endif - -#if !defined(__NR_inotify_rm_watch) -#define __NR_inotify_rm_watch 293 -#endif - -#if !defined(__NR_migrate_pages) -#define __NR_migrate_pages 294 -#endif - -#if !defined(__NR_openat) -#define __NR_openat 295 -#endif - -#if !defined(__NR_mkdirat) -#define __NR_mkdirat 296 -#endif - -#if !defined(__NR_mknodat) -#define __NR_mknodat 297 -#endif - -#if !defined(__NR_fchownat) -#define __NR_fchownat 298 -#endif - -#if !defined(__NR_futimesat) -#define __NR_futimesat 299 -#endif - -#if !defined(__NR_fstatat64) -#define __NR_fstatat64 300 -#endif - -#if !defined(__NR_unlinkat) -#define __NR_unlinkat 301 -#endif - -#if !defined(__NR_renameat) -#define __NR_renameat 302 -#endif - -#if !defined(__NR_linkat) -#define __NR_linkat 303 -#endif - -#if !defined(__NR_symlinkat) -#define __NR_symlinkat 304 -#endif - -#if !defined(__NR_readlinkat) -#define __NR_readlinkat 305 -#endif - -#if !defined(__NR_fchmodat) -#define __NR_fchmodat 306 -#endif - -#if !defined(__NR_faccessat) -#define __NR_faccessat 307 -#endif - -#if !defined(__NR_pselect6) -#define __NR_pselect6 308 -#endif - -#if !defined(__NR_ppoll) -#define __NR_ppoll 309 -#endif - -#if !defined(__NR_unshare) -#define __NR_unshare 310 -#endif - -#if !defined(__NR_set_robust_list) -#define __NR_set_robust_list 311 -#endif - -#if !defined(__NR_get_robust_list) -#define __NR_get_robust_list 312 -#endif - -#if !defined(__NR_splice) -#define __NR_splice 313 -#endif - -#if !defined(__NR_sync_file_range) -#define __NR_sync_file_range 314 -#endif - -#if !defined(__NR_tee) -#define __NR_tee 315 -#endif - -#if !defined(__NR_vmsplice) -#define __NR_vmsplice 316 -#endif - -#if !defined(__NR_move_pages) -#define __NR_move_pages 317 -#endif - -#if !defined(__NR_getcpu) -#define __NR_getcpu 318 -#endif - -#if !defined(__NR_epoll_pwait) -#define __NR_epoll_pwait 319 -#endif - -#if !defined(__NR_utimensat) -#define __NR_utimensat 320 -#endif - -#if !defined(__NR_signalfd) -#define __NR_signalfd 321 -#endif - -#if !defined(__NR_timerfd_create) -#define __NR_timerfd_create 322 -#endif - -#if !defined(__NR_eventfd) -#define __NR_eventfd 323 -#endif - -#if !defined(__NR_fallocate) -#define __NR_fallocate 324 -#endif - -#if !defined(__NR_timerfd_settime) -#define __NR_timerfd_settime 325 -#endif - -#if !defined(__NR_timerfd_gettime) -#define __NR_timerfd_gettime 326 -#endif - -#if !defined(__NR_signalfd4) -#define __NR_signalfd4 327 -#endif - -#if !defined(__NR_eventfd2) -#define __NR_eventfd2 328 -#endif - -#if !defined(__NR_epoll_create1) -#define __NR_epoll_create1 329 -#endif - -#if !defined(__NR_dup3) -#define __NR_dup3 330 -#endif - -#if !defined(__NR_pipe2) -#define __NR_pipe2 331 -#endif - -#if !defined(__NR_inotify_init1) -#define __NR_inotify_init1 332 -#endif - -#if !defined(__NR_preadv) -#define __NR_preadv 333 -#endif - -#if !defined(__NR_pwritev) -#define __NR_pwritev 334 -#endif - -#if !defined(__NR_rt_tgsigqueueinfo) -#define __NR_rt_tgsigqueueinfo 335 -#endif - -#if !defined(__NR_perf_event_open) -#define __NR_perf_event_open 336 -#endif - -#if !defined(__NR_recvmmsg) -#define __NR_recvmmsg 337 -#endif - -#if !defined(__NR_fanotify_init) -#define __NR_fanotify_init 338 -#endif - -#if !defined(__NR_fanotify_mark) -#define __NR_fanotify_mark 339 -#endif - -#if !defined(__NR_prlimit64) -#define __NR_prlimit64 340 -#endif - -#if !defined(__NR_name_to_handle_at) -#define __NR_name_to_handle_at 341 -#endif - -#if !defined(__NR_open_by_handle_at) -#define __NR_open_by_handle_at 342 -#endif - -#if !defined(__NR_clock_adjtime) -#define __NR_clock_adjtime 343 -#endif - -#if !defined(__NR_syncfs) -#define __NR_syncfs 344 -#endif - -#if !defined(__NR_sendmmsg) -#define __NR_sendmmsg 345 -#endif - -#if !defined(__NR_setns) -#define __NR_setns 346 -#endif - -#if !defined(__NR_process_vm_readv) -#define __NR_process_vm_readv 347 -#endif - -#if !defined(__NR_process_vm_writev) -#define __NR_process_vm_writev 348 -#endif - -#if !defined(__NR_kcmp) -#define __NR_kcmp 349 -#endif - -#if !defined(__NR_finit_module) -#define __NR_finit_module 350 -#endif - -#if !defined(__NR_sched_setattr) -#define __NR_sched_setattr 351 -#endif - -#if !defined(__NR_sched_getattr) -#define __NR_sched_getattr 352 -#endif - -#if !defined(__NR_renameat2) -#define __NR_renameat2 353 -#endif - -#if !defined(__NR_seccomp) -#define __NR_seccomp 354 -#endif - -#if !defined(__NR_getrandom) -#define __NR_getrandom 355 -#endif - -#if !defined(__NR_memfd_create) -#define __NR_memfd_create 356 -#endif - -#if !defined(__NR_bpf) -#define __NR_bpf 357 -#endif - -#if !defined(__NR_execveat) -#define __NR_execveat 358 -#endif - -#if !defined(__NR_socket) -#define __NR_socket 359 -#endif - -#if !defined(__NR_socketpair) -#define __NR_socketpair 360 -#endif - -#if !defined(__NR_bind) -#define __NR_bind 361 -#endif - -#if !defined(__NR_connect) -#define __NR_connect 362 -#endif - -#if !defined(__NR_listen) -#define __NR_listen 363 -#endif - -#if !defined(__NR_accept4) -#define __NR_accept4 364 -#endif - -#if !defined(__NR_getsockopt) -#define __NR_getsockopt 365 -#endif - -#if !defined(__NR_setsockopt) -#define __NR_setsockopt 366 -#endif - -#if !defined(__NR_getsockname) -#define __NR_getsockname 367 -#endif - -#if !defined(__NR_getpeername) -#define __NR_getpeername 368 -#endif - -#if !defined(__NR_sendto) -#define __NR_sendto 369 -#endif - -#if !defined(__NR_sendmsg) -#define __NR_sendmsg 370 -#endif - -#if !defined(__NR_recvfrom) -#define __NR_recvfrom 371 -#endif - -#if !defined(__NR_recvmsg) -#define __NR_recvmsg 372 -#endif - -#if !defined(__NR_shutdown) -#define __NR_shutdown 373 -#endif - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_ - diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h b/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h deleted file mode 100644 index 349504aee..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h +++ /dev/null @@ -1,1294 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Generated from the Linux kernel's syscall_64.tbl. -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_ - -#if !defined(__x86_64__) -#error "Including header on wrong architecture" -#endif - -#if !defined(__NR_read) -#define __NR_read 0 -#endif - -#if !defined(__NR_write) -#define __NR_write 1 -#endif - -#if !defined(__NR_open) -#define __NR_open 2 -#endif - -#if !defined(__NR_close) -#define __NR_close 3 -#endif - -#if !defined(__NR_stat) -#define __NR_stat 4 -#endif - -#if !defined(__NR_fstat) -#define __NR_fstat 5 -#endif - -#if !defined(__NR_lstat) -#define __NR_lstat 6 -#endif - -#if !defined(__NR_poll) -#define __NR_poll 7 -#endif - -#if !defined(__NR_lseek) -#define __NR_lseek 8 -#endif - -#if !defined(__NR_mmap) -#define __NR_mmap 9 -#endif - -#if !defined(__NR_mprotect) -#define __NR_mprotect 10 -#endif - -#if !defined(__NR_munmap) -#define __NR_munmap 11 -#endif - -#if !defined(__NR_brk) -#define __NR_brk 12 -#endif - -#if !defined(__NR_rt_sigaction) -#define __NR_rt_sigaction 13 -#endif - -#if !defined(__NR_rt_sigprocmask) -#define __NR_rt_sigprocmask 14 -#endif - -#if !defined(__NR_rt_sigreturn) -#define __NR_rt_sigreturn 15 -#endif - -#if !defined(__NR_ioctl) -#define __NR_ioctl 16 -#endif - -#if !defined(__NR_pread64) -#define __NR_pread64 17 -#endif - -#if !defined(__NR_pwrite64) -#define __NR_pwrite64 18 -#endif - -#if !defined(__NR_readv) -#define __NR_readv 19 -#endif - -#if !defined(__NR_writev) -#define __NR_writev 20 -#endif - -#if !defined(__NR_access) -#define __NR_access 21 -#endif - -#if !defined(__NR_pipe) -#define __NR_pipe 22 -#endif - -#if !defined(__NR_select) -#define __NR_select 23 -#endif - -#if !defined(__NR_sched_yield) -#define __NR_sched_yield 24 -#endif - -#if !defined(__NR_mremap) -#define __NR_mremap 25 -#endif - -#if !defined(__NR_msync) -#define __NR_msync 26 -#endif - -#if !defined(__NR_mincore) -#define __NR_mincore 27 -#endif - -#if !defined(__NR_madvise) -#define __NR_madvise 28 -#endif - -#if !defined(__NR_shmget) -#define __NR_shmget 29 -#endif - -#if !defined(__NR_shmat) -#define __NR_shmat 30 -#endif - -#if !defined(__NR_shmctl) -#define __NR_shmctl 31 -#endif - -#if !defined(__NR_dup) -#define __NR_dup 32 -#endif - -#if !defined(__NR_dup2) -#define __NR_dup2 33 -#endif - -#if !defined(__NR_pause) -#define __NR_pause 34 -#endif - -#if !defined(__NR_nanosleep) -#define __NR_nanosleep 35 -#endif - -#if !defined(__NR_getitimer) -#define __NR_getitimer 36 -#endif - -#if !defined(__NR_alarm) -#define __NR_alarm 37 -#endif - -#if !defined(__NR_setitimer) -#define __NR_setitimer 38 -#endif - -#if !defined(__NR_getpid) -#define __NR_getpid 39 -#endif - -#if !defined(__NR_sendfile) -#define __NR_sendfile 40 -#endif - -#if !defined(__NR_socket) -#define __NR_socket 41 -#endif - -#if !defined(__NR_connect) -#define __NR_connect 42 -#endif - -#if !defined(__NR_accept) -#define __NR_accept 43 -#endif - -#if !defined(__NR_sendto) -#define __NR_sendto 44 -#endif - -#if !defined(__NR_recvfrom) -#define __NR_recvfrom 45 -#endif - -#if !defined(__NR_sendmsg) -#define __NR_sendmsg 46 -#endif - -#if !defined(__NR_recvmsg) -#define __NR_recvmsg 47 -#endif - -#if !defined(__NR_shutdown) -#define __NR_shutdown 48 -#endif - -#if !defined(__NR_bind) -#define __NR_bind 49 -#endif - -#if !defined(__NR_listen) -#define __NR_listen 50 -#endif - -#if !defined(__NR_getsockname) -#define __NR_getsockname 51 -#endif - -#if !defined(__NR_getpeername) -#define __NR_getpeername 52 -#endif - -#if !defined(__NR_socketpair) -#define __NR_socketpair 53 -#endif - -#if !defined(__NR_setsockopt) -#define __NR_setsockopt 54 -#endif - -#if !defined(__NR_getsockopt) -#define __NR_getsockopt 55 -#endif - -#if !defined(__NR_clone) -#define __NR_clone 56 -#endif - -#if !defined(__NR_fork) -#define __NR_fork 57 -#endif - -#if !defined(__NR_vfork) -#define __NR_vfork 58 -#endif - -#if !defined(__NR_execve) -#define __NR_execve 59 -#endif - -#if !defined(__NR_exit) -#define __NR_exit 60 -#endif - -#if !defined(__NR_wait4) -#define __NR_wait4 61 -#endif - -#if !defined(__NR_kill) -#define __NR_kill 62 -#endif - -#if !defined(__NR_uname) -#define __NR_uname 63 -#endif - -#if !defined(__NR_semget) -#define __NR_semget 64 -#endif - -#if !defined(__NR_semop) -#define __NR_semop 65 -#endif - -#if !defined(__NR_semctl) -#define __NR_semctl 66 -#endif - -#if !defined(__NR_shmdt) -#define __NR_shmdt 67 -#endif - -#if !defined(__NR_msgget) -#define __NR_msgget 68 -#endif - -#if !defined(__NR_msgsnd) -#define __NR_msgsnd 69 -#endif - -#if !defined(__NR_msgrcv) -#define __NR_msgrcv 70 -#endif - -#if !defined(__NR_msgctl) -#define __NR_msgctl 71 -#endif - -#if !defined(__NR_fcntl) -#define __NR_fcntl 72 -#endif - -#if !defined(__NR_flock) -#define __NR_flock 73 -#endif - -#if !defined(__NR_fsync) -#define __NR_fsync 74 -#endif - -#if !defined(__NR_fdatasync) -#define __NR_fdatasync 75 -#endif - -#if !defined(__NR_truncate) -#define __NR_truncate 76 -#endif - -#if !defined(__NR_ftruncate) -#define __NR_ftruncate 77 -#endif - -#if !defined(__NR_getdents) -#define __NR_getdents 78 -#endif - -#if !defined(__NR_getcwd) -#define __NR_getcwd 79 -#endif - -#if !defined(__NR_chdir) -#define __NR_chdir 80 -#endif - -#if !defined(__NR_fchdir) -#define __NR_fchdir 81 -#endif - -#if !defined(__NR_rename) -#define __NR_rename 82 -#endif - -#if !defined(__NR_mkdir) -#define __NR_mkdir 83 -#endif - -#if !defined(__NR_rmdir) -#define __NR_rmdir 84 -#endif - -#if !defined(__NR_creat) -#define __NR_creat 85 -#endif - -#if !defined(__NR_link) -#define __NR_link 86 -#endif - -#if !defined(__NR_unlink) -#define __NR_unlink 87 -#endif - -#if !defined(__NR_symlink) -#define __NR_symlink 88 -#endif - -#if !defined(__NR_readlink) -#define __NR_readlink 89 -#endif - -#if !defined(__NR_chmod) -#define __NR_chmod 90 -#endif - -#if !defined(__NR_fchmod) -#define __NR_fchmod 91 -#endif - -#if !defined(__NR_chown) -#define __NR_chown 92 -#endif - -#if !defined(__NR_fchown) -#define __NR_fchown 93 -#endif - -#if !defined(__NR_lchown) -#define __NR_lchown 94 -#endif - -#if !defined(__NR_umask) -#define __NR_umask 95 -#endif - -#if !defined(__NR_gettimeofday) -#define __NR_gettimeofday 96 -#endif - -#if !defined(__NR_getrlimit) -#define __NR_getrlimit 97 -#endif - -#if !defined(__NR_getrusage) -#define __NR_getrusage 98 -#endif - -#if !defined(__NR_sysinfo) -#define __NR_sysinfo 99 -#endif - -#if !defined(__NR_times) -#define __NR_times 100 -#endif - -#if !defined(__NR_ptrace) -#define __NR_ptrace 101 -#endif - -#if !defined(__NR_getuid) -#define __NR_getuid 102 -#endif - -#if !defined(__NR_syslog) -#define __NR_syslog 103 -#endif - -#if !defined(__NR_getgid) -#define __NR_getgid 104 -#endif - -#if !defined(__NR_setuid) -#define __NR_setuid 105 -#endif - -#if !defined(__NR_setgid) -#define __NR_setgid 106 -#endif - -#if !defined(__NR_geteuid) -#define __NR_geteuid 107 -#endif - -#if !defined(__NR_getegid) -#define __NR_getegid 108 -#endif - -#if !defined(__NR_setpgid) -#define __NR_setpgid 109 -#endif - -#if !defined(__NR_getppid) -#define __NR_getppid 110 -#endif - -#if !defined(__NR_getpgrp) -#define __NR_getpgrp 111 -#endif - -#if !defined(__NR_setsid) -#define __NR_setsid 112 -#endif - -#if !defined(__NR_setreuid) -#define __NR_setreuid 113 -#endif - -#if !defined(__NR_setregid) -#define __NR_setregid 114 -#endif - -#if !defined(__NR_getgroups) -#define __NR_getgroups 115 -#endif - -#if !defined(__NR_setgroups) -#define __NR_setgroups 116 -#endif - -#if !defined(__NR_setresuid) -#define __NR_setresuid 117 -#endif - -#if !defined(__NR_getresuid) -#define __NR_getresuid 118 -#endif - -#if !defined(__NR_setresgid) -#define __NR_setresgid 119 -#endif - -#if !defined(__NR_getresgid) -#define __NR_getresgid 120 -#endif - -#if !defined(__NR_getpgid) -#define __NR_getpgid 121 -#endif - -#if !defined(__NR_setfsuid) -#define __NR_setfsuid 122 -#endif - -#if !defined(__NR_setfsgid) -#define __NR_setfsgid 123 -#endif - -#if !defined(__NR_getsid) -#define __NR_getsid 124 -#endif - -#if !defined(__NR_capget) -#define __NR_capget 125 -#endif - -#if !defined(__NR_capset) -#define __NR_capset 126 -#endif - -#if !defined(__NR_rt_sigpending) -#define __NR_rt_sigpending 127 -#endif - -#if !defined(__NR_rt_sigtimedwait) -#define __NR_rt_sigtimedwait 128 -#endif - -#if !defined(__NR_rt_sigqueueinfo) -#define __NR_rt_sigqueueinfo 129 -#endif - -#if !defined(__NR_rt_sigsuspend) -#define __NR_rt_sigsuspend 130 -#endif - -#if !defined(__NR_sigaltstack) -#define __NR_sigaltstack 131 -#endif - -#if !defined(__NR_utime) -#define __NR_utime 132 -#endif - -#if !defined(__NR_mknod) -#define __NR_mknod 133 -#endif - -#if !defined(__NR_uselib) -#define __NR_uselib 134 -#endif - -#if !defined(__NR_personality) -#define __NR_personality 135 -#endif - -#if !defined(__NR_ustat) -#define __NR_ustat 136 -#endif - -#if !defined(__NR_statfs) -#define __NR_statfs 137 -#endif - -#if !defined(__NR_fstatfs) -#define __NR_fstatfs 138 -#endif - -#if !defined(__NR_sysfs) -#define __NR_sysfs 139 -#endif - -#if !defined(__NR_getpriority) -#define __NR_getpriority 140 -#endif - -#if !defined(__NR_setpriority) -#define __NR_setpriority 141 -#endif - -#if !defined(__NR_sched_setparam) -#define __NR_sched_setparam 142 -#endif - -#if !defined(__NR_sched_getparam) -#define __NR_sched_getparam 143 -#endif - -#if !defined(__NR_sched_setscheduler) -#define __NR_sched_setscheduler 144 -#endif - -#if !defined(__NR_sched_getscheduler) -#define __NR_sched_getscheduler 145 -#endif - -#if !defined(__NR_sched_get_priority_max) -#define __NR_sched_get_priority_max 146 -#endif - -#if !defined(__NR_sched_get_priority_min) -#define __NR_sched_get_priority_min 147 -#endif - -#if !defined(__NR_sched_rr_get_interval) -#define __NR_sched_rr_get_interval 148 -#endif - -#if !defined(__NR_mlock) -#define __NR_mlock 149 -#endif - -#if !defined(__NR_munlock) -#define __NR_munlock 150 -#endif - -#if !defined(__NR_mlockall) -#define __NR_mlockall 151 -#endif - -#if !defined(__NR_munlockall) -#define __NR_munlockall 152 -#endif - -#if !defined(__NR_vhangup) -#define __NR_vhangup 153 -#endif - -#if !defined(__NR_modify_ldt) -#define __NR_modify_ldt 154 -#endif - -#if !defined(__NR_pivot_root) -#define __NR_pivot_root 155 -#endif - -#if !defined(__NR__sysctl) -#define __NR__sysctl 156 -#endif - -#if !defined(__NR_prctl) -#define __NR_prctl 157 -#endif - -#if !defined(__NR_arch_prctl) -#define __NR_arch_prctl 158 -#endif - -#if !defined(__NR_adjtimex) -#define __NR_adjtimex 159 -#endif - -#if !defined(__NR_setrlimit) -#define __NR_setrlimit 160 -#endif - -#if !defined(__NR_chroot) -#define __NR_chroot 161 -#endif - -#if !defined(__NR_sync) -#define __NR_sync 162 -#endif - -#if !defined(__NR_acct) -#define __NR_acct 163 -#endif - -#if !defined(__NR_settimeofday) -#define __NR_settimeofday 164 -#endif - -#if !defined(__NR_mount) -#define __NR_mount 165 -#endif - -#if !defined(__NR_umount2) -#define __NR_umount2 166 -#endif - -#if !defined(__NR_swapon) -#define __NR_swapon 167 -#endif - -#if !defined(__NR_swapoff) -#define __NR_swapoff 168 -#endif - -#if !defined(__NR_reboot) -#define __NR_reboot 169 -#endif - -#if !defined(__NR_sethostname) -#define __NR_sethostname 170 -#endif - -#if !defined(__NR_setdomainname) -#define __NR_setdomainname 171 -#endif - -#if !defined(__NR_iopl) -#define __NR_iopl 172 -#endif - -#if !defined(__NR_ioperm) -#define __NR_ioperm 173 -#endif - -#if !defined(__NR_create_module) -#define __NR_create_module 174 -#endif - -#if !defined(__NR_init_module) -#define __NR_init_module 175 -#endif - -#if !defined(__NR_delete_module) -#define __NR_delete_module 176 -#endif - -#if !defined(__NR_get_kernel_syms) -#define __NR_get_kernel_syms 177 -#endif - -#if !defined(__NR_query_module) -#define __NR_query_module 178 -#endif - -#if !defined(__NR_quotactl) -#define __NR_quotactl 179 -#endif - -#if !defined(__NR_nfsservctl) -#define __NR_nfsservctl 180 -#endif - -#if !defined(__NR_getpmsg) -#define __NR_getpmsg 181 -#endif - -#if !defined(__NR_putpmsg) -#define __NR_putpmsg 182 -#endif - -#if !defined(__NR_afs_syscall) -#define __NR_afs_syscall 183 -#endif - -#if !defined(__NR_tuxcall) -#define __NR_tuxcall 184 -#endif - -#if !defined(__NR_security) -#define __NR_security 185 -#endif - -#if !defined(__NR_gettid) -#define __NR_gettid 186 -#endif - -#if !defined(__NR_readahead) -#define __NR_readahead 187 -#endif - -#if !defined(__NR_setxattr) -#define __NR_setxattr 188 -#endif - -#if !defined(__NR_lsetxattr) -#define __NR_lsetxattr 189 -#endif - -#if !defined(__NR_fsetxattr) -#define __NR_fsetxattr 190 -#endif - -#if !defined(__NR_getxattr) -#define __NR_getxattr 191 -#endif - -#if !defined(__NR_lgetxattr) -#define __NR_lgetxattr 192 -#endif - -#if !defined(__NR_fgetxattr) -#define __NR_fgetxattr 193 -#endif - -#if !defined(__NR_listxattr) -#define __NR_listxattr 194 -#endif - -#if !defined(__NR_llistxattr) -#define __NR_llistxattr 195 -#endif - -#if !defined(__NR_flistxattr) -#define __NR_flistxattr 196 -#endif - -#if !defined(__NR_removexattr) -#define __NR_removexattr 197 -#endif - -#if !defined(__NR_lremovexattr) -#define __NR_lremovexattr 198 -#endif - -#if !defined(__NR_fremovexattr) -#define __NR_fremovexattr 199 -#endif - -#if !defined(__NR_tkill) -#define __NR_tkill 200 -#endif - -#if !defined(__NR_time) -#define __NR_time 201 -#endif - -#if !defined(__NR_futex) -#define __NR_futex 202 -#endif - -#if !defined(__NR_sched_setaffinity) -#define __NR_sched_setaffinity 203 -#endif - -#if !defined(__NR_sched_getaffinity) -#define __NR_sched_getaffinity 204 -#endif - -#if !defined(__NR_set_thread_area) -#define __NR_set_thread_area 205 -#endif - -#if !defined(__NR_io_setup) -#define __NR_io_setup 206 -#endif - -#if !defined(__NR_io_destroy) -#define __NR_io_destroy 207 -#endif - -#if !defined(__NR_io_getevents) -#define __NR_io_getevents 208 -#endif - -#if !defined(__NR_io_submit) -#define __NR_io_submit 209 -#endif - -#if !defined(__NR_io_cancel) -#define __NR_io_cancel 210 -#endif - -#if !defined(__NR_get_thread_area) -#define __NR_get_thread_area 211 -#endif - -#if !defined(__NR_lookup_dcookie) -#define __NR_lookup_dcookie 212 -#endif - -#if !defined(__NR_epoll_create) -#define __NR_epoll_create 213 -#endif - -#if !defined(__NR_epoll_ctl_old) -#define __NR_epoll_ctl_old 214 -#endif - -#if !defined(__NR_epoll_wait_old) -#define __NR_epoll_wait_old 215 -#endif - -#if !defined(__NR_remap_file_pages) -#define __NR_remap_file_pages 216 -#endif - -#if !defined(__NR_getdents64) -#define __NR_getdents64 217 -#endif - -#if !defined(__NR_set_tid_address) -#define __NR_set_tid_address 218 -#endif - -#if !defined(__NR_restart_syscall) -#define __NR_restart_syscall 219 -#endif - -#if !defined(__NR_semtimedop) -#define __NR_semtimedop 220 -#endif - -#if !defined(__NR_fadvise64) -#define __NR_fadvise64 221 -#endif - -#if !defined(__NR_timer_create) -#define __NR_timer_create 222 -#endif - -#if !defined(__NR_timer_settime) -#define __NR_timer_settime 223 -#endif - -#if !defined(__NR_timer_gettime) -#define __NR_timer_gettime 224 -#endif - -#if !defined(__NR_timer_getoverrun) -#define __NR_timer_getoverrun 225 -#endif - -#if !defined(__NR_timer_delete) -#define __NR_timer_delete 226 -#endif - -#if !defined(__NR_clock_settime) -#define __NR_clock_settime 227 -#endif - -#if !defined(__NR_clock_gettime) -#define __NR_clock_gettime 228 -#endif - -#if !defined(__NR_clock_getres) -#define __NR_clock_getres 229 -#endif - -#if !defined(__NR_clock_nanosleep) -#define __NR_clock_nanosleep 230 -#endif - -#if !defined(__NR_exit_group) -#define __NR_exit_group 231 -#endif - -#if !defined(__NR_epoll_wait) -#define __NR_epoll_wait 232 -#endif - -#if !defined(__NR_epoll_ctl) -#define __NR_epoll_ctl 233 -#endif - -#if !defined(__NR_tgkill) -#define __NR_tgkill 234 -#endif - -#if !defined(__NR_utimes) -#define __NR_utimes 235 -#endif - -#if !defined(__NR_vserver) -#define __NR_vserver 236 -#endif - -#if !defined(__NR_mbind) -#define __NR_mbind 237 -#endif - -#if !defined(__NR_set_mempolicy) -#define __NR_set_mempolicy 238 -#endif - -#if !defined(__NR_get_mempolicy) -#define __NR_get_mempolicy 239 -#endif - -#if !defined(__NR_mq_open) -#define __NR_mq_open 240 -#endif - -#if !defined(__NR_mq_unlink) -#define __NR_mq_unlink 241 -#endif - -#if !defined(__NR_mq_timedsend) -#define __NR_mq_timedsend 242 -#endif - -#if !defined(__NR_mq_timedreceive) -#define __NR_mq_timedreceive 243 -#endif - -#if !defined(__NR_mq_notify) -#define __NR_mq_notify 244 -#endif - -#if !defined(__NR_mq_getsetattr) -#define __NR_mq_getsetattr 245 -#endif - -#if !defined(__NR_kexec_load) -#define __NR_kexec_load 246 -#endif - -#if !defined(__NR_waitid) -#define __NR_waitid 247 -#endif - -#if !defined(__NR_add_key) -#define __NR_add_key 248 -#endif - -#if !defined(__NR_request_key) -#define __NR_request_key 249 -#endif - -#if !defined(__NR_keyctl) -#define __NR_keyctl 250 -#endif - -#if !defined(__NR_ioprio_set) -#define __NR_ioprio_set 251 -#endif - -#if !defined(__NR_ioprio_get) -#define __NR_ioprio_get 252 -#endif - -#if !defined(__NR_inotify_init) -#define __NR_inotify_init 253 -#endif - -#if !defined(__NR_inotify_add_watch) -#define __NR_inotify_add_watch 254 -#endif - -#if !defined(__NR_inotify_rm_watch) -#define __NR_inotify_rm_watch 255 -#endif - -#if !defined(__NR_migrate_pages) -#define __NR_migrate_pages 256 -#endif - -#if !defined(__NR_openat) -#define __NR_openat 257 -#endif - -#if !defined(__NR_mkdirat) -#define __NR_mkdirat 258 -#endif - -#if !defined(__NR_mknodat) -#define __NR_mknodat 259 -#endif - -#if !defined(__NR_fchownat) -#define __NR_fchownat 260 -#endif - -#if !defined(__NR_futimesat) -#define __NR_futimesat 261 -#endif - -#if !defined(__NR_newfstatat) -#define __NR_newfstatat 262 -#endif - -#if !defined(__NR_unlinkat) -#define __NR_unlinkat 263 -#endif - -#if !defined(__NR_renameat) -#define __NR_renameat 264 -#endif - -#if !defined(__NR_linkat) -#define __NR_linkat 265 -#endif - -#if !defined(__NR_symlinkat) -#define __NR_symlinkat 266 -#endif - -#if !defined(__NR_readlinkat) -#define __NR_readlinkat 267 -#endif - -#if !defined(__NR_fchmodat) -#define __NR_fchmodat 268 -#endif - -#if !defined(__NR_faccessat) -#define __NR_faccessat 269 -#endif - -#if !defined(__NR_pselect6) -#define __NR_pselect6 270 -#endif - -#if !defined(__NR_ppoll) -#define __NR_ppoll 271 -#endif - -#if !defined(__NR_unshare) -#define __NR_unshare 272 -#endif - -#if !defined(__NR_set_robust_list) -#define __NR_set_robust_list 273 -#endif - -#if !defined(__NR_get_robust_list) -#define __NR_get_robust_list 274 -#endif - -#if !defined(__NR_splice) -#define __NR_splice 275 -#endif - -#if !defined(__NR_tee) -#define __NR_tee 276 -#endif - -#if !defined(__NR_sync_file_range) -#define __NR_sync_file_range 277 -#endif - -#if !defined(__NR_vmsplice) -#define __NR_vmsplice 278 -#endif - -#if !defined(__NR_move_pages) -#define __NR_move_pages 279 -#endif - -#if !defined(__NR_utimensat) -#define __NR_utimensat 280 -#endif - -#if !defined(__NR_epoll_pwait) -#define __NR_epoll_pwait 281 -#endif - -#if !defined(__NR_signalfd) -#define __NR_signalfd 282 -#endif - -#if !defined(__NR_timerfd_create) -#define __NR_timerfd_create 283 -#endif - -#if !defined(__NR_eventfd) -#define __NR_eventfd 284 -#endif - -#if !defined(__NR_fallocate) -#define __NR_fallocate 285 -#endif - -#if !defined(__NR_timerfd_settime) -#define __NR_timerfd_settime 286 -#endif - -#if !defined(__NR_timerfd_gettime) -#define __NR_timerfd_gettime 287 -#endif - -#if !defined(__NR_accept4) -#define __NR_accept4 288 -#endif - -#if !defined(__NR_signalfd4) -#define __NR_signalfd4 289 -#endif - -#if !defined(__NR_eventfd2) -#define __NR_eventfd2 290 -#endif - -#if !defined(__NR_epoll_create1) -#define __NR_epoll_create1 291 -#endif - -#if !defined(__NR_dup3) -#define __NR_dup3 292 -#endif - -#if !defined(__NR_pipe2) -#define __NR_pipe2 293 -#endif - -#if !defined(__NR_inotify_init1) -#define __NR_inotify_init1 294 -#endif - -#if !defined(__NR_preadv) -#define __NR_preadv 295 -#endif - -#if !defined(__NR_pwritev) -#define __NR_pwritev 296 -#endif - -#if !defined(__NR_rt_tgsigqueueinfo) -#define __NR_rt_tgsigqueueinfo 297 -#endif - -#if !defined(__NR_perf_event_open) -#define __NR_perf_event_open 298 -#endif - -#if !defined(__NR_recvmmsg) -#define __NR_recvmmsg 299 -#endif - -#if !defined(__NR_fanotify_init) -#define __NR_fanotify_init 300 -#endif - -#if !defined(__NR_fanotify_mark) -#define __NR_fanotify_mark 301 -#endif - -#if !defined(__NR_prlimit64) -#define __NR_prlimit64 302 -#endif - -#if !defined(__NR_name_to_handle_at) -#define __NR_name_to_handle_at 303 -#endif - -#if !defined(__NR_open_by_handle_at) -#define __NR_open_by_handle_at 304 -#endif - -#if !defined(__NR_clock_adjtime) -#define __NR_clock_adjtime 305 -#endif - -#if !defined(__NR_syncfs) -#define __NR_syncfs 306 -#endif - -#if !defined(__NR_sendmmsg) -#define __NR_sendmmsg 307 -#endif - -#if !defined(__NR_setns) -#define __NR_setns 308 -#endif - -#if !defined(__NR_getcpu) -#define __NR_getcpu 309 -#endif - -#if !defined(__NR_process_vm_readv) -#define __NR_process_vm_readv 310 -#endif - -#if !defined(__NR_process_vm_writev) -#define __NR_process_vm_writev 311 -#endif - -#if !defined(__NR_kcmp) -#define __NR_kcmp 312 -#endif - -#if !defined(__NR_finit_module) -#define __NR_finit_module 313 -#endif - -#if !defined(__NR_sched_setattr) -#define __NR_sched_setattr 314 -#endif - -#if !defined(__NR_sched_getattr) -#define __NR_sched_getattr 315 -#endif - -#if !defined(__NR_renameat2) -#define __NR_renameat2 316 -#endif - -#if !defined(__NR_seccomp) -#define __NR_seccomp 317 -#endif - -#if !defined(__NR_getrandom) -#define __NR_getrandom 318 -#endif - -#if !defined(__NR_memfd_create) -#define __NR_memfd_create 319 -#endif - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_ - diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_ucontext.h b/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_ucontext.h deleted file mode 100644 index 1f1abe642..000000000 --- a/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_ucontext.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ - -#include <stdint.h> - -// We do something compatible with glibc. Hopefully, at some point Android will -// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. -// Spec: -// http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/libc-ddefs.html#AEN5668 - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#include <asm/sigcontext.h> - -struct _libc_fpxreg { - unsigned short significand[4]; - unsigned short exponent; - unsigned short padding[3]; -}; - -struct _libc_xmmreg { - uint32_t element[4]; -}; - -struct _libc_fpstate { - uint16_t cwd; - uint16_t swd; - uint16_t twd; - uint16_t fop; - uint64_t rip; - uint64_t rdp; - uint32_t mxcsr; - uint32_t mxcsr_mask; - struct _libc_fpxreg _st[8]; - struct _libc_xmmreg _xmm[16]; - uint32_t padding[24]; -}; - -typedef uint64_t greg_t; - -typedef struct { - greg_t gregs[23]; - struct _libc_fpstate* fpregs; - unsigned long __reserved1[8]; -} mcontext_t; - -enum { - REG_R8 = 0, - REG_R9, - REG_R10, - REG_R11, - REG_R12, - REG_R13, - REG_R14, - REG_R15, - REG_RDI, - REG_RSI, - REG_RBP, - REG_RBX, - REG_RDX, - REG_RAX, - REG_RCX, - REG_RSP, - REG_RIP, - REG_EFL, - REG_CSGSFS, - REG_ERR, - REG_TRAPNO, - REG_OLDMASK, - REG_CR2, - NGREG, -}; - -typedef struct ucontext { - unsigned long uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - struct _libc_fpstate __fpregs_mem; -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ diff --git a/security/sandbox/chromium/sandbox/sandbox_export.h b/security/sandbox/chromium/sandbox/sandbox_export.h deleted file mode 100644 index 35d6a1ba2..000000000 --- a/security/sandbox/chromium/sandbox/sandbox_export.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SANDBOX_EXPORT_H_ -#define SANDBOX_SANDBOX_EXPORT_H_ - -#if defined(WIN32) -#error "sandbox_export.h does not support WIN32." -#endif - -#if defined(COMPONENT_BUILD) - -#if defined(SANDBOX_IMPLEMENTATION) -#define SANDBOX_EXPORT __attribute__((visibility("default"))) -#else -#define SANDBOX_EXPORT -#endif // defined(SANDBOX_IMPLEMENTATION) - -#else // defined(COMPONENT_BUILD) - -#define SANDBOX_EXPORT - -#endif // defined(COMPONENT_BUILD) - -#endif // SANDBOX_SANDBOX_EXPORT_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/Wow64.cc b/security/sandbox/chromium/sandbox/win/src/Wow64.cc deleted file mode 100644 index c5984d629..000000000 --- a/security/sandbox/chromium/sandbox/win/src/Wow64.cc +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/Wow64.h" - -#include <stddef.h> - -#include <sstream> - -#include "base/bit_cast.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/win/scoped_process_information.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/target_process.h" - -namespace { - -// Holds the information needed for the interception of NtMapViewOfSection on -// 64 bits. -// Warning: do not modify this definition without changing also the code on the -// 64 bit helper process. -struct PatchInfo32 { - HANDLE dll_load; // Event to signal the broker. - ULONG pad1; - HANDLE continue_load; // Event to wait for the broker. - ULONG pad2; - HANDLE section; // First argument of the call. - ULONG pad3; - void* orig_MapViewOfSection; - ULONG original_high; - void* signal_and_wait; - ULONG pad4; - void* patch_location; - ULONG patch_high; -}; - -// Size of the 64 bit service entry. -const SIZE_T kServiceEntry64Size = 0x10; - -// Removes the interception of ntdll64. -bool Restore64Code(HANDLE child, PatchInfo32* patch_info) { - PatchInfo32 local_patch_info; - SIZE_T actual; - if (!::ReadProcessMemory(child, patch_info, &local_patch_info, - sizeof(local_patch_info), &actual)) - return false; - if (sizeof(local_patch_info) != actual) - return false; - - if (local_patch_info.original_high) - return false; - if (local_patch_info.patch_high) - return false; - - char buffer[kServiceEntry64Size]; - - if (!::ReadProcessMemory(child, local_patch_info.orig_MapViewOfSection, - &buffer, kServiceEntry64Size, &actual)) - return false; - if (kServiceEntry64Size != actual) - return false; - - if (!::WriteProcessMemory(child, local_patch_info.patch_location, &buffer, - kServiceEntry64Size, &actual)) - return false; - if (kServiceEntry64Size != actual) - return false; - return true; -} - -typedef BOOL (WINAPI* IsWow64ProcessFunction)(HANDLE process, BOOL* wow64); - -} // namespace - -namespace sandbox { - -Wow64::Wow64(TargetProcess* child, HMODULE ntdll) - : child_(child), ntdll_(ntdll), dll_load_(NULL), continue_load_(NULL) { -} - -Wow64::~Wow64() { -} - -// The basic idea is to allocate one page of memory on the child, and initialize -// the first part of it with our version of PatchInfo32. Then launch the helper -// process passing it that address on the child. The helper process will patch -// the 64 bit version of NtMapViewOfFile, and the interception will signal the -// first event on the buffer. We'll be waiting on that event and after the 32 -// bit version of ntdll is loaded, we'll remove the interception and return to -// our caller. -bool Wow64::WaitForNtdll() { - if (base::win::OSInfo::GetInstance()->wow64_status() != - base::win::OSInfo::WOW64_ENABLED) - return true; - - const size_t page_size = 4096; - - // Create some default manual reset un-named events, not signaled. - dll_load_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL)); - continue_load_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL)); - HANDLE current_process = ::GetCurrentProcess(); - HANDLE remote_load, remote_continue; - DWORD access = EVENT_MODIFY_STATE | SYNCHRONIZE; - if (!::DuplicateHandle(current_process, dll_load_.Get(), child_->Process(), - &remote_load, access, FALSE, 0)) { - return false; - } - if (!::DuplicateHandle(current_process, continue_load_.Get(), - child_->Process(), &remote_continue, access, FALSE, - 0)) { - return false; - } - - void* buffer = ::VirtualAllocEx(child_->Process(), NULL, page_size, - MEM_COMMIT, PAGE_EXECUTE_READWRITE); - DCHECK(buffer); - if (!buffer) - return false; - - PatchInfo32* patch_info = reinterpret_cast<PatchInfo32*>(buffer); - PatchInfo32 local_patch_info = {0}; - local_patch_info.dll_load = remote_load; - local_patch_info.continue_load = remote_continue; - SIZE_T written; - if (!::WriteProcessMemory(child_->Process(), patch_info, &local_patch_info, - offsetof(PatchInfo32, section), &written)) - return false; - if (offsetof(PatchInfo32, section) != written) - return false; - - if (!RunWowHelper(buffer)) - return false; - - // The child is intercepted on 64 bit, go on and wait for our event. - if (!DllMapped()) - return false; - - // The 32 bit version is available, cleanup the child. - return Restore64Code(child_->Process(), patch_info); -} - -bool Wow64::RunWowHelper(void* buffer) { - static_assert(sizeof(buffer) <= sizeof(DWORD), "unsupported 64 bits"); - - // Get the path to the helper (beside the exe). - wchar_t prog_name[MAX_PATH]; - GetModuleFileNameW(NULL, prog_name, MAX_PATH); - base::string16 path(prog_name); - size_t name_pos = path.find_last_of(L"\\"); - if (base::string16::npos == name_pos) - return false; - path.resize(name_pos + 1); - - std::basic_stringstream<base::char16> command; - command << std::hex << std::showbase << L"\"" << path << - L"wow_helper.exe\" " << child_->ProcessId() << " " << - bit_cast<ULONG>(buffer); - - scoped_ptr<wchar_t, base::FreeDeleter> - writable_command(_wcsdup(command.str().c_str())); - - STARTUPINFO startup_info = {0}; - startup_info.cb = sizeof(startup_info); - PROCESS_INFORMATION temp_process_info = {}; - if (!::CreateProcess(NULL, writable_command.get(), NULL, NULL, FALSE, 0, NULL, - NULL, &startup_info, &temp_process_info)) - return false; - base::win::ScopedProcessInformation process_info(temp_process_info); - - DWORD reason = ::WaitForSingleObject(process_info.process_handle(), INFINITE); - - DWORD code; - bool ok = - ::GetExitCodeProcess(process_info.process_handle(), &code) ? true : false; - - if (WAIT_TIMEOUT == reason) - return false; - - return ok && (0 == code); -} - -// First we must wake up the child, then wait for dll loads on the child until -// the one we care is loaded; at that point we must suspend the child again. -bool Wow64::DllMapped() { - if (1 != ::ResumeThread(child_->MainThread())) { - NOTREACHED(); - return false; - } - - for (;;) { - DWORD reason = ::WaitForSingleObject(dll_load_.Get(), INFINITE); - if (WAIT_TIMEOUT == reason || WAIT_ABANDONED == reason) - return false; - - if (!::ResetEvent(dll_load_.Get())) - return false; - - bool found = NtdllPresent(); - if (found) { - if (::SuspendThread(child_->MainThread())) - return false; - } - - if (!::SetEvent(continue_load_.Get())) - return false; - - if (found) - return true; - } -} - -bool Wow64::NtdllPresent() { - const size_t kBufferSize = 512; - char buffer[kBufferSize]; - SIZE_T read; - if (!::ReadProcessMemory(child_->Process(), ntdll_, &buffer, kBufferSize, - &read)) - return false; - if (kBufferSize != read) - return false; - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/Wow64.h b/security/sandbox/chromium/sandbox/win/src/Wow64.h deleted file mode 100644 index acabc3565..000000000 --- a/security/sandbox/chromium/sandbox/win/src/Wow64.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_WOW64_H__ -#define SANDBOX_SRC_WOW64_H__ - -#include <windows.h> - -#include "base/macros.h" -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace sandbox { - -class TargetProcess; - -// This class wraps the code needed to interact with the Windows On Windows -// subsystem on 64 bit OSes, from the point of view of interceptions. -class Wow64 { - public: - Wow64(TargetProcess* child, HMODULE ntdll); - ~Wow64(); - - // Waits for the 32 bit DLL to get loaded on the child process. This function - // will return immediately if not running under WOW, or launch the helper - // process and wait until ntdll is ready. - bool WaitForNtdll(); - - private: - // Runs the WOW helper process, passing the address of a buffer allocated on - // the child (one page). - bool RunWowHelper(void* buffer); - - // This method receives "notifications" whenever a DLL is mapped on the child. - bool DllMapped(); - - // Returns true if ntdll.dll is mapped on the child. - bool NtdllPresent(); - - TargetProcess* child_; // Child process. - HMODULE ntdll_; // ntdll on the parent. - // Event that is signaled on dll load. - base::win::ScopedHandle dll_load_; - // Event to signal to continue execution on the child. - base::win::ScopedHandle continue_load_; - DISALLOW_IMPLICIT_CONSTRUCTORS(Wow64); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_WOW64_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/Wow64_64.cc b/security/sandbox/chromium/sandbox/win/src/Wow64_64.cc deleted file mode 100644 index 357deb855..000000000 --- a/security/sandbox/chromium/sandbox/win/src/Wow64_64.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Wow64 implementation for native 64-bit Windows (in other words, never WOW). - -#include "sandbox/win/src/wow64.h" - -namespace sandbox { - -Wow64::Wow64(TargetProcess* child, HMODULE ntdll) - : child_(child), ntdll_(ntdll), dll_load_(NULL), continue_load_(NULL) { -} - -Wow64::~Wow64() { -} - -bool Wow64::WaitForNtdll() { - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/acl.cc b/security/sandbox/chromium/sandbox/win/src/acl.cc deleted file mode 100644 index f140c7e6c..000000000 --- a/security/sandbox/chromium/sandbox/win/src/acl.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/acl.h" - -#include <aclapi.h> -#include <sddl.h> - -#include "base/logging.h" - -namespace sandbox { - -bool GetDefaultDacl( - HANDLE token, - scoped_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter>* default_dacl) { - if (token == NULL) - return false; - - DCHECK(default_dacl != NULL); - - unsigned long length = 0; - ::GetTokenInformation(token, TokenDefaultDacl, NULL, 0, &length); - if (length == 0) { - NOTREACHED(); - return false; - } - - TOKEN_DEFAULT_DACL* acl = - reinterpret_cast<TOKEN_DEFAULT_DACL*>(malloc(length)); - default_dacl->reset(acl); - - if (!::GetTokenInformation(token, TokenDefaultDacl, default_dacl->get(), - length, &length)) - return false; - - return true; -} - -bool AddSidToDacl(const Sid& sid, ACL* old_dacl, ACCESS_MODE access_mode, - ACCESS_MASK access, ACL** new_dacl) { - EXPLICIT_ACCESS new_access = {0}; - new_access.grfAccessMode = access_mode; - new_access.grfAccessPermissions = access; - new_access.grfInheritance = NO_INHERITANCE; - - new_access.Trustee.pMultipleTrustee = NULL; - new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID; - new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>( - const_cast<SID*>(sid.GetPSID())); - - if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl)) - return false; - - return true; -} - -bool AddSidToDefaultDacl(HANDLE token, const Sid& sid, ACCESS_MASK access) { - if (token == NULL) - return false; - - scoped_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter> default_dacl; - if (!GetDefaultDacl(token, &default_dacl)) - return false; - - ACL* new_dacl = NULL; - if (!AddSidToDacl(sid, default_dacl->DefaultDacl, GRANT_ACCESS, access, - &new_dacl)) - return false; - - TOKEN_DEFAULT_DACL new_token_dacl = {0}; - new_token_dacl.DefaultDacl = new_dacl; - - BOOL ret = ::SetTokenInformation(token, TokenDefaultDacl, &new_token_dacl, - sizeof(new_token_dacl)); - ::LocalFree(new_dacl); - return (TRUE == ret); -} - -bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access) { - DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; - TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(malloc(size)); - - scoped_ptr<TOKEN_USER, base::FreeDeleter> token_user_ptr(token_user); - - if (!::GetTokenInformation(token, TokenUser, token_user, size, &size)) - return false; - - return AddSidToDefaultDacl(token, - reinterpret_cast<SID*>(token_user->User.Sid), - access); -} - -bool AddKnownSidToObject(HANDLE object, SE_OBJECT_TYPE object_type, - const Sid& sid, ACCESS_MODE access_mode, - ACCESS_MASK access) { - PSECURITY_DESCRIPTOR descriptor = NULL; - PACL old_dacl = NULL; - PACL new_dacl = NULL; - - if (ERROR_SUCCESS != ::GetSecurityInfo(object, object_type, - DACL_SECURITY_INFORMATION, NULL, NULL, - &old_dacl, NULL, &descriptor)) - return false; - - if (!AddSidToDacl(sid.GetPSID(), old_dacl, access_mode, access, &new_dacl)) { - ::LocalFree(descriptor); - return false; - } - - DWORD result = ::SetSecurityInfo(object, object_type, - DACL_SECURITY_INFORMATION, NULL, NULL, - new_dacl, NULL); - - ::LocalFree(new_dacl); - ::LocalFree(descriptor); - - if (ERROR_SUCCESS != result) - return false; - - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/acl.h b/security/sandbox/chromium/sandbox/win/src/acl.h deleted file mode 100644 index b5021e7be..000000000 --- a/security/sandbox/chromium/sandbox/win/src/acl.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_ACL_H_ -#define SANDBOX_SRC_ACL_H_ - -#include <AccCtrl.h> -#include <windows.h> - -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/sid.h" - -namespace sandbox { - -// Returns the default dacl from the token passed in. -bool GetDefaultDacl( - HANDLE token, - scoped_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter>* default_dacl); - -// Appends an ACE represented by |sid|, |access_mode|, and |access| to -// |old_dacl|. If the function succeeds, new_dacl contains the new dacl and -// must be freed using LocalFree. -bool AddSidToDacl(const Sid& sid, ACL* old_dacl, ACCESS_MODE access_mode, - ACCESS_MASK access, ACL** new_dacl); - -// Adds and ACE represented by |sid| and |access| to the default dacl present -// in the token. -bool AddSidToDefaultDacl(HANDLE token, const Sid& sid, ACCESS_MASK access); - -// Adds an ACE represented by the user sid and |access| to the default dacl -// present in the token. -bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access); - -// Adds an ACE represented by |known_sid|, |access_mode|, and |access| to -// the dacl of the kernel object referenced by |object| and of |object_type|. -bool AddKnownSidToObject(HANDLE object, SE_OBJECT_TYPE object_type, - const Sid& sid, ACCESS_MODE access_mode, - ACCESS_MASK access); - -} // namespace sandbox - - -#endif // SANDBOX_SRC_ACL_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/app_container.cc b/security/sandbox/chromium/sandbox/win/src/app_container.cc deleted file mode 100644 index a51f09208..000000000 --- a/security/sandbox/chromium/sandbox/win/src/app_container.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/app_container.h" - -#include <Sddl.h> -#include <stddef.h> -#include <vector> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/win/startup_information.h" -#include "sandbox/win/src/internal_types.h" - -namespace { - -// Converts the passed in sid string to a PSID that must be relased with -// LocalFree. -PSID ConvertSid(const base::string16& sid) { - PSID local_sid; - if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) - return NULL; - return local_sid; -} - -template <typename T> -T BindFunction(const char* name) { - HMODULE module = GetModuleHandle(sandbox::kKerneldllName); - void* function = GetProcAddress(module, name); - if (!function) { - module = GetModuleHandle(sandbox::kKernelBasedllName); - function = GetProcAddress(module, name); - } - return reinterpret_cast<T>(function); -} - -} // namespace - -namespace sandbox { - -AppContainerAttributes::AppContainerAttributes() { - memset(&capabilities_, 0, sizeof(capabilities_)); -} - -AppContainerAttributes::~AppContainerAttributes() { - for (size_t i = 0; i < attributes_.size(); i++) - LocalFree(attributes_[i].Sid); - LocalFree(capabilities_.AppContainerSid); -} - -ResultCode AppContainerAttributes::SetAppContainer( - const base::string16& app_container_sid, - const std::vector<base::string16>& capabilities) { - DCHECK(!capabilities_.AppContainerSid); - DCHECK(attributes_.empty()); - capabilities_.AppContainerSid = ConvertSid(app_container_sid); - if (!capabilities_.AppContainerSid) - return SBOX_ERROR_INVALID_APP_CONTAINER; - - for (size_t i = 0; i < capabilities.size(); i++) { - SID_AND_ATTRIBUTES sid_and_attributes; - sid_and_attributes.Sid = ConvertSid(capabilities[i]); - if (!sid_and_attributes.Sid) - return SBOX_ERROR_INVALID_CAPABILITY; - - sid_and_attributes.Attributes = SE_GROUP_ENABLED; - attributes_.push_back(sid_and_attributes); - } - - if (capabilities.size()) { - capabilities_.CapabilityCount = static_cast<DWORD>(capabilities.size()); - capabilities_.Capabilities = &attributes_[0]; - } - return SBOX_ALL_OK; -} - -ResultCode AppContainerAttributes::ShareForStartup( - base::win::StartupInformation* startup_information) const { - // The only thing we support so far is an AppContainer. - if (!capabilities_.AppContainerSid) - return SBOX_ERROR_INVALID_APP_CONTAINER; - - if (!startup_information->UpdateProcThreadAttribute( - PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, - const_cast<SECURITY_CAPABILITIES*>(&capabilities_), - sizeof(capabilities_))) { - DPLOG(ERROR) << "Failed UpdateProcThreadAttribute"; - return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; - } - return SBOX_ALL_OK; -} - -bool AppContainerAttributes::HasAppContainer() const { - return (capabilities_.AppContainerSid != NULL); -} - -ResultCode CreateAppContainer(const base::string16& sid, - const base::string16& name) { - PSID local_sid; - if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) - return SBOX_ERROR_INVALID_APP_CONTAINER; - - typedef HRESULT (WINAPI* AppContainerRegisterSidPtr)(PSID sid, - LPCWSTR moniker, - LPCWSTR display_name); - static AppContainerRegisterSidPtr AppContainerRegisterSid = NULL; - - if (!AppContainerRegisterSid) { - AppContainerRegisterSid = - BindFunction<AppContainerRegisterSidPtr>("AppContainerRegisterSid"); - } - - ResultCode operation_result = SBOX_ERROR_GENERIC; - if (AppContainerRegisterSid) { - HRESULT rv = AppContainerRegisterSid(local_sid, name.c_str(), name.c_str()); - if (SUCCEEDED(rv)) - operation_result = SBOX_ALL_OK; - else - DLOG(ERROR) << "AppContainerRegisterSid error:" << std::hex << rv; - } - LocalFree(local_sid); - return operation_result; -} - -ResultCode DeleteAppContainer(const base::string16& sid) { - PSID local_sid; - if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) - return SBOX_ERROR_INVALID_APP_CONTAINER; - - typedef HRESULT (WINAPI* AppContainerUnregisterSidPtr)(PSID sid); - static AppContainerUnregisterSidPtr AppContainerUnregisterSid = NULL; - - if (!AppContainerUnregisterSid) { - AppContainerUnregisterSid = - BindFunction<AppContainerUnregisterSidPtr>("AppContainerUnregisterSid"); - } - - ResultCode operation_result = SBOX_ERROR_GENERIC; - if (AppContainerUnregisterSid) { - HRESULT rv = AppContainerUnregisterSid(local_sid); - if (SUCCEEDED(rv)) - operation_result = SBOX_ALL_OK; - else - DLOG(ERROR) << "AppContainerUnregisterSid error:" << std::hex << rv; - } - LocalFree(local_sid); - return operation_result; -} - -base::string16 LookupAppContainer(const base::string16& sid) { - PSID local_sid; - if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) - return base::string16(); - - typedef HRESULT (WINAPI* AppContainerLookupMonikerPtr)(PSID sid, - LPWSTR* moniker); - typedef BOOLEAN (WINAPI* AppContainerFreeMemoryPtr)(void* ptr); - - static AppContainerLookupMonikerPtr AppContainerLookupMoniker = NULL; - static AppContainerFreeMemoryPtr AppContainerFreeMemory = NULL; - - if (!AppContainerLookupMoniker || !AppContainerFreeMemory) { - AppContainerLookupMoniker = - BindFunction<AppContainerLookupMonikerPtr>("AppContainerLookupMoniker"); - AppContainerFreeMemory = - BindFunction<AppContainerFreeMemoryPtr>("AppContainerFreeMemory"); - } - - if (!AppContainerLookupMoniker || !AppContainerFreeMemory) - return base::string16(); - - wchar_t* buffer = NULL; - HRESULT rv = AppContainerLookupMoniker(local_sid, &buffer); - if (FAILED(rv)) - return base::string16(); - - base::string16 name(buffer); - if (!AppContainerFreeMemory(buffer)) - NOTREACHED(); - return name; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/app_container.h b/security/sandbox/chromium/sandbox/win/src/app_container.h deleted file mode 100644 index fe2b18933..000000000 --- a/security/sandbox/chromium/sandbox/win/src/app_container.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_APP_CONTAINER_H_ -#define SANDBOX_WIN_SRC_APP_CONTAINER_H_ - -#include <windows.h> - -#include <vector> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace base { -namespace win { -class StartupInformation; -} -} - -namespace sandbox { - -// Maintains an attribute list to be used during creation of a new sandboxed -// process. -class AppContainerAttributes { - public: - AppContainerAttributes(); - ~AppContainerAttributes(); - - // Sets the AppContainer and capabilities to be used with the new process. - ResultCode SetAppContainer(const base::string16& app_container_sid, - const std::vector<base::string16>& capabilities); - - // Updates the proc_thred attribute list of the provided startup_information - // with the app container related data. - // WARNING: startup_information just points back to our internal memory, so - // the lifetime of this object has to be greater than the lifetime of the - // provided startup_information. - ResultCode ShareForStartup( - base::win::StartupInformation* startup_information) const; - - bool HasAppContainer() const; - - private: - SECURITY_CAPABILITIES capabilities_; - std::vector<SID_AND_ATTRIBUTES> attributes_; - - DISALLOW_COPY_AND_ASSIGN(AppContainerAttributes); -}; - -// Creates a new AppContainer on the system. |sid| is the identifier of the new -// AppContainer, and |name| will be used as both the display name and moniker. -// This function fails if the OS doesn't support AppContainers, or if there is -// an AppContainer registered with the same id. -ResultCode CreateAppContainer(const base::string16& sid, - const base::string16& name); - -// Deletes an AppContainer previously created with a successful call to -// CreateAppContainer. -ResultCode DeleteAppContainer(const base::string16& sid); - -// Retrieves the name associated with the provided AppContainer sid. Returns an -// empty string if the AppContainer is not registered with the system. -base::string16 LookupAppContainer(const base::string16& sid); - -} // namespace sandbox - -#endif // SANDBOX_WIN_SRC_APP_CONTAINER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/app_container_test.cc b/security/sandbox/chromium/sandbox/win/src/app_container_test.cc deleted file mode 100644 index ced5cbde7..000000000 --- a/security/sandbox/chromium/sandbox/win/src/app_container_test.cc +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <windows.h> - -#define _ATL_NO_EXCEPTIONS -#include <atlbase.h> -#include <atlsecurity.h> - -#include "base/strings/string16.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/sync_policy_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const wchar_t kAppContainerName[] = L"sbox_test"; -const wchar_t kAppContainerSid[] = - L"S-1-15-2-3251537155-1984446955-2931258699-841473695-1938553385-" - L"924012148-2839372144"; - -const ULONG kSharing = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; - -HANDLE CreateTaggedEvent(const base::string16& name, - const base::string16& sid) { - base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, name.c_str())); - if (!event.IsValid()) - return NULL; - - wchar_t file_name[MAX_PATH] = {}; - wchar_t temp_directory[MAX_PATH] = {}; - GetTempPath(MAX_PATH, temp_directory); - GetTempFileName(temp_directory, L"test", 0, file_name); - - base::win::ScopedHandle file; - file.Set(CreateFile(file_name, GENERIC_READ | STANDARD_RIGHTS_READ, kSharing, - NULL, OPEN_EXISTING, 0, NULL)); - DeleteFile(file_name); - if (!file.IsValid()) - return NULL; - - CSecurityDesc sd; - if (!AtlGetSecurityDescriptor(file.Get(), SE_FILE_OBJECT, &sd, - OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION)) { - return NULL; - } - - PSID local_sid; - if (!ConvertStringSidToSid(sid.c_str(), &local_sid)) - return NULL; - - CDacl new_dacl; - sd.GetDacl(&new_dacl); - CSid csid(reinterpret_cast<SID*>(local_sid)); - new_dacl.AddAllowedAce(csid, EVENT_ALL_ACCESS); - if (!AtlSetDacl(event.Get(), SE_KERNEL_OBJECT, new_dacl)) - event.Close(); - - LocalFree(local_sid); - return event.IsValid() ? event.Take() : NULL; -} - -} // namespace - -namespace sandbox { - -TEST(AppContainerTest, AllowOpenEvent) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return; - - TestRunner runner(JOB_UNPROTECTED, USER_UNPROTECTED, USER_UNPROTECTED); - - const wchar_t capability[] = L"S-1-15-3-12345678-87654321"; - base::win::ScopedHandle handle(CreateTaggedEvent(L"test", capability)); - ASSERT_TRUE(handle.IsValid()); - - EXPECT_EQ(SBOX_ALL_OK, - runner.broker()->InstallAppContainer(kAppContainerSid, - kAppContainerName)); - EXPECT_EQ(SBOX_ALL_OK, runner.GetPolicy()->SetCapability(capability)); - EXPECT_EQ(SBOX_ALL_OK, runner.GetPolicy()->SetAppContainer(kAppContainerSid)); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_Open f test")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_Open f test")); - EXPECT_EQ(SBOX_ALL_OK, - runner.broker()->UninstallAppContainer(kAppContainerSid)); -} - -TEST(AppContainerTest, DenyOpenEvent) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return; - - TestRunner runner(JOB_UNPROTECTED, USER_UNPROTECTED, USER_UNPROTECTED); - - const wchar_t capability[] = L"S-1-15-3-12345678-87654321"; - base::win::ScopedHandle handle(CreateTaggedEvent(L"test", capability)); - ASSERT_TRUE(handle.IsValid()); - - EXPECT_EQ(SBOX_ALL_OK, - runner.broker()->InstallAppContainer(kAppContainerSid, - kAppContainerName)); - EXPECT_EQ(SBOX_ALL_OK, runner.GetPolicy()->SetAppContainer(kAppContainerSid)); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test")); - EXPECT_EQ(SBOX_ALL_OK, - runner.broker()->UninstallAppContainer(kAppContainerSid)); -} - -TEST(AppContainerTest, NoImpersonation) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return; - - TestRunner runner(JOB_UNPROTECTED, USER_LIMITED, USER_LIMITED); - EXPECT_EQ(SBOX_ALL_OK, runner.GetPolicy()->SetAppContainer(kAppContainerSid)); -} - -TEST(AppContainerTest, WantsImpersonation) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return; - - TestRunner runner(JOB_UNPROTECTED, USER_UNPROTECTED, USER_NON_ADMIN); - EXPECT_EQ(SBOX_ERROR_CANNOT_INIT_APPCONTAINER, - runner.GetPolicy()->SetAppContainer(kAppContainerSid)); -} - -TEST(AppContainerTest, RequiresImpersonation) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return; - - TestRunner runner(JOB_UNPROTECTED, USER_RESTRICTED, USER_RESTRICTED); - EXPECT_EQ(SBOX_ERROR_CANNOT_INIT_APPCONTAINER, - runner.GetPolicy()->SetAppContainer(kAppContainerSid)); -} - -TEST(AppContainerTest, DenyOpenEventForLowBox) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return; - - TestRunner runner(JOB_UNPROTECTED, USER_UNPROTECTED, USER_UNPROTECTED); - - base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, L"test")); - ASSERT_TRUE(event.IsValid()); - - EXPECT_EQ(SBOX_ALL_OK, runner.GetPolicy()->SetLowBox(kAppContainerSid)); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test")); -} - -// TODO(shrikant): Please add some tests to prove usage of lowbox token like -// socket connection to local server in lock down mode. - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/app_container_unittest.cc b/security/sandbox/chromium/sandbox/win/src/app_container_unittest.cc deleted file mode 100644 index 4bce16a42..000000000 --- a/security/sandbox/chromium/sandbox/win/src/app_container_unittest.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/win/windows_version.h" -#include "sandbox/win/src/app_container.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -// Tests the low level AppContainer interface. -TEST(AppContainerTest, CreateAppContainer) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return; - - const wchar_t kName[] = L"Test"; - const wchar_t kValidSid[] = L"S-1-15-2-12345-234-567-890-123-456-789"; - - EXPECT_TRUE(LookupAppContainer(kValidSid).empty()); - EXPECT_EQ(SBOX_ERROR_GENERIC, DeleteAppContainer(kValidSid)); - - EXPECT_EQ(SBOX_ALL_OK, CreateAppContainer(kValidSid, kName)); - EXPECT_EQ(SBOX_ERROR_GENERIC, CreateAppContainer(kValidSid, kName)); - EXPECT_EQ(kName, LookupAppContainer(kValidSid)); - EXPECT_EQ(SBOX_ALL_OK, DeleteAppContainer(kValidSid)); - - EXPECT_TRUE(LookupAppContainer(kValidSid).empty()); - EXPECT_EQ(SBOX_ERROR_GENERIC, DeleteAppContainer(kValidSid)); - - EXPECT_EQ(SBOX_ERROR_INVALID_APP_CONTAINER, - CreateAppContainer(L"Foo", kName)); -} - -// Tests handling of security capabilities on the attribute list. -TEST(AppContainerTest, SecurityCapabilities) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return; - - scoped_ptr<AppContainerAttributes> attributes(new AppContainerAttributes); - std::vector<base::string16> capabilities; - EXPECT_EQ(SBOX_ERROR_INVALID_APP_CONTAINER, - attributes->SetAppContainer(L"S-1-foo", capabilities)); - - EXPECT_EQ(SBOX_ALL_OK, - attributes->SetAppContainer(L"S-1-15-2-12345-234", capabilities)); - EXPECT_TRUE(attributes->HasAppContainer()); - - attributes.reset(new AppContainerAttributes); - capabilities.push_back(L"S-1-15-3-12345678-87654321"); - capabilities.push_back(L"S-1-15-3-1"); - capabilities.push_back(L"S-1-15-3-2"); - capabilities.push_back(L"S-1-15-3-3"); - EXPECT_EQ(SBOX_ALL_OK, - attributes->SetAppContainer(L"S-1-15-2-1-2", capabilities)); - EXPECT_TRUE(attributes->HasAppContainer()); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.cc b/security/sandbox/chromium/sandbox/win/src/broker_services.cc deleted file mode 100644 index d6acb66fd..000000000 --- a/security/sandbox/chromium/sandbox/win/src/broker_services.cc +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/broker_services.h" - -#include <AclAPI.h> -#include <stddef.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" -#include "base/threading/platform_thread.h" -#include "base/win/scoped_handle.h" -#include "base/win/scoped_process_information.h" -#include "base/win/startup_information.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/app_container.h" -#include "sandbox/win/src/process_mitigations.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_policy_base.h" -#include "sandbox/win/src/target_process.h" -#include "sandbox/win/src/win2k_threadpool.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -// Utility function to associate a completion port to a job object. -bool AssociateCompletionPort(HANDLE job, HANDLE port, void* key) { - JOBOBJECT_ASSOCIATE_COMPLETION_PORT job_acp = { key, port }; - return ::SetInformationJobObject(job, - JobObjectAssociateCompletionPortInformation, - &job_acp, sizeof(job_acp))? true : false; -} - -// Utility function to do the cleanup necessary when something goes wrong -// while in SpawnTarget and we must terminate the target process. -sandbox::ResultCode SpawnCleanup(sandbox::TargetProcess* target, DWORD error) { - if (0 == error) - error = ::GetLastError(); - - target->Terminate(); - delete target; - ::SetLastError(error); - return sandbox::SBOX_ERROR_GENERIC; -} - -// the different commands that you can send to the worker thread that -// executes TargetEventsThread(). -enum { - THREAD_CTRL_NONE, - THREAD_CTRL_REMOVE_PEER, - THREAD_CTRL_QUIT, - THREAD_CTRL_LAST, -}; - -// Helper structure that allows the Broker to associate a job notification -// with a job object and with a policy. -struct JobTracker { - JobTracker(base::win::ScopedHandle job, sandbox::PolicyBase* policy) - : job(job.Pass()), policy(policy) { - } - ~JobTracker() { - FreeResources(); - } - - // Releases the Job and notifies the associated Policy object to release its - // resources as well. - void FreeResources(); - - base::win::ScopedHandle job; - sandbox::PolicyBase* policy; -}; - -void JobTracker::FreeResources() { - if (policy) { - BOOL res = ::TerminateJobObject(job.Get(), sandbox::SBOX_ALL_OK); - DCHECK(res); - // Closing the job causes the target process to be destroyed so this needs - // to happen before calling OnJobEmpty(). - HANDLE stale_job_handle = job.Get(); - job.Close(); - - // In OnJobEmpty() we don't actually use the job handle directly. - policy->OnJobEmpty(stale_job_handle); - policy->Release(); - policy = NULL; - } -} - -// Helper structure that allows the broker to track peer processes -struct PeerTracker { - PeerTracker(DWORD process_id, HANDLE broker_job_port) - : wait_object(NULL), id(process_id), job_port(broker_job_port) { - } - - HANDLE wait_object; - base::win::ScopedHandle process; - DWORD id; - HANDLE job_port; -}; - -void DeregisterPeerTracker(PeerTracker* peer) { - // Deregistration shouldn't fail, but we leak rather than crash if it does. - if (::UnregisterWaitEx(peer->wait_object, INVALID_HANDLE_VALUE)) { - delete peer; - } else { - NOTREACHED(); - } -} - -} // namespace - -namespace sandbox { - -BrokerServicesBase::BrokerServicesBase() : thread_pool_(NULL) { -} - -// The broker uses a dedicated worker thread that services the job completion -// port to perform policy notifications and associated cleanup tasks. -ResultCode BrokerServicesBase::Init() { - if (job_port_.IsValid() || (NULL != thread_pool_)) - return SBOX_ERROR_UNEXPECTED_CALL; - - ::InitializeCriticalSection(&lock_); - - job_port_.Set(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)); - if (!job_port_.IsValid()) - return SBOX_ERROR_GENERIC; - - no_targets_.Set(::CreateEventW(NULL, TRUE, FALSE, NULL)); - - job_thread_.Set(::CreateThread(NULL, 0, // Default security and stack. - TargetEventsThread, this, NULL, NULL)); - if (!job_thread_.IsValid()) - return SBOX_ERROR_GENERIC; - - return SBOX_ALL_OK; -} - -// The destructor should only be called when the Broker process is terminating. -// Since BrokerServicesBase is a singleton, this is called from the CRT -// termination handlers, if this code lives on a DLL it is called during -// DLL_PROCESS_DETACH in other words, holding the loader lock, so we cannot -// wait for threads here. -BrokerServicesBase::~BrokerServicesBase() { - // If there is no port Init() was never called successfully. - if (!job_port_.IsValid()) - return; - - // Closing the port causes, that no more Job notifications are delivered to - // the worker thread and also causes the thread to exit. This is what we - // want to do since we are going to close all outstanding Jobs and notifying - // the policy objects ourselves. - ::PostQueuedCompletionStatus(job_port_.Get(), 0, THREAD_CTRL_QUIT, FALSE); - - if (job_thread_.IsValid() && - WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_.Get(), 1000)) { - // Cannot clean broker services. - NOTREACHED(); - return; - } - - STLDeleteElements(&tracker_list_); - delete thread_pool_; - - // Cancel the wait events and delete remaining peer trackers. - for (PeerTrackerMap::iterator it = peer_map_.begin(); - it != peer_map_.end(); ++it) { - DeregisterPeerTracker(it->second); - } - - ::DeleteCriticalSection(&lock_); -} - -TargetPolicy* BrokerServicesBase::CreatePolicy() { - // If you change the type of the object being created here you must also - // change the downcast to it in SpawnTarget(). - return new PolicyBase; -} - -// The worker thread stays in a loop waiting for asynchronous notifications -// from the job objects. Right now we only care about knowing when the last -// process on a job terminates, but in general this is the place to tell -// the policy about events. -DWORD WINAPI BrokerServicesBase::TargetEventsThread(PVOID param) { - if (NULL == param) - return 1; - - base::PlatformThread::SetName("BrokerEvent"); - - BrokerServicesBase* broker = reinterpret_cast<BrokerServicesBase*>(param); - HANDLE port = broker->job_port_.Get(); - HANDLE no_targets = broker->no_targets_.Get(); - - int target_counter = 0; - ::ResetEvent(no_targets); - - while (true) { - DWORD events = 0; - ULONG_PTR key = 0; - LPOVERLAPPED ovl = NULL; - - if (!::GetQueuedCompletionStatus(port, &events, &key, &ovl, INFINITE)) { - // this call fails if the port has been closed before we have a - // chance to service the last packet which is 'exit' anyway so - // this is not an error. - return 1; - } - - if (key > THREAD_CTRL_LAST) { - // The notification comes from a job object. There are nine notifications - // that jobs can send and some of them depend on the job attributes set. - JobTracker* tracker = reinterpret_cast<JobTracker*>(key); - - switch (events) { - case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: { - // The job object has signaled that the last process associated - // with it has terminated. Assuming there is no way for a process - // to appear out of thin air in this job, it safe to assume that - // we can tell the policy to destroy the target object, and for - // us to release our reference to the policy object. - tracker->FreeResources(); - break; - } - - case JOB_OBJECT_MSG_NEW_PROCESS: { - ++target_counter; - if (1 == target_counter) { - ::ResetEvent(no_targets); - } - break; - } - - case JOB_OBJECT_MSG_EXIT_PROCESS: - case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: { - { - AutoLock lock(&broker->lock_); - broker->child_process_ids_.erase( - static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl))); - } - --target_counter; - if (0 == target_counter) - ::SetEvent(no_targets); - - DCHECK(target_counter >= 0); - break; - } - - case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT: { - break; - } - - case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: { - BOOL res = ::TerminateJobObject(tracker->job.Get(), - SBOX_FATAL_MEMORY_EXCEEDED); - DCHECK(res); - break; - } - - default: { - NOTREACHED(); - break; - } - } - } else if (THREAD_CTRL_REMOVE_PEER == key) { - // Remove a process from our list of peers. - AutoLock lock(&broker->lock_); - PeerTrackerMap::iterator it = broker->peer_map_.find( - static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl))); - DeregisterPeerTracker(it->second); - broker->peer_map_.erase(it); - } else if (THREAD_CTRL_QUIT == key) { - // The broker object is being destroyed so the thread needs to exit. - return 0; - } else { - // We have not implemented more commands. - NOTREACHED(); - } - } - - NOTREACHED(); - return 0; -} - -// SpawnTarget does all the interesting sandbox setup and creates the target -// process inside the sandbox. -ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, - const wchar_t* command_line, - TargetPolicy* policy, - PROCESS_INFORMATION* target_info) { - if (!exe_path) - return SBOX_ERROR_BAD_PARAMS; - - if (!policy) - return SBOX_ERROR_BAD_PARAMS; - - // Even though the resources touched by SpawnTarget can be accessed in - // multiple threads, the method itself cannot be called from more than - // 1 thread. This is to protect the global variables used while setting up - // the child process. - static DWORD thread_id = ::GetCurrentThreadId(); - DCHECK(thread_id == ::GetCurrentThreadId()); - - AutoLock lock(&lock_); - - // This downcast is safe as long as we control CreatePolicy() - PolicyBase* policy_base = static_cast<PolicyBase*>(policy); - - if (policy_base->GetAppContainer() && policy_base->GetLowBoxSid()) - return SBOX_ERROR_BAD_PARAMS; - - // Construct the tokens and the job object that we are going to associate - // with the soon to be created target process. - base::win::ScopedHandle initial_token; - base::win::ScopedHandle lockdown_token; - base::win::ScopedHandle lowbox_token; - ResultCode result = SBOX_ALL_OK; - - result = - policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token); - if (SBOX_ALL_OK != result) - return result; - - base::win::ScopedHandle job; - result = policy_base->MakeJobObject(&job); - if (SBOX_ALL_OK != result) - return result; - - // Initialize the startup information from the policy. - base::win::StartupInformation startup_info; - // The liftime of |mitigations| and |inherit_handle_list| have to be at least - // as long as |startup_info| because |UpdateProcThreadAttribute| requires that - // its |lpValue| parameter persist until |DeleteProcThreadAttributeList| is - // called; StartupInformation's destructor makes such a call. - DWORD64 mitigations; - - std::vector<HANDLE> inherited_handle_list; - - base::string16 desktop = policy_base->GetAlternateDesktop(); - if (!desktop.empty()) { - startup_info.startup_info()->lpDesktop = - const_cast<wchar_t*>(desktop.c_str()); - } - - bool inherit_handles = false; - - if (base::win::GetVersion() >= base::win::VERSION_VISTA) { - int attribute_count = 0; - const AppContainerAttributes* app_container = - policy_base->GetAppContainer(); - if (app_container) - ++attribute_count; - - size_t mitigations_size; - ConvertProcessMitigationsToPolicy(policy->GetProcessMitigations(), - &mitigations, &mitigations_size); - if (mitigations) - ++attribute_count; - - HANDLE stdout_handle = policy_base->GetStdoutHandle(); - HANDLE stderr_handle = policy_base->GetStderrHandle(); - - if (stdout_handle != INVALID_HANDLE_VALUE) - inherited_handle_list.push_back(stdout_handle); - - // Handles in the list must be unique. - if (stderr_handle != stdout_handle && stderr_handle != INVALID_HANDLE_VALUE) - inherited_handle_list.push_back(stderr_handle); - - const HandleList& policy_handle_list = policy_base->GetHandlesBeingShared(); - - for (auto handle : policy_handle_list) - inherited_handle_list.push_back(handle->Get()); - - if (inherited_handle_list.size()) - ++attribute_count; - - if (!startup_info.InitializeProcThreadAttributeList(attribute_count)) - return SBOX_ERROR_PROC_THREAD_ATTRIBUTES; - - if (app_container) { - result = app_container->ShareForStartup(&startup_info); - if (SBOX_ALL_OK != result) - return result; - } - - if (mitigations) { - if (!startup_info.UpdateProcThreadAttribute( - PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &mitigations, - mitigations_size)) { - return SBOX_ERROR_PROC_THREAD_ATTRIBUTES; - } - } - - if (inherited_handle_list.size()) { - if (!startup_info.UpdateProcThreadAttribute( - PROC_THREAD_ATTRIBUTE_HANDLE_LIST, - &inherited_handle_list[0], - sizeof(HANDLE) * inherited_handle_list.size())) { - return SBOX_ERROR_PROC_THREAD_ATTRIBUTES; - } - startup_info.startup_info()->dwFlags |= STARTF_USESTDHANDLES; - startup_info.startup_info()->hStdInput = INVALID_HANDLE_VALUE; - startup_info.startup_info()->hStdOutput = stdout_handle; - startup_info.startup_info()->hStdError = stderr_handle; - // Allowing inheritance of handles is only secure now that we - // have limited which handles will be inherited. - inherit_handles = true; - } - } else if (getenv("MOZ_WIN_INHERIT_STD_HANDLES_PRE_VISTA")) { - // On pre-Vista versions even if we can't limit what gets inherited, we - // sometimes want to inherit stdout/err for testing purposes. - startup_info.startup_info()->dwFlags |= STARTF_USESTDHANDLES; - startup_info.startup_info()->hStdInput = INVALID_HANDLE_VALUE; - startup_info.startup_info()->hStdOutput = policy_base->GetStdoutHandle(); - startup_info.startup_info()->hStdError = policy_base->GetStderrHandle(); - inherit_handles = true; - } - - // Construct the thread pool here in case it is expensive. - // The thread pool is shared by all the targets - if (NULL == thread_pool_) - thread_pool_ = new Win2kThreadPool(); - - // Create the TargetProces object and spawn the target suspended. Note that - // Brokerservices does not own the target object. It is owned by the Policy. - base::win::ScopedProcessInformation process_info; - TargetProcess* target = - new TargetProcess(initial_token.Pass(), lockdown_token.Pass(), - lowbox_token.Pass(), job.Get(), thread_pool_); - - DWORD win_result = target->Create(exe_path, command_line, inherit_handles, - startup_info, &process_info); - - policy_base->ClearSharedHandles(); - - if (ERROR_SUCCESS != win_result) { - SpawnCleanup(target, win_result); - return SBOX_ERROR_CREATE_PROCESS; - } - - // Now the policy is the owner of the target. - if (!policy_base->AddTarget(target)) { - return SpawnCleanup(target, 0); - } - - // We are going to keep a pointer to the policy because we'll call it when - // the job object generates notifications using the completion port. - policy_base->AddRef(); - if (job.IsValid()) { - scoped_ptr<JobTracker> tracker(new JobTracker(job.Pass(), policy_base)); - - // There is no obvious recovery after failure here. Previous version with - // SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639 - CHECK(AssociateCompletionPort(tracker->job.Get(), job_port_.Get(), - tracker.get())); - - // Save the tracker because in cleanup we might need to force closing - // the Jobs. - tracker_list_.push_back(tracker.release()); - child_process_ids_.insert(process_info.process_id()); - } else { - // We have to signal the event once here because the completion port will - // never get a message that this target is being terminated thus we should - // not block WaitForAllTargets until we have at least one target with job. - if (child_process_ids_.empty()) - ::SetEvent(no_targets_.Get()); - // We can not track the life time of such processes and it is responsibility - // of the host application to make sure that spawned targets without jobs - // are terminated when the main application don't need them anymore. - // Sandbox policy engine needs to know that these processes are valid - // targets for e.g. BrokerDuplicateHandle so track them as peer processes. - AddTargetPeer(process_info.process_handle()); - } - - *target_info = process_info.Take(); - return SBOX_ALL_OK; -} - - -ResultCode BrokerServicesBase::WaitForAllTargets() { - ::WaitForSingleObject(no_targets_.Get(), INFINITE); - return SBOX_ALL_OK; -} - -bool BrokerServicesBase::IsActiveTarget(DWORD process_id) { - AutoLock lock(&lock_); - return child_process_ids_.find(process_id) != child_process_ids_.end() || - peer_map_.find(process_id) != peer_map_.end(); -} - -VOID CALLBACK BrokerServicesBase::RemovePeer(PVOID parameter, BOOLEAN timeout) { - PeerTracker* peer = reinterpret_cast<PeerTracker*>(parameter); - // Don't check the return code because we this may fail (safely) at shutdown. - ::PostQueuedCompletionStatus( - peer->job_port, 0, THREAD_CTRL_REMOVE_PEER, - reinterpret_cast<LPOVERLAPPED>(static_cast<uintptr_t>(peer->id))); -} - -ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) { - scoped_ptr<PeerTracker> peer(new PeerTracker(::GetProcessId(peer_process), - job_port_.Get())); - if (!peer->id) - return SBOX_ERROR_GENERIC; - - HANDLE process_handle; - if (!::DuplicateHandle(::GetCurrentProcess(), peer_process, - ::GetCurrentProcess(), &process_handle, - SYNCHRONIZE, FALSE, 0)) { - return SBOX_ERROR_GENERIC; - } - peer->process.Set(process_handle); - - AutoLock lock(&lock_); - if (!peer_map_.insert(std::make_pair(peer->id, peer.get())).second) - return SBOX_ERROR_BAD_PARAMS; - - if (!::RegisterWaitForSingleObject( - &peer->wait_object, peer->process.Get(), RemovePeer, peer.get(), - INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD)) { - peer_map_.erase(peer->id); - return SBOX_ERROR_GENERIC; - } - - // Release the pointer since it will be cleaned up by the callback. - ignore_result(peer.release()); - return SBOX_ALL_OK; -} - -ResultCode BrokerServicesBase::InstallAppContainer(const wchar_t* sid, - const wchar_t* name) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return SBOX_ERROR_UNSUPPORTED; - - base::string16 old_name = LookupAppContainer(sid); - if (old_name.empty()) - return CreateAppContainer(sid, name); - - if (old_name != name) - return SBOX_ERROR_INVALID_APP_CONTAINER; - - return SBOX_ALL_OK; -} - -ResultCode BrokerServicesBase::UninstallAppContainer(const wchar_t* sid) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return SBOX_ERROR_UNSUPPORTED; - - base::string16 name = LookupAppContainer(sid); - if (name.empty()) - return SBOX_ERROR_INVALID_APP_CONTAINER; - - return DeleteAppContainer(sid); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.h b/security/sandbox/chromium/sandbox/win/src/broker_services.h deleted file mode 100644 index 6c8f5231c..000000000 --- a/security/sandbox/chromium/sandbox/win/src/broker_services.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_BROKER_SERVICES_H_ -#define SANDBOX_WIN_SRC_BROKER_SERVICES_H_ - -#include <list> -#include <map> -#include <set> -#include <utility> -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/job.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sharedmem_ipc_server.h" -#include "sandbox/win/src/win2k_threadpool.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -struct JobTracker; -struct PeerTracker; - -} // namespace - -namespace sandbox { - -class PolicyBase; - -// BrokerServicesBase --------------------------------------------------------- -// Broker implementation version 0 -// -// This is an implementation of the interface BrokerServices and -// of the associated TargetProcess interface. In this implementation -// TargetProcess is a friend of BrokerServices where the later manages a -// collection of the former. -class BrokerServicesBase final : public BrokerServices, - public SingletonBase<BrokerServicesBase> { - public: - BrokerServicesBase(); - - ~BrokerServicesBase(); - - // BrokerServices interface. - ResultCode Init() override; - TargetPolicy* CreatePolicy() override; - ResultCode SpawnTarget(const wchar_t* exe_path, - const wchar_t* command_line, - TargetPolicy* policy, - PROCESS_INFORMATION* target) override; - ResultCode WaitForAllTargets() override; - ResultCode AddTargetPeer(HANDLE peer_process) override; - ResultCode InstallAppContainer(const wchar_t* sid, - const wchar_t* name) override; - ResultCode UninstallAppContainer(const wchar_t* sid) override; - - // Checks if the supplied process ID matches one of the broker's active - // target processes - // Returns: - // true if there is an active target process for this ID, otherwise false. - bool IsActiveTarget(DWORD process_id); - - private: - typedef std::list<JobTracker*> JobTrackerList; - typedef std::map<DWORD, PeerTracker*> PeerTrackerMap; - - // The routine that the worker thread executes. It is in charge of - // notifications and cleanup-related tasks. - static DWORD WINAPI TargetEventsThread(PVOID param); - - // Removes a target peer from the process list if it expires. - static VOID CALLBACK RemovePeer(PVOID parameter, BOOLEAN timeout); - - // The completion port used by the job objects to communicate events to - // the worker thread. - base::win::ScopedHandle job_port_; - - // Handle to a manual-reset event that is signaled when the total target - // process count reaches zero. - base::win::ScopedHandle no_targets_; - - // Handle to the worker thread that reacts to job notifications. - base::win::ScopedHandle job_thread_; - - // Lock used to protect the list of targets from being modified by 2 - // threads at the same time. - CRITICAL_SECTION lock_; - - // provides a pool of threads that are used to wait on the IPC calls. - ThreadProvider* thread_pool_; - - // List of the trackers for closing and cleanup purposes. - JobTrackerList tracker_list_; - - // Maps peer process IDs to the saved handle and wait event. - // Prevents peer callbacks from accessing the broker after destruction. - PeerTrackerMap peer_map_; - - // Provides a fast lookup to identify sandboxed processes that belong to a - // job. Consult |jobless_process_handles_| for handles of pocess without job. - std::set<DWORD> child_process_ids_; - - DISALLOW_COPY_AND_ASSIGN(BrokerServicesBase); -}; - -} // namespace sandbox - - -#endif // SANDBOX_WIN_SRC_BROKER_SERVICES_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h deleted file mode 100644 index 60ff2437a..000000000 --- a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_CROSSCALL_CLIENT_H_ -#define SANDBOX_SRC_CROSSCALL_CLIENT_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "sandbox/win/src/crosscall_params.h" -#include "sandbox/win/src/sandbox.h" - -// This header defines the CrossCall(..) family of templated functions -// Their purpose is to simulate the syntax of regular call but to generate -// and IPC from the client-side. -// -// The basic pattern is to -// 1) use template argument deduction to compute the size of each -// parameter and the appropriate copy method -// 2) pack the parameters in the appropriate ActualCallParams< > object -// 3) call the IPC interface IPCProvider::DoCall( ) -// -// The general interface of CrossCall is: -// ResultCode CrossCall(IPCProvider& ipc_provider, -// uint32_t tag, -// const Par1& p1, const Par2& p2,...pn -// CrossCallReturn* answer) -// -// where: -// ipc_provider: is a specific implementation of the ipc transport see -// sharedmem_ipc_server.h for an example. -// tag : is the unique id for this IPC call. Is used to route the call to -// the appropriate service. -// p1, p2,.. pn : The input parameters of the IPC. Use only simple types -// and wide strings (can add support for others). -// answer : If the IPC was successful. The server-side answer is here. The -// interpretation of the answer is private to client and server. -// -// The return value is ALL_OK if the IPC was delivered to the server, other -// return codes indicate that the IPC transport failed to deliver it. -namespace sandbox { - -// this is the assumed channel size. This can be overridden in a given -// IPC implementation. -const uint32_t kIPCChannelSize = 1024; - -// The copy helper uses templates to deduce the appropriate copy function to -// copy the input parameters in the buffer that is going to be send across the -// IPC. These template facility can be made more sophisticated as need arises. - -// The default copy helper. It catches the general case where no other -// specialized template matches better. We set the type to UINT32_TYPE, so this -// only works with objects whose size is 32 bits. -template<typename T> -class CopyHelper { - public: - CopyHelper(const T& t) : t_(t) {} - - // Returns the pointer to the start of the input. - const void* GetStart() const { - return &t_; - } - - // Update the stored value with the value in the buffer. This is not - // supported for this type. - bool Update(void* buffer) { - // Not supported; - return true; - } - - // Returns the size of the input in bytes. - uint32_t GetSize() const { return sizeof(T); } - - // Returns true if the current type is used as an In or InOut parameter. - bool IsInOut() { - return false; - } - - // Returns this object's type. - ArgType GetType() { - static_assert(sizeof(T) == sizeof(uint32_t), "specialization needed"); - return UINT32_TYPE; - } - - private: - const T& t_; -}; - -// This copy helper template specialization if for the void pointer -// case both 32 and 64 bit. -template<> -class CopyHelper<void*> { - public: - CopyHelper(void* t) : t_(t) {} - - // Returns the pointer to the start of the input. - const void* GetStart() const { - return &t_; - } - - // Update the stored value with the value in the buffer. This is not - // supported for this type. - bool Update(void* buffer) { - // Not supported; - return true; - } - - // Returns the size of the input in bytes. - uint32_t GetSize() const { return sizeof(t_); } - - // Returns true if the current type is used as an In or InOut parameter. - bool IsInOut() { - return false; - } - - // Returns this object's type. - ArgType GetType() { - return VOIDPTR_TYPE; - } - - private: - const void* t_; -}; - -// This copy helper template specialization catches the cases where the -// parameter is a pointer to a string. -template<> -class CopyHelper<const wchar_t*> { - public: - CopyHelper(const wchar_t* t) - : t_(t) { - } - - // Returns the pointer to the start of the string. - const void* GetStart() const { - return t_; - } - - // Update the stored value with the value in the buffer. This is not - // supported for this type. - bool Update(void* buffer) { - // Not supported; - return true; - } - - // Returns the size of the string in bytes. We define a NULL string to - // be of zero length. - uint32_t GetSize() const { - __try { - return (!t_) ? 0 - : static_cast<uint32_t>(StringLength(t_) * sizeof(t_[0])); - } - __except(EXCEPTION_EXECUTE_HANDLER) { - return UINT32_MAX; - } - } - - // Returns true if the current type is used as an In or InOut parameter. - bool IsInOut() { - return false; - } - - ArgType GetType() { - return WCHAR_TYPE; - } - - private: - // We provide our not very optimized version of wcslen(), since we don't - // want to risk having the linker use the version in the CRT since the CRT - // might not be present when we do an early IPC call. - static size_t __cdecl StringLength(const wchar_t* wcs) { - const wchar_t *eos = wcs; - while (*eos++); - return static_cast<size_t>(eos - wcs - 1); - } - - const wchar_t* t_; -}; - -// Specialization for non-const strings. We just reuse the implementation of the -// const string specialization. -template<> -class CopyHelper<wchar_t*> : public CopyHelper<const wchar_t*> { - public: - typedef CopyHelper<const wchar_t*> Base; - CopyHelper(wchar_t* t) : Base(t) {} - - const void* GetStart() const { - return Base::GetStart(); - } - - bool Update(void* buffer) { - return Base::Update(buffer); - } - - uint32_t GetSize() const { return Base::GetSize(); } - - bool IsInOut() { - return Base::IsInOut(); - } - - ArgType GetType() { - return Base::GetType(); - } -}; - -// Specialization for wchar_t arrays strings. We just reuse the implementation -// of the const string specialization. -template<size_t n> -class CopyHelper<const wchar_t[n]> : public CopyHelper<const wchar_t*> { - public: - typedef const wchar_t array[n]; - typedef CopyHelper<const wchar_t*> Base; - CopyHelper(array t) : Base(t) {} - - const void* GetStart() const { - return Base::GetStart(); - } - - bool Update(void* buffer) { - return Base::Update(buffer); - } - - uint32_t GetSize() const { return Base::GetSize(); } - - bool IsInOut() { - return Base::IsInOut(); - } - - ArgType GetType() { - return Base::GetType(); - } -}; - -// Generic encapsulation class containing a pointer to a buffer and the -// size of the buffer. It is used by the IPC to be able to pass in/out -// parameters. -class InOutCountedBuffer : public CountedBuffer { - public: - InOutCountedBuffer(void* buffer, uint32_t size) - : CountedBuffer(buffer, size) {} -}; - -// This copy helper template specialization catches the cases where the -// parameter is a an input/output buffer. -template<> -class CopyHelper<InOutCountedBuffer> { - public: - CopyHelper(const InOutCountedBuffer t) : t_(t) {} - - // Returns the pointer to the start of the string. - const void* GetStart() const { - return t_.Buffer(); - } - - // Updates the buffer with the value from the new buffer in parameter. - bool Update(void* buffer) { - // We are touching user memory, this has to be done from inside a try - // except. - __try { - memcpy(t_.Buffer(), buffer, t_.Size()); - } - __except(EXCEPTION_EXECUTE_HANDLER) { - return false; - } - return true; - } - - // Returns the size of the string in bytes. We define a NULL string to - // be of zero length. - uint32_t GetSize() const { return t_.Size(); } - - // Returns true if the current type is used as an In or InOut parameter. - bool IsInOut() { - return true; - } - - ArgType GetType() { - return INOUTPTR_TYPE; - } - - private: - const InOutCountedBuffer t_; -}; - -// The following two macros make it less error prone the generation -// of CrossCall functions with ever more input parameters. - -#define XCALL_GEN_PARAMS_OBJ(num, params) \ - typedef ActualCallParams<num, kIPCChannelSize> ActualParams; \ - void* raw_mem = ipc_provider.GetBuffer(); \ - if (NULL == raw_mem) \ - return SBOX_ERROR_NO_SPACE; \ - ActualParams* params = new(raw_mem) ActualParams(tag); - -#define XCALL_GEN_COPY_PARAM(num, params) \ - static_assert(kMaxIpcParams >= num, "too many parameters"); \ - CopyHelper<Par##num> ch##num(p##num); \ - if (!params->CopyParamIn(num - 1, ch##num.GetStart(), ch##num.GetSize(), \ - ch##num.IsInOut(), ch##num.GetType())) \ - return SBOX_ERROR_NO_SPACE; - -#define XCALL_GEN_UPDATE_PARAM(num, params) \ - if (!ch##num.Update(params->GetParamPtr(num-1))) {\ - ipc_provider.FreeBuffer(raw_mem); \ - return SBOX_ERROR_BAD_PARAMS; \ - } - -#define XCALL_GEN_FREE_CHANNEL() \ - ipc_provider.FreeBuffer(raw_mem); - -// CrossCall template with one input parameter -template <typename IPCProvider, typename Par1> -ResultCode CrossCall(IPCProvider& ipc_provider, - uint32_t tag, - const Par1& p1, - CrossCallReturn* answer) { - XCALL_GEN_PARAMS_OBJ(1, call_params); - XCALL_GEN_COPY_PARAM(1, call_params); - - ResultCode result = ipc_provider.DoCall(call_params, answer); - - if (SBOX_ERROR_CHANNEL_ERROR != result) { - XCALL_GEN_UPDATE_PARAM(1, call_params); - XCALL_GEN_FREE_CHANNEL(); - } - - return result; -} - -// CrossCall template with two input parameters. -template <typename IPCProvider, typename Par1, typename Par2> -ResultCode CrossCall(IPCProvider& ipc_provider, - uint32_t tag, - const Par1& p1, - const Par2& p2, - CrossCallReturn* answer) { - XCALL_GEN_PARAMS_OBJ(2, call_params); - XCALL_GEN_COPY_PARAM(1, call_params); - XCALL_GEN_COPY_PARAM(2, call_params); - - ResultCode result = ipc_provider.DoCall(call_params, answer); - - if (SBOX_ERROR_CHANNEL_ERROR != result) { - XCALL_GEN_UPDATE_PARAM(1, call_params); - XCALL_GEN_UPDATE_PARAM(2, call_params); - XCALL_GEN_FREE_CHANNEL(); - } - return result; -} - -// CrossCall template with three input parameters. -template <typename IPCProvider, typename Par1, typename Par2, typename Par3> -ResultCode CrossCall(IPCProvider& ipc_provider, - uint32_t tag, - const Par1& p1, - const Par2& p2, - const Par3& p3, - CrossCallReturn* answer) { - XCALL_GEN_PARAMS_OBJ(3, call_params); - XCALL_GEN_COPY_PARAM(1, call_params); - XCALL_GEN_COPY_PARAM(2, call_params); - XCALL_GEN_COPY_PARAM(3, call_params); - - ResultCode result = ipc_provider.DoCall(call_params, answer); - - if (SBOX_ERROR_CHANNEL_ERROR != result) { - XCALL_GEN_UPDATE_PARAM(1, call_params); - XCALL_GEN_UPDATE_PARAM(2, call_params); - XCALL_GEN_UPDATE_PARAM(3, call_params); - XCALL_GEN_FREE_CHANNEL(); - } - return result; -} - -// CrossCall template with four input parameters. -template <typename IPCProvider, - typename Par1, - typename Par2, - typename Par3, - typename Par4> -ResultCode CrossCall(IPCProvider& ipc_provider, - uint32_t tag, - const Par1& p1, - const Par2& p2, - const Par3& p3, - const Par4& p4, - CrossCallReturn* answer) { - XCALL_GEN_PARAMS_OBJ(4, call_params); - XCALL_GEN_COPY_PARAM(1, call_params); - XCALL_GEN_COPY_PARAM(2, call_params); - XCALL_GEN_COPY_PARAM(3, call_params); - XCALL_GEN_COPY_PARAM(4, call_params); - - ResultCode result = ipc_provider.DoCall(call_params, answer); - - if (SBOX_ERROR_CHANNEL_ERROR != result) { - XCALL_GEN_UPDATE_PARAM(1, call_params); - XCALL_GEN_UPDATE_PARAM(2, call_params); - XCALL_GEN_UPDATE_PARAM(3, call_params); - XCALL_GEN_UPDATE_PARAM(4, call_params); - XCALL_GEN_FREE_CHANNEL(); - } - return result; -} - -// CrossCall template with five input parameters. -template <typename IPCProvider, - typename Par1, - typename Par2, - typename Par3, - typename Par4, - typename Par5> -ResultCode CrossCall(IPCProvider& ipc_provider, - uint32_t tag, - const Par1& p1, - const Par2& p2, - const Par3& p3, - const Par4& p4, - const Par5& p5, - CrossCallReturn* answer) { - XCALL_GEN_PARAMS_OBJ(5, call_params); - XCALL_GEN_COPY_PARAM(1, call_params); - XCALL_GEN_COPY_PARAM(2, call_params); - XCALL_GEN_COPY_PARAM(3, call_params); - XCALL_GEN_COPY_PARAM(4, call_params); - XCALL_GEN_COPY_PARAM(5, call_params); - - ResultCode result = ipc_provider.DoCall(call_params, answer); - - if (SBOX_ERROR_CHANNEL_ERROR != result) { - XCALL_GEN_UPDATE_PARAM(1, call_params); - XCALL_GEN_UPDATE_PARAM(2, call_params); - XCALL_GEN_UPDATE_PARAM(3, call_params); - XCALL_GEN_UPDATE_PARAM(4, call_params); - XCALL_GEN_UPDATE_PARAM(5, call_params); - XCALL_GEN_FREE_CHANNEL(); - } - return result; -} - -// CrossCall template with six input parameters. -template <typename IPCProvider, - typename Par1, - typename Par2, - typename Par3, - typename Par4, - typename Par5, - typename Par6> -ResultCode CrossCall(IPCProvider& ipc_provider, - uint32_t tag, - const Par1& p1, - const Par2& p2, - const Par3& p3, - const Par4& p4, - const Par5& p5, - const Par6& p6, - CrossCallReturn* answer) { - XCALL_GEN_PARAMS_OBJ(6, call_params); - XCALL_GEN_COPY_PARAM(1, call_params); - XCALL_GEN_COPY_PARAM(2, call_params); - XCALL_GEN_COPY_PARAM(3, call_params); - XCALL_GEN_COPY_PARAM(4, call_params); - XCALL_GEN_COPY_PARAM(5, call_params); - XCALL_GEN_COPY_PARAM(6, call_params); - - ResultCode result = ipc_provider.DoCall(call_params, answer); - - if (SBOX_ERROR_CHANNEL_ERROR != result) { - XCALL_GEN_UPDATE_PARAM(1, call_params); - XCALL_GEN_UPDATE_PARAM(2, call_params); - XCALL_GEN_UPDATE_PARAM(3, call_params); - XCALL_GEN_UPDATE_PARAM(4, call_params); - XCALL_GEN_UPDATE_PARAM(5, call_params); - XCALL_GEN_UPDATE_PARAM(6, call_params); - XCALL_GEN_FREE_CHANNEL(); - } - return result; -} - -// CrossCall template with seven input parameters. -template <typename IPCProvider, - typename Par1, - typename Par2, - typename Par3, - typename Par4, - typename Par5, - typename Par6, - typename Par7> -ResultCode CrossCall(IPCProvider& ipc_provider, - uint32_t tag, - const Par1& p1, - const Par2& p2, - const Par3& p3, - const Par4& p4, - const Par5& p5, - const Par6& p6, - const Par7& p7, - CrossCallReturn* answer) { - XCALL_GEN_PARAMS_OBJ(7, call_params); - XCALL_GEN_COPY_PARAM(1, call_params); - XCALL_GEN_COPY_PARAM(2, call_params); - XCALL_GEN_COPY_PARAM(3, call_params); - XCALL_GEN_COPY_PARAM(4, call_params); - XCALL_GEN_COPY_PARAM(5, call_params); - XCALL_GEN_COPY_PARAM(6, call_params); - XCALL_GEN_COPY_PARAM(7, call_params); - - ResultCode result = ipc_provider.DoCall(call_params, answer); - - if (SBOX_ERROR_CHANNEL_ERROR != result) { - XCALL_GEN_UPDATE_PARAM(1, call_params); - XCALL_GEN_UPDATE_PARAM(2, call_params); - XCALL_GEN_UPDATE_PARAM(3, call_params); - XCALL_GEN_UPDATE_PARAM(4, call_params); - XCALL_GEN_UPDATE_PARAM(5, call_params); - XCALL_GEN_UPDATE_PARAM(6, call_params); - XCALL_GEN_UPDATE_PARAM(7, call_params); - XCALL_GEN_FREE_CHANNEL(); - } - return result; -} -} // namespace sandbox - -#endif // SANDBOX_SRC_CROSSCALL_CLIENT_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h deleted file mode 100644 index eb59c4423..000000000 --- a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_CROSSCALL_PARAMS_H__ -#define SANDBOX_SRC_CROSSCALL_PARAMS_H__ - -#include <windows.h> -#include <lmaccess.h> -#include <stddef.h> -#include <stdint.h> - -#include <memory> - -#include "base/macros.h" -#include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/sandbox_types.h" - -// Increases |value| until there is no need for padding given an int64_t -// alignment. Returns the increased value. -inline uint32_t Align(uint32_t value) { - uint32_t alignment = sizeof(int64_t); - return ((value + alignment - 1) / alignment) * alignment; -} - -// This header is part of CrossCall: the sandbox inter-process communication. -// This header defines the basic types used both in the client IPC and in the -// server IPC code. CrossCallParams and ActualCallParams model the input -// parameters of an IPC call and CrossCallReturn models the output params and -// the return value. -// -// An IPC call is defined by its 'tag' which is a (uint32_t) unique identifier -// that is used to route the IPC call to the proper server. Every tag implies -// a complete call signature including the order and type of each parameter. -// -// Like most IPC systems. CrossCall is designed to take as inputs 'simple' -// types such as integers and strings. Classes, generic arrays or pointers to -// them are not supported. -// -// Another limitation of CrossCall is that the return value and output -// parameters can only be uint32_t integers. Returning complex structures or -// strings is not supported. - -namespace sandbox { - -// max number of extended return parameters. See CrossCallReturn -const size_t kExtendedReturnCount = 8; - -// Union of multiple types to be used as extended results -// in the CrossCallReturn. -union MultiType { - uint32_t unsigned_int; - void* pointer; - HANDLE handle; - ULONG_PTR ulong_ptr; -}; - -// Maximum number of IPC parameters currently supported. -// To increase this value, we have to: -// - Add another Callback typedef to Dispatcher. -// - Add another case to the switch on SharedMemIPCServer::InvokeCallback. -// - Add another case to the switch in GetActualAndMaxBufferSize -const int kMaxIpcParams = 9; - -// Contains the information about a parameter in the ipc buffer. -struct ParamInfo { - ArgType type_; - uint32_t offset_; - uint32_t size_; -}; - -// Models the return value and the return parameters of an IPC call -// currently limited to one status code and eight generic return values -// which cannot be pointers to other data. For x64 ports this structure -// might have to use other integer types. -struct CrossCallReturn { - // the IPC tag. It should match the original IPC tag. - uint32_t tag; - // The result of the IPC operation itself. - ResultCode call_outcome; - // the result of the IPC call as executed in the server. The interpretation - // of this value depends on the specific service. - union { - NTSTATUS nt_status; - DWORD win32_result; - }; - // Number of extended return values. - uint32_t extended_count; - // for calls that should return a windows handle. It is found here. - HANDLE handle; - // The array of extended values. - MultiType extended[kExtendedReturnCount]; -}; - -// CrossCallParams base class that models the input params all packed in a -// single compact memory blob. The representation can vary but in general a -// given child of this class is meant to represent all input parameters -// necessary to make a IPC call. -// -// This class cannot have virtual members because its assumed the IPC -// parameters start from the 'this' pointer to the end, which is defined by -// one of the subclasses -// -// Objects of this class cannot be constructed directly. Only derived -// classes have the proper knowledge to construct it. -class CrossCallParams { - public: - // Returns the tag (ipc unique id) associated with this IPC. - uint32_t GetTag() const { return tag_; } - - // Returns the beggining of the buffer where the IPC params can be stored. - // prior to an IPC call - const void* GetBuffer() const { - return this; - } - - // Returns how many parameter this IPC call should have. - uint32_t GetParamsCount() const { return params_count_; } - - // Returns a pointer to the CrossCallReturn structure. - CrossCallReturn* GetCallReturn() { - return &call_return; - } - - // Returns TRUE if this call contains InOut parameters. - bool IsInOut() const { return (1 == is_in_out_); } - - // Tells the CrossCall object if it contains InOut parameters. - void SetIsInOut(bool value) { - if (value) - is_in_out_ = 1; - else - is_in_out_ = 0; - } - - protected: - // constructs the IPC call params. Called only from the derived classes - CrossCallParams(uint32_t tag, uint32_t params_count) - : tag_(tag), is_in_out_(0), params_count_(params_count) {} - - private: - uint32_t tag_; - uint32_t is_in_out_; - CrossCallReturn call_return; - const uint32_t params_count_; - DISALLOW_COPY_AND_ASSIGN(CrossCallParams); -}; - -// ActualCallParams models an specific IPC call parameters with respect to the -// storage allocation that the packed parameters should need. -// NUMBER_PARAMS: the number of parameters, valid from 1 to N -// BLOCK_SIZE: the total storage that the NUMBER_PARAMS parameters can take, -// typically the block size is defined by the channel size of the underlying -// ipc mechanism. -// In practice this class is used to levergage C++ capacity to properly -// calculate sizes and displacements given the possibility of the packed params -// blob to be complex. -// -// As is, this class assumes that the layout of the blob is as follows. Assume -// that NUMBER_PARAMS = 2 and a 32-bit build: -// -// [ tag 4 bytes] -// [ IsOnOut 4 bytes] -// [ call return 52 bytes] -// [ params count 4 bytes] -// [ parameter 0 type 4 bytes] -// [ parameter 0 offset 4 bytes] ---delta to ---\ -// [ parameter 0 size 4 bytes] | -// [ parameter 1 type 4 bytes] | -// [ parameter 1 offset 4 bytes] ---------------|--\ -// [ parameter 1 size 4 bytes] | | -// [ parameter 2 type 4 bytes] | | -// [ parameter 2 offset 4 bytes] ----------------------\ -// [ parameter 2 size 4 bytes] | | | -// |---------------------------| | | | -// | value 0 (x bytes) | <--------------/ | | -// | value 1 (y bytes) | <-----------------/ | -// | | | -// | end of buffer | <---------------------/ -// |---------------------------| -// -// Note that the actual number of params is NUMBER_PARAMS + 1 -// so that the size of each actual param can be computed from the difference -// between one parameter and the next down. The offset of the last param -// points to the end of the buffer and the type and size are undefined. -// -template <size_t NUMBER_PARAMS, size_t BLOCK_SIZE> -class ActualCallParams : public CrossCallParams { - public: - // constructor. Pass the ipc unique tag as input - explicit ActualCallParams(uint32_t tag) - : CrossCallParams(tag, NUMBER_PARAMS) { - param_info_[0].offset_ = - static_cast<uint32_t>(parameters_ - reinterpret_cast<char*>(this)); - } - - // Testing-only constructor. Allows setting the |number_params| to a - // wrong value. - ActualCallParams(uint32_t tag, uint32_t number_params) - : CrossCallParams(tag, number_params) { - param_info_[0].offset_ = - static_cast<uint32_t>(parameters_ - reinterpret_cast<char*>(this)); - } - - // Testing-only method. Allows setting the apparent size to a wrong value. - // returns the previous size. - uint32_t OverrideSize(uint32_t new_size) { - uint32_t previous_size = param_info_[NUMBER_PARAMS].offset_; - param_info_[NUMBER_PARAMS].offset_ = new_size; - return previous_size; - } - - // Copies each paramter into the internal buffer. For each you must supply: - // index: 0 for the first param, 1 for the next an so on - bool CopyParamIn(uint32_t index, - const void* parameter_address, - uint32_t size, - bool is_in_out, - ArgType type) { - if (index >= NUMBER_PARAMS) { - return false; - } - - if (UINT32_MAX == size) { - // Memory error while getting the size. - return false; - } - - if (size && !parameter_address) { - return false; - } - - if ((size > sizeof(*this)) || - (param_info_[index].offset_ > (sizeof(*this) - size))) { - // It does not fit, abort copy. - return false; - } - - char* dest = reinterpret_cast<char*>(this) + param_info_[index].offset_; - - // We might be touching user memory, this has to be done from inside a try - // except. - __try { - memcpy(dest, parameter_address, size); - } - __except(EXCEPTION_EXECUTE_HANDLER) { - return false; - } - - // Set the flag to tell the broker to update the buffer once the call is - // made. - if (is_in_out) - SetIsInOut(true); - - param_info_[index + 1].offset_ = Align(param_info_[index].offset_ + - size); - param_info_[index].size_ = size; - param_info_[index].type_ = type; - return true; - } - - // Returns a pointer to a parameter in the memory section. - void* GetParamPtr(size_t index) { - return reinterpret_cast<char*>(this) + param_info_[index].offset_; - } - - // Returns the total size of the buffer. Only valid once all the paramters - // have been copied in with CopyParamIn. - uint32_t GetSize() const { return param_info_[NUMBER_PARAMS].offset_; } - - protected: - ActualCallParams() : CrossCallParams(0, NUMBER_PARAMS) { } - - private: - ParamInfo param_info_[NUMBER_PARAMS + 1]; - char parameters_[BLOCK_SIZE - sizeof(CrossCallParams) - - sizeof(ParamInfo) * (NUMBER_PARAMS + 1)]; - DISALLOW_COPY_AND_ASSIGN(ActualCallParams); -}; - -static_assert(sizeof(ActualCallParams<1, 1024>) == 1024, "bad size buffer"); -static_assert(sizeof(ActualCallParams<2, 1024>) == 1024, "bad size buffer"); -static_assert(sizeof(ActualCallParams<3, 1024>) == 1024, "bad size buffer"); - -} // namespace sandbox - -#endif // SANDBOX_SRC_CROSSCALL_PARAMS_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc deleted file mode 100644 index 9f71f333f..000000000 --- a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/crosscall_server.h" - -#include <stddef.h> -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/logging.h" -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/crosscall_params.h" - -// This code performs the ipc message validation. Potential security flaws -// on the ipc are likelier to be found in this code than in the rest of -// the ipc code. - -namespace { - -// The buffer for a message must match the max channel size. -const size_t kMaxBufferSize = sandbox::kIPCChannelSize; - -} - -namespace sandbox { - -// Returns the actual size for the parameters in an IPC buffer. Returns -// zero if the |param_count| is zero or too big. -uint32_t GetActualBufferSize(uint32_t param_count, void* buffer_base) { - // The template types are used to calculate the maximum expected size. - typedef ActualCallParams<1, kMaxBufferSize> ActualCP1; - typedef ActualCallParams<2, kMaxBufferSize> ActualCP2; - typedef ActualCallParams<3, kMaxBufferSize> ActualCP3; - typedef ActualCallParams<4, kMaxBufferSize> ActualCP4; - typedef ActualCallParams<5, kMaxBufferSize> ActualCP5; - typedef ActualCallParams<6, kMaxBufferSize> ActualCP6; - typedef ActualCallParams<7, kMaxBufferSize> ActualCP7; - typedef ActualCallParams<8, kMaxBufferSize> ActualCP8; - typedef ActualCallParams<9, kMaxBufferSize> ActualCP9; - - // Retrieve the actual size and the maximum size of the params buffer. - switch (param_count) { - case 0: - return 0; - case 1: - return reinterpret_cast<ActualCP1*>(buffer_base)->GetSize(); - case 2: - return reinterpret_cast<ActualCP2*>(buffer_base)->GetSize(); - case 3: - return reinterpret_cast<ActualCP3*>(buffer_base)->GetSize(); - case 4: - return reinterpret_cast<ActualCP4*>(buffer_base)->GetSize(); - case 5: - return reinterpret_cast<ActualCP5*>(buffer_base)->GetSize(); - case 6: - return reinterpret_cast<ActualCP6*>(buffer_base)->GetSize(); - case 7: - return reinterpret_cast<ActualCP7*>(buffer_base)->GetSize(); - case 8: - return reinterpret_cast<ActualCP8*>(buffer_base)->GetSize(); - case 9: - return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize(); - default: - return 0; - } -} - -// Verifies that the declared sizes of an IPC buffer are within range. -bool IsSizeWithinRange(uint32_t buffer_size, - uint32_t min_declared_size, - uint32_t declared_size) { - if ((buffer_size < min_declared_size) || - (sizeof(CrossCallParamsEx) > min_declared_size)) { - // Minimal computed size bigger than existing buffer or param_count - // integer overflow. - return false; - } - - if ((declared_size > buffer_size) || (declared_size < min_declared_size)) { - // Declared size is bigger than buffer or smaller than computed size - // or param_count is equal to 0 or bigger than 9. - return false; - } - - return true; -} - -CrossCallParamsEx::CrossCallParamsEx() - :CrossCallParams(0, 0) { -} - -// We override the delete operator because the object's backing memory -// is hand allocated in CreateFromBuffer. We don't override the new operator -// because the constructors are private so there is no way to mismatch -// new & delete. -void CrossCallParamsEx::operator delete(void* raw_memory) throw() { - if (NULL == raw_memory) { - // C++ standard allows 'delete 0' behavior. - return; - } - delete[] reinterpret_cast<char*>(raw_memory); -} - -// This function uses a SEH try block so cannot use C++ objects that -// have destructors or else you get Compiler Error C2712. So no DCHECKs -// inside this function. -CrossCallParamsEx* CrossCallParamsEx::CreateFromBuffer(void* buffer_base, - uint32_t buffer_size, - uint32_t* output_size) { - // IMPORTANT: Everything inside buffer_base and derived from it such - // as param_count and declared_size is untrusted. - if (NULL == buffer_base) { - return NULL; - } - if (buffer_size < sizeof(CrossCallParams)) { - return NULL; - } - if (buffer_size > kMaxBufferSize) { - return NULL; - } - - char* backing_mem = NULL; - uint32_t param_count = 0; - uint32_t declared_size; - uint32_t min_declared_size; - CrossCallParamsEx* copied_params = NULL; - - // Touching the untrusted buffer is done under a SEH try block. This - // will catch memory access violations so we don't crash. - __try { - CrossCallParams* call_params = - reinterpret_cast<CrossCallParams*>(buffer_base); - - // Check against the minimum size given the number of stated params - // if too small we bail out. - param_count = call_params->GetParamsCount(); - min_declared_size = sizeof(CrossCallParams) + - ((param_count + 1) * sizeof(ParamInfo)); - - // Retrieve the declared size which if it fails returns 0. - declared_size = GetActualBufferSize(param_count, buffer_base); - - if (!IsSizeWithinRange(buffer_size, min_declared_size, declared_size)) - return NULL; - - // Now we copy the actual amount of the message. - *output_size = declared_size; - backing_mem = new char[declared_size]; - copied_params = reinterpret_cast<CrossCallParamsEx*>(backing_mem); - memcpy(backing_mem, call_params, declared_size); - - // Avoid compiler optimizations across this point. Any value stored in - // memory should be stored for real, and values previously read from memory - // should be actually read. - _ReadWriteBarrier(); - - min_declared_size = sizeof(CrossCallParams) + - ((param_count + 1) * sizeof(ParamInfo)); - - // Check that the copied buffer is still valid. - if (copied_params->GetParamsCount() != param_count || - GetActualBufferSize(param_count, backing_mem) != declared_size || - !IsSizeWithinRange(buffer_size, min_declared_size, declared_size)) { - delete [] backing_mem; - return NULL; - } - - } __except(EXCEPTION_EXECUTE_HANDLER) { - // In case of a windows exception we know it occurred while touching the - // untrusted buffer so we bail out as is. - delete [] backing_mem; - return NULL; - } - - const char* last_byte = &backing_mem[declared_size]; - const char* first_byte = &backing_mem[min_declared_size]; - - // Verify here that all and each parameters make sense. This is done in the - // local copy. - for (uint32_t ix = 0; ix != param_count; ++ix) { - uint32_t size = 0; - ArgType type; - char* address = reinterpret_cast<char*>( - copied_params->GetRawParameter(ix, &size, &type)); - if ((NULL == address) || // No null params. - (INVALID_TYPE >= type) || (LAST_TYPE <= type) || // Unknown type. - (address < backing_mem) || // Start cannot point before buffer. - (address < first_byte) || // Start cannot point too low. - (address > last_byte) || // Start cannot point past buffer. - ((address + size) < address) || // Invalid size. - ((address + size) > last_byte)) { // End cannot point past buffer. - // Malformed. - delete[] backing_mem; - return NULL; - } - } - // The parameter buffer looks good. - return copied_params; -} - -// Accessors to the parameters in the raw buffer. -void* CrossCallParamsEx::GetRawParameter(uint32_t index, - uint32_t* size, - ArgType* type) { - if (index >= GetParamsCount()) { - return NULL; - } - // The size is always computed from the parameter minus the next - // parameter, this works because the message has an extra parameter slot - *size = param_info_[index].size_; - *type = param_info_[index].type_; - - return param_info_[index].offset_ + reinterpret_cast<char*>(this); -} - -// Covers common case for 32 bit integers. -bool CrossCallParamsEx::GetParameter32(uint32_t index, uint32_t* param) { - uint32_t size = 0; - ArgType type; - void* start = GetRawParameter(index, &size, &type); - if ((NULL == start) || (4 != size) || (UINT32_TYPE != type)) { - return false; - } - // Copy the 4 bytes. - *(reinterpret_cast<uint32_t*>(param)) = *(reinterpret_cast<uint32_t*>(start)); - return true; -} - -bool CrossCallParamsEx::GetParameterVoidPtr(uint32_t index, void** param) { - uint32_t size = 0; - ArgType type; - void* start = GetRawParameter(index, &size, &type); - if ((NULL == start) || (sizeof(void*) != size) || (VOIDPTR_TYPE != type)) { - return false; - } - *param = *(reinterpret_cast<void**>(start)); - return true; -} - -// Covers the common case of reading a string. Note that the string is not -// scanned for invalid characters. -bool CrossCallParamsEx::GetParameterStr(uint32_t index, - base::string16* string) { - uint32_t size = 0; - ArgType type; - void* start = GetRawParameter(index, &size, &type); - if (WCHAR_TYPE != type) { - return false; - } - - // Check if this is an empty string. - if (size == 0) { - *string = L""; - return true; - } - - if ((NULL == start) || ((size % sizeof(wchar_t)) != 0)) { - return false; - } - string->append(reinterpret_cast<wchar_t*>(start), size/(sizeof(wchar_t))); - return true; -} - -bool CrossCallParamsEx::GetParameterPtr(uint32_t index, - uint32_t expected_size, - void** pointer) { - uint32_t size = 0; - ArgType type; - void* start = GetRawParameter(index, &size, &type); - - if ((size != expected_size) || (INOUTPTR_TYPE != type)) { - return false; - } - - if (NULL == start) { - return false; - } - - *pointer = start; - return true; -} - -void SetCallError(ResultCode error, CrossCallReturn* call_return) { - call_return->call_outcome = error; - call_return->extended_count = 0; -} - -void SetCallSuccess(CrossCallReturn* call_return) { - call_return->call_outcome = SBOX_ALL_OK; -} - -Dispatcher* Dispatcher::OnMessageReady(IPCParams* ipc, - CallbackGeneric* callback) { - DCHECK(callback); - std::vector<IPCCall>::iterator it = ipc_calls_.begin(); - for (; it != ipc_calls_.end(); ++it) { - if (it->params.Matches(ipc)) { - *callback = it->callback; - return this; - } - } - return NULL; -} - -Dispatcher::Dispatcher() { -} - -Dispatcher::~Dispatcher() { -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_server.h b/security/sandbox/chromium/sandbox/win/src/crosscall_server.h deleted file mode 100644 index 0820ac440..000000000 --- a/security/sandbox/chromium/sandbox/win/src/crosscall_server.h +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_CROSSCALL_SERVER_H_ -#define SANDBOX_SRC_CROSSCALL_SERVER_H_ - -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_params.h" - -// This is the IPC server interface for CrossCall: The IPC for the Sandbox -// On the server, CrossCall needs two things: -// 1) threads: Or better said, someone to provide them, that is what the -// ThreadProvider interface is defined for. These thread(s) are -// the ones that will actually execute the IPC data retrieval. -// -// 2) a dispatcher: This interface represents the way to route and process -// an IPC call given the IPC tag. -// -// The other class included here CrossCallParamsEx is the server side version -// of the CrossCallParams class of /sandbox/crosscall_params.h The difference -// is that the sever version is paranoid about the correctness of the IPC -// message and will do all sorts of verifications. -// -// A general diagram of the interaction is as follows: -// -// ------------ -// | | -// ThreadProvider <--(1)Register--| IPC | -// | | Implemen | -// | | -tation | -// (2) | | OnMessage -// IPC fired --callback ------>| |--(3)---> Dispatcher -// | | -// ------------ -// -// The IPC implementation sits as a middleman between the handling of the -// specifics of scheduling a thread to service the IPC and the multiple -// entities that can potentially serve each particular IPC. -namespace sandbox { - -class InterceptionManager; - -// This function signature is required as the callback when an IPC call fires. -// context: a user-defined pointer that was set using ThreadProvider -// reason: 0 if the callback was fired because of a timeout. -// 1 if the callback was fired because of an event. -typedef void (__stdcall * CrossCallIPCCallback)(void* context, - unsigned char reason); - -// ThreadProvider models a thread factory. The idea is to decouple thread -// creation and lifetime from the inner guts of the IPC. The contract is -// simple: -// - the IPC implementation calls RegisterWait with a waitable object that -// becomes signaled when an IPC arrives and needs to be serviced. -// - when the waitable object becomes signaled, the thread provider conjures -// a thread that calls the callback (CrossCallIPCCallback) function -// - the callback function tries its best not to block and return quickly -// and should not assume that the next callback will use the same thread -// - when the callback returns the ThreadProvider owns again the thread -// and can destroy it or keep it around. -class ThreadProvider { - public: - // Registers a waitable object with the thread provider. - // client: A number to associate with all the RegisterWait calls, typically - // this is the address of the caller object. This parameter cannot - // be zero. - // waitable_object : a kernel object that can be waited on - // callback: a function pointer which is the function that will be called - // when the waitable object fires - // context: a user-provider pointer that is passed back to the callback - // when its called - virtual bool RegisterWait(const void* client, HANDLE waitable_object, - CrossCallIPCCallback callback, - void* context) = 0; - - // Removes all the registrations done with the same cookie parameter. - // This frees internal thread pool resources. - virtual bool UnRegisterWaits(void* cookie) = 0; - virtual ~ThreadProvider() {} -}; - -// Models the server-side of the original input parameters. -// Provides IPC buffer validation and it is capable of reading the parameters -// out of the IPC buffer. -class CrossCallParamsEx : public CrossCallParams { - public: - // Factory constructor. Pass an IPCbuffer (and buffer size) that contains a - // pending IPCcall. This constructor will: - // 1) validate the IPC buffer. returns NULL is the IPCbuffer is malformed. - // 2) make a copy of the IPCbuffer (parameter capture) - static CrossCallParamsEx* CreateFromBuffer(void* buffer_base, - uint32_t buffer_size, - uint32_t* output_size); - - // Provides IPCinput parameter raw access: - // index : the parameter to read; 0 is the first parameter - // returns NULL if the parameter is non-existent. If it exists it also - // returns the size in *size - void* GetRawParameter(uint32_t index, uint32_t* size, ArgType* type); - - // Gets a parameter that is four bytes in size. - // Returns false if the parameter does not exist or is not 32 bits wide. - bool GetParameter32(uint32_t index, uint32_t* param); - - // Gets a parameter that is void pointer in size. - // Returns false if the parameter does not exist or is not void pointer sized. - bool GetParameterVoidPtr(uint32_t index, void** param); - - // Gets a parameter that is a string. Returns false if the parameter does not - // exist. - bool GetParameterStr(uint32_t index, base::string16* string); - - // Gets a parameter that is an in/out buffer. Returns false is the parameter - // does not exist or if the size of the actual parameter is not equal to the - // expected size. - bool GetParameterPtr(uint32_t index, uint32_t expected_size, void** pointer); - - // Frees the memory associated with the IPC parameters. - static void operator delete(void* raw_memory) throw(); - - private: - // Only the factory method CreateFromBuffer can construct these objects. - CrossCallParamsEx(); - - ParamInfo param_info_[1]; - DISALLOW_COPY_AND_ASSIGN(CrossCallParamsEx); -}; - -// Simple helper function that sets the members of CrossCallReturn -// to the proper state to signal a basic error. -void SetCallError(ResultCode error, CrossCallReturn* call_return); - -// Sets the internal status of call_return to signify the that IPC call -// completed successfully. -void SetCallSuccess(CrossCallReturn* call_return); - -// Represents the client process that initiated the IPC which boils down to the -// process handle and the job object handle that contains the client process. -struct ClientInfo { - HANDLE process; - DWORD process_id; -}; - -// All IPC-related information to be passed to the IPC handler. -struct IPCInfo { - int ipc_tag; - const ClientInfo* client_info; - CrossCallReturn return_info; -}; - -// This structure identifies IPC signatures. -struct IPCParams { - int ipc_tag; - ArgType args[kMaxIpcParams]; - - bool Matches(IPCParams* other) const { - return !memcmp(this, other, sizeof(*other)); - } -}; - -// Models an entity that can process an IPC message or it can route to another -// one that could handle it. When an IPC arrives the IPC implementation will: -// 1) call OnMessageReady() with the tag of the pending IPC. If the dispatcher -// returns NULL it means that it cannot handle this IPC but if it returns -// non-null, it must be the pointer to a dispatcher that can handle it. -// 2) When the IPC finally obtains a valid Dispatcher the IPC -// implementation creates a CrossCallParamsEx from the raw IPC buffer. -// 3) It calls the returned callback, with the IPC info and arguments. -class Dispatcher { - public: - // Called from the IPC implementation to handle a specific IPC message. - typedef bool (Dispatcher::*CallbackGeneric)(); - typedef bool (Dispatcher::*Callback0)(IPCInfo* ipc); - typedef bool (Dispatcher::*Callback1)(IPCInfo* ipc, void* p1); - typedef bool (Dispatcher::*Callback2)(IPCInfo* ipc, void* p1, void* p2); - typedef bool (Dispatcher::*Callback3)(IPCInfo* ipc, void* p1, void* p2, - void* p3); - typedef bool (Dispatcher::*Callback4)(IPCInfo* ipc, void* p1, void* p2, - void* p3, void* p4); - typedef bool (Dispatcher::*Callback5)(IPCInfo* ipc, void* p1, void* p2, - void* p3, void* p4, void* p5); - typedef bool (Dispatcher::*Callback6)(IPCInfo* ipc, void* p1, void* p2, - void* p3, void* p4, void* p5, void* p6); - typedef bool (Dispatcher::*Callback7)(IPCInfo* ipc, void* p1, void* p2, - void* p3, void* p4, void* p5, void* p6, - void* p7); - typedef bool (Dispatcher::*Callback8)(IPCInfo* ipc, void* p1, void* p2, - void* p3, void* p4, void* p5, void* p6, - void* p7, void* p8); - typedef bool (Dispatcher::*Callback9)(IPCInfo* ipc, void* p1, void* p2, - void* p3, void* p4, void* p5, void* p6, - void* p7, void* p8, void* p9); - - // Called from the IPC implementation when an IPC message is ready override - // on a derived class to handle a set of IPC messages. Return NULL if your - // subclass does not handle the message or return the pointer to the subclass - // that can handle it. - virtual Dispatcher* OnMessageReady(IPCParams* ipc, CallbackGeneric* callback); - - // Called when a target proces is created, to setup the interceptions related - // with the given service (IPC). - virtual bool SetupService(InterceptionManager* manager, int service) = 0; - - Dispatcher(); - virtual ~Dispatcher(); - - protected: - // Structure that defines an IPC Call with all the parameters and the handler. - struct IPCCall { - IPCParams params; - CallbackGeneric callback; - }; - - // List of IPC Calls supported by the class. - std::vector<IPCCall> ipc_calls_; -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_CROSSCALL_SERVER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/eat_resolver.cc b/security/sandbox/chromium/sandbox/win/src/eat_resolver.cc deleted file mode 100644 index 48681e83b..000000000 --- a/security/sandbox/chromium/sandbox/win/src/eat_resolver.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/eat_resolver.h" - -#include <stddef.h> - -#include "base/win/pe_image.h" -#include "sandbox/win/src/sandbox_nt_util.h" - -namespace sandbox { - -NTSTATUS EatResolverThunk::Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) { - NTSTATUS ret = Init(target_module, interceptor_module, target_name, - interceptor_name, interceptor_entry_point, - thunk_storage, storage_bytes); - if (!NT_SUCCESS(ret)) - return ret; - - if (!eat_entry_) - return STATUS_INVALID_PARAMETER; - -#if defined(_WIN64) - // We have two thunks, in order: the return path and the forward path. - if (!SetInternalThunk(thunk_storage, storage_bytes, NULL, target_)) - return STATUS_BUFFER_TOO_SMALL; - - size_t thunk_bytes = GetInternalThunkSize(); - storage_bytes -= thunk_bytes; - thunk_storage = reinterpret_cast<char*>(thunk_storage) + thunk_bytes; -#endif - - if (!SetInternalThunk(thunk_storage, storage_bytes, target_, interceptor_)) - return STATUS_BUFFER_TOO_SMALL; - - AutoProtectMemory memory; - ret = memory.ChangeProtection(eat_entry_, sizeof(DWORD), PAGE_READWRITE); - if (!NT_SUCCESS(ret)) - return ret; - - // Perform the patch. - *eat_entry_ = static_cast<DWORD>(reinterpret_cast<uintptr_t>(thunk_storage)) - - static_cast<DWORD>(reinterpret_cast<uintptr_t>(target_module)); - - if (NULL != storage_used) - *storage_used = GetThunkSize(); - - return ret; -} - -NTSTATUS EatResolverThunk::ResolveTarget(const void* module, - const char* function_name, - void** address) { - DCHECK_NT(address); - if (!module) - return STATUS_INVALID_PARAMETER; - - base::win::PEImage pe(module); - if (!pe.VerifyMagic()) - return STATUS_INVALID_IMAGE_FORMAT; - - eat_entry_ = pe.GetExportEntry(function_name); - - if (!eat_entry_) - return STATUS_PROCEDURE_NOT_FOUND; - - *address = pe.RVAToAddr(*eat_entry_); - - return STATUS_SUCCESS; -} - -size_t EatResolverThunk::GetThunkSize() const { -#if defined(_WIN64) - return GetInternalThunkSize() * 2; -#else - return GetInternalThunkSize(); -#endif -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/eat_resolver.h b/security/sandbox/chromium/sandbox/win/src/eat_resolver.h deleted file mode 100644 index a45d0063b..000000000 --- a/security/sandbox/chromium/sandbox/win/src/eat_resolver.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_EAT_RESOLVER_H__ -#define SANDBOX_SRC_EAT_RESOLVER_H__ - -#include <stddef.h> - -#include "base/macros.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/resolver.h" - -namespace sandbox { - -// This is the concrete resolver used to perform exports table interceptions. -class EatResolverThunk : public ResolverThunk { - public: - EatResolverThunk() : eat_entry_(NULL) {} - ~EatResolverThunk() override {} - - // Implementation of Resolver::Setup. - NTSTATUS Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) override; - - // Implementation of Resolver::ResolveTarget. - NTSTATUS ResolveTarget(const void* module, - const char* function_name, - void** address) override; - - // Implementation of Resolver::GetThunkSize. - size_t GetThunkSize() const override; - - private: - // The entry to patch. - DWORD* eat_entry_; - - DISALLOW_COPY_AND_ASSIGN(EatResolverThunk); -}; - -} // namespace sandbox - - -#endif // SANDBOX_SRC_EAT_RESOLVER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/file_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/file_policy_test.cc deleted file mode 100644 index f7509bd36..000000000 --- a/security/sandbox/chromium/sandbox/win/src/file_policy_test.cc +++ /dev/null @@ -1,673 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <algorithm> -#include <cctype> - -#include <windows.h> -#include <winioctl.h> - -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/filesystem_policy.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/win_utils.h" -#include "sandbox/win/tests/common/controller.h" -#include "sandbox/win/tests/common/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -#define BINDNTDLL(name) \ - name ## Function name = reinterpret_cast<name ## Function>( \ - ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name)) - -namespace sandbox { - -const ULONG kSharing = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; - -// Creates a file using different desired access. Returns if the call succeeded -// or not. The first argument in argv is the filename. The second argument -// determines the type of access and the dispositino of the file. -SBOX_TESTS_COMMAND int File_Create(int argc, wchar_t **argv) { - if (argc != 2) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - std::wstring operation(argv[0]); - - if (operation == L"Read") { - base::win::ScopedHandle file1(CreateFile( - argv[1], GENERIC_READ, kSharing, NULL, OPEN_EXISTING, 0, NULL)); - base::win::ScopedHandle file2(CreateFile( - argv[1], FILE_EXECUTE, kSharing, NULL, OPEN_EXISTING, 0, NULL)); - - if (file1.IsValid() == file2.IsValid()) - return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED; - return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR; - - } else if (operation == L"Write") { - base::win::ScopedHandle file1(CreateFile( - argv[1], GENERIC_ALL, kSharing, NULL, OPEN_EXISTING, 0, NULL)); - base::win::ScopedHandle file2(CreateFile( - argv[1], GENERIC_READ | FILE_WRITE_DATA, kSharing, NULL, OPEN_EXISTING, - 0, NULL)); - - if (file1.IsValid() == file2.IsValid()) - return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED; - return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR; - - } else if (operation == L"ReadCreate") { - base::win::ScopedHandle file2(CreateFile( - argv[1], GENERIC_READ, kSharing, NULL, CREATE_NEW, 0, NULL)); - base::win::ScopedHandle file1(CreateFile( - argv[1], GENERIC_READ, kSharing, NULL, CREATE_ALWAYS, 0, NULL)); - - if (file1.IsValid() == file2.IsValid()) - return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED; - return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR; - } - - return SBOX_TEST_INVALID_PARAMETER; -} - -SBOX_TESTS_COMMAND int File_Win32Create(int argc, wchar_t **argv) { - if (argc != 1) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - - base::string16 full_path = MakePathToSys(argv[0], false); - if (full_path.empty()) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - - HANDLE file = ::CreateFileW(full_path.c_str(), GENERIC_READ, kSharing, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (INVALID_HANDLE_VALUE != file) { - ::CloseHandle(file); - return SBOX_TEST_SUCCEEDED; - } else { - if (ERROR_ACCESS_DENIED == ::GetLastError()) { - return SBOX_TEST_DENIED; - } else { - return SBOX_TEST_FAILED; - } - } - return SBOX_TEST_SUCCEEDED; -} - -// Creates the file in parameter using the NtCreateFile api and returns if the -// call succeeded or not. -SBOX_TESTS_COMMAND int File_CreateSys32(int argc, wchar_t **argv) { - BINDNTDLL(NtCreateFile); - BINDNTDLL(RtlInitUnicodeString); - if (!NtCreateFile || !RtlInitUnicodeString) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - if (argc != 1) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - base::string16 file(argv[0]); - if (0 != _wcsnicmp(file.c_str(), kNTDevicePrefix, kNTDevicePrefixLen)) - file = MakePathToSys(argv[0], true); - - UNICODE_STRING object_name; - RtlInitUnicodeString(&object_name, file.c_str()); - - OBJECT_ATTRIBUTES obj_attributes = {}; - InitializeObjectAttributes(&obj_attributes, &object_name, - OBJ_CASE_INSENSITIVE, NULL, NULL); - - HANDLE handle; - IO_STATUS_BLOCK io_block = {}; - NTSTATUS status = NtCreateFile(&handle, FILE_READ_DATA, &obj_attributes, - &io_block, NULL, 0, kSharing, FILE_OPEN, - 0, NULL, 0); - if (NT_SUCCESS(status)) { - ::CloseHandle(handle); - return SBOX_TEST_SUCCEEDED; - } else if (STATUS_ACCESS_DENIED == status) { - return SBOX_TEST_DENIED; - } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) { - return SBOX_TEST_NOT_FOUND; - } - return SBOX_TEST_FAILED; -} - -// Opens the file in parameter using the NtOpenFile api and returns if the -// call succeeded or not. -SBOX_TESTS_COMMAND int File_OpenSys32(int argc, wchar_t **argv) { - BINDNTDLL(NtOpenFile); - BINDNTDLL(RtlInitUnicodeString); - if (!NtOpenFile || !RtlInitUnicodeString) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - if (argc != 1) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - base::string16 file = MakePathToSys(argv[0], true); - UNICODE_STRING object_name; - RtlInitUnicodeString(&object_name, file.c_str()); - - OBJECT_ATTRIBUTES obj_attributes = {}; - InitializeObjectAttributes(&obj_attributes, &object_name, - OBJ_CASE_INSENSITIVE, NULL, NULL); - - HANDLE handle; - IO_STATUS_BLOCK io_block = {}; - NTSTATUS status = NtOpenFile(&handle, FILE_READ_DATA, &obj_attributes, - &io_block, kSharing, 0); - if (NT_SUCCESS(status)) { - ::CloseHandle(handle); - return SBOX_TEST_SUCCEEDED; - } else if (STATUS_ACCESS_DENIED == status) { - return SBOX_TEST_DENIED; - } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) { - return SBOX_TEST_NOT_FOUND; - } - return SBOX_TEST_FAILED; -} - -SBOX_TESTS_COMMAND int File_GetDiskSpace(int argc, wchar_t **argv) { - base::string16 sys_path = MakePathToSys(L"", false); - if (sys_path.empty()) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - ULARGE_INTEGER free_user = {}; - ULARGE_INTEGER total = {}; - ULARGE_INTEGER free_total = {}; - if (::GetDiskFreeSpaceExW(sys_path.c_str(), &free_user, &total, - &free_total)) { - if ((total.QuadPart != 0) && (free_total.QuadPart !=0)) { - return SBOX_TEST_SUCCEEDED; - } - } else { - if (ERROR_ACCESS_DENIED == ::GetLastError()) { - return SBOX_TEST_DENIED; - } else { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - } - return SBOX_TEST_SUCCEEDED; -} - -// Move a file using the MoveFileEx api and returns if the call succeeded or -// not. -SBOX_TESTS_COMMAND int File_Rename(int argc, wchar_t **argv) { - if (argc != 2) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - if (::MoveFileEx(argv[0], argv[1], 0)) - return SBOX_TEST_SUCCEEDED; - - if (::GetLastError() != ERROR_ACCESS_DENIED) - return SBOX_TEST_FAILED; - - return SBOX_TEST_DENIED; -} - -// Query the attributes of file in parameter using the NtQueryAttributesFile api -// and NtQueryFullAttributesFile and returns if the call succeeded or not. The -// second argument in argv is "d" or "f" telling if we expect the attributes to -// specify a file or a directory. The expected attribute has to match the real -// attributes for the call to be successful. -SBOX_TESTS_COMMAND int File_QueryAttributes(int argc, wchar_t **argv) { - BINDNTDLL(NtQueryAttributesFile); - BINDNTDLL(NtQueryFullAttributesFile); - BINDNTDLL(RtlInitUnicodeString); - if (!NtQueryAttributesFile || !NtQueryFullAttributesFile || - !RtlInitUnicodeString) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - if (argc != 2) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - bool expect_directory = (L'd' == argv[1][0]); - - UNICODE_STRING object_name; - base::string16 file = MakePathToSys(argv[0], true); - RtlInitUnicodeString(&object_name, file.c_str()); - - OBJECT_ATTRIBUTES obj_attributes = {}; - InitializeObjectAttributes(&obj_attributes, &object_name, - OBJ_CASE_INSENSITIVE, NULL, NULL); - - FILE_BASIC_INFORMATION info = {}; - FILE_NETWORK_OPEN_INFORMATION full_info = {}; - NTSTATUS status1 = NtQueryAttributesFile(&obj_attributes, &info); - NTSTATUS status2 = NtQueryFullAttributesFile(&obj_attributes, &full_info); - - if (status1 != status2) - return SBOX_TEST_FAILED; - - if (NT_SUCCESS(status1)) { - if (info.FileAttributes != full_info.FileAttributes) - return SBOX_TEST_FAILED; - - bool is_directory1 = (info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - if (expect_directory == is_directory1) - return SBOX_TEST_SUCCEEDED; - } else if (STATUS_ACCESS_DENIED == status1) { - return SBOX_TEST_DENIED; - } else if (STATUS_OBJECT_NAME_NOT_FOUND == status1) { - return SBOX_TEST_NOT_FOUND; - } - - return SBOX_TEST_FAILED; -} - -TEST(FilePolicyTest, DenyNtCreateCalc) { - TestRunner runner; - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, - L"calc.exe")); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 calc.exe")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe")); -} - -TEST(FilePolicyTest, AllowNtCreateCalc) { - TestRunner runner; - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.exe")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe")); -} - -TEST(FilePolicyTest, AllowNtCreateWithNativePath) { - if (base::win::GetVersion() < base::win::VERSION_WIN7) - return; - - base::string16 calc = MakePathToSys(L"calc.exe", false); - base::string16 nt_path; - ASSERT_TRUE(GetNtPathFromWin32Path(calc, &nt_path)); - TestRunner runner; - runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, nt_path.c_str()); - - wchar_t buff[MAX_PATH]; - ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str()); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff)); - - std::transform(nt_path.begin(), nt_path.end(), nt_path.begin(), std::tolower); - ::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str()); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff)); -} - -TEST(FilePolicyTest, AllowReadOnly) { - TestRunner runner; - - // Create a temp file because we need write access to it. - wchar_t temp_directory[MAX_PATH]; - wchar_t temp_file_name[MAX_PATH]; - ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u); - - EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, - temp_file_name)); - - wchar_t command_read[MAX_PATH + 20] = {}; - wsprintf(command_read, L"File_Create Read \"%ls\"", temp_file_name); - wchar_t command_read_create[MAX_PATH + 20] = {}; - wsprintf(command_read_create, L"File_Create ReadCreate \"%ls\"", - temp_file_name); - wchar_t command_write[MAX_PATH + 20] = {}; - wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name); - - // Verify that we cannot create the file after revert. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_read_create)); - - // Verify that we don't have write access after revert. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write)); - - // Verify that we have read access after revert. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_read)); - - // Verify that we really have write access to the file. - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write)); - - DeleteFile(temp_file_name); -} - -// Tests support of "\\\\.\\DeviceName" kind of paths. -TEST(FilePolicyTest, AllowImplicitDeviceName) { - if (base::win::GetVersion() < base::win::VERSION_WIN7) - return; - - TestRunner runner; - - wchar_t temp_directory[MAX_PATH]; - wchar_t temp_file_name[MAX_PATH]; - ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u); - - std::wstring path(temp_file_name); - EXPECT_TRUE(ConvertToLongPath(&path)); - EXPECT_TRUE(GetNtPathFromWin32Path(path, &path)); - path = path.substr(sandbox::kNTDevicePrefixLen); - - wchar_t command[MAX_PATH + 20] = {}; - wsprintf(command, L"File_Create Read \"\\\\.\\%ls\"", path.c_str()); - path = std::wstring(kNTPrefix) + path; - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command)); - EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, path.c_str())); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command)); - - DeleteFile(temp_file_name); -} - -TEST(FilePolicyTest, AllowWildcard) { - TestRunner runner; - - // Create a temp file because we need write access to it. - wchar_t temp_directory[MAX_PATH]; - wchar_t temp_file_name[MAX_PATH]; - ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u); - - wcscat_s(temp_directory, MAX_PATH, L"*"); - EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_directory)); - - wchar_t command_write[MAX_PATH + 20] = {}; - wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name); - - // Verify that we have write access after revert. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write)); - - DeleteFile(temp_file_name); -} - -TEST(FilePolicyTest, AllowNtCreatePatternRule) { - TestRunner runner; - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"App*.dll")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"File_OpenSys32 appmgmts.dll")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_OpenSys32 appwiz.cpl")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"File_OpenSys32 appmgmts.dll")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_OpenSys32 appwiz.cpl")); -} - -TEST(FilePolicyTest, CheckNotFound) { - TestRunner runner; - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"n*.dll")); - - EXPECT_EQ(SBOX_TEST_NOT_FOUND, - runner.RunTest(L"File_OpenSys32 notfound.dll")); -} - -TEST(FilePolicyTest, CheckNoLeak) { - TestRunner runner; - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 notfound.exe")); -} - -TEST(FilePolicyTest, TestQueryAttributesFile) { - TestRunner runner; - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, - L"appmgmts.dll")); - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, - L"notfound.exe")); - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"drivers")); - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY, - L"ipconfig.exe")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"File_QueryAttributes drivers d")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"File_QueryAttributes appmgmts.dll f")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"File_QueryAttributes ipconfig.exe f")); - - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"File_QueryAttributes ftp.exe f")); - - EXPECT_EQ(SBOX_TEST_NOT_FOUND, - runner.RunTest(L"File_QueryAttributes notfound.exe f")); -} - -// Makes sure that we don't leak information when there is not policy to allow -// a path. -TEST(FilePolicyTest, TestQueryAttributesFileNoPolicy) { - TestRunner runner; - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"File_QueryAttributes ftp.exe f")); - - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"File_QueryAttributes notfound.exe f")); -} - -TEST(FilePolicyTest, TestRename) { - TestRunner runner; - - // Give access to the temp directory. - wchar_t temp_directory[MAX_PATH]; - wchar_t temp_file_name1[MAX_PATH]; - wchar_t temp_file_name2[MAX_PATH]; - wchar_t temp_file_name3[MAX_PATH]; - wchar_t temp_file_name4[MAX_PATH]; - wchar_t temp_file_name5[MAX_PATH]; - wchar_t temp_file_name6[MAX_PATH]; - wchar_t temp_file_name7[MAX_PATH]; - wchar_t temp_file_name8[MAX_PATH]; - ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name1), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name2), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name3), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name4), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name5), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name6), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name7), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name8), 0u); - - - // Add rules to make file1->file2 succeed. - ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name1)); - ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name2)); - - // Add rules to make file3->file4 fail. - ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name3)); - ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, - temp_file_name4)); - - // Add rules to make file5->file6 fail. - ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, - temp_file_name5)); - ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name6)); - - // Add rules to make file7->no_pol_file fail. - ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name7)); - - // Delete the files where the files are going to be renamed to. - ::DeleteFile(temp_file_name2); - ::DeleteFile(temp_file_name4); - ::DeleteFile(temp_file_name6); - ::DeleteFile(temp_file_name8); - - wchar_t command[MAX_PATH * 2 + 20] = {}; - wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name1, - temp_file_name2); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command)); - - wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name3, - temp_file_name4); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command)); - - wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name5, - temp_file_name6); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command)); - - wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name7, - temp_file_name8); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command)); - - - // Delete all the files in case they are still there. - ::DeleteFile(temp_file_name1); - ::DeleteFile(temp_file_name2); - ::DeleteFile(temp_file_name3); - ::DeleteFile(temp_file_name4); - ::DeleteFile(temp_file_name5); - ::DeleteFile(temp_file_name6); - ::DeleteFile(temp_file_name7); - ::DeleteFile(temp_file_name8); -} - -TEST(FilePolicyTest, OpenSys32FilesDenyBecauseOfDir) { - TestRunner runner; - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, - L"notepad.exe")); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"File_Win32Create notepad.exe")); -} - -TEST(FilePolicyTest, OpenSys32FilesAllowNotepad) { - TestRunner runner; - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, - L"notepad.exe")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"File_Win32Create notepad.exe")); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create calc.exe")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"File_Win32Create notepad.exe")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_Win32Create calc.exe")); -} - -TEST(FilePolicyTest, FileGetDiskSpace) { - TestRunner runner; - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_GetDiskSpace")); - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace")); - - // Add an 'allow' rule in the windows\system32 such that GetDiskFreeSpaceEx - // succeeds (it does an NtOpenFile) but windows\system32\notepad.exe is - // denied since there is no wild card in the rule. - EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L"")); - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace")); - - runner.SetTestState(AFTER_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe")); -} - -TEST(FilePolicyTest, TestReparsePoint) { - TestRunner runner; - - // Create a temp file because we need write access to it. - wchar_t temp_directory[MAX_PATH]; - wchar_t temp_file_name[MAX_PATH]; - ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u); - - // Delete the file and create a directory instead. - ASSERT_TRUE(::DeleteFile(temp_file_name)); - ASSERT_TRUE(::CreateDirectory(temp_file_name, NULL)); - - // Create a temporary file in the subfolder. - base::string16 subfolder = temp_file_name; - base::string16 temp_file_title = subfolder.substr(subfolder.rfind(L"\\") + 1); - base::string16 temp_file = subfolder + L"\\file_" + temp_file_title; - - HANDLE file = ::CreateFile(temp_file.c_str(), FILE_ALL_ACCESS, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - CREATE_ALWAYS, 0, NULL); - ASSERT_TRUE(INVALID_HANDLE_VALUE != file); - ASSERT_TRUE(::CloseHandle(file)); - - // Create a temporary file in the temp directory. - base::string16 temp_dir = temp_directory; - base::string16 temp_file_in_temp = temp_dir + L"file_" + temp_file_title; - file = ::CreateFile(temp_file_in_temp.c_str(), FILE_ALL_ACCESS, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - CREATE_ALWAYS, 0, NULL); - ASSERT_TRUE(file != NULL); - ASSERT_TRUE(::CloseHandle(file)); - - // Give write access to the temp directory. - base::string16 temp_dir_wildcard = temp_dir + L"*"; - EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, - temp_dir_wildcard.c_str())); - - // Prepare the command to execute. - base::string16 command_write; - command_write += L"File_Create Write \""; - command_write += temp_file; - command_write += L"\""; - - // Verify that we have write access to the original file - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write.c_str())); - - // Replace the subfolder by a reparse point to %temp%. - ::DeleteFile(temp_file.c_str()); - HANDLE dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - EXPECT_TRUE(INVALID_HANDLE_VALUE != dir); - - base::string16 temp_dir_nt; - temp_dir_nt += L"\\??\\"; - temp_dir_nt += temp_dir; - EXPECT_TRUE(SetReparsePoint(dir, temp_dir_nt.c_str())); - EXPECT_TRUE(::CloseHandle(dir)); - - // Try to open the file again. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write.c_str())); - - // Remove the reparse point. - dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, - NULL); - EXPECT_TRUE(INVALID_HANDLE_VALUE != dir); - EXPECT_TRUE(DeleteReparsePoint(dir)); - EXPECT_TRUE(::CloseHandle(dir)); - - // Cleanup. - EXPECT_TRUE(::DeleteFile(temp_file_in_temp.c_str())); - EXPECT_TRUE(::RemoveDirectory(subfolder.c_str())); -} - -TEST(FilePolicyTest, CheckExistingNTPrefixEscape) { - base::string16 name = L"\\??\\NAME"; - - base::string16 result = FixNTPrefixForMatch(name); - - EXPECT_STREQ(result.c_str(), L"\\/?/?\\NAME"); -} - -TEST(FilePolicyTest, CheckEscapedNTPrefixNoEscape) { - base::string16 name = L"\\/?/?\\NAME"; - - base::string16 result = FixNTPrefixForMatch(name); - - EXPECT_STREQ(result.c_str(), name.c_str()); -} - -TEST(FilePolicyTest, CheckMissingNTPrefixEscape) { - base::string16 name = L"C:\\NAME"; - - base::string16 result = FixNTPrefixForMatch(name); - - EXPECT_STREQ(result.c_str(), L"\\/?/?\\C:\\NAME"); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc deleted file mode 100644 index 6f96be240..000000000 --- a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/filesystem_dispatcher.h" - -#include <stdint.h> - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/filesystem_interception.h" -#include "sandbox/win/src/filesystem_policy.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_broker.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_nt_util.h" - -namespace sandbox { - -FilesystemDispatcher::FilesystemDispatcher(PolicyBase* policy_base) - : policy_base_(policy_base) { - static const IPCCall create_params = { - {IPC_NTCREATEFILE_TAG, - {WCHAR_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtCreateFile)}; - - static const IPCCall open_file = { - {IPC_NTOPENFILE_TAG, - {WCHAR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtOpenFile)}; - - static const IPCCall attribs = { - {IPC_NTQUERYATTRIBUTESFILE_TAG, {WCHAR_TYPE, UINT32_TYPE, INOUTPTR_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &FilesystemDispatcher::NtQueryAttributesFile)}; - - static const IPCCall full_attribs = { - {IPC_NTQUERYFULLATTRIBUTESFILE_TAG, - {WCHAR_TYPE, UINT32_TYPE, INOUTPTR_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &FilesystemDispatcher::NtQueryFullAttributesFile)}; - - static const IPCCall set_info = { - {IPC_NTSETINFO_RENAME_TAG, - {VOIDPTR_TYPE, INOUTPTR_TYPE, INOUTPTR_TYPE, UINT32_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &FilesystemDispatcher::NtSetInformationFile)}; - - ipc_calls_.push_back(create_params); - ipc_calls_.push_back(open_file); - ipc_calls_.push_back(attribs); - ipc_calls_.push_back(full_attribs); - ipc_calls_.push_back(set_info); -} - -bool FilesystemDispatcher::SetupService(InterceptionManager* manager, - int service) { - switch (service) { - case IPC_NTCREATEFILE_TAG: - return INTERCEPT_NT(manager, NtCreateFile, CREATE_FILE_ID, 48); - - case IPC_NTOPENFILE_TAG: - return INTERCEPT_NT(manager, NtOpenFile, OPEN_FILE_ID, 28); - - case IPC_NTQUERYATTRIBUTESFILE_TAG: - return INTERCEPT_NT(manager, NtQueryAttributesFile, QUERY_ATTRIB_FILE_ID, - 12); - - case IPC_NTQUERYFULLATTRIBUTESFILE_TAG: - return INTERCEPT_NT(manager, NtQueryFullAttributesFile, - QUERY_FULL_ATTRIB_FILE_ID, 12); - - case IPC_NTSETINFO_RENAME_TAG: - return INTERCEPT_NT(manager, NtSetInformationFile, SET_INFO_FILE_ID, 24); - - default: - return false; - } -} - -bool FilesystemDispatcher::NtCreateFile(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - uint32_t desired_access, - uint32_t file_attributes, - uint32_t share_access, - uint32_t create_disposition, - uint32_t create_options) { - if (!PreProcessName(name)) { - // The path requested might contain a reparse point. - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - const wchar_t* filename = name->c_str(); - - uint32_t broker = TRUE; - CountedParameterSet<OpenFile> params; - params[OpenFile::NAME] = ParamPickerMake(filename); - params[OpenFile::ACCESS] = ParamPickerMake(desired_access); - params[OpenFile::DISPOSITION] = ParamPickerMake(create_disposition); - params[OpenFile::OPTIONS] = ParamPickerMake(create_options); - params[OpenFile::BROKER] = ParamPickerMake(broker); - - // To evaluate the policy we need to call back to the policy object. We - // are just middlemen in the operation since is the FileSystemPolicy which - // knows what to do. - EvalResult result = policy_base_->EvalPolicy(IPC_NTCREATEFILE_TAG, - params.GetBase()); - HANDLE handle; - ULONG_PTR io_information = 0; - NTSTATUS nt_status; - if (!FileSystemPolicy::CreateFileAction(result, *ipc->client_info, *name, - attributes, desired_access, - file_attributes, share_access, - create_disposition, create_options, - &handle, &nt_status, - &io_information)) { - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - // Return operation status on the IPC. - ipc->return_info.extended[0].ulong_ptr = io_information; - ipc->return_info.nt_status = nt_status; - ipc->return_info.handle = handle; - return true; -} - -bool FilesystemDispatcher::NtOpenFile(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - uint32_t desired_access, - uint32_t share_access, - uint32_t open_options) { - if (!PreProcessName(name)) { - // The path requested might contain a reparse point. - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - const wchar_t* filename = name->c_str(); - - uint32_t broker = TRUE; - uint32_t create_disposition = FILE_OPEN; - CountedParameterSet<OpenFile> params; - params[OpenFile::NAME] = ParamPickerMake(filename); - params[OpenFile::ACCESS] = ParamPickerMake(desired_access); - params[OpenFile::DISPOSITION] = ParamPickerMake(create_disposition); - params[OpenFile::OPTIONS] = ParamPickerMake(open_options); - params[OpenFile::BROKER] = ParamPickerMake(broker); - - // To evaluate the policy we need to call back to the policy object. We - // are just middlemen in the operation since is the FileSystemPolicy which - // knows what to do. - EvalResult result = policy_base_->EvalPolicy(IPC_NTOPENFILE_TAG, - params.GetBase()); - HANDLE handle; - ULONG_PTR io_information = 0; - NTSTATUS nt_status; - if (!FileSystemPolicy::OpenFileAction(result, *ipc->client_info, *name, - attributes, desired_access, - share_access, open_options, &handle, - &nt_status, &io_information)) { - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - // Return operation status on the IPC. - ipc->return_info.extended[0].ulong_ptr = io_information; - ipc->return_info.nt_status = nt_status; - ipc->return_info.handle = handle; - return true; -} - -bool FilesystemDispatcher::NtQueryAttributesFile(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - CountedBuffer* info) { - if (sizeof(FILE_BASIC_INFORMATION) != info->Size()) - return false; - - if (!PreProcessName(name)) { - // The path requested might contain a reparse point. - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - uint32_t broker = TRUE; - const wchar_t* filename = name->c_str(); - CountedParameterSet<FileName> params; - params[FileName::NAME] = ParamPickerMake(filename); - params[FileName::BROKER] = ParamPickerMake(broker); - - // To evaluate the policy we need to call back to the policy object. We - // are just middlemen in the operation since is the FileSystemPolicy which - // knows what to do. - EvalResult result = policy_base_->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG, - params.GetBase()); - - FILE_BASIC_INFORMATION* information = - reinterpret_cast<FILE_BASIC_INFORMATION*>(info->Buffer()); - NTSTATUS nt_status; - if (!FileSystemPolicy::QueryAttributesFileAction(result, *ipc->client_info, - *name, attributes, - information, &nt_status)) { - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - // Return operation status on the IPC. - ipc->return_info.nt_status = nt_status; - return true; -} - -bool FilesystemDispatcher::NtQueryFullAttributesFile(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - CountedBuffer* info) { - if (sizeof(FILE_NETWORK_OPEN_INFORMATION) != info->Size()) - return false; - - if (!PreProcessName(name)) { - // The path requested might contain a reparse point. - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - uint32_t broker = TRUE; - const wchar_t* filename = name->c_str(); - CountedParameterSet<FileName> params; - params[FileName::NAME] = ParamPickerMake(filename); - params[FileName::BROKER] = ParamPickerMake(broker); - - // To evaluate the policy we need to call back to the policy object. We - // are just middlemen in the operation since is the FileSystemPolicy which - // knows what to do. - EvalResult result = policy_base_->EvalPolicy( - IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase()); - - FILE_NETWORK_OPEN_INFORMATION* information = - reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION*>(info->Buffer()); - NTSTATUS nt_status; - if (!FileSystemPolicy::QueryFullAttributesFileAction(result, - *ipc->client_info, - *name, attributes, - information, - &nt_status)) { - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - // Return operation status on the IPC. - ipc->return_info.nt_status = nt_status; - return true; -} - -bool FilesystemDispatcher::NtSetInformationFile(IPCInfo* ipc, - HANDLE handle, - CountedBuffer* status, - CountedBuffer* info, - uint32_t length, - uint32_t info_class) { - if (sizeof(IO_STATUS_BLOCK) != status->Size()) - return false; - if (length != info->Size()) - return false; - - FILE_RENAME_INFORMATION* rename_info = - reinterpret_cast<FILE_RENAME_INFORMATION*>(info->Buffer()); - - if (!IsSupportedRenameCall(rename_info, length, info_class)) - return false; - - base::string16 name; - name.assign(rename_info->FileName, rename_info->FileNameLength / - sizeof(rename_info->FileName[0])); - if (!PreProcessName(&name)) { - // The path requested might contain a reparse point. - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - uint32_t broker = TRUE; - const wchar_t* filename = name.c_str(); - CountedParameterSet<FileName> params; - params[FileName::NAME] = ParamPickerMake(filename); - params[FileName::BROKER] = ParamPickerMake(broker); - - // To evaluate the policy we need to call back to the policy object. We - // are just middlemen in the operation since is the FileSystemPolicy which - // knows what to do. - EvalResult result = policy_base_->EvalPolicy(IPC_NTSETINFO_RENAME_TAG, - params.GetBase()); - - IO_STATUS_BLOCK* io_status = - reinterpret_cast<IO_STATUS_BLOCK*>(status->Buffer()); - NTSTATUS nt_status; - if (!FileSystemPolicy::SetInformationFileAction(result, *ipc->client_info, - handle, rename_info, length, - info_class, io_status, - &nt_status)) { - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - // Return operation status on the IPC. - ipc->return_info.nt_status = nt_status; - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.h deleted file mode 100644 index 61d918ed0..000000000 --- a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_FILESYSTEM_DISPATCHER_H__ -#define SANDBOX_SRC_FILESYSTEM_DISPATCHER_H__ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox_policy_base.h" - -namespace sandbox { - -// This class handles file system-related IPC calls. -class FilesystemDispatcher : public Dispatcher { - public: - explicit FilesystemDispatcher(PolicyBase* policy_base); - ~FilesystemDispatcher() override {} - - // Dispatcher interface. - bool SetupService(InterceptionManager* manager, int service) override; - - private: - // Processes IPC requests coming from calls to NtCreateFile in the target. - bool NtCreateFile(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - uint32_t desired_access, - uint32_t file_attributes, - uint32_t share_access, - uint32_t create_disposition, - uint32_t create_options); - - // Processes IPC requests coming from calls to NtOpenFile in the target. - bool NtOpenFile(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - uint32_t desired_access, - uint32_t share_access, - uint32_t create_options); - - // Processes IPC requests coming from calls to NtQueryAttributesFile in the - // target. - bool NtQueryAttributesFile(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - CountedBuffer* info); - - // Processes IPC requests coming from calls to NtQueryFullAttributesFile in - // the target. - bool NtQueryFullAttributesFile(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - CountedBuffer* info); - - // Processes IPC requests coming from calls to NtSetInformationFile with the - // rename information class. - bool NtSetInformationFile(IPCInfo* ipc, - HANDLE handle, - CountedBuffer* status, - CountedBuffer* info, - uint32_t length, - uint32_t info_class); - - PolicyBase* policy_base_; - DISALLOW_COPY_AND_ASSIGN(FilesystemDispatcher); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_FILESYSTEM_DISPATCHER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc deleted file mode 100644 index 1da2b43db..000000000 --- a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/filesystem_interception.h" - -#include <stdint.h> - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/policy_target.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/target_services.h" -#include "mozilla/sandboxing/sandboxLogging.h" - -namespace sandbox { - -NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile, - PHANDLE file, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, - PIO_STATUS_BLOCK io_status, - PLARGE_INTEGER allocation_size, - ULONG file_attributes, ULONG sharing, - ULONG disposition, ULONG options, - PVOID ea_buffer, ULONG ea_length) { - // Check if the process can open it first. - NTSTATUS status = orig_CreateFile(file, desired_access, object_attributes, - io_status, allocation_size, - file_attributes, sharing, disposition, - options, ea_buffer, ea_length); - if (STATUS_ACCESS_DENIED != status) - return status; - - mozilla::sandboxing::LogBlocked("NtCreateFile", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - wchar_t* name = NULL; - do { - if (!ValidParameter(file, sizeof(HANDLE), WRITE)) - break; - if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - uint32_t attributes = 0; - NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, - NULL); - if (!NT_SUCCESS(ret) || NULL == name) - break; - - uint32_t desired_access_uint32 = desired_access; - uint32_t options_uint32 = options; - uint32_t disposition_uint32 = disposition; - uint32_t broker = FALSE; - CountedParameterSet<OpenFile> params; - params[OpenFile::NAME] = ParamPickerMake(name); - params[OpenFile::ACCESS] = ParamPickerMake(desired_access_uint32); - params[OpenFile::DISPOSITION] = ParamPickerMake(disposition_uint32); - params[OpenFile::OPTIONS] = ParamPickerMake(options_uint32); - params[OpenFile::BROKER] = ParamPickerMake(broker); - - if (!QueryBroker(IPC_NTCREATEFILE_TAG, params.GetBase())) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - // The following call must match in the parameters with - // FilesystemDispatcher::ProcessNtCreateFile. - ResultCode code = CrossCall(ipc, IPC_NTCREATEFILE_TAG, name, attributes, - desired_access_uint32, file_attributes, sharing, - disposition, options_uint32, &answer); - if (SBOX_ALL_OK != code) - break; - - status = answer.nt_status; - - if (!NT_SUCCESS(answer.nt_status)) - break; - - __try { - *file = answer.handle; - io_status->Status = answer.nt_status; - io_status->Information = answer.extended[0].ulong_ptr; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - mozilla::sandboxing::LogAllowed("NtCreateFile", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } while (false); - - if (name) - operator delete(name, NT_ALLOC); - - return status; -} - -NTSTATUS WINAPI TargetNtOpenFile(NtOpenFileFunction orig_OpenFile, PHANDLE file, - ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, - PIO_STATUS_BLOCK io_status, ULONG sharing, - ULONG options) { - // Check if the process can open it first. - NTSTATUS status = orig_OpenFile(file, desired_access, object_attributes, - io_status, sharing, options); - if (STATUS_ACCESS_DENIED != status) - return status; - - mozilla::sandboxing::LogBlocked("NtOpenFile", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - wchar_t* name = NULL; - do { - if (!ValidParameter(file, sizeof(HANDLE), WRITE)) - break; - if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - uint32_t attributes; - NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, - NULL); - if (!NT_SUCCESS(ret) || NULL == name) - break; - - uint32_t desired_access_uint32 = desired_access; - uint32_t options_uint32 = options; - uint32_t disposition_uint32 = FILE_OPEN; - uint32_t broker = FALSE; - CountedParameterSet<OpenFile> params; - params[OpenFile::NAME] = ParamPickerMake(name); - params[OpenFile::ACCESS] = ParamPickerMake(desired_access_uint32); - params[OpenFile::DISPOSITION] = ParamPickerMake(disposition_uint32); - params[OpenFile::OPTIONS] = ParamPickerMake(options_uint32); - params[OpenFile::BROKER] = ParamPickerMake(broker); - - if (!QueryBroker(IPC_NTOPENFILE_TAG, params.GetBase())) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTOPENFILE_TAG, name, attributes, - desired_access_uint32, sharing, options_uint32, - &answer); - if (SBOX_ALL_OK != code) - break; - - status = answer.nt_status; - - if (!NT_SUCCESS(answer.nt_status)) - break; - - __try { - *file = answer.handle; - io_status->Status = answer.nt_status; - io_status->Information = answer.extended[0].ulong_ptr; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - mozilla::sandboxing::LogAllowed("NtOpenFile", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } while (false); - - if (name) - operator delete(name, NT_ALLOC); - - return status; -} - -NTSTATUS WINAPI TargetNtQueryAttributesFile( - NtQueryAttributesFileFunction orig_QueryAttributes, - POBJECT_ATTRIBUTES object_attributes, - PFILE_BASIC_INFORMATION file_attributes) { - // Check if the process can query it first. - NTSTATUS status = orig_QueryAttributes(object_attributes, file_attributes); - if (STATUS_ACCESS_DENIED != status) - return status; - - mozilla::sandboxing::LogBlocked("NtQueryAttributesFile", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - wchar_t* name = NULL; - do { - if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - uint32_t attributes = 0; - NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, - NULL); - if (!NT_SUCCESS(ret) || NULL == name) - break; - - InOutCountedBuffer file_info(file_attributes, - sizeof(FILE_BASIC_INFORMATION)); - - uint32_t broker = FALSE; - CountedParameterSet<FileName> params; - params[FileName::NAME] = ParamPickerMake(name); - params[FileName::BROKER] = ParamPickerMake(broker); - - if (!QueryBroker(IPC_NTQUERYATTRIBUTESFILE_TAG, params.GetBase())) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTQUERYATTRIBUTESFILE_TAG, name, - attributes, file_info, &answer); - - if (SBOX_ALL_OK != code) - break; - - status = answer.nt_status; - - mozilla::sandboxing::LogAllowed("NtQueryAttributesFile", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } while (false); - - if (name) - operator delete(name, NT_ALLOC); - - return status; -} - -NTSTATUS WINAPI TargetNtQueryFullAttributesFile( - NtQueryFullAttributesFileFunction orig_QueryFullAttributes, - POBJECT_ATTRIBUTES object_attributes, - PFILE_NETWORK_OPEN_INFORMATION file_attributes) { - // Check if the process can query it first. - NTSTATUS status = orig_QueryFullAttributes(object_attributes, - file_attributes); - if (STATUS_ACCESS_DENIED != status) - return status; - - mozilla::sandboxing::LogBlocked("NtQueryFullAttributesFile", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - wchar_t* name = NULL; - do { - if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION), - WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - uint32_t attributes = 0; - NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, - NULL); - if (!NT_SUCCESS(ret) || NULL == name) - break; - - InOutCountedBuffer file_info(file_attributes, - sizeof(FILE_NETWORK_OPEN_INFORMATION)); - - uint32_t broker = FALSE; - CountedParameterSet<FileName> params; - params[FileName::NAME] = ParamPickerMake(name); - params[FileName::BROKER] = ParamPickerMake(broker); - - if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase())) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG, name, - attributes, file_info, &answer); - - if (SBOX_ALL_OK != code) - break; - - status = answer.nt_status; - - mozilla::sandboxing::LogAllowed("NtQueryFullAttributesFile", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } while (false); - - if (name) - operator delete(name, NT_ALLOC); - - return status; -} - -NTSTATUS WINAPI TargetNtSetInformationFile( - NtSetInformationFileFunction orig_SetInformationFile, HANDLE file, - PIO_STATUS_BLOCK io_status, PVOID file_info, ULONG length, - FILE_INFORMATION_CLASS file_info_class) { - // Check if the process can open it first. - NTSTATUS status = orig_SetInformationFile(file, io_status, file_info, length, - file_info_class); - if (STATUS_ACCESS_DENIED != status) - return status; - - mozilla::sandboxing::LogBlocked("NtSetInformationFile"); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - wchar_t* name = NULL; - do { - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) - break; - - if (!ValidParameter(file_info, length, READ)) - break; - - FILE_RENAME_INFORMATION* file_rename_info = - reinterpret_cast<FILE_RENAME_INFORMATION*>(file_info); - OBJECT_ATTRIBUTES object_attributes; - UNICODE_STRING object_name; - InitializeObjectAttributes(&object_attributes, &object_name, 0, NULL, NULL); - - __try { - if (!IsSupportedRenameCall(file_rename_info, length, file_info_class)) - break; - - object_attributes.RootDirectory = file_rename_info->RootDirectory; - object_name.Buffer = file_rename_info->FileName; - object_name.Length = object_name.MaximumLength = - static_cast<USHORT>(file_rename_info->FileNameLength); - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - - NTSTATUS ret = AllocAndCopyName(&object_attributes, &name, NULL, NULL); - if (!NT_SUCCESS(ret) || !name) - break; - - uint32_t broker = FALSE; - CountedParameterSet<FileName> params; - params[FileName::NAME] = ParamPickerMake(name); - params[FileName::BROKER] = ParamPickerMake(broker); - - if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG, params.GetBase())) - break; - - InOutCountedBuffer io_status_buffer(io_status, sizeof(IO_STATUS_BLOCK)); - // This is actually not an InOut buffer, only In, but using InOut facility - // really helps to simplify the code. - InOutCountedBuffer file_info_buffer(file_info, length); - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTSETINFO_RENAME_TAG, file, - io_status_buffer, file_info_buffer, length, - file_info_class, &answer); - - if (SBOX_ALL_OK != code) - break; - - status = answer.nt_status; - mozilla::sandboxing::LogAllowed("NtSetInformationFile"); - } while (false); - - if (name) - operator delete(name, NT_ALLOC); - - return status; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.h b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.h deleted file mode 100644 index 2fafb4499..000000000 --- a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_FILESYSTEM_INTERCEPTION_H__ -#define SANDBOX_SRC_FILESYSTEM_INTERCEPTION_H__ - -namespace sandbox { - -extern "C" { - -// Interception of NtCreateFile on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateFile( - NtCreateFileFunction orig_CreateFile, PHANDLE file, - ACCESS_MASK desired_access, POBJECT_ATTRIBUTES object_attributes, - PIO_STATUS_BLOCK io_status, PLARGE_INTEGER allocation_size, - ULONG file_attributes, ULONG sharing, ULONG disposition, ULONG options, - PVOID ea_buffer, ULONG ea_length); - -// Interception of NtOpenFile on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenFile( - NtOpenFileFunction orig_OpenFile, PHANDLE file, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PIO_STATUS_BLOCK io_status, - ULONG sharing, ULONG options); - -// Interception of NtQueryAtttributesFile on the child process. -// It should never be called directly. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtQueryAttributesFile( - NtQueryAttributesFileFunction orig_QueryAttributes, - POBJECT_ATTRIBUTES object_attributes, - PFILE_BASIC_INFORMATION file_attributes); - -// Interception of NtQueryFullAtttributesFile on the child process. -// It should never be called directly. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtQueryFullAttributesFile( - NtQueryFullAttributesFileFunction orig_QueryAttributes, - POBJECT_ATTRIBUTES object_attributes, - PFILE_NETWORK_OPEN_INFORMATION file_attributes); - -// Interception of NtSetInformationFile on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationFile( - NtSetInformationFileFunction orig_SetInformationFile, HANDLE file, - PIO_STATUS_BLOCK io_status, PVOID file_information, ULONG length, - FILE_INFORMATION_CLASS file_information_class); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_FILESYSTEM_INTERCEPTION_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc deleted file mode 100644 index fe7f62fc2..000000000 --- a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc +++ /dev/null @@ -1,435 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include <string> - -#include "sandbox/win/src/filesystem_policy.h" - -#include "base/logging.h" -#include "base/macros.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sandbox_utils.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -NTSTATUS NtCreateFileInTarget(HANDLE* target_file_handle, - ACCESS_MASK desired_access, - OBJECT_ATTRIBUTES* obj_attributes, - IO_STATUS_BLOCK* io_status_block, - ULONG file_attributes, - ULONG share_access, - ULONG create_disposition, - ULONG create_options, - PVOID ea_buffer, - ULONG ea_lenght, - HANDLE target_process) { - NtCreateFileFunction NtCreateFile = NULL; - ResolveNTFunctionPtr("NtCreateFile", &NtCreateFile); - - HANDLE local_handle = INVALID_HANDLE_VALUE; - NTSTATUS status = NtCreateFile(&local_handle, desired_access, obj_attributes, - io_status_block, NULL, file_attributes, - share_access, create_disposition, - create_options, ea_buffer, ea_lenght); - if (!NT_SUCCESS(status)) { - return status; - } - - if (!sandbox::SameObject(local_handle, obj_attributes->ObjectName->Buffer)) { - // The handle points somewhere else. Fail the operation. - ::CloseHandle(local_handle); - return STATUS_ACCESS_DENIED; - } - - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - target_process, target_file_handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - return STATUS_SUCCESS; -} - -// Get an initialized anonymous level Security QOS. -SECURITY_QUALITY_OF_SERVICE GetAnonymousQOS() { - SECURITY_QUALITY_OF_SERVICE security_qos = {0}; - security_qos.Length = sizeof(security_qos); - security_qos.ImpersonationLevel = SecurityAnonymous; - // Set dynamic tracking so that a pipe doesn't capture the broker's token - security_qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; - security_qos.EffectiveOnly = TRUE; - - return security_qos; -} - -} // namespace. - -namespace sandbox { - -bool FileSystemPolicy::GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy) { - base::string16 mod_name(name); - if (mod_name.empty()) { - return false; - } - - if (!PreProcessName(&mod_name)) { - // The path to be added might contain a reparse point. - NOTREACHED(); - return false; - } - - // TODO(cpu) bug 32224: This prefix add is a hack because we don't have the - // infrastructure to normalize names. In any case we need to escape the - // question marks. - if (_wcsnicmp(mod_name.c_str(), kNTDevicePrefix, kNTDevicePrefixLen)) { - mod_name = FixNTPrefixForMatch(mod_name); - name = mod_name.c_str(); - } - - EvalResult result = ASK_BROKER; - - // List of supported calls for the filesystem. - const unsigned kCallNtCreateFile = 0x1; - const unsigned kCallNtOpenFile = 0x2; - const unsigned kCallNtQueryAttributesFile = 0x4; - const unsigned kCallNtQueryFullAttributesFile = 0x8; - const unsigned kCallNtSetInfoRename = 0x10; - - DWORD rule_to_add = kCallNtOpenFile | kCallNtCreateFile | - kCallNtQueryAttributesFile | - kCallNtQueryFullAttributesFile | kCallNtSetInfoRename; - - PolicyRule create(result); - PolicyRule open(result); - PolicyRule query(result); - PolicyRule query_full(result); - PolicyRule rename(result); - - switch (semantics) { - case TargetPolicy::FILES_ALLOW_DIR_ANY: { - open.AddNumberMatch(IF, OpenFile::OPTIONS, FILE_DIRECTORY_FILE, AND); - create.AddNumberMatch(IF, OpenFile::OPTIONS, FILE_DIRECTORY_FILE, AND); - break; - } - case TargetPolicy::FILES_ALLOW_READONLY: { - // We consider all flags that are not known to be readonly as potentially - // used for write. - DWORD allowed_flags = FILE_READ_DATA | FILE_READ_ATTRIBUTES | - FILE_READ_EA | SYNCHRONIZE | FILE_EXECUTE | - GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL; - DWORD restricted_flags = ~allowed_flags; - open.AddNumberMatch(IF_NOT, OpenFile::ACCESS, restricted_flags, AND); - open.AddNumberMatch(IF, OpenFile::DISPOSITION, FILE_OPEN, EQUAL); - create.AddNumberMatch(IF_NOT, OpenFile::ACCESS, restricted_flags, AND); - create.AddNumberMatch(IF, OpenFile::DISPOSITION, FILE_OPEN, EQUAL); - - // Read only access don't work for rename. - rule_to_add &= ~kCallNtSetInfoRename; - break; - } - case TargetPolicy::FILES_ALLOW_QUERY: { - // Here we don't want to add policy for the open or the create. - rule_to_add &= ~(kCallNtOpenFile | kCallNtCreateFile | - kCallNtSetInfoRename); - break; - } - case TargetPolicy::FILES_ALLOW_ANY: { - break; - } - default: { - NOTREACHED(); - return false; - } - } - - if ((rule_to_add & kCallNtCreateFile) && - (!create.AddStringMatch(IF, OpenFile::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTCREATEFILE_TAG, &create))) { - return false; - } - - if ((rule_to_add & kCallNtOpenFile) && - (!open.AddStringMatch(IF, OpenFile::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTOPENFILE_TAG, &open))) { - return false; - } - - if ((rule_to_add & kCallNtQueryAttributesFile) && - (!query.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTQUERYATTRIBUTESFILE_TAG, &query))) { - return false; - } - - if ((rule_to_add & kCallNtQueryFullAttributesFile) && - (!query_full.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) - || !policy->AddRule(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, - &query_full))) { - return false; - } - - if ((rule_to_add & kCallNtSetInfoRename) && - (!rename.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTSETINFO_RENAME_TAG, &rename))) { - return false; - } - - return true; -} - -// Right now we insert two rules, to be evaluated before any user supplied rule: -// - go to the broker if the path doesn't look like the paths that we push on -// the policy (namely \??\something). -// - go to the broker if it looks like this is a short-name path. -// -// It is possible to add a rule to go to the broker in any case; it would look -// something like: -// rule = new PolicyRule(ASK_BROKER); -// rule->AddNumberMatch(IF_NOT, FileName::BROKER, TRUE, AND); -// policy->AddRule(service, rule); -bool FileSystemPolicy::SetInitialRules(LowLevelPolicy* policy) { - PolicyRule format(ASK_BROKER); - PolicyRule short_name(ASK_BROKER); - - bool rv = format.AddNumberMatch(IF_NOT, FileName::BROKER, TRUE, AND); - rv &= format.AddStringMatch(IF_NOT, FileName::NAME, L"\\/?/?\\*", - CASE_SENSITIVE); - - rv &= short_name.AddNumberMatch(IF_NOT, FileName::BROKER, TRUE, AND); - rv &= short_name.AddStringMatch(IF, FileName::NAME, L"*~*", CASE_SENSITIVE); - - if (!rv || !policy->AddRule(IPC_NTCREATEFILE_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTCREATEFILE_TAG, &short_name)) - return false; - - if (!policy->AddRule(IPC_NTOPENFILE_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTOPENFILE_TAG, &short_name)) - return false; - - if (!policy->AddRule(IPC_NTQUERYATTRIBUTESFILE_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTQUERYATTRIBUTESFILE_TAG, &short_name)) - return false; - - if (!policy->AddRule(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, &short_name)) - return false; - - if (!policy->AddRule(IPC_NTSETINFO_RENAME_TAG, &format)) - return false; - - if (!policy->AddRule(IPC_NTSETINFO_RENAME_TAG, &short_name)) - return false; - - return true; -} - -bool FileSystemPolicy::CreateFileAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& file, - uint32_t attributes, - uint32_t desired_access, - uint32_t file_attributes, - uint32_t share_access, - uint32_t create_disposition, - uint32_t create_options, - HANDLE* handle, - NTSTATUS* nt_status, - ULONG_PTR* io_information) { - // The only action supported is ASK_BROKER which means create the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return false; - } - IO_STATUS_BLOCK io_block = {}; - UNICODE_STRING uni_name = {}; - OBJECT_ATTRIBUTES obj_attributes = {}; - SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS(); - - InitObjectAttribs(file, attributes, NULL, &obj_attributes, - &uni_name, IsPipe(file) ? &security_qos : NULL); - *nt_status = NtCreateFileInTarget(handle, desired_access, &obj_attributes, - &io_block, file_attributes, share_access, - create_disposition, create_options, NULL, - 0, client_info.process); - - *io_information = io_block.Information; - return true; -} - -bool FileSystemPolicy::OpenFileAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& file, - uint32_t attributes, - uint32_t desired_access, - uint32_t share_access, - uint32_t open_options, - HANDLE* handle, - NTSTATUS* nt_status, - ULONG_PTR* io_information) { - // The only action supported is ASK_BROKER which means open the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - // An NtOpen is equivalent to an NtCreate with FileAttributes = 0 and - // CreateDisposition = FILE_OPEN. - IO_STATUS_BLOCK io_block = {}; - UNICODE_STRING uni_name = {}; - OBJECT_ATTRIBUTES obj_attributes = {}; - SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS(); - - InitObjectAttribs(file, attributes, NULL, &obj_attributes, - &uni_name, IsPipe(file) ? &security_qos : NULL); - *nt_status = NtCreateFileInTarget(handle, desired_access, &obj_attributes, - &io_block, 0, share_access, FILE_OPEN, - open_options, NULL, 0, - client_info.process); - - *io_information = io_block.Information; - return true; -} - -bool FileSystemPolicy::QueryAttributesFileAction( - EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& file, - uint32_t attributes, - FILE_BASIC_INFORMATION* file_info, - NTSTATUS* nt_status) { - // The only action supported is ASK_BROKER which means query the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - NtQueryAttributesFileFunction NtQueryAttributesFile = NULL; - ResolveNTFunctionPtr("NtQueryAttributesFile", &NtQueryAttributesFile); - - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS(); - - InitObjectAttribs(file, attributes, NULL, &obj_attributes, - &uni_name, IsPipe(file) ? &security_qos : NULL); - *nt_status = NtQueryAttributesFile(&obj_attributes, file_info); - - return true; -} - -bool FileSystemPolicy::QueryFullAttributesFileAction( - EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& file, - uint32_t attributes, - FILE_NETWORK_OPEN_INFORMATION* file_info, - NTSTATUS* nt_status) { - // The only action supported is ASK_BROKER which means query the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - NtQueryFullAttributesFileFunction NtQueryFullAttributesFile = NULL; - ResolveNTFunctionPtr("NtQueryFullAttributesFile", &NtQueryFullAttributesFile); - - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS(); - - InitObjectAttribs(file, attributes, NULL, &obj_attributes, - &uni_name, IsPipe(file) ? &security_qos : NULL); - *nt_status = NtQueryFullAttributesFile(&obj_attributes, file_info); - - return true; -} - -bool FileSystemPolicy::SetInformationFileAction(EvalResult eval_result, - const ClientInfo& client_info, - HANDLE target_file_handle, - void* file_info, - uint32_t length, - uint32_t info_class, - IO_STATUS_BLOCK* io_block, - NTSTATUS* nt_status) { - // The only action supported is ASK_BROKER which means open the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - NtSetInformationFileFunction NtSetInformationFile = NULL; - ResolveNTFunctionPtr("NtSetInformationFile", &NtSetInformationFile); - - HANDLE local_handle = NULL; - if (!::DuplicateHandle(client_info.process, target_file_handle, - ::GetCurrentProcess(), &local_handle, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - base::win::ScopedHandle handle(local_handle); - - FILE_INFORMATION_CLASS file_info_class = - static_cast<FILE_INFORMATION_CLASS>(info_class); - *nt_status = NtSetInformationFile(local_handle, io_block, file_info, length, - file_info_class); - - return true; -} - -bool PreProcessName(base::string16* path) { - ConvertToLongPath(path); - - if (ERROR_NOT_A_REPARSE_POINT == IsReparsePoint(*path)) - return true; - - // We can't process a reparsed file. - return false; -} - -base::string16 FixNTPrefixForMatch(const base::string16& name) { - base::string16 mod_name = name; - - // NT prefix escaped for rule matcher - const wchar_t kNTPrefixEscaped[] = L"\\/?/?\\"; - const int kNTPrefixEscapedLen = arraysize(kNTPrefixEscaped) - 1; - - if (0 != mod_name.compare(0, kNTPrefixLen, kNTPrefix)) { - if (0 != mod_name.compare(0, kNTPrefixEscapedLen, kNTPrefixEscaped)) { - // TODO(nsylvain): Find a better way to do name resolution. Right now we - // take the name and we expand it. - mod_name.insert(0, kNTPrefixEscaped); - } - } else { - // Start of name matches NT prefix, replace with escaped format - // Fixes bug: 334882 - mod_name.replace(0, kNTPrefixLen, kNTPrefixEscaped); - } - - return mod_name; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.h b/security/sandbox/chromium/sandbox/win/src/filesystem_policy.h deleted file mode 100644 index c2ee160d5..000000000 --- a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_FILESYSTEM_POLICY_H__ -#define SANDBOX_SRC_FILESYSTEM_POLICY_H__ - -#include <stdint.h> - -#include <string> - -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/sandbox_policy.h" - -namespace sandbox { - -enum EvalResult; - -// This class centralizes most of the knowledge related to file system policy -class FileSystemPolicy { - public: - // Creates the required low-level policy rules to evaluate a high-level - // policy rule for File IO, in particular open or create actions. - // 'name' is the file or directory name. - // 'semantics' is the desired semantics for the open or create. - // 'policy' is the policy generator to which the rules are going to be added. - static bool GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy); - - // Add basic file system rules. - static bool SetInitialRules(LowLevelPolicy* policy); - - // Performs the desired policy action on a create request with an - // API that is compatible with the IPC-received parameters. - // 'client_info' : the target process that is making the request. - // 'eval_result' : The desired policy action to accomplish. - // 'file' : The target file or directory. - static bool CreateFileAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& file, - uint32_t attributes, - uint32_t desired_access, - uint32_t file_attributes, - uint32_t share_access, - uint32_t create_disposition, - uint32_t create_options, - HANDLE* handle, - NTSTATUS* nt_status, - ULONG_PTR* io_information); - - // Performs the desired policy action on an open request with an - // API that is compatible with the IPC-received parameters. - // 'client_info' : the target process that is making the request. - // 'eval_result' : The desired policy action to accomplish. - // 'file' : The target file or directory. - static bool OpenFileAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& file, - uint32_t attributes, - uint32_t desired_access, - uint32_t share_access, - uint32_t open_options, - HANDLE* handle, - NTSTATUS* nt_status, - ULONG_PTR* io_information); - - // Performs the desired policy action on a query request with an - // API that is compatible with the IPC-received parameters. - static bool QueryAttributesFileAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& file, - uint32_t attributes, - FILE_BASIC_INFORMATION* file_info, - NTSTATUS* nt_status); - - // Performs the desired policy action on a query request with an - // API that is compatible with the IPC-received parameters. - static bool QueryFullAttributesFileAction( - EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& file, - uint32_t attributes, - FILE_NETWORK_OPEN_INFORMATION* file_info, - NTSTATUS* nt_status); - - // Performs the desired policy action on a set_info request with an - // API that is compatible with the IPC-received parameters. - static bool SetInformationFileAction(EvalResult eval_result, - const ClientInfo& client_info, - HANDLE target_file_handle, - void* file_info, - uint32_t length, - uint32_t info_class, - IO_STATUS_BLOCK* io_block, - NTSTATUS* nt_status); -}; - -// Expands the path and check if it's a reparse point. Returns false if the path -// cannot be trusted. -bool PreProcessName(base::string16* path); - -// Corrects global paths to have a correctly escaped NT prefix at the -// beginning. If the name has no NT prefix (either normal or escaped) -// add the escaped form to the string -base::string16 FixNTPrefixForMatch(const base::string16& name); - -} // namespace sandbox - -#endif // SANDBOX_SRC_FILESYSTEM_POLICY_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/handle_closer.cc b/security/sandbox/chromium/sandbox/win/src/handle_closer.cc deleted file mode 100644 index f2012b7e0..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_closer.cc +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/handle_closer.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/process_thread_interception.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -template<typename T> T RoundUpToWordSize(T v) { - if (size_t mod = v % sizeof(size_t)) - v += sizeof(size_t) - mod; - return v; -} - -template<typename T> T* RoundUpToWordSize(T* v) { - return reinterpret_cast<T*>(RoundUpToWordSize(reinterpret_cast<size_t>(v))); -} - -} // namespace - -namespace sandbox { - -// Memory buffer mapped from the parent, with the list of handles. -SANDBOX_INTERCEPT HandleCloserInfo* g_handles_to_close; - -HandleCloser::HandleCloser() { -} - -HandleCloser::~HandleCloser() { -} - -ResultCode HandleCloser::AddHandle(const base::char16* handle_type, - const base::char16* handle_name) { - if (!handle_type) - return SBOX_ERROR_BAD_PARAMS; - - base::string16 resolved_name; - if (handle_name) { - resolved_name = handle_name; - if (handle_type == base::string16(L"Key")) - if (!ResolveRegistryName(resolved_name, &resolved_name)) - return SBOX_ERROR_BAD_PARAMS; - } - - HandleMap::iterator names = handles_to_close_.find(handle_type); - if (names == handles_to_close_.end()) { // We have no entries for this type. - std::pair<HandleMap::iterator, bool> result = handles_to_close_.insert( - HandleMap::value_type(handle_type, HandleMap::mapped_type())); - names = result.first; - if (handle_name) - names->second.insert(resolved_name); - } else if (!handle_name) { // Now we need to close all handles of this type. - names->second.clear(); - } else if (!names->second.empty()) { // Add another name for this type. - names->second.insert(resolved_name); - } // If we're already closing all handles of type then we're done. - - return SBOX_ALL_OK; -} - -size_t HandleCloser::GetBufferSize() { - size_t bytes_total = offsetof(HandleCloserInfo, handle_entries); - - for (HandleMap::iterator i = handles_to_close_.begin(); - i != handles_to_close_.end(); ++i) { - size_t bytes_entry = offsetof(HandleListEntry, handle_type) + - (i->first.size() + 1) * sizeof(base::char16); - for (HandleMap::mapped_type::iterator j = i->second.begin(); - j != i->second.end(); ++j) { - bytes_entry += ((*j).size() + 1) * sizeof(base::char16); - } - - // Round up to the nearest multiple of word size. - bytes_entry = RoundUpToWordSize(bytes_entry); - bytes_total += bytes_entry; - } - - return bytes_total; -} - -bool HandleCloser::InitializeTargetHandles(TargetProcess* target) { - // Do nothing on an empty list (global pointer already initialized to NULL). - if (handles_to_close_.empty()) - return true; - - size_t bytes_needed = GetBufferSize(); - scoped_ptr<size_t[]> local_buffer( - new size_t[bytes_needed / sizeof(size_t)]); - - if (!SetupHandleList(local_buffer.get(), bytes_needed)) - return false; - - HANDLE child = target->Process(); - - // Allocate memory in the target process without specifying the address - void* remote_data = ::VirtualAllocEx(child, NULL, bytes_needed, - MEM_COMMIT, PAGE_READWRITE); - if (NULL == remote_data) - return false; - - // Copy the handle buffer over. - SIZE_T bytes_written; - BOOL result = ::WriteProcessMemory(child, remote_data, local_buffer.get(), - bytes_needed, &bytes_written); - if (!result || bytes_written != bytes_needed) { - ::VirtualFreeEx(child, remote_data, 0, MEM_RELEASE); - return false; - } - - g_handles_to_close = reinterpret_cast<HandleCloserInfo*>(remote_data); - - ResultCode rc = target->TransferVariable("g_handles_to_close", - &g_handles_to_close, - sizeof(g_handles_to_close)); - - return (SBOX_ALL_OK == rc); -} - -bool HandleCloser::SetupHandleList(void* buffer, size_t buffer_bytes) { - ::ZeroMemory(buffer, buffer_bytes); - HandleCloserInfo* handle_info = reinterpret_cast<HandleCloserInfo*>(buffer); - handle_info->record_bytes = buffer_bytes; - handle_info->num_handle_types = handles_to_close_.size(); - - base::char16* output = reinterpret_cast<base::char16*>( - &handle_info->handle_entries[0]); - base::char16* end = reinterpret_cast<base::char16*>( - reinterpret_cast<char*>(buffer) + buffer_bytes); - for (HandleMap::iterator i = handles_to_close_.begin(); - i != handles_to_close_.end(); ++i) { - if (output >= end) - return false; - HandleListEntry* list_entry = reinterpret_cast<HandleListEntry*>(output); - output = &list_entry->handle_type[0]; - - // Copy the typename and set the offset and count. - i->first._Copy_s(output, i->first.size(), i->first.size()); - *(output += i->first.size()) = L'\0'; - output++; - list_entry->offset_to_names = reinterpret_cast<char*>(output) - - reinterpret_cast<char*>(list_entry); - list_entry->name_count = i->second.size(); - - // Copy the handle names. - for (HandleMap::mapped_type::iterator j = i->second.begin(); - j != i->second.end(); ++j) { - output = std::copy((*j).begin(), (*j).end(), output) + 1; - } - - // Round up to the nearest multiple of sizeof(size_t). - output = RoundUpToWordSize(output); - list_entry->record_bytes = reinterpret_cast<char*>(output) - - reinterpret_cast<char*>(list_entry); - } - - DCHECK_EQ(reinterpret_cast<size_t>(output), reinterpret_cast<size_t>(end)); - return output <= end; -} - -bool GetHandleName(HANDLE handle, base::string16* handle_name) { - static NtQueryObject QueryObject = NULL; - if (!QueryObject) - ResolveNTFunctionPtr("NtQueryObject", &QueryObject); - - ULONG size = MAX_PATH; - scoped_ptr<UNICODE_STRING, base::FreeDeleter> name; - NTSTATUS result; - - do { - name.reset(static_cast<UNICODE_STRING*>(malloc(size))); - DCHECK(name.get()); - result = QueryObject(handle, ObjectNameInformation, name.get(), - size, &size); - } while (result == STATUS_INFO_LENGTH_MISMATCH || - result == STATUS_BUFFER_OVERFLOW); - - if (NT_SUCCESS(result) && name->Buffer && name->Length) - handle_name->assign(name->Buffer, name->Length / sizeof(wchar_t)); - else - handle_name->clear(); - - return NT_SUCCESS(result); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/handle_closer.h b/security/sandbox/chromium/sandbox/win/src/handle_closer.h deleted file mode 100644 index 9592230a0..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_closer.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_HANDLE_CLOSER_H_ -#define SANDBOX_SRC_HANDLE_CLOSER_H_ - -#include <stddef.h> - -#include <map> -#include <set> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/target_process.h" - -namespace sandbox { - -// This is a map of handle-types to names that we need to close in the -// target process. A null set means we need to close all handles of the -// given type. -typedef std::map<const base::string16, std::set<base::string16> > HandleMap; - -// Type and set of corresponding handle names to close. -struct HandleListEntry { - size_t record_bytes; // Rounded to sizeof(size_t) bytes. - size_t offset_to_names; // Nul terminated strings of name_count names. - size_t name_count; - base::char16 handle_type[1]; -}; - -// Global parameters and a pointer to the list of entries. -struct HandleCloserInfo { - size_t record_bytes; // Rounded to sizeof(size_t) bytes. - size_t num_handle_types; - struct HandleListEntry handle_entries[1]; -}; - -SANDBOX_INTERCEPT HandleCloserInfo* g_handle_closer_info; - -// Adds handles to close after lockdown. -class HandleCloser { - public: - HandleCloser(); - ~HandleCloser(); - - // Adds a handle that will be closed in the target process after lockdown. - // A NULL value for handle_name indicates all handles of the specified type. - // An empty string for handle_name indicates the handle is unnamed. - ResultCode AddHandle(const base::char16* handle_type, - const base::char16* handle_name); - - // Serializes and copies the closer table into the target process. - bool InitializeTargetHandles(TargetProcess* target); - - private: - // Calculates the memory needed to copy the serialized handles list (rounded - // to the nearest machine-word size). - size_t GetBufferSize(); - - // Serializes the handle list into the target process. - bool SetupHandleList(void* buffer, size_t buffer_bytes); - - HandleMap handles_to_close_; - - DISALLOW_COPY_AND_ASSIGN(HandleCloser); -}; - -// Returns the object manager's name associated with a handle -bool GetHandleName(HANDLE handle, base::string16* handle_name); - -} // namespace sandbox - -#endif // SANDBOX_SRC_HANDLE_CLOSER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/handle_closer_agent.cc b/security/sandbox/chromium/sandbox/win/src/handle_closer_agent.cc deleted file mode 100644 index 6b17f6547..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_closer_agent.cc +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/handle_closer_agent.h" - -#include <limits.h> -#include <stddef.h> - -#include "base/logging.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -// Returns type infomation for an NT object. This routine is expected to be -// called for invalid handles so it catches STATUS_INVALID_HANDLE exceptions -// that can be generated when handle tracing is enabled. -NTSTATUS QueryObjectTypeInformation(HANDLE handle, - void* buffer, - ULONG* size) { - static NtQueryObject QueryObject = NULL; - if (!QueryObject) - ResolveNTFunctionPtr("NtQueryObject", &QueryObject); - - NTSTATUS status = STATUS_UNSUCCESSFUL; - __try { - status = QueryObject(handle, ObjectTypeInformation, buffer, *size, size); - } __except(GetExceptionCode() == STATUS_INVALID_HANDLE ? - EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { - status = STATUS_INVALID_HANDLE; - } - return status; -} - -} // namespace - -namespace sandbox { - -// Memory buffer mapped from the parent, with the list of handles. -SANDBOX_INTERCEPT HandleCloserInfo* g_handles_to_close = NULL; - -bool HandleCloserAgent::NeedsHandlesClosed() { - return g_handles_to_close != NULL; -} - -HandleCloserAgent::HandleCloserAgent() - : dummy_handle_(::CreateEvent(NULL, FALSE, FALSE, NULL)) { -} - -HandleCloserAgent::~HandleCloserAgent() { -} - -// Attempts to stuff |closed_handle| with a duplicated handle for a dummy Event -// with no access. This should allow the handle to be closed, to avoid -// generating EXCEPTION_INVALID_HANDLE on shutdown, but nothing else. For now -// the only supported |type| is Event or File. -bool HandleCloserAgent::AttemptToStuffHandleSlot(HANDLE closed_handle, - const base::string16& type) { - // Only attempt to stuff Files and Events at the moment. - if (type != L"Event" && type != L"File") { - return true; - } - - if (!dummy_handle_.IsValid()) - return false; - - // This should never happen, as g_dummy is created before closing to_stuff. - DCHECK(dummy_handle_.Get() != closed_handle); - - std::vector<HANDLE> to_close; - HANDLE dup_dummy = NULL; - size_t count = 16; - - do { - if (!::DuplicateHandle(::GetCurrentProcess(), dummy_handle_.Get(), - ::GetCurrentProcess(), &dup_dummy, 0, FALSE, 0)) - break; - if (dup_dummy != closed_handle) - to_close.push_back(dup_dummy); - } while (count-- && - reinterpret_cast<uintptr_t>(dup_dummy) < - reinterpret_cast<uintptr_t>(closed_handle)); - - for (auto h : to_close) - ::CloseHandle(h); - - // Useful to know when we're not able to stuff handles. - DCHECK(dup_dummy == closed_handle); - - return dup_dummy == closed_handle; -} - -// Reads g_handles_to_close and creates the lookup map. -void HandleCloserAgent::InitializeHandlesToClose(bool* is_csrss_connected) { - CHECK(g_handles_to_close != NULL); - - // Default to connected state - *is_csrss_connected = true; - - // Grab the header. - HandleListEntry* entry = g_handles_to_close->handle_entries; - for (size_t i = 0; i < g_handles_to_close->num_handle_types; ++i) { - // Set the type name. - base::char16* input = entry->handle_type; - if (!wcscmp(input, L"ALPC Port")) { - *is_csrss_connected = false; - } - HandleMap::mapped_type& handle_names = handles_to_close_[input]; - input = reinterpret_cast<base::char16*>(reinterpret_cast<char*>(entry) - + entry->offset_to_names); - // Grab all the handle names. - for (size_t j = 0; j < entry->name_count; ++j) { - std::pair<HandleMap::mapped_type::iterator, bool> name - = handle_names.insert(input); - CHECK(name.second); - input += name.first->size() + 1; - } - - // Move on to the next entry. - entry = reinterpret_cast<HandleListEntry*>(reinterpret_cast<char*>(entry) - + entry->record_bytes); - - DCHECK(reinterpret_cast<base::char16*>(entry) >= input); - DCHECK(reinterpret_cast<base::char16*>(entry) - input < - static_cast<ptrdiff_t>(sizeof(size_t) / sizeof(base::char16))); - } - - // Clean up the memory we copied over. - ::VirtualFree(g_handles_to_close, 0, MEM_RELEASE); - g_handles_to_close = NULL; -} - -bool HandleCloserAgent::CloseHandles() { - DWORD handle_count = UINT_MAX; - const int kInvalidHandleThreshold = 100; - const size_t kHandleOffset = 4; // Handles are always a multiple of 4. - - if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count)) - return false; - - // Set up buffers for the type info and the name. - std::vector<BYTE> type_info_buffer(sizeof(OBJECT_TYPE_INFORMATION) + - 32 * sizeof(wchar_t)); - OBJECT_TYPE_INFORMATION* type_info = - reinterpret_cast<OBJECT_TYPE_INFORMATION*>(&(type_info_buffer[0])); - base::string16 handle_name; - HANDLE handle = NULL; - int invalid_count = 0; - - // Keep incrementing until we hit the number of handles reported by - // GetProcessHandleCount(). If we hit a very long sequence of invalid - // handles we assume that we've run past the end of the table. - while (handle_count && invalid_count < kInvalidHandleThreshold) { - reinterpret_cast<size_t&>(handle) += kHandleOffset; - NTSTATUS rc; - - // Get the type name, reusing the buffer. - ULONG size = static_cast<ULONG>(type_info_buffer.size()); - rc = QueryObjectTypeInformation(handle, type_info, &size); - while (rc == STATUS_INFO_LENGTH_MISMATCH || - rc == STATUS_BUFFER_OVERFLOW) { - type_info_buffer.resize(size + sizeof(wchar_t)); - type_info = reinterpret_cast<OBJECT_TYPE_INFORMATION*>( - &(type_info_buffer[0])); - rc = QueryObjectTypeInformation(handle, type_info, &size); - // Leave padding for the nul terminator. - if (NT_SUCCESS(rc) && size == type_info_buffer.size()) - rc = STATUS_INFO_LENGTH_MISMATCH; - } - if (!NT_SUCCESS(rc) || !type_info->Name.Buffer) { - ++invalid_count; - continue; - } - - --handle_count; - type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0'; - - // Check if we're looking for this type of handle. - HandleMap::iterator result = - handles_to_close_.find(type_info->Name.Buffer); - if (result != handles_to_close_.end()) { - HandleMap::mapped_type& names = result->second; - // Empty set means close all handles of this type; otherwise check name. - if (!names.empty()) { - // Move on to the next handle if this name doesn't match. - if (!GetHandleName(handle, &handle_name) || !names.count(handle_name)) - continue; - } - - if (!::SetHandleInformation(handle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0)) - return false; - if (!::CloseHandle(handle)) - return false; - // Attempt to stuff this handle with a new dummy Event. - AttemptToStuffHandleSlot(handle, result->first); - } - } - - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/handle_closer_agent.h b/security/sandbox/chromium/sandbox/win/src/handle_closer_agent.h deleted file mode 100644 index 042c98eaf..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_closer_agent.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_HANDLE_CLOSER_AGENT_H_ -#define SANDBOX_SRC_HANDLE_CLOSER_AGENT_H_ - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/handle_closer.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/target_services.h" - - -namespace sandbox { - -// Target process code to close the handle list copied over from the broker. -class HandleCloserAgent { - public: - HandleCloserAgent(); - ~HandleCloserAgent(); - - // Reads the serialized list from the broker and creates the lookup map. - // Updates is_csrss_connected based on type of handles closed. - void InitializeHandlesToClose(bool* is_csrss_connected); - - // Closes any handles matching those in the lookup map. - bool CloseHandles(); - - // True if we have handles waiting to be closed. - static bool NeedsHandlesClosed(); - - private: - // Attempt to stuff a closed handle with a dummy Event. - bool AttemptToStuffHandleSlot(HANDLE closed_handle, - const base::string16& type); - - HandleMap handles_to_close_; - base::win::ScopedHandle dummy_handle_; - - DISALLOW_COPY_AND_ASSIGN(HandleCloserAgent); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_HANDLE_CLOSER_AGENT_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/handle_closer_test.cc b/security/sandbox/chromium/sandbox/win/src/handle_closer_test.cc deleted file mode 100644 index ceba818a7..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_closer_test.cc +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <limits.h> -#include <stddef.h> - -#include "base/strings/stringprintf.h" -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/handle_closer_agent.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/target_services.h" -#include "sandbox/win/tests/common/controller.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const wchar_t *kFileExtensions[] = { L".1", L".2", L".3", L".4" }; - -// Returns a handle to a unique marker file that can be retrieved between runs. -HANDLE GetMarkerFile(const wchar_t *extension) { - wchar_t path_buffer[MAX_PATH + 1]; - CHECK(::GetTempPath(MAX_PATH, path_buffer)); - base::string16 marker_path = path_buffer; - marker_path += L"\\sbox_marker_"; - - // Generate a unique value from the exe's size and timestamp. - CHECK(::GetModuleFileName(NULL, path_buffer, MAX_PATH)); - base::win::ScopedHandle module(::CreateFile(path_buffer, - FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); - CHECK(module.IsValid()); - FILETIME timestamp; - CHECK(::GetFileTime(module.Get(), ×tamp, NULL, NULL)); - marker_path += base::StringPrintf(L"%08x%08x%08x", - ::GetFileSize(module.Get(), NULL), - timestamp.dwLowDateTime, - timestamp.dwHighDateTime); - marker_path += extension; - - // Make the file delete-on-close so cleanup is automatic. - return CreateFile(marker_path.c_str(), FILE_ALL_ACCESS, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); -} - -// Returns type infomation for an NT object. This routine is expected to be -// called for invalid handles so it catches STATUS_INVALID_HANDLE exceptions -// that can be generated when handle tracing is enabled. -NTSTATUS QueryObjectTypeInformation(HANDLE handle, void* buffer, ULONG* size) { - static NtQueryObject QueryObject = NULL; - if (!QueryObject) - ResolveNTFunctionPtr("NtQueryObject", &QueryObject); - - NTSTATUS status = STATUS_UNSUCCESSFUL; - __try { - status = QueryObject(handle, ObjectTypeInformation, buffer, *size, size); - } - __except(GetExceptionCode() == STATUS_INVALID_HANDLE - ? EXCEPTION_EXECUTE_HANDLER - : EXCEPTION_CONTINUE_SEARCH) { - status = STATUS_INVALID_HANDLE; - } - return status; -} - -// Used by the thread pool tests. -HANDLE finish_event; -const int kWaitCount = 20; - -} // namespace - -namespace sandbox { - -// Checks for the presence of a list of files (in object path form). -// Format: CheckForFileHandle (Y|N) \path\to\file1 [\path\to\file2 ...] -// - Y or N depending if the file should exist or not. -SBOX_TESTS_COMMAND int CheckForFileHandles(int argc, wchar_t **argv) { - if (argc < 2) - return SBOX_TEST_FAILED_TO_RUN_TEST; - bool should_find = argv[0][0] == L'Y'; - if (argv[0][1] != L'\0' || (!should_find && argv[0][0] != L'N')) - return SBOX_TEST_FAILED_TO_RUN_TEST; - - static int state = BEFORE_INIT; - switch (state++) { - case BEFORE_INIT: - // Create a unique marker file that is open while the test is running. - // The handles leak, but it will be closed by the test or on exit. - for (const wchar_t* kExtension : kFileExtensions) - CHECK_NE(GetMarkerFile(kExtension), INVALID_HANDLE_VALUE); - return SBOX_TEST_SUCCEEDED; - - case AFTER_REVERT: { - // Brute force the handle table to find what we're looking for. - DWORD handle_count = UINT_MAX; - const int kInvalidHandleThreshold = 100; - const size_t kHandleOffset = 4; // Handles are always a multiple of 4. - HANDLE handle = NULL; - int invalid_count = 0; - base::string16 handle_name; - - if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count)) - return SBOX_TEST_FAILED_TO_RUN_TEST; - - while (handle_count && invalid_count < kInvalidHandleThreshold) { - reinterpret_cast<size_t&>(handle) += kHandleOffset; - if (GetHandleName(handle, &handle_name)) { - for (int i = 1; i < argc; ++i) { - if (handle_name == argv[i]) - return should_find ? SBOX_TEST_SUCCEEDED : SBOX_TEST_FAILED; - } - --handle_count; - } else { - ++invalid_count; - } - } - - return should_find ? SBOX_TEST_FAILED : SBOX_TEST_SUCCEEDED; - } - - default: // Do nothing. - break; - } - - return SBOX_TEST_SUCCEEDED; -} - -// Checks that supplied handle is an Event and it's not waitable. -// Format: CheckForEventHandles -SBOX_TESTS_COMMAND int CheckForEventHandles(int argc, wchar_t** argv) { - static int state = BEFORE_INIT; - static std::vector<HANDLE> to_check; - - switch (state++) { - case BEFORE_INIT: - // Create a unique marker file that is open while the test is running. - for (const wchar_t* kExtension : kFileExtensions) { - HANDLE handle = GetMarkerFile(kExtension); - CHECK_NE(handle, INVALID_HANDLE_VALUE); - to_check.push_back(handle); - } - return SBOX_TEST_SUCCEEDED; - - case AFTER_REVERT: - for (auto handle : to_check) { - // Set up buffers for the type info and the name. - std::vector<BYTE> type_info_buffer(sizeof(OBJECT_TYPE_INFORMATION) + - 32 * sizeof(wchar_t)); - OBJECT_TYPE_INFORMATION* type_info = - reinterpret_cast<OBJECT_TYPE_INFORMATION*>(&(type_info_buffer[0])); - NTSTATUS rc; - - // Get the type name, reusing the buffer. - ULONG size = static_cast<ULONG>(type_info_buffer.size()); - rc = QueryObjectTypeInformation(handle, type_info, &size); - while (rc == STATUS_INFO_LENGTH_MISMATCH || - rc == STATUS_BUFFER_OVERFLOW) { - type_info_buffer.resize(size + sizeof(wchar_t)); - type_info = reinterpret_cast<OBJECT_TYPE_INFORMATION*>( - &(type_info_buffer[0])); - rc = QueryObjectTypeInformation(handle, type_info, &size); - // Leave padding for the nul terminator. - if (NT_SUCCESS(rc) && size == type_info_buffer.size()) - rc = STATUS_INFO_LENGTH_MISMATCH; - } - - CHECK(NT_SUCCESS(rc)); - CHECK(type_info->Name.Buffer); - - type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = - L'\0'; - - // Should be an Event now. - CHECK_EQ(wcslen(type_info->Name.Buffer), 5U); - CHECK_EQ(wcscmp(L"Event", type_info->Name.Buffer), 0); - - // Should not be able to wait. - CHECK_EQ(WaitForSingleObject(handle, INFINITE), WAIT_FAILED); - - // Should be able to close. - CHECK_EQ(TRUE, CloseHandle(handle)); - } - return SBOX_TEST_SUCCEEDED; - - default: // Do nothing. - break; - } - - return SBOX_TEST_SUCCEEDED; -} - -TEST(HandleCloserTest, CheckForMarkerFiles) { - TestRunner runner; - runner.SetTimeout(2000); - runner.SetTestState(EVERY_STATE); - - base::string16 command = base::string16(L"CheckForFileHandles Y"); - for (const wchar_t* kExtension : kFileExtensions) { - base::string16 handle_name; - base::win::ScopedHandle marker(GetMarkerFile(kExtension)); - CHECK(marker.IsValid()); - CHECK(sandbox::GetHandleName(marker.Get(), &handle_name)); - command += (L" "); - command += handle_name; - } - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command.c_str())) << - "Failed: " << command; -} - -TEST(HandleCloserTest, CloseMarkerFiles) { - TestRunner runner; - runner.SetTimeout(2000); - runner.SetTestState(EVERY_STATE); - sandbox::TargetPolicy* policy = runner.GetPolicy(); - - base::string16 command = base::string16(L"CheckForFileHandles N"); - for (const wchar_t* kExtension : kFileExtensions) { - base::string16 handle_name; - base::win::ScopedHandle marker(GetMarkerFile(kExtension)); - CHECK(marker.IsValid()); - CHECK(sandbox::GetHandleName(marker.Get(), &handle_name)); - CHECK_EQ(policy->AddKernelObjectToClose(L"File", handle_name.c_str()), - SBOX_ALL_OK); - command += (L" "); - command += handle_name; - } - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command.c_str())) << - "Failed: " << command; -} - -TEST(HandleCloserTest, CheckStuffedHandle) { - TestRunner runner; - runner.SetTimeout(2000); - runner.SetTestState(EVERY_STATE); - sandbox::TargetPolicy* policy = runner.GetPolicy(); - - for (const wchar_t* kExtension : kFileExtensions) { - base::string16 handle_name; - base::win::ScopedHandle marker(GetMarkerFile(kExtension)); - CHECK(marker.IsValid()); - CHECK(sandbox::GetHandleName(marker.Get(), &handle_name)); - CHECK_EQ(policy->AddKernelObjectToClose(L"File", handle_name.c_str()), - SBOX_ALL_OK); - } - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckForEventHandles")); -} - -void WINAPI ThreadPoolTask(void* event, BOOLEAN timeout) { - static volatile LONG waiters_remaining = kWaitCount; - CHECK(!timeout); - CHECK(::CloseHandle(event)); - if (::InterlockedDecrement(&waiters_remaining) == 0) - CHECK(::SetEvent(finish_event)); -} - -// Run a thread pool inside a sandbox without a CSRSS connection. -SBOX_TESTS_COMMAND int RunThreadPool(int argc, wchar_t **argv) { - HANDLE wait_list[20]; - finish_event = ::CreateEvent(NULL, TRUE, FALSE, NULL); - CHECK(finish_event); - - // Set up a bunch of waiters. - HANDLE pool = NULL; - for (int i = 0; i < kWaitCount; ++i) { - HANDLE event = ::CreateEvent(NULL, TRUE, FALSE, NULL); - CHECK(event); - CHECK(::RegisterWaitForSingleObject(&pool, event, ThreadPoolTask, event, - INFINITE, WT_EXECUTEONLYONCE)); - wait_list[i] = event; - } - - // Signal all the waiters. - for (int i = 0; i < kWaitCount; ++i) - CHECK(::SetEvent(wait_list[i])); - - CHECK_EQ(::WaitForSingleObject(finish_event, INFINITE), WAIT_OBJECT_0); - CHECK(::CloseHandle(finish_event)); - - return SBOX_TEST_SUCCEEDED; -} - -TEST(HandleCloserTest, RunThreadPool) { - TestRunner runner; - runner.SetTimeout(2000); - runner.SetTestState(AFTER_REVERT); - sandbox::TargetPolicy* policy = runner.GetPolicy(); - - // Sever the CSRSS connection by closing ALPC ports inside the sandbox. - CHECK_EQ(policy->AddKernelObjectToClose(L"ALPC Port", NULL), SBOX_ALL_OK); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"RunThreadPool")); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc deleted file mode 100644 index 4b98acd4c..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/handle_dispatcher.h" - -#include <stdint.h> - -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/handle_interception.h" -#include "sandbox/win/src/handle_policy.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_broker.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sandbox_utils.h" - -namespace sandbox { - -HandleDispatcher::HandleDispatcher(PolicyBase* policy_base) - : policy_base_(policy_base) { - static const IPCCall duplicate_handle_proxy = { - {IPC_DUPLICATEHANDLEPROXY_TAG, - {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &HandleDispatcher::DuplicateHandleProxy)}; - - ipc_calls_.push_back(duplicate_handle_proxy); -} - -bool HandleDispatcher::SetupService(InterceptionManager* manager, - int service) { - // We perform no interceptions for handles right now. - switch (service) { - case IPC_DUPLICATEHANDLEPROXY_TAG: - return true; - } - - return false; -} - -bool HandleDispatcher::DuplicateHandleProxy(IPCInfo* ipc, - HANDLE source_handle, - uint32_t target_process_id, - uint32_t desired_access, - uint32_t options) { - static NtQueryObject QueryObject = NULL; - if (!QueryObject) - ResolveNTFunctionPtr("NtQueryObject", &QueryObject); - - // Get a copy of the handle for use in the broker process. - HANDLE handle_temp; - if (!::DuplicateHandle(ipc->client_info->process, source_handle, - ::GetCurrentProcess(), &handle_temp, - 0, FALSE, DUPLICATE_SAME_ACCESS | options)) { - ipc->return_info.win32_result = ::GetLastError(); - return false; - } - options &= ~DUPLICATE_CLOSE_SOURCE; - base::win::ScopedHandle handle(handle_temp); - - // Get the object type (32 characters is safe; current max is 14). - BYTE buffer[sizeof(OBJECT_TYPE_INFORMATION) + 32 * sizeof(wchar_t)]; - OBJECT_TYPE_INFORMATION* type_info = - reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer); - ULONG size = sizeof(buffer) - sizeof(wchar_t); - NTSTATUS error = - QueryObject(handle.Get(), ObjectTypeInformation, type_info, size, &size); - if (!NT_SUCCESS(error)) { - ipc->return_info.nt_status = error; - return false; - } - type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0'; - - CountedParameterSet<HandleTarget> params; - params[HandleTarget::NAME] = ParamPickerMake(type_info->Name.Buffer); - params[HandleTarget::TARGET] = ParamPickerMake(target_process_id); - - EvalResult eval = policy_base_->EvalPolicy(IPC_DUPLICATEHANDLEPROXY_TAG, - params.GetBase()); - ipc->return_info.win32_result = - HandlePolicy::DuplicateHandleProxyAction(eval, handle.Get(), - target_process_id, - &ipc->return_info.handle, - desired_access, options); - return true; -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h deleted file mode 100644 index 24dcdac2a..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_HANDLE_DISPATCHER_H_ -#define SANDBOX_SRC_HANDLE_DISPATCHER_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox_policy_base.h" - -namespace sandbox { - -// This class handles handle-related IPC calls. -class HandleDispatcher : public Dispatcher { - public: - explicit HandleDispatcher(PolicyBase* policy_base); - ~HandleDispatcher() override {} - - // Dispatcher interface. - bool SetupService(InterceptionManager* manager, int service) override; - - private: - // Processes IPC requests coming from calls to - // TargetServices::DuplicateHandle() in the target. - bool DuplicateHandleProxy(IPCInfo* ipc, - HANDLE source_handle, - uint32_t target_process_id, - uint32_t desired_access, - uint32_t options); - - PolicyBase* policy_base_; - DISALLOW_COPY_AND_ASSIGN(HandleDispatcher); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_HANDLE_DISPATCHER_H_ - diff --git a/security/sandbox/chromium/sandbox/win/src/handle_inheritance_test.cc b/security/sandbox/chromium/sandbox/win/src/handle_inheritance_test.cc deleted file mode 100644 index d8c2808da..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_inheritance_test.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdio.h> - -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" -#include "sandbox/win/tests/common/controller.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -SBOX_TESTS_COMMAND int HandleInheritanceTests_PrintToStdout(int argc, - wchar_t** argv) { - printf("Example output to stdout\n"); - return SBOX_TEST_SUCCEEDED; -} - -TEST(HandleInheritanceTests, TestStdoutInheritance) { - base::ScopedTempDir temp_directory; - base::FilePath temp_file_name; - ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); - ASSERT_TRUE(CreateTemporaryFileInDir(temp_directory.path(), &temp_file_name)); - - SECURITY_ATTRIBUTES attrs = {}; - attrs.nLength = sizeof(attrs); - attrs.bInheritHandle = TRUE; - base::win::ScopedHandle tmp_handle( - CreateFile(temp_file_name.value().c_str(), GENERIC_WRITE, - FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, - &attrs, OPEN_EXISTING, 0, NULL)); - ASSERT_TRUE(tmp_handle.IsValid()); - - TestRunner runner; - ASSERT_EQ(SBOX_ALL_OK, runner.GetPolicy()->SetStdoutHandle(tmp_handle.Get())); - int result = runner.RunTest(L"HandleInheritanceTests_PrintToStdout"); - ASSERT_EQ(SBOX_TEST_SUCCEEDED, result); - - std::string data; - ASSERT_TRUE(base::ReadFileToString(base::FilePath(temp_file_name), &data)); - // Redirection uses a feature that was added in Windows Vista. - if (base::win::GetVersion() >= base::win::VERSION_VISTA) { - ASSERT_EQ("Example output to stdout\r\n", data); - } else { - ASSERT_EQ("", data); - } -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc deleted file mode 100644 index 6fe2f117d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/handle_interception.h" - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/target_services.h" -#include "mozilla/sandboxing/sandboxLogging.h" - -namespace sandbox { - -ResultCode DuplicateHandleProxy(HANDLE source_handle, - DWORD target_process_id, - HANDLE* target_handle, - DWORD desired_access, - DWORD options) { - *target_handle = NULL; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - return SBOX_ERROR_NO_SPACE; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_DUPLICATEHANDLEPROXY_TAG, - source_handle, target_process_id, - desired_access, options, &answer); - if (SBOX_ALL_OK != code) - return code; - - if (answer.win32_result) { - ::SetLastError(answer.win32_result); - mozilla::sandboxing::LogBlocked("DuplicateHandle"); - return SBOX_ERROR_GENERIC; - } - - *target_handle = answer.handle; - mozilla::sandboxing::LogAllowed("DuplicateHandle"); - return SBOX_ALL_OK; -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.h b/security/sandbox/chromium/sandbox/win/src/handle_interception.h deleted file mode 100644 index 6f60811f1..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_interception.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_HANDLE_INTERCEPTION_H_ -#define SANDBOX_SRC_HANDLE_INTERCEPTION_H_ - -namespace sandbox { - -// TODO(jschuh) Add an interception to catch dangerous DuplicateHandle calls. - -ResultCode DuplicateHandleProxy(HANDLE source_handle, - DWORD target_process_id, - HANDLE* target_handle, - DWORD desired_access, - DWORD options); - -} // namespace sandbox - -#endif // SANDBOX_SRC_HANDLE_INTERCEPTION_H_ - diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc deleted file mode 100644 index 102303079..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_policy.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/handle_policy.h" - -#include <string> - -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/broker_services.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sandbox_utils.h" - -namespace sandbox { - -bool HandlePolicy::GenerateRules(const wchar_t* type_name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy) { - PolicyRule duplicate_rule(ASK_BROKER); - - switch (semantics) { - case TargetPolicy::HANDLES_DUP_ANY: { - if (!duplicate_rule.AddNumberMatch(IF_NOT, HandleTarget::TARGET, - ::GetCurrentProcessId(), EQUAL)) { - return false; - } - break; - } - - case TargetPolicy::HANDLES_DUP_BROKER: { - if (!duplicate_rule.AddNumberMatch(IF, HandleTarget::TARGET, - ::GetCurrentProcessId(), EQUAL)) { - return false; - } - break; - } - - default: - return false; - } - if (!duplicate_rule.AddStringMatch(IF, HandleTarget::NAME, type_name, - CASE_INSENSITIVE)) { - return false; - } - if (!policy->AddRule(IPC_DUPLICATEHANDLEPROXY_TAG, &duplicate_rule)) { - return false; - } - return true; -} - -DWORD HandlePolicy::DuplicateHandleProxyAction(EvalResult eval_result, - HANDLE source_handle, - DWORD target_process_id, - HANDLE* target_handle, - DWORD desired_access, - DWORD options) { - // The only action supported is ASK_BROKER which means duplicate the handle. - if (ASK_BROKER != eval_result) { - return ERROR_ACCESS_DENIED; - } - - base::win::ScopedHandle remote_target_process; - if (target_process_id != ::GetCurrentProcessId()) { - // Sandboxed children are dynamic, so we check that manually. - if (!BrokerServicesBase::GetInstance()->IsActiveTarget(target_process_id)) { - return ERROR_ACCESS_DENIED; - } - - remote_target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, - target_process_id)); - if (!remote_target_process.IsValid()) - return ::GetLastError(); - } - - // If the policy didn't block us and we have no valid target, then the broker - // (this process) is the valid target. - HANDLE target_process = remote_target_process.IsValid() ? - remote_target_process.Get() : ::GetCurrentProcess(); - if (!::DuplicateHandle(::GetCurrentProcess(), source_handle, target_process, - target_handle, desired_access, FALSE, - options)) { - return ::GetLastError(); - } - - return ERROR_SUCCESS; -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.h b/security/sandbox/chromium/sandbox/win/src/handle_policy.h deleted file mode 100644 index 29ce5ab66..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_policy.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_HANDLE_POLICY_H_ -#define SANDBOX_SRC_HANDLE_POLICY_H_ - -#include <string> - -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/sandbox_policy.h" - -namespace sandbox { - -enum EvalResult; - -// This class centralizes most of the knowledge related to handle policy. -class HandlePolicy { - public: - // Creates the required low-level policy rules to evaluate a high-level - // policy rule for handles, in particular duplicate action. - static bool GenerateRules(const wchar_t* type_name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy); - - // Processes a 'TargetPolicy::DuplicateHandle()' request from the target. - static DWORD DuplicateHandleProxyAction(EvalResult eval_result, - HANDLE source_handle, - DWORD target_process_id, - HANDLE* target_handle, - DWORD desired_access, - DWORD options); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_HANDLE_POLICY_H_ - diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc deleted file mode 100644 index 11382da81..000000000 --- a/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/stringprintf.h" -#include "sandbox/win/src/handle_policy.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/win_utils.h" -#include "sandbox/win/tests/common/controller.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -// Just waits for the supplied number of milliseconds. -SBOX_TESTS_COMMAND int Handle_WaitProcess(int argc, wchar_t **argv) { - if (argc != 1) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - ::Sleep(::wcstoul(argv[0], NULL, 10)); - return SBOX_TEST_TIMED_OUT; -} - -// Attempts to duplicate an event handle into the target process. -SBOX_TESTS_COMMAND int Handle_DuplicateEvent(int argc, wchar_t **argv) { - if (argc != 1) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - // Create a test event to use as a handle. - base::win::ScopedHandle test_event; - test_event.Set(::CreateEvent(NULL, TRUE, TRUE, NULL)); - if (!test_event.IsValid()) - return SBOX_TEST_FIRST_ERROR; - - // Get the target process ID. - DWORD target_process_id = ::wcstoul(argv[0], NULL, 10); - - HANDLE handle = NULL; - ResultCode result = SandboxFactory::GetTargetServices()->DuplicateHandle( - test_event.Get(), target_process_id, &handle, 0, DUPLICATE_SAME_ACCESS); - - return (result == SBOX_ALL_OK) ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED; -} - -// Tests that duplicating an object works only when the policy allows it. -TEST(HandlePolicyTest, DuplicateHandle) { - TestRunner target; - TestRunner runner; - - // Kick off an asynchronous target process for testing. - target.SetAsynchronous(true); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000")); - - // First test that we fail to open the event. - base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d", - target.process_id()); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str())); - - // Now successfully open the event after adding a duplicate handle rule. - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES, - TargetPolicy::HANDLES_DUP_ANY, - L"Event")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str())); -} - -// Tests that duplicating an object works only when the policy allows it. -TEST(HandlePolicyTest, DuplicatePeerHandle) { - TestRunner target; - TestRunner runner; - - // Kick off an asynchronous target process for testing. - target.SetAsynchronous(true); - target.SetUnsandboxed(true); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000")); - - // First test that we fail to open the event. - base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d", - target.process_id()); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str())); - - // Now successfully open the event after adding a duplicate handle rule. - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES, - TargetPolicy::HANDLES_DUP_ANY, - L"Event")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str())); -} - -// Tests that duplicating an object works only when the policy allows it. -TEST(HandlePolicyTest, DuplicateBrokerHandle) { - TestRunner runner; - - // First test that we fail to open the event. - base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d", - ::GetCurrentProcessId()); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str())); - - // Add the peer rule and make sure we fail again. - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES, - TargetPolicy::HANDLES_DUP_ANY, - L"Event")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str())); - - - // Now successfully open the event after adding a broker handle rule. - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES, - TargetPolicy::HANDLES_DUP_BROKER, - L"Event")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str())); -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/integrity_level_test.cc b/security/sandbox/chromium/sandbox/win/src/integrity_level_test.cc deleted file mode 100644 index f962033ca..000000000 --- a/security/sandbox/chromium/sandbox/win/src/integrity_level_test.cc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <windows.h> -#include <atlsecurity.h> - -#include "base/win/windows_version.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/tests/common/controller.h" - -namespace sandbox { - - -SBOX_TESTS_COMMAND int CheckIntegrityLevel(int argc, wchar_t **argv) { - ATL::CAccessToken token; - if (!token.GetEffectiveToken(TOKEN_READ)) - return SBOX_TEST_FAILED; - - char* buffer[100]; - DWORD buf_size = 100; - if (!::GetTokenInformation(token.GetHandle(), TokenIntegrityLevel, - reinterpret_cast<void*>(buffer), buf_size, - &buf_size)) - return SBOX_TEST_FAILED; - - TOKEN_MANDATORY_LABEL* label = - reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buffer); - - PSID sid_low = NULL; - if (!::ConvertStringSidToSid(L"S-1-16-4096", &sid_low)) - return SBOX_TEST_FAILED; - - BOOL is_low_sid = ::EqualSid(label->Label.Sid, sid_low); - - ::LocalFree(sid_low); - - if (is_low_sid) - return SBOX_TEST_SUCCEEDED; - - return SBOX_TEST_DENIED; -} - -TEST(IntegrityLevelTest, TestLowILReal) { - if (base::win::GetVersion() != base::win::VERSION_VISTA) - return; - - TestRunner runner(JOB_LOCKDOWN, USER_INTERACTIVE, USER_INTERACTIVE); - - runner.SetTimeout(INFINITE); - - runner.GetPolicy()->SetAlternateDesktop(true); - runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel")); -} - -TEST(DelayedIntegrityLevelTest, TestLowILDelayed) { - if (base::win::GetVersion() != base::win::VERSION_VISTA) - return; - - TestRunner runner(JOB_LOCKDOWN, USER_INTERACTIVE, USER_INTERACTIVE); - - runner.SetTimeout(INFINITE); - - runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel")); - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"CheckIntegrityLevel")); -} - -TEST(IntegrityLevelTest, TestNoILChange) { - if (base::win::GetVersion() != base::win::VERSION_VISTA) - return; - - TestRunner runner(JOB_LOCKDOWN, USER_INTERACTIVE, USER_INTERACTIVE); - - runner.SetTimeout(INFINITE); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"CheckIntegrityLevel")); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/interception.cc b/security/sandbox/chromium/sandbox/win/src/interception.cc deleted file mode 100644 index f0a2a61fb..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interception.cc +++ /dev/null @@ -1,560 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// For information about interceptions as a whole see -// http://dev.chromium.org/developers/design-documents/sandbox . - -#include <stddef.h> - -#include <set> - -#include "sandbox/win/src/interception.h" - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "base/win/pe_image.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/interception_internal.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_rand.h" -#include "sandbox/win/src/service_resolver.h" -#include "sandbox/win/src/target_interceptions.h" -#include "sandbox/win/src/target_process.h" -#include "sandbox/win/src/wow64.h" - -namespace sandbox { - -namespace { - -// Standard allocation granularity and page size for Windows. -const size_t kAllocGranularity = 65536; -const size_t kPageSize = 4096; - -} // namespace - -namespace internal { - -// Find a random offset within 64k and aligned to ceil(log2(size)). -size_t GetGranularAlignedRandomOffset(size_t size) { - CHECK_LE(size, kAllocGranularity); - unsigned int offset; - - do { - GetRandom(&offset); - offset &= (kAllocGranularity - 1); - } while (offset > (kAllocGranularity - size)); - - // Find an alignment between 64 and the page size (4096). - size_t align_size = kPageSize; - for (size_t new_size = align_size / 2; new_size >= size; new_size /= 2) { - align_size = new_size; - } - return offset & ~(align_size - 1); -} - -} // namespace internal - -SANDBOX_INTERCEPT SharedMemory* g_interceptions; - -// Table of the unpatched functions that we intercept. Mapped from the parent. -SANDBOX_INTERCEPT OriginalFunctions g_originals = { NULL }; - -// Magic constant that identifies that this function is not to be patched. -const char kUnloadDLLDummyFunction[] = "@"; - -InterceptionManager::InterceptionData::InterceptionData() { -} - -InterceptionManager::InterceptionData::~InterceptionData() { -} - -InterceptionManager::InterceptionManager(TargetProcess* child_process, - bool relaxed) - : child_(child_process), names_used_(false), relaxed_(relaxed) { - child_->AddRef(); -} -InterceptionManager::~InterceptionManager() { - child_->Release(); -} - -bool InterceptionManager::AddToPatchedFunctions( - const wchar_t* dll_name, const char* function_name, - InterceptionType interception_type, const void* replacement_code_address, - InterceptorId id) { - InterceptionData function; - function.type = interception_type; - function.id = id; - function.dll = dll_name; - function.function = function_name; - function.interceptor_address = replacement_code_address; - - interceptions_.push_back(function); - return true; -} - -bool InterceptionManager::AddToPatchedFunctions( - const wchar_t* dll_name, const char* function_name, - InterceptionType interception_type, const char* replacement_function_name, - InterceptorId id) { - InterceptionData function; - function.type = interception_type; - function.id = id; - function.dll = dll_name; - function.function = function_name; - function.interceptor = replacement_function_name; - function.interceptor_address = NULL; - - interceptions_.push_back(function); - names_used_ = true; - return true; -} - -bool InterceptionManager::AddToUnloadModules(const wchar_t* dll_name) { - InterceptionData module_to_unload; - module_to_unload.type = INTERCEPTION_UNLOAD_MODULE; - module_to_unload.dll = dll_name; - // The next two are dummy values that make the structures regular, instead - // of having special cases. They should not be used. - module_to_unload.function = kUnloadDLLDummyFunction; - module_to_unload.interceptor_address = reinterpret_cast<void*>(1); - - interceptions_.push_back(module_to_unload); - return true; -} - -bool InterceptionManager::InitializeInterceptions() { - if (interceptions_.empty()) - return true; // Nothing to do here - - size_t buffer_bytes = GetBufferSize(); - scoped_ptr<char[]> local_buffer(new char[buffer_bytes]); - - if (!SetupConfigBuffer(local_buffer.get(), buffer_bytes)) - return false; - - void* remote_buffer; - if (!CopyDataToChild(local_buffer.get(), buffer_bytes, &remote_buffer)) - return false; - - bool hot_patch_needed = (0 != buffer_bytes); - if (!PatchNtdll(hot_patch_needed)) - return false; - - g_interceptions = reinterpret_cast<SharedMemory*>(remote_buffer); - ResultCode rc = child_->TransferVariable("g_interceptions", - &g_interceptions, - sizeof(g_interceptions)); - return (SBOX_ALL_OK == rc); -} - -size_t InterceptionManager::GetBufferSize() const { - std::set<base::string16> dlls; - size_t buffer_bytes = 0; - - std::list<InterceptionData>::const_iterator it = interceptions_.begin(); - for (; it != interceptions_.end(); ++it) { - // skip interceptions that are performed from the parent - if (!IsInterceptionPerformedByChild(*it)) - continue; - - if (!dlls.count(it->dll)) { - // NULL terminate the dll name on the structure - size_t dll_name_bytes = (it->dll.size() + 1) * sizeof(wchar_t); - - // include the dll related size - buffer_bytes += RoundUpToMultiple(offsetof(DllPatchInfo, dll_name) + - dll_name_bytes, sizeof(size_t)); - dlls.insert(it->dll); - } - - // we have to NULL terminate the strings on the structure - size_t strings_chars = it->function.size() + it->interceptor.size() + 2; - - // a new FunctionInfo is required per function - size_t record_bytes = offsetof(FunctionInfo, function) + strings_chars; - record_bytes = RoundUpToMultiple(record_bytes, sizeof(size_t)); - buffer_bytes += record_bytes; - } - - if (0 != buffer_bytes) - // add the part of SharedMemory that we have not counted yet - buffer_bytes += offsetof(SharedMemory, dll_list); - - return buffer_bytes; -} - -// Basically, walk the list of interceptions moving them to the config buffer, -// but keeping together all interceptions that belong to the same dll. -// The config buffer is a local buffer, not the one allocated on the child. -bool InterceptionManager::SetupConfigBuffer(void* buffer, size_t buffer_bytes) { - if (0 == buffer_bytes) - return true; - - DCHECK(buffer_bytes > sizeof(SharedMemory)); - - SharedMemory* shared_memory = reinterpret_cast<SharedMemory*>(buffer); - DllPatchInfo* dll_info = shared_memory->dll_list; - int num_dlls = 0; - - shared_memory->interceptor_base = names_used_ ? child_->MainModule() : NULL; - - buffer_bytes -= offsetof(SharedMemory, dll_list); - buffer = dll_info; - - std::list<InterceptionData>::iterator it = interceptions_.begin(); - for (; it != interceptions_.end();) { - // skip interceptions that are performed from the parent - if (!IsInterceptionPerformedByChild(*it)) { - ++it; - continue; - } - - const base::string16 dll = it->dll; - if (!SetupDllInfo(*it, &buffer, &buffer_bytes)) - return false; - - // walk the interceptions from this point, saving the ones that are - // performed on this dll, and removing the entry from the list. - // advance the iterator before removing the element from the list - std::list<InterceptionData>::iterator rest = it; - for (; rest != interceptions_.end();) { - if (rest->dll == dll) { - if (!SetupInterceptionInfo(*rest, &buffer, &buffer_bytes, dll_info)) - return false; - if (it == rest) - ++it; - rest = interceptions_.erase(rest); - } else { - ++rest; - } - } - dll_info = reinterpret_cast<DllPatchInfo*>(buffer); - ++num_dlls; - } - - shared_memory->num_intercepted_dlls = num_dlls; - return true; -} - -// Fills up just the part that depends on the dll, not the info that depends on -// the actual interception. -bool InterceptionManager::SetupDllInfo(const InterceptionData& data, - void** buffer, - size_t* buffer_bytes) const { - DCHECK(buffer_bytes); - DCHECK(buffer); - DCHECK(*buffer); - - DllPatchInfo* dll_info = reinterpret_cast<DllPatchInfo*>(*buffer); - - // the strings have to be zero terminated - size_t required = offsetof(DllPatchInfo, dll_name) + - (data.dll.size() + 1) * sizeof(wchar_t); - required = RoundUpToMultiple(required, sizeof(size_t)); - if (*buffer_bytes < required) - return false; - - *buffer_bytes -= required; - *buffer = reinterpret_cast<char*>(*buffer) + required; - - // set up the dll info to be what we know about it at this time - dll_info->unload_module = (data.type == INTERCEPTION_UNLOAD_MODULE); - dll_info->record_bytes = required; - dll_info->offset_to_functions = required; - dll_info->num_functions = 0; - data.dll._Copy_s(dll_info->dll_name, data.dll.size(), data.dll.size()); - dll_info->dll_name[data.dll.size()] = L'\0'; - - return true; -} - -bool InterceptionManager::SetupInterceptionInfo(const InterceptionData& data, - void** buffer, - size_t* buffer_bytes, - DllPatchInfo* dll_info) const { - DCHECK(buffer_bytes); - DCHECK(buffer); - DCHECK(*buffer); - - if ((dll_info->unload_module) && - (data.function != kUnloadDLLDummyFunction)) { - // Can't specify a dll for both patch and unload. - NOTREACHED(); - } - - FunctionInfo* function = reinterpret_cast<FunctionInfo*>(*buffer); - - size_t name_bytes = data.function.size(); - size_t interceptor_bytes = data.interceptor.size(); - - // the strings at the end of the structure are zero terminated - size_t required = offsetof(FunctionInfo, function) + - name_bytes + interceptor_bytes + 2; - required = RoundUpToMultiple(required, sizeof(size_t)); - if (*buffer_bytes < required) - return false; - - // update the caller's values - *buffer_bytes -= required; - *buffer = reinterpret_cast<char*>(*buffer) + required; - - function->record_bytes = required; - function->type = data.type; - function->id = data.id; - function->interceptor_address = data.interceptor_address; - char* names = function->function; - - data.function._Copy_s(names, name_bytes, name_bytes); - names += name_bytes; - *names++ = '\0'; - - // interceptor follows the function_name - data.interceptor._Copy_s(names, interceptor_bytes, interceptor_bytes); - names += interceptor_bytes; - *names++ = '\0'; - - // update the dll table - dll_info->num_functions++; - dll_info->record_bytes += required; - - return true; -} - -bool InterceptionManager::CopyDataToChild(const void* local_buffer, - size_t buffer_bytes, - void** remote_buffer) const { - DCHECK(NULL != remote_buffer); - if (0 == buffer_bytes) { - *remote_buffer = NULL; - return true; - } - - HANDLE child = child_->Process(); - - // Allocate memory on the target process without specifying the address - void* remote_data = ::VirtualAllocEx(child, NULL, buffer_bytes, - MEM_COMMIT, PAGE_READWRITE); - if (NULL == remote_data) - return false; - - SIZE_T bytes_written; - BOOL success = ::WriteProcessMemory(child, remote_data, local_buffer, - buffer_bytes, &bytes_written); - if (FALSE == success || bytes_written != buffer_bytes) { - ::VirtualFreeEx(child, remote_data, 0, MEM_RELEASE); - return false; - } - - *remote_buffer = remote_data; - - return true; -} - -// Only return true if the child should be able to perform this interception. -bool InterceptionManager::IsInterceptionPerformedByChild( - const InterceptionData& data) const { - if (INTERCEPTION_INVALID == data.type) - return false; - - if (INTERCEPTION_SERVICE_CALL == data.type) - return false; - - if (data.type >= INTERCEPTION_LAST) - return false; - - base::string16 ntdll(kNtdllName); - if (ntdll == data.dll) - return false; // ntdll has to be intercepted from the parent - - return true; -} - -bool InterceptionManager::PatchNtdll(bool hot_patch_needed) { - // Maybe there is nothing to do - if (!hot_patch_needed && interceptions_.empty()) - return true; - - if (hot_patch_needed) { -#if SANDBOX_EXPORTS - // Make sure the functions are not excluded by the linker. -#if defined(_WIN64) - #pragma comment(linker, "/include:TargetNtMapViewOfSection64") - #pragma comment(linker, "/include:TargetNtUnmapViewOfSection64") -#else - #pragma comment(linker, "/include:_TargetNtMapViewOfSection@44") - #pragma comment(linker, "/include:_TargetNtUnmapViewOfSection@12") -#endif -#endif - ADD_NT_INTERCEPTION(NtMapViewOfSection, MAP_VIEW_OF_SECTION_ID, 44); - ADD_NT_INTERCEPTION(NtUnmapViewOfSection, UNMAP_VIEW_OF_SECTION_ID, 12); - } - - // Reserve a full 64k memory range in the child process. - HANDLE child = child_->Process(); - BYTE* thunk_base = reinterpret_cast<BYTE*>( - ::VirtualAllocEx(child, NULL, kAllocGranularity, - MEM_RESERVE, PAGE_NOACCESS)); - - // Find an aligned, random location within the reserved range. - size_t thunk_bytes = interceptions_.size() * sizeof(ThunkData) + - sizeof(DllInterceptionData); - size_t thunk_offset = internal::GetGranularAlignedRandomOffset(thunk_bytes); - - // Split the base and offset along page boundaries. - thunk_base += thunk_offset & ~(kPageSize - 1); - thunk_offset &= kPageSize - 1; - - // Make an aligned, padded allocation, and move the pointer to our chunk. - size_t thunk_bytes_padded = (thunk_bytes + kPageSize - 1) & ~(kPageSize - 1); - thunk_base = reinterpret_cast<BYTE*>( - ::VirtualAllocEx(child, thunk_base, thunk_bytes_padded, - MEM_COMMIT, PAGE_EXECUTE_READWRITE)); - CHECK(thunk_base); // If this fails we'd crash anyway on an invalid access. - DllInterceptionData* thunks = reinterpret_cast<DllInterceptionData*>( - thunk_base + thunk_offset); - - DllInterceptionData dll_data; - dll_data.data_bytes = thunk_bytes; - dll_data.num_thunks = 0; - dll_data.used_bytes = offsetof(DllInterceptionData, thunks); - - // Reset all helpers for a new child. - memset(g_originals, 0, sizeof(g_originals)); - - // this should write all the individual thunks to the child's memory - if (!PatchClientFunctions(thunks, thunk_bytes, &dll_data)) - return false; - - // and now write the first part of the table to the child's memory - SIZE_T written; - bool ok = FALSE != ::WriteProcessMemory(child, thunks, &dll_data, - offsetof(DllInterceptionData, thunks), - &written); - - if (!ok || (offsetof(DllInterceptionData, thunks) != written)) - return false; - - // Attempt to protect all the thunks, but ignore failure - DWORD old_protection; - ::VirtualProtectEx(child, thunks, thunk_bytes, - PAGE_EXECUTE_READ, &old_protection); - - ResultCode ret = child_->TransferVariable("g_originals", g_originals, - sizeof(g_originals)); - return (SBOX_ALL_OK == ret); -} - -bool InterceptionManager::PatchClientFunctions(DllInterceptionData* thunks, - size_t thunk_bytes, - DllInterceptionData* dll_data) { - DCHECK(NULL != thunks); - DCHECK(NULL != dll_data); - - HMODULE ntdll_base = ::GetModuleHandle(kNtdllName); - if (!ntdll_base) - return false; - - base::win::PEImage ntdll_image(ntdll_base); - - // Bypass purify's interception. - wchar_t* loader_get = reinterpret_cast<wchar_t*>( - ntdll_image.GetProcAddress("LdrGetDllHandle")); - if (loader_get) { - if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - loader_get, &ntdll_base)) - return false; - } - - if (base::win::GetVersion() <= base::win::VERSION_VISTA) { - Wow64 WowHelper(child_, ntdll_base); - if (!WowHelper.WaitForNtdll()) - return false; - } - - char* interceptor_base = NULL; - -#if SANDBOX_EXPORTS - interceptor_base = reinterpret_cast<char*>(child_->MainModule()); - HMODULE local_interceptor = ::LoadLibrary(child_->Name()); -#endif - - ServiceResolverThunk* thunk; -#if defined(_WIN64) - thunk = new ServiceResolverThunk(child_->Process(), relaxed_); -#else - base::win::OSInfo* os_info = base::win::OSInfo::GetInstance(); - if (os_info->wow64_status() == base::win::OSInfo::WOW64_ENABLED) { - if (os_info->version() >= base::win::VERSION_WIN10) - thunk = new Wow64W10ResolverThunk(child_->Process(), relaxed_); - else if (os_info->version() >= base::win::VERSION_WIN8) - thunk = new Wow64W8ResolverThunk(child_->Process(), relaxed_); - else - thunk = new Wow64ResolverThunk(child_->Process(), relaxed_); - } else if (os_info->version() >= base::win::VERSION_WIN8) { - thunk = new Win8ResolverThunk(child_->Process(), relaxed_); - } else { - thunk = new ServiceResolverThunk(child_->Process(), relaxed_); - } -#endif - - std::list<InterceptionData>::iterator it = interceptions_.begin(); - for (; it != interceptions_.end(); ++it) { - const base::string16 ntdll(kNtdllName); - if (it->dll != ntdll) - break; - - if (INTERCEPTION_SERVICE_CALL != it->type) - break; - -#if SANDBOX_EXPORTS - // We may be trying to patch by function name. - if (NULL == it->interceptor_address) { - const char* address; - NTSTATUS ret = thunk->ResolveInterceptor(local_interceptor, - it->interceptor.c_str(), - reinterpret_cast<const void**>( - &address)); - if (!NT_SUCCESS(ret)) - break; - - // Translate the local address to an address on the child. - it->interceptor_address = interceptor_base + (address - - reinterpret_cast<char*>(local_interceptor)); - } -#endif - NTSTATUS ret = thunk->Setup(ntdll_base, - interceptor_base, - it->function.c_str(), - it->interceptor.c_str(), - it->interceptor_address, - &thunks->thunks[dll_data->num_thunks], - thunk_bytes - dll_data->used_bytes, - NULL); - if (!NT_SUCCESS(ret)) - break; - - DCHECK(!g_originals[it->id]); - g_originals[it->id] = &thunks->thunks[dll_data->num_thunks]; - - dll_data->num_thunks++; - dll_data->used_bytes += sizeof(ThunkData); - } - - delete(thunk); - -#if SANDBOX_EXPORTS - if (NULL != local_interceptor) - ::FreeLibrary(local_interceptor); -#endif - - if (it != interceptions_.end()) - return false; - - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/interception.h b/security/sandbox/chromium/sandbox/win/src/interception.h deleted file mode 100644 index 4d1ee82ba..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interception.h +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Defines InterceptionManager, the class in charge of setting up interceptions -// for the sandboxed process. For more details see -// http://dev.chromium.org/developers/design-documents/sandbox . - -#ifndef SANDBOX_SRC_INTERCEPTION_H_ -#define SANDBOX_SRC_INTERCEPTION_H_ - -#include <stddef.h> - -#include <list> -#include <string> - -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace sandbox { - -class TargetProcess; -enum InterceptorId; - -// Internal structures used for communication between the broker and the target. -struct DllPatchInfo; -struct DllInterceptionData; - -// The InterceptionManager executes on the parent application, and it is in -// charge of setting up the desired interceptions, and placing the Interception -// Agent into the child application. -// -// The exposed API consists of two methods: AddToPatchedFunctions to set up a -// particular interception, and InitializeInterceptions to actually go ahead and -// perform all interceptions and transfer data to the child application. -// -// The typical usage is something like this: -// -// InterceptionManager interception_manager(child); -// if (!interception_manager.AddToPatchedFunctions( -// L"ntdll.dll", "NtCreateFile", -// sandbox::INTERCEPTION_SERVICE_CALL, &MyNtCreateFile, MY_ID_1)) -// return false; -// -// if (!interception_manager.AddToPatchedFunctions( -// L"kernel32.dll", "CreateDirectoryW", -// sandbox::INTERCEPTION_EAT, L"MyCreateDirectoryW@12", MY_ID_2)) -// return false; -// -// if (!interception_manager.InitializeInterceptions()) { -// DWORD error = ::GetLastError(); -// return false; -// } -// -// Any required syncronization must be performed outside this class. Also, it is -// not possible to perform further interceptions after InitializeInterceptions -// is called. -// -class InterceptionManager { - // The unit test will access private members. - // Allow tests to be marked DISABLED_. Note that FLAKY_ and FAILS_ prefixes - // do not work with sandbox tests. - FRIEND_TEST_ALL_PREFIXES(InterceptionManagerTest, BufferLayout1); - FRIEND_TEST_ALL_PREFIXES(InterceptionManagerTest, BufferLayout2); - - public: - // An interception manager performs interceptions on a given child process. - // If we are allowed to intercept functions that have been patched by somebody - // else, relaxed should be set to true. - // Note: We increase the child's reference count internally. - InterceptionManager(TargetProcess* child_process, bool relaxed); - ~InterceptionManager(); - - // Patches function_name inside dll_name to point to replacement_code_address. - // function_name has to be an exported symbol of dll_name. - // Returns true on success. - // - // The new function should match the prototype and calling convention of the - // function to intercept except for one extra argument (the first one) that - // contains a pointer to the original function, to simplify the development - // of interceptors (for IA32). In x64, there is no extra argument to the - // interceptor, so the provided InterceptorId is used to keep a table of - // intercepted functions so that the interceptor can index that table to get - // the pointer that would have been the first argument (g_originals[id]). - // - // For example, to intercept NtClose, the following code could be used: - // - // typedef NTSTATUS (WINAPI *NtCloseFunction) (IN HANDLE Handle); - // NTSTATUS WINAPI MyNtCose(IN NtCloseFunction OriginalClose, - // IN HANDLE Handle) { - // // do something - // // call the original function - // return OriginalClose(Handle); - // } - // - // And in x64: - // - // typedef NTSTATUS (WINAPI *NtCloseFunction) (IN HANDLE Handle); - // NTSTATUS WINAPI MyNtCose64(IN HANDLE Handle) { - // // do something - // // call the original function - // NtCloseFunction OriginalClose = g_originals[NT_CLOSE_ID]; - // return OriginalClose(Handle); - // } - bool AddToPatchedFunctions(const wchar_t* dll_name, - const char* function_name, - InterceptionType interception_type, - const void* replacement_code_address, - InterceptorId id); - - // Patches function_name inside dll_name to point to - // replacement_function_name. - bool AddToPatchedFunctions(const wchar_t* dll_name, - const char* function_name, - InterceptionType interception_type, - const char* replacement_function_name, - InterceptorId id); - - // The interception agent will unload the dll with dll_name. - bool AddToUnloadModules(const wchar_t* dll_name); - - // Initializes all interceptions on the client. - // Returns true on success. - // - // The child process must be created suspended, and cannot be resumed until - // after this method returns. In addition, no action should be performed on - // the child that may cause it to resume momentarily, such as injecting - // threads or APCs. - // - // This function must be called only once, after all interceptions have been - // set up using AddToPatchedFunctions. - bool InitializeInterceptions(); - - private: - // Used to store the interception information until the actual set-up. - struct InterceptionData { - InterceptionData(); - ~InterceptionData(); - - InterceptionType type; // Interception type. - InterceptorId id; // Interceptor id. - base::string16 dll; // Name of dll to intercept. - std::string function; // Name of function to intercept. - std::string interceptor; // Name of interceptor function. - const void* interceptor_address; // Interceptor's entry point. - }; - - // Calculates the size of the required configuration buffer. - size_t GetBufferSize() const; - - // Rounds up the size of a given buffer, considering alignment (padding). - // value is the current size of the buffer, and alignment is specified in - // bytes. - static inline size_t RoundUpToMultiple(size_t value, size_t alignment) { - return ((value + alignment -1) / alignment) * alignment; - } - - // Sets up a given buffer with all the information that has to be transfered - // to the child. - // Returns true on success. - // - // The buffer size should be at least the value returned by GetBufferSize - bool SetupConfigBuffer(void* buffer, size_t buffer_bytes); - - // Fills up the part of the transfer buffer that corresponds to information - // about one dll to patch. - // data is the first recorded interception for this dll. - // Returns true on success. - // - // On successful return, buffer will be advanced from it's current position - // to the point where the next block of configuration data should be written - // (the actual interception info), and the current size of the buffer will - // decrease to account the space used by this method. - bool SetupDllInfo(const InterceptionData& data, - void** buffer, size_t* buffer_bytes) const; - - // Fills up the part of the transfer buffer that corresponds to a single - // function to patch. - // dll_info points to the dll being updated with the interception stored on - // data. The buffer pointer and remaining size are updated by this call. - // Returns true on success. - bool SetupInterceptionInfo(const InterceptionData& data, void** buffer, - size_t* buffer_bytes, - DllPatchInfo* dll_info) const; - - // Returns true if this interception is to be performed by the child - // as opposed to from the parent. - bool IsInterceptionPerformedByChild(const InterceptionData& data) const; - - // Allocates a buffer on the child's address space (returned on - // remote_buffer), and fills it with the contents of a local buffer. - // Returns true on success. - bool CopyDataToChild(const void* local_buffer, size_t buffer_bytes, - void** remote_buffer) const; - - // Performs the cold patch (from the parent) of ntdll. - // Returns true on success. - // - // This method will insert additional interceptions to launch the interceptor - // agent on the child process, if there are additional interceptions to do. - bool PatchNtdll(bool hot_patch_needed); - - // Peforms the actual interceptions on ntdll. - // thunks is the memory to store all the thunks for this dll (on the child), - // and dll_data is a local buffer to hold global dll interception info. - // Returns true on success. - bool PatchClientFunctions(DllInterceptionData* thunks, - size_t thunk_bytes, - DllInterceptionData* dll_data); - - // The process to intercept. - TargetProcess* child_; - // Holds all interception info until the call to initialize (perform the - // actual patch). - std::list<InterceptionData> interceptions_; - - // Keep track of patches added by name. - bool names_used_; - - // true if we are allowed to patch already-patched functions. - bool relaxed_; - - DISALLOW_COPY_AND_ASSIGN(InterceptionManager); -}; - -// This macro simply calls interception_manager.AddToPatchedFunctions with -// the given service to intercept (INTERCEPTION_SERVICE_CALL), and assumes that -// the interceptor is called "TargetXXX", where XXX is the name of the service. -// Note that num_params is the number of bytes to pop out of the stack for -// the exported interceptor, following the calling convention of a service call -// (WINAPI = with the "C" underscore). -#if SANDBOX_EXPORTS -#if defined(_WIN64) -#define MAKE_SERVICE_NAME(service, params) "Target" # service "64" -#else -#define MAKE_SERVICE_NAME(service, params) "_Target" # service "@" # params -#endif - -#define ADD_NT_INTERCEPTION(service, id, num_params) \ - AddToPatchedFunctions(kNtdllName, #service, \ - sandbox::INTERCEPTION_SERVICE_CALL, \ - MAKE_SERVICE_NAME(service, num_params), id) - -#define INTERCEPT_NT(manager, service, id, num_params) \ - ((&Target##service) ? \ - manager->ADD_NT_INTERCEPTION(service, id, num_params) : false) - -// When intercepting the EAT it is important that the patched version of the -// function not call any functions imported from system libraries unless -// |TargetServices::InitCalled()| returns true, because it is only then that -// we are guaranteed that our IAT has been initialized. -#define INTERCEPT_EAT(manager, dll, function, id, num_params) \ - ((&Target##function) ? \ - manager->AddToPatchedFunctions(dll, #function, sandbox::INTERCEPTION_EAT, \ - MAKE_SERVICE_NAME(function, num_params), \ - id) : \ - false) -#else // SANDBOX_EXPORTS -#if defined(_WIN64) -#define MAKE_SERVICE_NAME(service) &Target##service##64 -#else -#define MAKE_SERVICE_NAME(service) &Target##service -#endif - -#define ADD_NT_INTERCEPTION(service, id, num_params) \ - AddToPatchedFunctions(kNtdllName, #service, \ - sandbox::INTERCEPTION_SERVICE_CALL, \ - MAKE_SERVICE_NAME(service), id) - -#define INTERCEPT_NT(manager, service, id, num_params) \ - manager->ADD_NT_INTERCEPTION(service, id, num_params) - -// When intercepting the EAT it is important that the patched version of the -// function not call any functions imported from system libraries unless -// |TargetServices::InitCalled()| returns true, because it is only then that -// we are guaranteed that our IAT has been initialized. -#define INTERCEPT_EAT(manager, dll, function, id, num_params) \ - manager->AddToPatchedFunctions(dll, #function, sandbox::INTERCEPTION_EAT, \ - MAKE_SERVICE_NAME(function), id) -#endif // SANDBOX_EXPORTS - -} // namespace sandbox - -#endif // SANDBOX_SRC_INTERCEPTION_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/interception_agent.cc b/security/sandbox/chromium/sandbox/win/src/interception_agent.cc deleted file mode 100644 index 1ef688638..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interception_agent.cc +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// For information about interceptions as a whole see -// http://dev.chromium.org/developers/design-documents/sandbox . - -#include "sandbox/win/src/interception_agent.h" - -#include <stddef.h> - -#include "sandbox/win/src/eat_resolver.h" -#include "sandbox/win/src/interception_internal.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sidestep_resolver.h" - -namespace { - -// Returns true if target lies between base and base + range. -bool IsWithinRange(const void* base, size_t range, const void* target) { - const char* end = reinterpret_cast<const char*>(base) + range; - return reinterpret_cast<const char*>(target) < end; -} - -} // namespace - -namespace sandbox { - -// This is the list of all imported symbols from ntdll.dll. -SANDBOX_INTERCEPT NtExports g_nt; - -// The list of intercepted functions back-pointers. -SANDBOX_INTERCEPT OriginalFunctions g_originals; - -// Memory buffer mapped from the parent, with the list of interceptions. -SANDBOX_INTERCEPT SharedMemory* g_interceptions = NULL; - -InterceptionAgent* InterceptionAgent::GetInterceptionAgent() { - static InterceptionAgent* s_singleton = NULL; - if (!s_singleton) { - if (!g_interceptions) - return NULL; - - size_t array_bytes = g_interceptions->num_intercepted_dlls * sizeof(void*); - s_singleton = reinterpret_cast<InterceptionAgent*>( - new(NT_ALLOC) char[array_bytes + sizeof(InterceptionAgent)]); - - bool success = s_singleton->Init(g_interceptions); - if (!success) { - operator delete(s_singleton, NT_ALLOC); - s_singleton = NULL; - } - } - return s_singleton; -} - -bool InterceptionAgent::Init(SharedMemory* shared_memory) { - interceptions_ = shared_memory; - for (int i = 0 ; i < shared_memory->num_intercepted_dlls; i++) - dlls_[i] = NULL; - return true; -} - -bool InterceptionAgent::DllMatch(const UNICODE_STRING* full_path, - const UNICODE_STRING* name, - const DllPatchInfo* dll_info) { - UNICODE_STRING current_name; - current_name.Length = static_cast<USHORT>(g_nt.wcslen(dll_info->dll_name) * - sizeof(wchar_t)); - current_name.MaximumLength = current_name.Length; - current_name.Buffer = const_cast<wchar_t*>(dll_info->dll_name); - - BOOLEAN case_insensitive = TRUE; - if (full_path && - !g_nt.RtlCompareUnicodeString(¤t_name, full_path, case_insensitive)) - return true; - - if (name && - !g_nt.RtlCompareUnicodeString(¤t_name, name, case_insensitive)) - return true; - - return false; -} - -bool InterceptionAgent::OnDllLoad(const UNICODE_STRING* full_path, - const UNICODE_STRING* name, - void* base_address) { - DllPatchInfo* dll_info = interceptions_->dll_list; - int i = 0; - for (; i < interceptions_->num_intercepted_dlls; i++) { - if (DllMatch(full_path, name, dll_info)) - break; - - dll_info = reinterpret_cast<DllPatchInfo*>( - reinterpret_cast<char*>(dll_info) + dll_info->record_bytes); - } - - // Return now if the dll is not in our list of interest. - if (i == interceptions_->num_intercepted_dlls) - return true; - - // The dll must be unloaded. - if (dll_info->unload_module) - return false; - - // Purify causes this condition to trigger. - if (dlls_[i]) - return true; - - size_t buffer_bytes = offsetof(DllInterceptionData, thunks) + - dll_info->num_functions * sizeof(ThunkData); - dlls_[i] = reinterpret_cast<DllInterceptionData*>( - new(NT_PAGE, base_address) char[buffer_bytes]); - - DCHECK_NT(dlls_[i]); - if (!dlls_[i]) - return true; - - dlls_[i]->data_bytes = buffer_bytes; - dlls_[i]->num_thunks = 0; - dlls_[i]->base = base_address; - dlls_[i]->used_bytes = offsetof(DllInterceptionData, thunks); - - VERIFY(PatchDll(dll_info, dlls_[i])); - - ULONG old_protect; - SIZE_T real_size = buffer_bytes; - void* to_protect = dlls_[i]; - VERIFY_SUCCESS(g_nt.ProtectVirtualMemory(NtCurrentProcess, &to_protect, - &real_size, PAGE_EXECUTE_READ, - &old_protect)); - return true; -} - -void InterceptionAgent::OnDllUnload(void* base_address) { - for (int i = 0; i < interceptions_->num_intercepted_dlls; i++) { - if (dlls_[i] && dlls_[i]->base == base_address) { - operator delete(dlls_[i], NT_PAGE); - dlls_[i] = NULL; - break; - } - } -} - -// TODO(rvargas): We have to deal with prebinded dlls. I see two options: change -// the timestamp of the patched dll, or modify the info on the prebinded dll. -// the first approach messes matching of debug symbols, the second one is more -// complicated. -bool InterceptionAgent::PatchDll(const DllPatchInfo* dll_info, - DllInterceptionData* thunks) { - DCHECK_NT(NULL != thunks); - DCHECK_NT(NULL != dll_info); - - const FunctionInfo* function = reinterpret_cast<const FunctionInfo*>( - reinterpret_cast<const char*>(dll_info) + dll_info->offset_to_functions); - - for (int i = 0; i < dll_info->num_functions; i++) { - if (!IsWithinRange(dll_info, dll_info->record_bytes, function->function)) { - NOTREACHED_NT(); - return false; - } - - ResolverThunk* resolver = GetResolver(function->type); - if (!resolver) - return false; - - const char* interceptor = function->function + - g_nt.strlen(function->function) + 1; - - if (!IsWithinRange(function, function->record_bytes, interceptor) || - !IsWithinRange(dll_info, dll_info->record_bytes, interceptor)) { - NOTREACHED_NT(); - return false; - } - - NTSTATUS ret = resolver->Setup(thunks->base, - interceptions_->interceptor_base, - function->function, - interceptor, - function->interceptor_address, - &thunks->thunks[i], - sizeof(ThunkData), - NULL); - if (!NT_SUCCESS(ret)) { - NOTREACHED_NT(); - return false; - } - - DCHECK_NT(!g_originals[function->id]); - g_originals[function->id] = &thunks->thunks[i]; - - thunks->num_thunks++; - thunks->used_bytes += sizeof(ThunkData); - - function = reinterpret_cast<const FunctionInfo*>( - reinterpret_cast<const char*>(function) + function->record_bytes); - } - - return true; -} - -// This method is called from within the loader lock -ResolverThunk* InterceptionAgent::GetResolver(InterceptionType type) { - static EatResolverThunk* eat_resolver = NULL; - static SidestepResolverThunk* sidestep_resolver = NULL; - static SmartSidestepResolverThunk* smart_sidestep_resolver = NULL; - - if (!eat_resolver) - eat_resolver = new(NT_ALLOC) EatResolverThunk; - -#if !defined(_WIN64) - // Sidestep is not supported for x64. - if (!sidestep_resolver) - sidestep_resolver = new(NT_ALLOC) SidestepResolverThunk; - - if (!smart_sidestep_resolver) - smart_sidestep_resolver = new(NT_ALLOC) SmartSidestepResolverThunk; -#endif - - switch (type) { - case INTERCEPTION_EAT: - return eat_resolver; - case INTERCEPTION_SIDESTEP: - return sidestep_resolver; - case INTERCEPTION_SMART_SIDESTEP: - return smart_sidestep_resolver; - default: - NOTREACHED_NT(); - } - - return NULL; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/interception_agent.h b/security/sandbox/chromium/sandbox/win/src/interception_agent.h deleted file mode 100644 index b2bce08b0..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interception_agent.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Defines InterceptionAgent, the class in charge of setting up interceptions -// from the inside of the sandboxed process. For more details see -// http://dev.chromium.org/developers/design-documents/sandbox . - -#ifndef SANDBOX_SRC_INTERCEPTION_AGENT_H__ -#define SANDBOX_SRC_INTERCEPTION_AGENT_H__ - -#include "base/macros.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace sandbox { - -// Internal structures used for communication between the broker and the target. -struct DllInterceptionData; -struct SharedMemory; -struct DllPatchInfo; - -class ResolverThunk; - -// The InterceptionAgent executes on the target application, and it is in charge -// of setting up the desired interceptions or indicating what module needs to -// be unloaded. -// -// The exposed API consists of three methods: GetInterceptionAgent to retrieve -// the single class instance, OnDllLoad and OnDllUnload to process a dll being -// loaded and unloaded respectively. -// -// This class assumes that it will get called for every dll being loaded, -// starting with kernel32, so the singleton will be instantiated from within the -// loader lock. -class InterceptionAgent { - public: - // Returns the single InterceptionAgent object for this process. - static InterceptionAgent* GetInterceptionAgent(); - - // This method should be invoked whenever a new dll is loaded to perform the - // required patches. If the return value is false, this dll should not be - // allowed to load. - // - // full_path is the (optional) full name of the module being loaded and name - // is the internal module name. If full_path is provided, it will be used - // before the internal name to determine if we care about this dll. - bool OnDllLoad(const UNICODE_STRING* full_path, const UNICODE_STRING* name, - void* base_address); - - // Performs cleanup when a dll is unloaded. - void OnDllUnload(void* base_address); - - private: - ~InterceptionAgent() {} - - // Performs initialization of the singleton. - bool Init(SharedMemory* shared_memory); - - // Returns true if we are interested on this dll. dll_info is an entry of the - // list of intercepted dlls. - bool DllMatch(const UNICODE_STRING* full_path, const UNICODE_STRING* name, - const DllPatchInfo* dll_info); - - // Performs the patching of the dll loaded at base_address. - // The patches to perform are described on dll_info, and thunks is the thunk - // storage for the whole dll. - // Returns true on success. - bool PatchDll(const DllPatchInfo* dll_info, DllInterceptionData* thunks); - - // Returns a resolver for a given interception type. - ResolverThunk* GetResolver(InterceptionType type); - - // Shared memory containing the list of functions to intercept. - SharedMemory* interceptions_; - - // Array of thunk data buffers for the intercepted dlls. This object singleton - // is allocated with a placement new with enough space to hold the complete - // array of pointers, not just the first element. - DllInterceptionData* dlls_[1]; - - DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptionAgent); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_INTERCEPTION_AGENT_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/interception_internal.h b/security/sandbox/chromium/sandbox/win/src/interception_internal.h deleted file mode 100644 index 45a0557e5..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interception_internal.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Defines InterceptionManager, the class in charge of setting up interceptions -// for the sandboxed process. For more details see: -// http://dev.chromium.org/developers/design-documents/sandbox . - -#ifndef SANDBOX_SRC_INTERCEPTION_INTERNAL_H_ -#define SANDBOX_SRC_INTERCEPTION_INTERNAL_H_ - -#include <stddef.h> - -#include "sandbox/win/src/sandbox_types.h" - -namespace sandbox { - -const int kMaxThunkDataBytes = 64; - -enum InterceptorId; - -// The following structures contain variable size fields at the end, and will be -// used to transfer information between two processes. In order to guarantee -// our ability to follow the chain of structures, the alignment should be fixed, -// hence this pragma. -#pragma pack(push, 4) - -// Structures for the shared memory that contains patching information -// for the InterceptionAgent. -// A single interception: -struct FunctionInfo { - size_t record_bytes; // rounded to sizeof(size_t) bytes - InterceptionType type; - InterceptorId id; - const void* interceptor_address; - char function[1]; // placeholder for null terminated name - // char interceptor[] // followed by the interceptor function -}; - -// A single dll: -struct DllPatchInfo { - size_t record_bytes; // rounded to sizeof(size_t) bytes - size_t offset_to_functions; - int num_functions; - bool unload_module; - wchar_t dll_name[1]; // placeholder for null terminated name - // FunctionInfo function_info[] // followed by the functions to intercept -}; - -// All interceptions: -struct SharedMemory { - int num_intercepted_dlls; - void* interceptor_base; - DllPatchInfo dll_list[1]; // placeholder for the list of dlls -}; - -// Dummy single thunk: -struct ThunkData { - char data[kMaxThunkDataBytes]; -}; - -// In-memory representation of the interceptions for a given dll: -struct DllInterceptionData { - size_t data_bytes; - size_t used_bytes; - void* base; - int num_thunks; -#if defined(_WIN64) - int dummy; // Improve alignment. -#endif - ThunkData thunks[1]; -}; - -#pragma pack(pop) - -} // namespace sandbox - -#endif // SANDBOX_SRC_INTERCEPTION_INTERNAL_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/interception_unittest.cc b/security/sandbox/chromium/sandbox/win/src/interception_unittest.cc deleted file mode 100644 index 7b7932af6..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interception_unittest.cc +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains unit tests for InterceptionManager. -// The tests require private information so the whole interception.cc file is -// included from this file. - -#include <windows.h> -#include <stddef.h> - -#include <algorithm> -#include <set> - -#include "base/bits.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/interception_internal.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/target_process.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -namespace internal { -size_t GetGranularAlignedRandomOffset(size_t size); -} - -// Walks the settings buffer, verifying that the values make sense and counting -// objects. -// Arguments: -// buffer (in): the buffer to walk. -// size (in): buffer size -// num_dlls (out): count of the dlls on the buffer. -// num_function (out): count of intercepted functions. -// num_names (out): count of named interceptor functions. -void WalkBuffer(void* buffer, size_t size, int* num_dlls, int* num_functions, - int* num_names) { - ASSERT_TRUE(NULL != buffer); - ASSERT_TRUE(NULL != num_functions); - ASSERT_TRUE(NULL != num_names); - *num_dlls = *num_functions = *num_names = 0; - SharedMemory *memory = reinterpret_cast<SharedMemory*>(buffer); - - ASSERT_GT(size, sizeof(SharedMemory)); - DllPatchInfo *dll = &memory->dll_list[0]; - - for (int i = 0; i < memory->num_intercepted_dlls; i++) { - ASSERT_NE(0u, wcslen(dll->dll_name)); - ASSERT_EQ(0u, dll->record_bytes % sizeof(size_t)); - ASSERT_EQ(0u, dll->offset_to_functions % sizeof(size_t)); - ASSERT_NE(0, dll->num_functions); - - FunctionInfo *function = reinterpret_cast<FunctionInfo*>( - reinterpret_cast<char*>(dll) + dll->offset_to_functions); - - for (int j = 0; j < dll->num_functions; j++) { - ASSERT_EQ(0u, function->record_bytes % sizeof(size_t)); - - char* name = function->function; - size_t length = strlen(name); - ASSERT_NE(0u, length); - name += length + 1; - - // look for overflows - ASSERT_GT(reinterpret_cast<char*>(buffer) + size, name + strlen(name)); - - // look for a named interceptor - if (strlen(name)) { - (*num_names)++; - EXPECT_TRUE(NULL == function->interceptor_address); - } else { - EXPECT_TRUE(NULL != function->interceptor_address); - } - - (*num_functions)++; - function = reinterpret_cast<FunctionInfo*>( - reinterpret_cast<char*>(function) + function->record_bytes); - } - - (*num_dlls)++; - dll = reinterpret_cast<DllPatchInfo*>(reinterpret_cast<char*>(dll) + - dll->record_bytes); - } -} - -TEST(InterceptionManagerTest, GetGranularAlignedRandomOffset) { - std::set<size_t> sizes; - - // 544 is current value of interceptions_.size() * sizeof(ThunkData) + - // sizeof(DllInterceptionData). - const size_t kThunkBytes = 544; - - // ciel(log2(544)) = 10. - // Alignment must be 2^10 = 1024. - const size_t kAlignmentBits = base::bits::Log2Ceiling(kThunkBytes); - const size_t kAlignment = static_cast<size_t>(1) << kAlignmentBits; - - const size_t kAllocGranularity = 65536; - - // Generate enough sample data to ensure there is at least one value in each - // potential bucket. - for (size_t i = 0; i < 1000000; i++) - sizes.insert(internal::GetGranularAlignedRandomOffset(kThunkBytes)); - - size_t prev_val = 0; - size_t min_val = kAllocGranularity; - size_t min_nonzero_val = kAllocGranularity; - size_t max_val = 0; - - for (size_t val : sizes) { - ASSERT_LT(val, kAllocGranularity); - if (prev_val) - ASSERT_EQ(val - prev_val, kAlignment); - if (val) - min_nonzero_val = std::min(val, min_nonzero_val); - min_val = std::min(val, min_val); - prev_val = val; - max_val = std::max(val, max_val); - } - ASSERT_EQ(max_val, kAllocGranularity - kAlignment); - ASSERT_EQ(0u, min_val); - ASSERT_EQ(min_nonzero_val, kAlignment); -} - -TEST(InterceptionManagerTest, BufferLayout1) { - wchar_t exe_name[MAX_PATH]; - ASSERT_NE(0u, GetModuleFileName(NULL, exe_name, MAX_PATH - 1)); - - TargetProcess *target = MakeTestTargetProcess(::GetCurrentProcess(), - ::GetModuleHandle(exe_name)); - - InterceptionManager interceptions(target, true); - - // Any pointer will do for a function pointer. - void* function = &interceptions; - - // We don't care about the interceptor id. - interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtCreateFile", - INTERCEPTION_SERVICE_CALL, function, - OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateFileEx", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"kernel32.dll", "SomeFileEx", - INTERCEPTION_SMART_SIDESTEP, function, - OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"user32.dll", "FindWindow", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateMutex", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"user32.dll", "PostMsg", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"user32.dll", "PostMsg", - INTERCEPTION_EAT, "replacement", - OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtClose", - INTERCEPTION_SERVICE_CALL, function, - OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtOpenFile", - INTERCEPTION_SIDESTEP, function, - OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"some.dll", "Superfn", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg", - INTERCEPTION_EAT, "a", OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg", - INTERCEPTION_SIDESTEP, "ab", OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg", - INTERCEPTION_EAT, "abc", OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"a.dll", "p", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"b.dll", - "TheIncredibleCallToSaveTheWorld", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"a.dll", "BIsLame", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - interceptions.AddToPatchedFunctions(L"a.dll", "ARules", - INTERCEPTION_EAT, function, OPEN_KEY_ID); - - // Verify that all interceptions were added - ASSERT_EQ(18u, interceptions.interceptions_.size()); - - size_t buffer_size = interceptions.GetBufferSize(); - scoped_ptr<BYTE[]> local_buffer(new BYTE[buffer_size]); - - ASSERT_TRUE(interceptions.SetupConfigBuffer(local_buffer.get(), - buffer_size)); - - // At this point, the interceptions should have been separated into two - // groups: one group with the local ("cold") interceptions, consisting of - // everything from ntdll and stuff set as INTRECEPTION_SERVICE_CALL, and - // another group with the interceptions belonging to dlls that will be "hot" - // patched on the client. The second group lives on local_buffer, and the - // first group remains on the list of interceptions (inside the object - // "interceptions"). There are 3 local interceptions (of ntdll); the - // other 15 have to be sent to the child to be performed "hot". - EXPECT_EQ(3u, interceptions.interceptions_.size()); - - int num_dlls, num_functions, num_names; - WalkBuffer(local_buffer.get(), buffer_size, &num_dlls, &num_functions, - &num_names); - - // The 15 interceptions on the buffer (to the child) should be grouped on 6 - // dlls. Only four interceptions are using an explicit name for the - // interceptor function. - EXPECT_EQ(6, num_dlls); - EXPECT_EQ(15, num_functions); - EXPECT_EQ(4, num_names); -} - -TEST(InterceptionManagerTest, BufferLayout2) { - wchar_t exe_name[MAX_PATH]; - ASSERT_NE(0u, GetModuleFileName(NULL, exe_name, MAX_PATH - 1)); - - TargetProcess *target = MakeTestTargetProcess(::GetCurrentProcess(), - ::GetModuleHandle(exe_name)); - - InterceptionManager interceptions(target, true); - - // Any pointer will do for a function pointer. - void* function = &interceptions; - interceptions.AddToUnloadModules(L"some01.dll"); - // We don't care about the interceptor id. - interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtCreateFile", - INTERCEPTION_SERVICE_CALL, function, - OPEN_FILE_ID); - interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateFileEx", - INTERCEPTION_EAT, function, OPEN_FILE_ID); - interceptions.AddToUnloadModules(L"some02.dll"); - interceptions.AddToPatchedFunctions(L"kernel32.dll", "SomeFileEx", - INTERCEPTION_SMART_SIDESTEP, function, - OPEN_FILE_ID); - // Verify that all interceptions were added - ASSERT_EQ(5u, interceptions.interceptions_.size()); - - size_t buffer_size = interceptions.GetBufferSize(); - scoped_ptr<BYTE[]> local_buffer(new BYTE[buffer_size]); - - ASSERT_TRUE(interceptions.SetupConfigBuffer(local_buffer.get(), - buffer_size)); - - // At this point, the interceptions should have been separated into two - // groups: one group with the local ("cold") interceptions, and another - // group with the interceptions belonging to dlls that will be "hot" - // patched on the client. The second group lives on local_buffer, and the - // first group remains on the list of interceptions, in this case just one. - EXPECT_EQ(1u, interceptions.interceptions_.size()); - - int num_dlls, num_functions, num_names; - WalkBuffer(local_buffer.get(), buffer_size, &num_dlls, &num_functions, - &num_names); - - EXPECT_EQ(3, num_dlls); - EXPECT_EQ(4, num_functions); - EXPECT_EQ(0, num_names); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/interceptors.h b/security/sandbox/chromium/sandbox/win/src/interceptors.h deleted file mode 100644 index a17447aa1..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interceptors.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_INTERCEPTORS_H_ -#define SANDBOX_SRC_INTERCEPTORS_H_ - -#if defined(_WIN64) -#include "sandbox/win/src/interceptors_64.h" -#endif - -namespace sandbox { - -enum InterceptorId { - // Internal use: - MAP_VIEW_OF_SECTION_ID = 0, - UNMAP_VIEW_OF_SECTION_ID, - // Policy broker: - SET_INFORMATION_THREAD_ID, - OPEN_THREAD_TOKEN_ID, - OPEN_THREAD_TOKEN_EX_ID, - OPEN_TREAD_ID, - OPEN_PROCESS_ID, - OPEN_PROCESS_TOKEN_ID, - OPEN_PROCESS_TOKEN_EX_ID, - // Filesystem dispatcher: - CREATE_FILE_ID, - OPEN_FILE_ID, - QUERY_ATTRIB_FILE_ID, - QUERY_FULL_ATTRIB_FILE_ID, - SET_INFO_FILE_ID, - // Named pipe dispatcher: - CREATE_NAMED_PIPE_ID, - // Process-thread dispatcher: - CREATE_PROCESSW_ID, - CREATE_PROCESSA_ID, - // Registry dispatcher: - CREATE_KEY_ID, - OPEN_KEY_ID, - OPEN_KEY_EX_ID, - // Sync dispatcher: - CREATE_EVENT_ID, - OPEN_EVENT_ID, - // Process mitigations Win32k dispatcher: - GDIINITIALIZE_ID, - GETSTOCKOBJECT_ID, - REGISTERCLASSW_ID, - INTERCEPTOR_MAX_ID -}; - -typedef void* OriginalFunctions[INTERCEPTOR_MAX_ID]; - -} // namespace sandbox - -#endif // SANDBOX_SRC_INTERCEPTORS_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/interceptors_64.cc b/security/sandbox/chromium/sandbox/win/src/interceptors_64.cc deleted file mode 100644 index ef0b5f001..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interceptors_64.cc +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/interceptors_64.h" - -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/filesystem_interception.h" -#include "sandbox/win/src/named_pipe_interception.h" -#include "sandbox/win/src/policy_target.h" -#include "sandbox/win/src/process_mitigations_win32k_interception.h" -#include "sandbox/win/src/process_thread_interception.h" -#include "sandbox/win/src/registry_interception.h" -#include "sandbox/win/src/sandbox_nt_types.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sync_interception.h" -#include "sandbox/win/src/target_interceptions.h" - -namespace sandbox { - -SANDBOX_INTERCEPT NtExports g_nt; -SANDBOX_INTERCEPT OriginalFunctions g_originals; - -NTSTATUS WINAPI TargetNtMapViewOfSection64( - HANDLE section, HANDLE process, PVOID *base, ULONG_PTR zero_bits, - SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size, - SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect) { - NtMapViewOfSectionFunction orig_fn = reinterpret_cast< - NtMapViewOfSectionFunction>(g_originals[MAP_VIEW_OF_SECTION_ID]); - - return TargetNtMapViewOfSection(orig_fn, section, process, base, zero_bits, - commit_size, offset, view_size, inherit, - allocation_type, protect); -} - -NTSTATUS WINAPI TargetNtUnmapViewOfSection64(HANDLE process, PVOID base) { - NtUnmapViewOfSectionFunction orig_fn = reinterpret_cast< - NtUnmapViewOfSectionFunction>(g_originals[UNMAP_VIEW_OF_SECTION_ID]); - return TargetNtUnmapViewOfSection(orig_fn, process, base); -} - -// ----------------------------------------------------------------------- - -NTSTATUS WINAPI TargetNtSetInformationThread64( - HANDLE thread, NT_THREAD_INFORMATION_CLASS thread_info_class, - PVOID thread_information, ULONG thread_information_bytes) { - NtSetInformationThreadFunction orig_fn = reinterpret_cast< - NtSetInformationThreadFunction>(g_originals[SET_INFORMATION_THREAD_ID]); - return TargetNtSetInformationThread(orig_fn, thread, thread_info_class, - thread_information, - thread_information_bytes); -} - -NTSTATUS WINAPI TargetNtOpenThreadToken64( - HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, - PHANDLE token) { - NtOpenThreadTokenFunction orig_fn = reinterpret_cast< - NtOpenThreadTokenFunction>(g_originals[OPEN_THREAD_TOKEN_ID]); - return TargetNtOpenThreadToken(orig_fn, thread, desired_access, open_as_self, - token); -} - -NTSTATUS WINAPI TargetNtOpenThreadTokenEx64( - HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, - ULONG handle_attributes, PHANDLE token) { - NtOpenThreadTokenExFunction orig_fn = reinterpret_cast< - NtOpenThreadTokenExFunction>(g_originals[OPEN_THREAD_TOKEN_EX_ID]); - return TargetNtOpenThreadTokenEx(orig_fn, thread, desired_access, - open_as_self, handle_attributes, token); -} - -// ----------------------------------------------------------------------- - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateFile64( - PHANDLE file, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PIO_STATUS_BLOCK io_status, - PLARGE_INTEGER allocation_size, ULONG file_attributes, ULONG sharing, - ULONG disposition, ULONG options, PVOID ea_buffer, ULONG ea_length) { - NtCreateFileFunction orig_fn = reinterpret_cast< - NtCreateFileFunction>(g_originals[CREATE_FILE_ID]); - return TargetNtCreateFile(orig_fn, file, desired_access, object_attributes, - io_status, allocation_size, file_attributes, - sharing, disposition, options, ea_buffer, - ea_length); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenFile64( - PHANDLE file, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PIO_STATUS_BLOCK io_status, - ULONG sharing, ULONG options) { - NtOpenFileFunction orig_fn = reinterpret_cast< - NtOpenFileFunction>(g_originals[OPEN_FILE_ID]); - return TargetNtOpenFile(orig_fn, file, desired_access, object_attributes, - io_status, sharing, options); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtQueryAttributesFile64( - POBJECT_ATTRIBUTES object_attributes, - PFILE_BASIC_INFORMATION file_attributes) { - NtQueryAttributesFileFunction orig_fn = reinterpret_cast< - NtQueryAttributesFileFunction>(g_originals[QUERY_ATTRIB_FILE_ID]); - return TargetNtQueryAttributesFile(orig_fn, object_attributes, - file_attributes); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtQueryFullAttributesFile64( - POBJECT_ATTRIBUTES object_attributes, - PFILE_NETWORK_OPEN_INFORMATION file_attributes) { - NtQueryFullAttributesFileFunction orig_fn = reinterpret_cast< - NtQueryFullAttributesFileFunction>( - g_originals[QUERY_FULL_ATTRIB_FILE_ID]); - return TargetNtQueryFullAttributesFile(orig_fn, object_attributes, - file_attributes); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationFile64( - HANDLE file, PIO_STATUS_BLOCK io_status, PVOID file_information, - ULONG length, FILE_INFORMATION_CLASS file_information_class) { - NtSetInformationFileFunction orig_fn = reinterpret_cast< - NtSetInformationFileFunction>(g_originals[SET_INFO_FILE_ID]); - return TargetNtSetInformationFile(orig_fn, file, io_status, file_information, - length, file_information_class); -} - -// ----------------------------------------------------------------------- - -SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateNamedPipeW64( - LPCWSTR pipe_name, DWORD open_mode, DWORD pipe_mode, DWORD max_instance, - DWORD out_buffer_size, DWORD in_buffer_size, DWORD default_timeout, - LPSECURITY_ATTRIBUTES security_attributes) { - CreateNamedPipeWFunction orig_fn = reinterpret_cast< - CreateNamedPipeWFunction>(g_originals[CREATE_NAMED_PIPE_ID]); - return TargetCreateNamedPipeW(orig_fn, pipe_name, open_mode, pipe_mode, - max_instance, out_buffer_size, in_buffer_size, - default_timeout, security_attributes); -} - -// ----------------------------------------------------------------------- - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThread64( - PHANDLE thread, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PCLIENT_ID client_id) { - NtOpenThreadFunction orig_fn = reinterpret_cast< - NtOpenThreadFunction>(g_originals[OPEN_TREAD_ID]); - return TargetNtOpenThread(orig_fn, thread, desired_access, object_attributes, - client_id); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcess64( - PHANDLE process, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PCLIENT_ID client_id) { - NtOpenProcessFunction orig_fn = reinterpret_cast< - NtOpenProcessFunction>(g_originals[OPEN_PROCESS_ID]); - return TargetNtOpenProcess(orig_fn, process, desired_access, - object_attributes, client_id); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcessToken64( - HANDLE process, ACCESS_MASK desired_access, PHANDLE token) { - NtOpenProcessTokenFunction orig_fn = reinterpret_cast< - NtOpenProcessTokenFunction>(g_originals[OPEN_PROCESS_TOKEN_ID]); - return TargetNtOpenProcessToken(orig_fn, process, desired_access, token); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcessTokenEx64( - HANDLE process, ACCESS_MASK desired_access, ULONG handle_attributes, - PHANDLE token) { - NtOpenProcessTokenExFunction orig_fn = reinterpret_cast< - NtOpenProcessTokenExFunction>(g_originals[OPEN_PROCESS_TOKEN_EX_ID]); - return TargetNtOpenProcessTokenEx(orig_fn, process, desired_access, - handle_attributes, token); -} - -SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessW64( - LPCWSTR application_name, LPWSTR command_line, - LPSECURITY_ATTRIBUTES process_attributes, - LPSECURITY_ATTRIBUTES thread_attributes, BOOL inherit_handles, DWORD flags, - LPVOID environment, LPCWSTR current_directory, LPSTARTUPINFOW startup_info, - LPPROCESS_INFORMATION process_information) { - CreateProcessWFunction orig_fn = reinterpret_cast< - CreateProcessWFunction>(g_originals[CREATE_PROCESSW_ID]); - return TargetCreateProcessW(orig_fn, application_name, command_line, - process_attributes, thread_attributes, - inherit_handles, flags, environment, - current_directory, startup_info, - process_information); -} - -SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessA64( - LPCSTR application_name, LPSTR command_line, - LPSECURITY_ATTRIBUTES process_attributes, - LPSECURITY_ATTRIBUTES thread_attributes, BOOL inherit_handles, DWORD flags, - LPVOID environment, LPCSTR current_directory, LPSTARTUPINFOA startup_info, - LPPROCESS_INFORMATION process_information) { - CreateProcessAFunction orig_fn = reinterpret_cast< - CreateProcessAFunction>(g_originals[CREATE_PROCESSA_ID]); - return TargetCreateProcessA(orig_fn, application_name, command_line, - process_attributes, thread_attributes, - inherit_handles, flags, environment, - current_directory, startup_info, - process_information); -} - -// ----------------------------------------------------------------------- - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateKey64( - PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, ULONG title_index, - PUNICODE_STRING class_name, ULONG create_options, PULONG disposition) { - NtCreateKeyFunction orig_fn = reinterpret_cast< - NtCreateKeyFunction>(g_originals[CREATE_KEY_ID]); - return TargetNtCreateKey(orig_fn, key, desired_access, object_attributes, - title_index, class_name, create_options, - disposition); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKey64( - PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes) { - NtOpenKeyFunction orig_fn = reinterpret_cast< - NtOpenKeyFunction>(g_originals[OPEN_KEY_ID]); - return TargetNtOpenKey(orig_fn, key, desired_access, object_attributes); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKeyEx64( - PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, ULONG open_options) { - NtOpenKeyExFunction orig_fn = reinterpret_cast< - NtOpenKeyExFunction>(g_originals[OPEN_KEY_EX_ID]); - return TargetNtOpenKeyEx(orig_fn, key, desired_access, object_attributes, - open_options); -} - -// ----------------------------------------------------------------------- - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateEvent64( - PHANDLE event_handle, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, EVENT_TYPE event_type, - BOOLEAN initial_state) { - NtCreateEventFunction orig_fn = reinterpret_cast< - NtCreateEventFunction>(g_originals[CREATE_EVENT_ID]); - return TargetNtCreateEvent(orig_fn, event_handle, desired_access, - object_attributes, event_type, initial_state); -} - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenEvent64( - PHANDLE event_handle, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes) { - NtOpenEventFunction orig_fn = reinterpret_cast< - NtOpenEventFunction>(g_originals[OPEN_EVENT_ID]); - return TargetNtOpenEvent(orig_fn, event_handle, desired_access, - object_attributes); -} - -// ----------------------------------------------------------------------- - -SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize64( - HANDLE dll, - DWORD reason) { - GdiDllInitializeFunction orig_fn = reinterpret_cast< - GdiDllInitializeFunction>(g_originals[GDIINITIALIZE_ID]); - return TargetGdiDllInitialize(orig_fn, dll, reason); -} - -SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject64(int object) { - GetStockObjectFunction orig_fn = reinterpret_cast< - GetStockObjectFunction>(g_originals[GETSTOCKOBJECT_ID]); - return TargetGetStockObject(orig_fn, object); -} - -SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW64( - const WNDCLASS* wnd_class) { - RegisterClassWFunction orig_fn = reinterpret_cast< - RegisterClassWFunction>(g_originals[REGISTERCLASSW_ID]); - return TargetRegisterClassW(orig_fn, wnd_class); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/interceptors_64.h b/security/sandbox/chromium/sandbox/win/src/interceptors_64.h deleted file mode 100644 index 7368ceb84..000000000 --- a/security/sandbox/chromium/sandbox/win/src/interceptors_64.h +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_INTERCEPTORS_64_H_ -#define SANDBOX_SRC_INTERCEPTORS_64_H_ - -namespace sandbox { - -extern "C" { - -// Interception of NtMapViewOfSection on the child process. -// It should never be called directly. This function provides the means to -// detect dlls being loaded, so we can patch them if needed. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtMapViewOfSection64( - HANDLE section, HANDLE process, PVOID *base, ULONG_PTR zero_bits, - SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size, - SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect); - -// Interception of NtUnmapViewOfSection on the child process. -// It should never be called directly. This function provides the means to -// detect dlls being unloaded, so we can clean up our interceptions. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtUnmapViewOfSection64(HANDLE process, - PVOID base); - -// ----------------------------------------------------------------------- -// Interceptors without IPC. - -// Interception of NtSetInformationThread on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationThread64( - HANDLE thread, NT_THREAD_INFORMATION_CLASS thread_info_class, - PVOID thread_information, ULONG thread_information_bytes); - -// Interception of NtOpenThreadToken on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadToken64( - HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, - PHANDLE token); - -// Interception of NtOpenThreadTokenEx on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadTokenEx64( - HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, - ULONG handle_attributes, PHANDLE token); - -// ----------------------------------------------------------------------- -// Interceptors handled by the file system dispatcher. - -// Interception of NtCreateFile on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateFile64( - PHANDLE file, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PIO_STATUS_BLOCK io_status, - PLARGE_INTEGER allocation_size, ULONG file_attributes, ULONG sharing, - ULONG disposition, ULONG options, PVOID ea_buffer, ULONG ea_length); - -// Interception of NtOpenFile on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenFile64( - PHANDLE file, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PIO_STATUS_BLOCK io_status, - ULONG sharing, ULONG options); - -// Interception of NtQueryAtttributesFile on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtQueryAttributesFile64( - POBJECT_ATTRIBUTES object_attributes, - PFILE_BASIC_INFORMATION file_attributes); - -// Interception of NtQueryFullAtttributesFile on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtQueryFullAttributesFile64( - POBJECT_ATTRIBUTES object_attributes, - PFILE_NETWORK_OPEN_INFORMATION file_attributes); - -// Interception of NtSetInformationFile on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationFile64( - HANDLE file, PIO_STATUS_BLOCK io_status, PVOID file_information, - ULONG length, FILE_INFORMATION_CLASS file_information_class); - -// ----------------------------------------------------------------------- -// Interceptors handled by the named pipe dispatcher. - -// Interception of CreateNamedPipeW in kernel32.dll -SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateNamedPipeW64( - LPCWSTR pipe_name, DWORD open_mode, DWORD pipe_mode, DWORD max_instance, - DWORD out_buffer_size, DWORD in_buffer_size, DWORD default_timeout, - LPSECURITY_ATTRIBUTES security_attributes); - -// ----------------------------------------------------------------------- -// Interceptors handled by the process-thread dispatcher. - -// Interception of NtOpenThread on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThread64( - PHANDLE thread, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PCLIENT_ID client_id); - -// Interception of NtOpenProcess on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcess64( - PHANDLE process, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, PCLIENT_ID client_id); - -// Interception of NtOpenProcessToken on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcessToken64( - HANDLE process, ACCESS_MASK desired_access, PHANDLE token); - -// Interception of NtOpenProcessTokenEx on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcessTokenEx64( - HANDLE process, ACCESS_MASK desired_access, ULONG handle_attributes, - PHANDLE token); - -// Interception of CreateProcessW in kernel32.dll. -SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessW64( - LPCWSTR application_name, LPWSTR command_line, - LPSECURITY_ATTRIBUTES process_attributes, - LPSECURITY_ATTRIBUTES thread_attributes, BOOL inherit_handles, DWORD flags, - LPVOID environment, LPCWSTR current_directory, LPSTARTUPINFOW startup_info, - LPPROCESS_INFORMATION process_information); - -// Interception of CreateProcessA in kernel32.dll. -SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessA64( - LPCSTR application_name, LPSTR command_line, - LPSECURITY_ATTRIBUTES process_attributes, - LPSECURITY_ATTRIBUTES thread_attributes, BOOL inherit_handles, DWORD flags, - LPVOID environment, LPCSTR current_directory, LPSTARTUPINFOA startup_info, - LPPROCESS_INFORMATION process_information); - -// ----------------------------------------------------------------------- -// Interceptors handled by the registry dispatcher. - -// Interception of NtCreateKey on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateKey64( - PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, ULONG title_index, - PUNICODE_STRING class_name, ULONG create_options, PULONG disposition); - -// Interception of NtOpenKey on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKey64( - PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes); - -// Interception of NtOpenKeyEx on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKeyEx64( - PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, ULONG open_options); - -// ----------------------------------------------------------------------- -// Interceptors handled by the sync dispatcher. - -// Interception of NtCreateEvent/NtOpenEvent on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateEvent64( - PHANDLE event_handle, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, EVENT_TYPE event_type, - BOOLEAN initial_state); - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenEvent64( - PHANDLE event_handle, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes); - -// ----------------------------------------------------------------------- -// Interceptors handled by the process mitigations win32k lockdown code. - -// Interceptor for the GdiDllInitialize function. -SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize64( - HANDLE dll, - DWORD reason); - -// Interceptor for the GetStockObject function. -SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject64(int object); - -// Interceptor for the RegisterClassW function. -SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW64(const WNDCLASS* wnd_class); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_INTERCEPTORS_64_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/internal_types.h b/security/sandbox/chromium/sandbox/win/src/internal_types.h deleted file mode 100644 index e1028189d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/internal_types.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_INTERNAL_TYPES_H_ -#define SANDBOX_WIN_SRC_INTERNAL_TYPES_H_ - -#include <stdint.h> - -namespace sandbox { - -const wchar_t kNtdllName[] = L"ntdll.dll"; -const wchar_t kKerneldllName[] = L"kernel32.dll"; -const wchar_t kKernelBasedllName[] = L"kernelbase.dll"; - -// Defines the supported C++ types encoding to numeric id. Like a poor's man -// RTTI. Note that true C++ RTTI will not work because the types are not -// polymorphic anyway. -enum ArgType { - INVALID_TYPE = 0, - WCHAR_TYPE, - UINT32_TYPE, - UNISTR_TYPE, - VOIDPTR_TYPE, - INPTR_TYPE, - INOUTPTR_TYPE, - LAST_TYPE -}; - -// Encapsulates a pointer to a buffer and the size of the buffer. -class CountedBuffer { - public: - CountedBuffer(void* buffer, uint32_t size) : size_(size), buffer_(buffer) {} - - uint32_t Size() const { return size_; } - - void* Buffer() const { - return buffer_; - } - - private: - uint32_t size_; - void* buffer_; -}; - -// Helper class to convert void-pointer packed ints for both -// 32 and 64 bit builds. This construct is non-portable. -class IPCInt { - public: - explicit IPCInt(void* buffer) { - buffer_.vp = buffer; - } - - explicit IPCInt(unsigned __int32 i32) { - buffer_.vp = NULL; - buffer_.i32 = i32; - } - - unsigned __int32 As32Bit() const { - return buffer_.i32; - } - - void* AsVoidPtr() const { - return buffer_.vp; - } - - private: - union U { - void* vp; - unsigned __int32 i32; - } buffer_; -}; - -} // namespace sandbox - -#endif // SANDBOX_WIN_SRC_INTERNAL_TYPES_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_ping_test.cc b/security/sandbox/chromium/sandbox/win/src/ipc_ping_test.cc deleted file mode 100644 index 64e3de6c5..000000000 --- a/security/sandbox/chromium/sandbox/win/src/ipc_ping_test.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "testing/gtest/include/gtest/gtest.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/target_services.h" -#include "sandbox/win/tests/common/controller.h" - -namespace sandbox { - -// Tests that the IPC is working by issuing a special IPC that is not exposed -// in the public API. -SBOX_TESTS_COMMAND int IPC_Ping(int argc, wchar_t **argv) { - if (argc != 1) - return SBOX_TEST_FAILED; - - TargetServices* ts = SandboxFactory::GetTargetServices(); - if (NULL == ts) - return SBOX_TEST_FAILED; - - // Downcast because we have internal knowledge of the object returned. - TargetServicesBase* ts_base = reinterpret_cast<TargetServicesBase*>(ts); - - int version = 0; - if (L'1' == argv[0][0]) - version = 1; - else - version = 2; - - if (!ts_base->TestIPCPing(version)) - return SBOX_TEST_FAILED; - - ::Sleep(1); - if (!ts_base->TestIPCPing(version)) - return SBOX_TEST_FAILED; - - return SBOX_TEST_SUCCEEDED; -} - -// The IPC ping test should work before and after the token drop. -TEST(IPCTest, IPCPingTestSimple) { - TestRunner runner; - runner.SetTimeout(2000); - runner.SetTestState(EVERY_STATE); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"IPC_Ping 1")); -} - -TEST(IPCTest, IPCPingTestWithOutput) { - TestRunner runner; - runner.SetTimeout(2000); - runner.SetTestState(EVERY_STATE); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"IPC_Ping 2")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"IPC_Ping 2")); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h deleted file mode 100644 index d680411da..000000000 --- a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_IPC_TAGS_H__ -#define SANDBOX_SRC_IPC_TAGS_H__ - -namespace sandbox { - -enum { - IPC_UNUSED_TAG = 0, - IPC_PING1_TAG, // Takes a cookie in parameters and returns the cookie - // multiplied by 2 and the tick_count. Used for testing only. - IPC_PING2_TAG, // Takes an in/out cookie in parameters and modify the cookie - // to be multiplied by 3. Used for testing only. - IPC_NTCREATEFILE_TAG, - IPC_NTOPENFILE_TAG, - IPC_NTQUERYATTRIBUTESFILE_TAG, - IPC_NTQUERYFULLATTRIBUTESFILE_TAG, - IPC_NTSETINFO_RENAME_TAG, - IPC_CREATENAMEDPIPEW_TAG, - IPC_NTOPENTHREAD_TAG, - IPC_NTOPENPROCESS_TAG, - IPC_NTOPENPROCESSTOKEN_TAG, - IPC_NTOPENPROCESSTOKENEX_TAG, - IPC_CREATEPROCESSW_TAG, - IPC_CREATEEVENT_TAG, - IPC_OPENEVENT_TAG, - IPC_NTCREATEKEY_TAG, - IPC_NTOPENKEY_TAG, - IPC_DUPLICATEHANDLEPROXY_TAG, - IPC_GDI_GDIDLLINITIALIZE_TAG, - IPC_GDI_GETSTOCKOBJECT_TAG, - IPC_USER_REGISTERCLASSW_TAG, - IPC_LAST_TAG -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_IPC_TAGS_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_unittest.cc b/security/sandbox/chromium/sandbox/win/src/ipc_unittest.cc deleted file mode 100644 index c41720da3..000000000 --- a/security/sandbox/chromium/sandbox/win/src/ipc_unittest.cc +++ /dev/null @@ -1,632 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/sharedmem_ipc_server.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -// Helper function to make the fake shared memory with some -// basic elements initialized. -IPCControl* MakeChannels(size_t channel_size, size_t total_shared_size, - size_t* base_start) { - // Allocate memory - char* mem = new char[total_shared_size]; - memset(mem, 0, total_shared_size); - // Calculate how many channels we can fit in the shared memory. - total_shared_size -= offsetof(IPCControl, channels); - size_t channel_count = - total_shared_size / (sizeof(ChannelControl) + channel_size); - // Calculate the start of the first channel. - *base_start = (sizeof(ChannelControl)* channel_count) + - offsetof(IPCControl, channels); - // Setup client structure. - IPCControl* client_control = reinterpret_cast<IPCControl*>(mem); - client_control->channels_count = channel_count; - return client_control; -} - -enum TestFixMode { - FIX_NO_EVENTS, - FIX_PONG_READY, - FIX_PONG_NOT_READY -}; - -void FixChannels(IPCControl* client_control, size_t base_start, - size_t channel_size, TestFixMode mode) { - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - channel.channel_base = base_start; - channel.state = kFreeChannel; - if (mode != FIX_NO_EVENTS) { - BOOL signaled = (FIX_PONG_READY == mode)? TRUE : FALSE; - channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL); - channel.pong_event = ::CreateEventW(NULL, FALSE, signaled, NULL); - } - base_start += channel_size; - } -} - -void CloseChannelEvents(IPCControl* client_control) { - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - ::CloseHandle(channel.ping_event); - ::CloseHandle(channel.pong_event); - } -} - -TEST(IPCTest, ChannelMaker) { - // Test that our testing rig is computing offsets properly. We should have - // 5 channnels and the offset to the first channel is 108 bytes in 32 bits - // and 216 in 64 bits. - size_t channel_start = 0; - IPCControl* client_control = MakeChannels(12 * 64, 4096, &channel_start); - ASSERT_TRUE(NULL != client_control); - EXPECT_EQ(5u, client_control->channels_count); -#if defined(_WIN64) - EXPECT_EQ(216u, channel_start); -#else - EXPECT_EQ(108u, channel_start); -#endif - delete[] reinterpret_cast<char*>(client_control); -} - -TEST(IPCTest, ClientLockUnlock) { - // Make 7 channels of kIPCChannelSize (1kb) each. Test that we lock and - // unlock channels properly. - size_t base_start = 0; - IPCControl* client_control = - MakeChannels(kIPCChannelSize, 4096 * 2, &base_start); - FixChannels(client_control, base_start, kIPCChannelSize, FIX_NO_EVENTS); - - char* mem = reinterpret_cast<char*>(client_control); - SharedMemIPCClient client(mem); - - // Test that we lock the first 3 channels in sequence. - void* buff0 = client.GetBuffer(); - EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0); - EXPECT_EQ(kBusyChannel, client_control->channels[0].state); - EXPECT_EQ(kFreeChannel, client_control->channels[1].state); - EXPECT_EQ(kFreeChannel, client_control->channels[2].state); - EXPECT_EQ(kFreeChannel, client_control->channels[3].state); - EXPECT_EQ(kFreeChannel, client_control->channels[4].state); - EXPECT_EQ(kFreeChannel, client_control->channels[5].state); - - void* buff1 = client.GetBuffer(); - EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1); - EXPECT_EQ(kBusyChannel, client_control->channels[0].state); - EXPECT_EQ(kBusyChannel, client_control->channels[1].state); - EXPECT_EQ(kFreeChannel, client_control->channels[2].state); - EXPECT_EQ(kFreeChannel, client_control->channels[3].state); - EXPECT_EQ(kFreeChannel, client_control->channels[4].state); - EXPECT_EQ(kFreeChannel, client_control->channels[5].state); - - void* buff2 = client.GetBuffer(); - EXPECT_TRUE(mem + client_control->channels[2].channel_base == buff2); - EXPECT_EQ(kBusyChannel, client_control->channels[0].state); - EXPECT_EQ(kBusyChannel, client_control->channels[1].state); - EXPECT_EQ(kBusyChannel, client_control->channels[2].state); - EXPECT_EQ(kFreeChannel, client_control->channels[3].state); - EXPECT_EQ(kFreeChannel, client_control->channels[4].state); - EXPECT_EQ(kFreeChannel, client_control->channels[5].state); - - // Test that we unlock and re-lock the right channel. - client.FreeBuffer(buff1); - EXPECT_EQ(kBusyChannel, client_control->channels[0].state); - EXPECT_EQ(kFreeChannel, client_control->channels[1].state); - EXPECT_EQ(kBusyChannel, client_control->channels[2].state); - EXPECT_EQ(kFreeChannel, client_control->channels[3].state); - EXPECT_EQ(kFreeChannel, client_control->channels[4].state); - EXPECT_EQ(kFreeChannel, client_control->channels[5].state); - - void* buff2b = client.GetBuffer(); - EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff2b); - EXPECT_EQ(kBusyChannel, client_control->channels[0].state); - EXPECT_EQ(kBusyChannel, client_control->channels[1].state); - EXPECT_EQ(kBusyChannel, client_control->channels[2].state); - EXPECT_EQ(kFreeChannel, client_control->channels[3].state); - EXPECT_EQ(kFreeChannel, client_control->channels[4].state); - EXPECT_EQ(kFreeChannel, client_control->channels[5].state); - - client.FreeBuffer(buff0); - EXPECT_EQ(kFreeChannel, client_control->channels[0].state); - EXPECT_EQ(kBusyChannel, client_control->channels[1].state); - EXPECT_EQ(kBusyChannel, client_control->channels[2].state); - EXPECT_EQ(kFreeChannel, client_control->channels[3].state); - EXPECT_EQ(kFreeChannel, client_control->channels[4].state); - EXPECT_EQ(kFreeChannel, client_control->channels[5].state); - - delete[] reinterpret_cast<char*>(client_control); -} - -TEST(IPCTest, CrossCallStrPacking) { - // This test tries the CrossCall object with null and non-null string - // combination of parameters, integer types and verifies that the unpacker - // can read them properly. - size_t base_start = 0; - IPCControl* client_control = - MakeChannels(kIPCChannelSize, 4096 * 4, &base_start); - client_control->server_alive = HANDLE(1); - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY); - - char* mem = reinterpret_cast<char*>(client_control); - SharedMemIPCClient client(mem); - - CrossCallReturn answer; - uint32_t tag1 = 666; - const wchar_t *text = L"98765 - 43210"; - base::string16 copied_text; - CrossCallParamsEx* actual_params; - - CrossCall(client, tag1, text, &answer); - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); - EXPECT_EQ(1u, actual_params->GetParamsCount()); - EXPECT_EQ(tag1, actual_params->GetTag()); - EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text)); - EXPECT_STREQ(text, copied_text.c_str()); - - // Check with an empty string. - uint32_t tag2 = 777; - const wchar_t* null_text = NULL; - CrossCall(client, tag2, null_text, &answer); - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); - EXPECT_EQ(1u, actual_params->GetParamsCount()); - EXPECT_EQ(tag2, actual_params->GetTag()); - uint32_t param_size = 1; - ArgType type = INVALID_TYPE; - void* param_addr = actual_params->GetRawParameter(0, ¶m_size, &type); - EXPECT_TRUE(NULL != param_addr); - EXPECT_EQ(0u, param_size); - EXPECT_EQ(WCHAR_TYPE, type); - EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text)); - - uint32_t tag3 = 888; - param_size = 1; - copied_text.clear(); - - // Check with an empty string and a non-empty string. - CrossCall(client, tag3, null_text, text, &answer); - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); - EXPECT_EQ(2u, actual_params->GetParamsCount()); - EXPECT_EQ(tag3, actual_params->GetTag()); - type = INVALID_TYPE; - param_addr = actual_params->GetRawParameter(0, ¶m_size, &type); - EXPECT_TRUE(NULL != param_addr); - EXPECT_EQ(0u, param_size); - EXPECT_EQ(WCHAR_TYPE, type); - EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text)); - EXPECT_TRUE(actual_params->GetParameterStr(1, &copied_text)); - EXPECT_STREQ(text, copied_text.c_str()); - - param_size = 1; - base::string16 copied_text_p0, copied_text_p2; - - const wchar_t *text2 = L"AeFG"; - CrossCall(client, tag1, text2, null_text, text, &answer); - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); - EXPECT_EQ(3u, actual_params->GetParamsCount()); - EXPECT_EQ(tag1, actual_params->GetTag()); - EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text_p0)); - EXPECT_STREQ(text2, copied_text_p0.c_str()); - EXPECT_TRUE(actual_params->GetParameterStr(2, &copied_text_p2)); - EXPECT_STREQ(text, copied_text_p2.c_str()); - type = INVALID_TYPE; - param_addr = actual_params->GetRawParameter(1, ¶m_size, &type); - EXPECT_TRUE(NULL != param_addr); - EXPECT_EQ(0u, param_size); - EXPECT_EQ(WCHAR_TYPE, type); - - CloseChannelEvents(client_control); - delete[] reinterpret_cast<char*>(client_control); -} - -TEST(IPCTest, CrossCallIntPacking) { - // Check handling for regular 32 bit integers used in Windows. - size_t base_start = 0; - IPCControl* client_control = - MakeChannels(kIPCChannelSize, 4096 * 4, &base_start); - client_control->server_alive = HANDLE(1); - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY); - - uint32_t tag1 = 999; - uint32_t tag2 = 111; - const wchar_t *text = L"godzilla"; - CrossCallParamsEx* actual_params; - - char* mem = reinterpret_cast<char*>(client_control); - SharedMemIPCClient client(mem); - - CrossCallReturn answer; - DWORD dw = 0xE6578; - CrossCall(client, tag2, dw, &answer); - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); - EXPECT_EQ(1u, actual_params->GetParamsCount()); - EXPECT_EQ(tag2, actual_params->GetTag()); - ArgType type = INVALID_TYPE; - uint32_t param_size = 1; - void* param_addr = actual_params->GetRawParameter(0, ¶m_size, &type); - ASSERT_EQ(sizeof(dw), param_size); - EXPECT_EQ(UINT32_TYPE, type); - ASSERT_TRUE(NULL != param_addr); - EXPECT_EQ(0, memcmp(&dw, param_addr, param_size)); - - // Check handling for windows HANDLES. - HANDLE h = HANDLE(0x70000500); - CrossCall(client, tag1, text, h, &answer); - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); - EXPECT_EQ(2u, actual_params->GetParamsCount()); - EXPECT_EQ(tag1, actual_params->GetTag()); - type = INVALID_TYPE; - param_addr = actual_params->GetRawParameter(1, ¶m_size, &type); - ASSERT_EQ(sizeof(h), param_size); - EXPECT_EQ(VOIDPTR_TYPE, type); - ASSERT_TRUE(NULL != param_addr); - EXPECT_EQ(0, memcmp(&h, param_addr, param_size)); - - // Check combination of 32 and 64 bits. - CrossCall(client, tag2, h, dw, h, &answer); - actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); - EXPECT_EQ(3u, actual_params->GetParamsCount()); - EXPECT_EQ(tag2, actual_params->GetTag()); - type = INVALID_TYPE; - param_addr = actual_params->GetRawParameter(0, ¶m_size, &type); - ASSERT_EQ(sizeof(h), param_size); - EXPECT_EQ(VOIDPTR_TYPE, type); - ASSERT_TRUE(NULL != param_addr); - EXPECT_EQ(0, memcmp(&h, param_addr, param_size)); - type = INVALID_TYPE; - param_addr = actual_params->GetRawParameter(1, ¶m_size, &type); - ASSERT_EQ(sizeof(dw), param_size); - EXPECT_EQ(UINT32_TYPE, type); - ASSERT_TRUE(NULL != param_addr); - EXPECT_EQ(0, memcmp(&dw, param_addr, param_size)); - type = INVALID_TYPE; - param_addr = actual_params->GetRawParameter(2, ¶m_size, &type); - ASSERT_EQ(sizeof(h), param_size); - EXPECT_EQ(VOIDPTR_TYPE, type); - ASSERT_TRUE(NULL != param_addr); - EXPECT_EQ(0, memcmp(&h, param_addr, param_size)); - - CloseChannelEvents(client_control); - delete[] reinterpret_cast<char*>(client_control); -} - -TEST(IPCTest, CrossCallValidation) { - // First a sanity test with a well formed parameter object. - unsigned long value = 124816; - const uint32_t kTag = 33; - const uint32_t kBufferSize = 256; - ActualCallParams<1, kBufferSize> params_1(kTag); - params_1.CopyParamIn(0, &value, sizeof(value), false, UINT32_TYPE); - void* buffer = const_cast<void*>(params_1.GetBuffer()); - - uint32_t out_size = 0; - CrossCallParamsEx* ccp = 0; - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(), - &out_size); - ASSERT_TRUE(NULL != ccp); - EXPECT_TRUE(ccp->GetBuffer() != buffer); - EXPECT_EQ(kTag, ccp->GetTag()); - EXPECT_EQ(1u, ccp->GetParamsCount()); - delete[] (reinterpret_cast<char*>(ccp)); - - // Test that we handle integer overflow on the number of params - // correctly. We use a test-only ctor for ActualCallParams that - // allows to create malformed cross-call buffers. - const int32_t kPtrDiffSz = sizeof(ptrdiff_t); - for (int32_t ix = -1; ix != 3; ++ix) { - uint32_t fake_num_params = (UINT32_MAX / kPtrDiffSz) + ix; - ActualCallParams<1, kBufferSize> params_2(kTag, fake_num_params); - params_2.CopyParamIn(0, &value, sizeof(value), false, UINT32_TYPE); - buffer = const_cast<void*>(params_2.GetBuffer()); - - EXPECT_TRUE(NULL != buffer); - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(), - &out_size); - // If the buffer is malformed the return is NULL. - EXPECT_TRUE(NULL == ccp); - } - - ActualCallParams<1, kBufferSize> params_3(kTag, 1); - params_3.CopyParamIn(0, &value, sizeof(value), false, UINT32_TYPE); - buffer = const_cast<void*>(params_3.GetBuffer()); - EXPECT_TRUE(NULL != buffer); - - uint32_t correct_size = params_3.OverrideSize(1); - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size); - EXPECT_TRUE(NULL == ccp); - - // The correct_size is 8 bytes aligned. - params_3.OverrideSize(correct_size - 7); - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size); - EXPECT_TRUE(NULL == ccp); - - params_3.OverrideSize(correct_size); - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size); - EXPECT_TRUE(NULL != ccp); - - // Make sure that two parameters work as expected. - ActualCallParams<2, kBufferSize> params_4(kTag, 2); - params_4.CopyParamIn(0, &value, sizeof(value), false, UINT32_TYPE); - params_4.CopyParamIn(1, buffer, sizeof(buffer), false, VOIDPTR_TYPE); - buffer = const_cast<void*>(params_4.GetBuffer()); - EXPECT_TRUE(NULL != buffer); - - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size); - EXPECT_TRUE(NULL != ccp); - -#if defined(_WIN64) - correct_size = params_4.OverrideSize(1); - params_4.OverrideSize(correct_size - 1); - ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size); - EXPECT_TRUE(NULL == ccp); -#endif -} - -// This structure is passed to the mock server threads to simulate -// the server side IPC so it has the required kernel objects. -struct ServerEvents { - HANDLE ping; - HANDLE pong; - volatile LONG* state; - HANDLE mutex; -}; - -// This is the server thread that quicky answers an IPC and exits. -DWORD WINAPI QuickResponseServer(PVOID param) { - ServerEvents* events = reinterpret_cast<ServerEvents*>(param); - DWORD wait_result = 0; - wait_result = ::WaitForSingleObject(events->ping, INFINITE); - ::InterlockedExchange(events->state, kAckChannel); - ::SetEvent(events->pong); - return wait_result; -} - -class CrossCallParamsMock : public CrossCallParams { - public: - CrossCallParamsMock(uint32_t tag, uint32_t params_count) - : CrossCallParams(tag, params_count) {} -}; - -void FakeOkAnswerInChannel(void* channel) { - CrossCallReturn* answer = reinterpret_cast<CrossCallReturn*>(channel); - answer->call_outcome = SBOX_ALL_OK; -} - -// Create two threads that will quickly answer IPCs; the first one -// using channel 1 (channel 0 is busy) and one using channel 0. No time-out -// should occur. -TEST(IPCTest, ClientFastServer) { - const size_t channel_size = kIPCChannelSize; - size_t base_start = 0; - IPCControl* client_control = - MakeChannels(channel_size, 4096 * 2, &base_start); - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY); - client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL); - - char* mem = reinterpret_cast<char*>(client_control); - SharedMemIPCClient client(mem); - - ServerEvents events = {0}; - events.ping = client_control->channels[1].ping_event; - events.pong = client_control->channels[1].pong_event; - events.state = &client_control->channels[1].state; - - HANDLE t1 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL); - ASSERT_TRUE(NULL != t1); - ::CloseHandle(t1); - - void* buff0 = client.GetBuffer(); - EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0); - EXPECT_EQ(kBusyChannel, client_control->channels[0].state); - EXPECT_EQ(kFreeChannel, client_control->channels[1].state); - EXPECT_EQ(kFreeChannel, client_control->channels[2].state); - - void* buff1 = client.GetBuffer(); - EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1); - EXPECT_EQ(kBusyChannel, client_control->channels[0].state); - EXPECT_EQ(kBusyChannel, client_control->channels[1].state); - EXPECT_EQ(kFreeChannel, client_control->channels[2].state); - - EXPECT_EQ(0u, client_control->channels[1].ipc_tag); - - uint32_t tag = 7654; - CrossCallReturn answer; - CrossCallParamsMock* params1 = new(buff1) CrossCallParamsMock(tag, 1); - FakeOkAnswerInChannel(buff1); - - ResultCode result = client.DoCall(params1, &answer); - if (SBOX_ERROR_CHANNEL_ERROR != result) - client.FreeBuffer(buff1); - - EXPECT_TRUE(SBOX_ALL_OK == result); - EXPECT_EQ(tag, client_control->channels[1].ipc_tag); - EXPECT_EQ(kBusyChannel, client_control->channels[0].state); - EXPECT_EQ(kFreeChannel, client_control->channels[1].state); - EXPECT_EQ(kFreeChannel, client_control->channels[2].state); - - HANDLE t2 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL); - ASSERT_TRUE(NULL != t2); - ::CloseHandle(t2); - - client.FreeBuffer(buff0); - events.ping = client_control->channels[0].ping_event; - events.pong = client_control->channels[0].pong_event; - events.state = &client_control->channels[0].state; - - tag = 4567; - CrossCallParamsMock* params2 = new(buff0) CrossCallParamsMock(tag, 1); - FakeOkAnswerInChannel(buff0); - - result = client.DoCall(params2, &answer); - if (SBOX_ERROR_CHANNEL_ERROR != result) - client.FreeBuffer(buff0); - - EXPECT_TRUE(SBOX_ALL_OK == result); - EXPECT_EQ(tag, client_control->channels[0].ipc_tag); - EXPECT_EQ(kFreeChannel, client_control->channels[0].state); - EXPECT_EQ(kFreeChannel, client_control->channels[1].state); - EXPECT_EQ(kFreeChannel, client_control->channels[2].state); - - CloseChannelEvents(client_control); - ::CloseHandle(client_control->server_alive); - - delete[] reinterpret_cast<char*>(client_control); -} - -// This is the server thread that very slowly answers an IPC and exits. Note -// that the pong event needs to be signaled twice. -DWORD WINAPI SlowResponseServer(PVOID param) { - ServerEvents* events = reinterpret_cast<ServerEvents*>(param); - DWORD wait_result = 0; - wait_result = ::WaitForSingleObject(events->ping, INFINITE); - ::Sleep(kIPCWaitTimeOut1 + kIPCWaitTimeOut2 + 200); - ::InterlockedExchange(events->state, kAckChannel); - ::SetEvent(events->pong); - return wait_result; -} - -// This thread's job is to keep the mutex locked. -DWORD WINAPI MainServerThread(PVOID param) { - ServerEvents* events = reinterpret_cast<ServerEvents*>(param); - DWORD wait_result = 0; - wait_result = ::WaitForSingleObject(events->mutex, INFINITE); - Sleep(kIPCWaitTimeOut1 * 20); - return wait_result; -} - -// Creates a server thread that answers the IPC so slow that is guaranteed to -// trigger the time-out code path in the client. A second thread is created -// to hold locked the server_alive mutex: this signals the client that the -// server is not dead and it retries the wait. -TEST(IPCTest, ClientSlowServer) { - size_t base_start = 0; - IPCControl* client_control = - MakeChannels(kIPCChannelSize, 4096*2, &base_start); - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY); - client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL); - - char* mem = reinterpret_cast<char*>(client_control); - SharedMemIPCClient client(mem); - - ServerEvents events = {0}; - events.ping = client_control->channels[0].ping_event; - events.pong = client_control->channels[0].pong_event; - events.state = &client_control->channels[0].state; - - HANDLE t1 = ::CreateThread(NULL, 0, SlowResponseServer, &events, 0, NULL); - ASSERT_TRUE(NULL != t1); - ::CloseHandle(t1); - - ServerEvents events2 = {0}; - events2.pong = events.pong; - events2.mutex = client_control->server_alive; - - HANDLE t2 = ::CreateThread(NULL, 0, MainServerThread, &events2, 0, NULL); - ASSERT_TRUE(NULL != t2); - ::CloseHandle(t2); - - ::Sleep(1); - - void* buff0 = client.GetBuffer(); - uint32_t tag = 4321; - CrossCallReturn answer; - CrossCallParamsMock* params1 = new(buff0) CrossCallParamsMock(tag, 1); - FakeOkAnswerInChannel(buff0); - - ResultCode result = client.DoCall(params1, &answer); - if (SBOX_ERROR_CHANNEL_ERROR != result) - client.FreeBuffer(buff0); - - EXPECT_TRUE(SBOX_ALL_OK == result); - EXPECT_EQ(tag, client_control->channels[0].ipc_tag); - EXPECT_EQ(kFreeChannel, client_control->channels[0].state); - - CloseChannelEvents(client_control); - ::CloseHandle(client_control->server_alive); - delete[] reinterpret_cast<char*>(client_control); -} - -// This test-only IPC dispatcher has two handlers with the same signature -// but only CallOneHandler should be used. -class UnitTestIPCDispatcher : public Dispatcher { - public: - enum { - CALL_ONE_TAG = 78, - CALL_TWO_TAG = 87 - }; - - UnitTestIPCDispatcher(); - ~UnitTestIPCDispatcher() override{}; - - bool SetupService(InterceptionManager* manager, int service) override { - return true; - } - - private: - bool CallOneHandler(IPCInfo* ipc, HANDLE p1, uint32_t p2) { - ipc->return_info.extended[0].handle = p1; - ipc->return_info.extended[1].unsigned_int = p2; - return true; - } - - bool CallTwoHandler(IPCInfo* ipc, HANDLE p1, uint32_t p2) { return true; } -}; - -UnitTestIPCDispatcher::UnitTestIPCDispatcher() { - static const IPCCall call_one = {{CALL_ONE_TAG, {VOIDPTR_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &UnitTestIPCDispatcher::CallOneHandler)}; - static const IPCCall call_two = {{CALL_TWO_TAG, {VOIDPTR_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &UnitTestIPCDispatcher::CallTwoHandler)}; - ipc_calls_.push_back(call_one); - ipc_calls_.push_back(call_two); -} - -// This test does most of the shared memory IPC client-server roundtrip -// and tests the packing, unpacking and call dispatching. -TEST(IPCTest, SharedMemServerTests) { - size_t base_start = 0; - IPCControl* client_control = - MakeChannels(kIPCChannelSize, 4096, &base_start); - client_control->server_alive = HANDLE(1); - FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY); - - char* mem = reinterpret_cast<char*>(client_control); - SharedMemIPCClient client(mem); - - CrossCallReturn answer; - HANDLE bar = HANDLE(191919); - DWORD foo = 6767676; - CrossCall(client, UnitTestIPCDispatcher::CALL_ONE_TAG, bar, foo, &answer); - void* buff = client.GetBuffer(); - ASSERT_TRUE(NULL != buff); - - UnitTestIPCDispatcher dispatcher; - // Since we are directly calling InvokeCallback, most of this structure - // can be set to NULL. - sandbox::SharedMemIPCServer::ServerControl srv_control = {}; - srv_control.channel_size = kIPCChannelSize; - srv_control.shared_base = reinterpret_cast<char*>(client_control); - srv_control.dispatcher = &dispatcher; - - sandbox::CrossCallReturn call_return = {0}; - EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control, buff, - &call_return)); - EXPECT_EQ(SBOX_ALL_OK, call_return.call_outcome); - EXPECT_TRUE(bar == call_return.extended[0].handle); - EXPECT_EQ(foo, call_return.extended[1].unsigned_int); - - CloseChannelEvents(client_control); - delete[] reinterpret_cast<char*>(client_control); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/job.cc b/security/sandbox/chromium/sandbox/win/src/job.cc deleted file mode 100644 index adf392ddd..000000000 --- a/security/sandbox/chromium/sandbox/win/src/job.cc +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/job.h" - -#include <stddef.h> - -#include "base/win/windows_version.h" -#include "sandbox/win/src/restricted_token.h" - -namespace sandbox { - -Job::Job() : job_handle_(NULL) { -}; - -Job::~Job() { -}; - -DWORD Job::Init(JobLevel security_level, - const wchar_t* job_name, - DWORD ui_exceptions, - size_t memory_limit) { - if (job_handle_.IsValid()) - return ERROR_ALREADY_INITIALIZED; - - job_handle_.Set(::CreateJobObject(NULL, // No security attribute - job_name)); - if (!job_handle_.IsValid()) - return ::GetLastError(); - - JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {}; - JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {}; - - // Set the settings for the different security levels. Note: The higher levels - // inherit from the lower levels. - switch (security_level) { - case JOB_LOCKDOWN: { - jeli.BasicLimitInformation.LimitFlags |= - JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION; - } - case JOB_RESTRICTED: { - jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD; - jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD; - jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES; - jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS; - } - case JOB_LIMITED_USER: { - jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS; - jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS; - jeli.BasicLimitInformation.ActiveProcessLimit = 1; - } - case JOB_INTERACTIVE: { - jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS; - jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP; - jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS; - } - case JOB_UNPROTECTED: { - if (memory_limit) { - jeli.BasicLimitInformation.LimitFlags |= - JOB_OBJECT_LIMIT_PROCESS_MEMORY; - jeli.ProcessMemoryLimit = memory_limit; - } - - jeli.BasicLimitInformation.LimitFlags |= - JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - break; - } - default: { - return ERROR_BAD_ARGUMENTS; - } - } - - if (FALSE == ::SetInformationJobObject(job_handle_.Get(), - JobObjectExtendedLimitInformation, - &jeli, - sizeof(jeli))) { - return ::GetLastError(); - } - - jbur.UIRestrictionsClass = jbur.UIRestrictionsClass & (~ui_exceptions); - if (FALSE == ::SetInformationJobObject(job_handle_.Get(), - JobObjectBasicUIRestrictions, - &jbur, - sizeof(jbur))) { - return ::GetLastError(); - } - - return ERROR_SUCCESS; -} - -DWORD Job::UserHandleGrantAccess(HANDLE handle) { - if (!job_handle_.IsValid()) - return ERROR_NO_DATA; - - if (!::UserHandleGrantAccess(handle, - job_handle_.Get(), - TRUE)) { // Access allowed. - return ::GetLastError(); - } - - return ERROR_SUCCESS; -} - -base::win::ScopedHandle Job::Take() { - return job_handle_.Pass(); -} - -DWORD Job::AssignProcessToJob(HANDLE process_handle) { - if (!job_handle_.IsValid()) - return ERROR_NO_DATA; - - if (FALSE == ::AssignProcessToJobObject(job_handle_.Get(), process_handle)) - return ::GetLastError(); - - return ERROR_SUCCESS; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/job.h b/security/sandbox/chromium/sandbox/win/src/job.h deleted file mode 100644 index ad3dd41f2..000000000 --- a/security/sandbox/chromium/sandbox/win/src/job.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_JOB_H_ -#define SANDBOX_SRC_JOB_H_ - -#include <stddef.h> - -#include "base/macros.h" -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/restricted_token_utils.h" - -namespace sandbox { - -// Handles the creation of job objects based on a security profile. -// Sample usage: -// Job job; -// job.Init(JOB_LOCKDOWN, NULL); //no job name -// job.AssignProcessToJob(process_handle); -class Job { - public: - Job(); - - ~Job(); - - // Initializes and creates the job object. The security of the job is based - // on the security_level parameter. - // job_name can be NULL if the job is unnamed. - // If the chosen profile has too many ui restrictions, you can disable some - // by specifying them in the ui_exceptions parameters. - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD Init(JobLevel security_level, - const wchar_t* job_name, - DWORD ui_exceptions, - size_t memory_limit); - - // Assigns the process referenced by process_handle to the job. - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AssignProcessToJob(HANDLE process_handle); - - // Grants access to "handle" to the job. All processes in the job can - // subsequently recognize and use the handle. - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD UserHandleGrantAccess(HANDLE handle); - - // Revokes ownership to the job handle and returns it. - // If the object is not yet initialized, it returns an invalid handle. - base::win::ScopedHandle Take(); - - private: - // Handle to the job referenced by the object. - base::win::ScopedHandle job_handle_; - - DISALLOW_COPY_AND_ASSIGN(Job); -}; - -} // namespace sandbox - - -#endif // SANDBOX_SRC_JOB_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/job_unittest.cc b/security/sandbox/chromium/sandbox/win/src/job_unittest.cc deleted file mode 100644 index 7ed9cf0d7..000000000 --- a/security/sandbox/chromium/sandbox/win/src/job_unittest.cc +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains unit tests for the job object. - -#include "base/win/scoped_process_information.h" -#include "sandbox/win/src/job.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -// Tests the creation and destruction of the job. -TEST(JobTest, TestCreation) { - // Scope the creation of Job. - { - // Create the job. - Job job; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); - - // check if the job exists. - HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, - L"my_test_job_name"); - ASSERT_TRUE(job_handle != NULL); - - if (job_handle) - CloseHandle(job_handle); - } - - // Check if the job is destroyed when the object goes out of scope. - HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name"); - ASSERT_TRUE(job_handle == NULL); - ASSERT_EQ(static_cast<DWORD>(ERROR_FILE_NOT_FOUND), ::GetLastError()); -} - -// Tests the method "Take". -TEST(JobTest, Take) { - base::win::ScopedHandle job_handle; - // Scope the creation of Job. - { - // Create the job. - Job job; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); - - job_handle = job.Take(); - ASSERT_TRUE(job_handle.IsValid()); - } - - // Check to be sure that the job is still alive even after the object is gone - // out of scope. - HANDLE job_handle_dup = ::OpenJobObjectW(GENERIC_ALL, FALSE, - L"my_test_job_name"); - ASSERT_TRUE(job_handle_dup != NULL); - - // Remove all references. - if (job_handle_dup) - ::CloseHandle(job_handle_dup); - - job_handle.Close(); - - // Check if the jbo is really dead. - job_handle_dup = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name"); - ASSERT_TRUE(job_handle_dup == NULL); - ASSERT_EQ(static_cast<DWORD>(ERROR_FILE_NOT_FOUND), ::GetLastError()); -} - -// Tests the ui exceptions -TEST(JobTest, TestExceptions) { - base::win::ScopedHandle job_handle; - // Scope the creation of Job. - { - // Create the job. - Job job; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job.Init(JOB_LOCKDOWN, L"my_test_job_name", - JOB_OBJECT_UILIMIT_READCLIPBOARD, 0)); - - job_handle = job.Take(); - ASSERT_TRUE(job_handle.IsValid()); - - JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; - DWORD size = sizeof(jbur); - BOOL result = ::QueryInformationJobObject(job_handle.Get(), - JobObjectBasicUIRestrictions, - &jbur, size, &size); - ASSERT_TRUE(result); - - ASSERT_EQ(0u, jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD); - job_handle.Close(); - } - - // Scope the creation of Job. - { - // Create the job. - Job job; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); - - job_handle = job.Take(); - ASSERT_TRUE(job_handle.IsValid()); - - JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; - DWORD size = sizeof(jbur); - BOOL result = ::QueryInformationJobObject(job_handle.Get(), - JobObjectBasicUIRestrictions, - &jbur, size, &size); - ASSERT_TRUE(result); - - ASSERT_EQ(static_cast<DWORD>(JOB_OBJECT_UILIMIT_READCLIPBOARD), - jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD); - } -} - -// Tests the error case when the job is initialized twice. -TEST(JobTest, DoubleInit) { - // Create the job. - Job job; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); - ASSERT_EQ(static_cast<DWORD>(ERROR_ALREADY_INITIALIZED), - job.Init(JOB_LOCKDOWN, L"test", 0, 0)); -} - -// Tests the error case when we use a method and the object is not yet -// initialized. -TEST(JobTest, NoInit) { - Job job; - ASSERT_EQ(static_cast<DWORD>(ERROR_NO_DATA), job.UserHandleGrantAccess(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_NO_DATA), job.AssignProcessToJob(NULL)); - ASSERT_FALSE(job.Take().IsValid()); -} - -// Tests the initialization of the job with different security level. -TEST(JobTest, SecurityLevel) { - Job job1; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job1.Init(JOB_LOCKDOWN, L"job1", 0, 0)); - - Job job2; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job2.Init(JOB_RESTRICTED, L"job2", 0, 0)); - - Job job3; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job3.Init(JOB_LIMITED_USER, L"job3", 0, 0)); - - Job job4; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job4.Init(JOB_INTERACTIVE, L"job4", 0, 0)); - - Job job5; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job5.Init(JOB_UNPROTECTED, L"job5", 0, 0)); - - // JOB_NONE means we run without a job object so Init should fail. - Job job6; - ASSERT_EQ(static_cast<DWORD>(ERROR_BAD_ARGUMENTS), - job6.Init(JOB_NONE, L"job6", 0, 0)); - - Job job7; - ASSERT_EQ(static_cast<DWORD>(ERROR_BAD_ARGUMENTS), - job7.Init(static_cast<JobLevel>(JOB_NONE + 1), L"job7", 0, 0)); -} - -// Tests the method "AssignProcessToJob". -TEST(JobTest, ProcessInJob) { - // Create the job. - Job job; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job.Init(JOB_UNPROTECTED, L"job_test_process", 0, 0)); - - BOOL result = FALSE; - - wchar_t notepad[] = L"notepad"; - STARTUPINFO si = { sizeof(si) }; - PROCESS_INFORMATION temp_process_info = {}; - result = ::CreateProcess(NULL, notepad, NULL, NULL, FALSE, 0, NULL, NULL, &si, - &temp_process_info); - ASSERT_TRUE(result); - base::win::ScopedProcessInformation pi(temp_process_info); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - job.AssignProcessToJob(pi.process_handle())); - - // Get the job handle. - base::win::ScopedHandle job_handle = job.Take(); - - // Check if the process is in the job. - JOBOBJECT_BASIC_PROCESS_ID_LIST jbpidl = {0}; - DWORD size = sizeof(jbpidl); - result = ::QueryInformationJobObject(job_handle.Get(), - JobObjectBasicProcessIdList, - &jbpidl, size, &size); - EXPECT_TRUE(result); - - EXPECT_EQ(1u, jbpidl.NumberOfAssignedProcesses); - EXPECT_EQ(1u, jbpidl.NumberOfProcessIdsInList); - EXPECT_EQ(pi.process_id(), jbpidl.ProcessIdList[0]); - - EXPECT_TRUE(::TerminateProcess(pi.process_handle(), 0)); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/named_pipe_dispatcher.cc deleted file mode 100644 index ea8d38035..000000000 --- a/security/sandbox/chromium/sandbox/win/src/named_pipe_dispatcher.cc +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/named_pipe_dispatcher.h" - -#include <stdint.h> - -#include "base/strings/string_split.h" - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/named_pipe_interception.h" -#include "sandbox/win/src/named_pipe_policy.h" -#include "sandbox/win/src/policy_broker.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox.h" - - -namespace sandbox { - -NamedPipeDispatcher::NamedPipeDispatcher(PolicyBase* policy_base) - : policy_base_(policy_base) { - static const IPCCall create_params = { - {IPC_CREATENAMEDPIPEW_TAG, - {WCHAR_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>(&NamedPipeDispatcher::CreateNamedPipe)}; - - ipc_calls_.push_back(create_params); -} - -bool NamedPipeDispatcher::SetupService(InterceptionManager* manager, - int service) { - if (IPC_CREATENAMEDPIPEW_TAG == service) - return INTERCEPT_EAT(manager, kKerneldllName, CreateNamedPipeW, - CREATE_NAMED_PIPE_ID, 36); - - return false; -} - -bool NamedPipeDispatcher::CreateNamedPipe(IPCInfo* ipc, - base::string16* name, - uint32_t open_mode, - uint32_t pipe_mode, - uint32_t max_instances, - uint32_t out_buffer_size, - uint32_t in_buffer_size, - uint32_t default_timeout) { - ipc->return_info.win32_result = ERROR_ACCESS_DENIED; - ipc->return_info.handle = INVALID_HANDLE_VALUE; - - base::StringPiece16 dotdot(L".."); - - for (const base::StringPiece16& path : base::SplitStringPiece( - *name, base::string16(1, '/'), - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { - for (const base::StringPiece16& inner : base::SplitStringPiece( - path, base::string16(1, '\\'), - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { - if (inner == dotdot) - return true; - } - } - - const wchar_t* pipe_name = name->c_str(); - CountedParameterSet<NameBased> params; - params[NameBased::NAME] = ParamPickerMake(pipe_name); - - EvalResult eval = policy_base_->EvalPolicy(IPC_CREATENAMEDPIPEW_TAG, - params.GetBase()); - - // "For file I/O, the "\\?\" prefix to a path string tells the Windows APIs to - // disable all string parsing and to send the string that follows it straight - // to the file system." - // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx - // This ensures even if there is a path traversal in the pipe name, and it is - // able to get past the checks above, it will still not be allowed to escape - // our whitelisted namespace. - if (name->compare(0, 4, L"\\\\.\\") == 0) - name->replace(0, 4, L"\\\\\?\\"); - - HANDLE pipe; - DWORD ret = NamedPipePolicy::CreateNamedPipeAction(eval, *ipc->client_info, - *name, open_mode, - pipe_mode, max_instances, - out_buffer_size, - in_buffer_size, - default_timeout, &pipe); - - ipc->return_info.win32_result = ret; - ipc->return_info.handle = pipe; - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/named_pipe_dispatcher.h deleted file mode 100644 index 83f45e093..000000000 --- a/security/sandbox/chromium/sandbox/win/src/named_pipe_dispatcher.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_NAMED_PIPE_DISPATCHER_H__ -#define SANDBOX_SRC_NAMED_PIPE_DISPATCHER_H__ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox_policy_base.h" - -namespace sandbox { - -// This class handles named pipe related IPC calls. -class NamedPipeDispatcher : public Dispatcher { - public: - explicit NamedPipeDispatcher(PolicyBase* policy_base); - ~NamedPipeDispatcher() override {} - - // Dispatcher interface. - bool SetupService(InterceptionManager* manager, int service) override; - - private: - // Processes IPC requests coming from calls to CreateNamedPipeW() in the - // target. - bool CreateNamedPipe(IPCInfo* ipc, - base::string16* name, - uint32_t open_mode, - uint32_t pipe_mode, - uint32_t max_instances, - uint32_t out_buffer_size, - uint32_t in_buffer_size, - uint32_t default_timeout); - - PolicyBase* policy_base_; - DISALLOW_COPY_AND_ASSIGN(NamedPipeDispatcher); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_NAMED_PIPE_DISPATCHER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc b/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc deleted file mode 100644 index a18327308..000000000 --- a/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/named_pipe_interception.h" - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/policy_target.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/target_services.h" -#include "mozilla/sandboxing/sandboxLogging.h" - -namespace sandbox { - -HANDLE WINAPI TargetCreateNamedPipeW( - CreateNamedPipeWFunction orig_CreateNamedPipeW, LPCWSTR pipe_name, - DWORD open_mode, DWORD pipe_mode, DWORD max_instance, DWORD out_buffer_size, - DWORD in_buffer_size, DWORD default_timeout, - LPSECURITY_ATTRIBUTES security_attributes) { - HANDLE pipe = orig_CreateNamedPipeW(pipe_name, open_mode, pipe_mode, - max_instance, out_buffer_size, - in_buffer_size, default_timeout, - security_attributes); - if (INVALID_HANDLE_VALUE != pipe) - return pipe; - - mozilla::sandboxing::LogBlocked("CreateNamedPipeW", pipe_name); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return INVALID_HANDLE_VALUE; - - DWORD original_error = ::GetLastError(); - - // We don't support specific Security Attributes. - if (security_attributes) - return INVALID_HANDLE_VALUE; - - do { - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - CountedParameterSet<NameBased> params; - params[NameBased::NAME] = ParamPickerMake(pipe_name); - - if (!QueryBroker(IPC_CREATENAMEDPIPEW_TAG, params.GetBase())) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_CREATENAMEDPIPEW_TAG, pipe_name, - open_mode, pipe_mode, max_instance, - out_buffer_size, in_buffer_size, - default_timeout, &answer); - if (SBOX_ALL_OK != code) - break; - - ::SetLastError(answer.win32_result); - - if (ERROR_SUCCESS != answer.win32_result) - return INVALID_HANDLE_VALUE; - - mozilla::sandboxing::LogAllowed("CreateNamedPipeW", pipe_name); - return answer.handle; - } while (false); - - ::SetLastError(original_error); - return INVALID_HANDLE_VALUE; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.h b/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.h deleted file mode 100644 index fdbee1976..000000000 --- a/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_NAMED_PIPE_INTERCEPTION_H__ -#define SANDBOX_SRC_NAMED_PIPE_INTERCEPTION_H__ - -namespace sandbox { - -extern "C" { - -typedef HANDLE (WINAPI *CreateNamedPipeWFunction) ( - LPCWSTR lpName, - DWORD dwOpenMode, - DWORD dwPipeMode, - DWORD nMaxInstances, - DWORD nOutBufferSize, - DWORD nInBufferSize, - DWORD nDefaultTimeOut, - LPSECURITY_ATTRIBUTES lpSecurityAttributes); - -// Interception of CreateNamedPipeW in kernel32.dll -SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateNamedPipeW( - CreateNamedPipeWFunction orig_CreateNamedPipeW, LPCWSTR pipe_name, - DWORD open_mode, DWORD pipe_mode, DWORD max_instance, DWORD out_buffer_size, - DWORD in_buffer_size, DWORD default_timeout, - LPSECURITY_ATTRIBUTES security_attributes); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_NAMED_PIPE_INTERCEPTION_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_policy.cc b/security/sandbox/chromium/sandbox/win/src/named_pipe_policy.cc deleted file mode 100644 index eee719e50..000000000 --- a/security/sandbox/chromium/sandbox/win/src/named_pipe_policy.cc +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/named_pipe_policy.h" - -#include <string> - -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace { - -// Creates a named pipe and duplicates the handle to 'target_process'. The -// remaining parameters are the same as CreateNamedPipeW(). -HANDLE CreateNamedPipeHelper(HANDLE target_process, LPCWSTR pipe_name, - DWORD open_mode, DWORD pipe_mode, - DWORD max_instances, DWORD out_buffer_size, - DWORD in_buffer_size, DWORD default_timeout, - LPSECURITY_ATTRIBUTES security_attributes) { - HANDLE pipe = ::CreateNamedPipeW(pipe_name, open_mode, pipe_mode, - max_instances, out_buffer_size, - in_buffer_size, default_timeout, - security_attributes); - if (INVALID_HANDLE_VALUE == pipe) - return pipe; - - HANDLE new_pipe; - if (!::DuplicateHandle(::GetCurrentProcess(), pipe, - target_process, &new_pipe, - 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return INVALID_HANDLE_VALUE; - } - - return new_pipe; -} - -} // namespace - -namespace sandbox { - -bool NamedPipePolicy::GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy) { - if (TargetPolicy::NAMEDPIPES_ALLOW_ANY != semantics) { - return false; - } - PolicyRule pipe(ASK_BROKER); - if (!pipe.AddStringMatch(IF, NameBased::NAME, name, CASE_INSENSITIVE)) { - return false; - } - if (!policy->AddRule(IPC_CREATENAMEDPIPEW_TAG, &pipe)) { - return false; - } - return true; -} - -DWORD NamedPipePolicy::CreateNamedPipeAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16 &name, - DWORD open_mode, DWORD pipe_mode, - DWORD max_instances, - DWORD out_buffer_size, - DWORD in_buffer_size, - DWORD default_timeout, - HANDLE* pipe) { - // The only action supported is ASK_BROKER which means create the pipe. - if (ASK_BROKER != eval_result) { - return ERROR_ACCESS_DENIED; - } - - *pipe = CreateNamedPipeHelper(client_info.process, name.c_str(), - open_mode, pipe_mode, max_instances, - out_buffer_size, in_buffer_size, - default_timeout, NULL); - - if (INVALID_HANDLE_VALUE == *pipe) - return ERROR_ACCESS_DENIED; - - return ERROR_SUCCESS; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_policy.h b/security/sandbox/chromium/sandbox/win/src/named_pipe_policy.h deleted file mode 100644 index 02aa26c61..000000000 --- a/security/sandbox/chromium/sandbox/win/src/named_pipe_policy.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_NAMED_PIPE_POLICY_H__ -#define SANDBOX_SRC_NAMED_PIPE_POLICY_H__ - -#include <string> - -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/sandbox_policy.h" - -namespace sandbox { - -enum EvalResult; - -// This class centralizes most of the knowledge related to named pipe creation. -class NamedPipePolicy { - public: - // Creates the required low-level policy rules to evaluate a high-level. - // policy rule for named pipe creation - // 'name' is the named pipe to be created - // 'semantics' is the desired semantics. - // 'policy' is the policy generator to which the rules are going to be added. - static bool GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy); - - // Processes a 'CreateNamedPipeW()' request from the target. - static DWORD CreateNamedPipeAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16 &name, - DWORD open_mode, DWORD pipe_mode, - DWORD max_instances, - DWORD out_buffer_size, - DWORD in_buffer_size, - DWORD default_timeout, HANDLE* pipe); -}; - -} // namespace sandbox - - -#endif // SANDBOX_SRC_NAMED_PIPE_POLICY_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/named_pipe_policy_test.cc deleted file mode 100644 index 813cf1f46..000000000 --- a/security/sandbox/chromium/sandbox/win/src/named_pipe_policy_test.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/win/windows_version.h" -#include "sandbox/win/src/handle_closer.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/tests/common/controller.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - - -SBOX_TESTS_COMMAND int NamedPipe_Create(int argc, wchar_t **argv) { - if (argc < 1 || argc > 2) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - if ((NULL == argv) || (NULL == argv[0])) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - - HANDLE pipe = ::CreateNamedPipeW(argv[0], - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, 4096, - 4096, 2000, NULL); - if (INVALID_HANDLE_VALUE == pipe) - return SBOX_TEST_DENIED; - - // The second parameter allows us to enforce a whitelist for where the - // pipe should be in the object namespace after creation. - if (argc == 2) { - base::string16 handle_name; - if (GetHandleName(pipe, &handle_name)) { - if (handle_name.compare(0, wcslen(argv[1]), argv[1]) != 0) - return SBOX_TEST_FAILED; - } else { - return SBOX_TEST_FAILED; - } - } - - OVERLAPPED overlapped = {0}; - overlapped.hEvent = ::CreateEvent(NULL, TRUE, TRUE, NULL); - BOOL result = ::ConnectNamedPipe(pipe, &overlapped); - - if (!result) { - DWORD error = ::GetLastError(); - if (ERROR_PIPE_CONNECTED != error && - ERROR_IO_PENDING != error) { - return SBOX_TEST_FAILED; - } - } - - if (!::CloseHandle(pipe)) - return SBOX_TEST_FAILED; - - ::CloseHandle(overlapped.hEvent); - return SBOX_TEST_SUCCEEDED; -} - -// Tests if we can create a pipe in the sandbox. -TEST(NamedPipePolicyTest, CreatePipe) { - TestRunner runner; - // TODO(nsylvain): This policy is wrong because "*" is a valid char in a - // namedpipe name. Here we apply it like a wildcard. http://b/893603 - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES, - TargetPolicy::NAMEDPIPES_ALLOW_ANY, - L"\\\\.\\pipe\\test*")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh")); - - // On XP, the sandbox can create a pipe without any help but it fails on - // Vista+, this is why we do not test the "denied" case. - if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh")); - } -} - -// Tests if we can create a pipe with a path traversal in the sandbox. -TEST(NamedPipePolicyTest, CreatePipeTraversal) { - TestRunner runner; - // TODO(nsylvain): This policy is wrong because "*" is a valid char in a - // namedpipe name. Here we apply it like a wildcard. http://b/893603 - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES, - TargetPolicy::NAMEDPIPES_ALLOW_ANY, - L"\\\\.\\pipe\\test*")); - - // On XP, the sandbox can create a pipe without any help but it fails on - // Vista+, this is why we do not test the "denied" case. - if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\..\\bleh")); - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/../bleh")); - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\../bleh")); - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/..\\bleh")); - } -} - -// This tests that path canonicalization is actually disabled if we use \\?\ -// syntax. -TEST(NamedPipePolicyTest, CreatePipeCanonicalization) { - // "For file I/O, the "\\?\" prefix to a path string tells the Windows APIs to - // disable all string parsing and to send the string that follows it straight - // to the file system." - // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx - const wchar_t* argv[2] = { L"\\\\?\\pipe\\test\\..\\bleh", - L"\\Device\\NamedPipe\\test" }; - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - NamedPipe_Create(2, const_cast<wchar_t**>(argv))); -} - -// The same test as CreatePipe but this time using strict interceptions. -TEST(NamedPipePolicyTest, CreatePipeStrictInterceptions) { - TestRunner runner; - runner.GetPolicy()->SetStrictInterceptions(); - - // TODO(nsylvain): This policy is wrong because "*" is a valid char in a - // namedpipe name. Here we apply it like a wildcard. http://b/893603 - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES, - TargetPolicy::NAMEDPIPES_ALLOW_ANY, - L"\\\\.\\pipe\\test*")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh")); - - // On XP, the sandbox can create a pipe without any help but it fails on - // Vista+, this is why we do not test the "denied" case. - if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh")); - } -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/nt_internals.h b/security/sandbox/chromium/sandbox/win/src/nt_internals.h deleted file mode 100644 index 2a39d5b94..000000000 --- a/security/sandbox/chromium/sandbox/win/src/nt_internals.h +++ /dev/null @@ -1,703 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file holds definitions related to the ntdll API. - -#ifndef SANDBOX_WIN_SRC_NT_INTERNALS_H__ -#define SANDBOX_WIN_SRC_NT_INTERNALS_H__ - -#include <windows.h> -#include <stddef.h> - -typedef LONG NTSTATUS; -#define NT_SUCCESS(st) (st >= 0) - -#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) -#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L) -#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) -#define STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) -#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) -#ifndef STATUS_INVALID_PARAMETER -// It is now defined in Windows 2008 SDK. -#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL) -#endif -#define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS)0xC0000018L) -#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) -#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) -#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L) -#define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS)0xC0000035L) -#define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS)0xC000007AL) -#define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL) -#define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL) - -#define CURRENT_PROCESS ((HANDLE) -1) -#define CURRENT_THREAD ((HANDLE) -2) -#define NtCurrentProcess CURRENT_PROCESS - -typedef struct _UNICODE_STRING { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING; -typedef UNICODE_STRING *PUNICODE_STRING; -typedef const UNICODE_STRING *PCUNICODE_STRING; - -typedef struct _STRING { - USHORT Length; - USHORT MaximumLength; - PCHAR Buffer; -} STRING; -typedef STRING *PSTRING; - -typedef STRING ANSI_STRING; -typedef PSTRING PANSI_STRING; -typedef CONST PSTRING PCANSI_STRING; - -typedef STRING OEM_STRING; -typedef PSTRING POEM_STRING; -typedef CONST STRING* PCOEM_STRING; - -#define OBJ_CASE_INSENSITIVE 0x00000040L -#define OBJ_OPENIF 0x00000080L - -typedef struct _OBJECT_ATTRIBUTES { - ULONG Length; - HANDLE RootDirectory; - PUNICODE_STRING ObjectName; - ULONG Attributes; - PVOID SecurityDescriptor; - PVOID SecurityQualityOfService; -} OBJECT_ATTRIBUTES; -typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; - -#define InitializeObjectAttributes(p, n, a, r, s) { \ - (p)->Length = sizeof(OBJECT_ATTRIBUTES);\ - (p)->RootDirectory = r;\ - (p)->Attributes = a;\ - (p)->ObjectName = n;\ - (p)->SecurityDescriptor = s;\ - (p)->SecurityQualityOfService = NULL;\ -} - -typedef struct _IO_STATUS_BLOCK { - union { - NTSTATUS Status; - PVOID Pointer; - }; - ULONG_PTR Information; -} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; - -// ----------------------------------------------------------------------- -// File IO - -// Create disposition values. - -#define FILE_SUPERSEDE 0x00000000 -#define FILE_OPEN 0x00000001 -#define FILE_CREATE 0x00000002 -#define FILE_OPEN_IF 0x00000003 -#define FILE_OVERWRITE 0x00000004 -#define FILE_OVERWRITE_IF 0x00000005 -#define FILE_MAXIMUM_DISPOSITION 0x00000005 - -// Create/open option flags. - -#define FILE_DIRECTORY_FILE 0x00000001 -#define FILE_WRITE_THROUGH 0x00000002 -#define FILE_SEQUENTIAL_ONLY 0x00000004 -#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 - -#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 -#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 -#define FILE_NON_DIRECTORY_FILE 0x00000040 -#define FILE_CREATE_TREE_CONNECTION 0x00000080 - -#define FILE_COMPLETE_IF_OPLOCKED 0x00000100 -#define FILE_NO_EA_KNOWLEDGE 0x00000200 -#define FILE_OPEN_REMOTE_INSTANCE 0x00000400 -#define FILE_RANDOM_ACCESS 0x00000800 - -#define FILE_DELETE_ON_CLOSE 0x00001000 -#define FILE_OPEN_BY_FILE_ID 0x00002000 -#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 -#define FILE_NO_COMPRESSION 0x00008000 - -#define FILE_RESERVE_OPFILTER 0x00100000 -#define FILE_OPEN_REPARSE_POINT 0x00200000 -#define FILE_OPEN_NO_RECALL 0x00400000 -#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 - -// Create/open result values. These are the disposition values returned on the -// io status information. -#define FILE_SUPERSEDED 0x00000000 -#define FILE_OPENED 0x00000001 -#define FILE_CREATED 0x00000002 -#define FILE_OVERWRITTEN 0x00000003 -#define FILE_EXISTS 0x00000004 -#define FILE_DOES_NOT_EXIST 0x00000005 - -typedef NTSTATUS (WINAPI *NtCreateFileFunction)( - OUT PHANDLE FileHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN PLARGE_INTEGER AllocationSize OPTIONAL, - IN ULONG FileAttributes, - IN ULONG ShareAccess, - IN ULONG CreateDisposition, - IN ULONG CreateOptions, - IN PVOID EaBuffer OPTIONAL, - IN ULONG EaLength); - -typedef NTSTATUS (WINAPI *NtOpenFileFunction)( - OUT PHANDLE FileHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG ShareAccess, - IN ULONG OpenOptions); - -typedef NTSTATUS (WINAPI *NtCloseFunction)( - IN HANDLE Handle); - -typedef enum _FILE_INFORMATION_CLASS { - FileRenameInformation = 10 -} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; - -typedef struct _FILE_RENAME_INFORMATION { - BOOLEAN ReplaceIfExists; - HANDLE RootDirectory; - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; - -typedef NTSTATUS (WINAPI *NtSetInformationFileFunction)( - IN HANDLE FileHandle, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN PVOID FileInformation, - IN ULONG Length, - IN FILE_INFORMATION_CLASS FileInformationClass); - -typedef struct FILE_BASIC_INFORMATION { - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - ULONG FileAttributes; -} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; - -typedef NTSTATUS (WINAPI *NtQueryAttributesFileFunction)( - IN POBJECT_ATTRIBUTES ObjectAttributes, - OUT PFILE_BASIC_INFORMATION FileAttributes); - -typedef struct _FILE_NETWORK_OPEN_INFORMATION { - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER AllocationSize; - LARGE_INTEGER EndOfFile; - ULONG FileAttributes; -} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; - -typedef NTSTATUS (WINAPI *NtQueryFullAttributesFileFunction)( - IN POBJECT_ATTRIBUTES ObjectAttributes, - OUT PFILE_NETWORK_OPEN_INFORMATION FileAttributes); - -// ----------------------------------------------------------------------- -// Sections - -typedef NTSTATUS (WINAPI *NtCreateSectionFunction)( - OUT PHANDLE SectionHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN PLARGE_INTEGER MaximumSize OPTIONAL, - IN ULONG SectionPageProtection, - IN ULONG AllocationAttributes, - IN HANDLE FileHandle OPTIONAL); - -typedef ULONG SECTION_INHERIT; -#define ViewShare 1 -#define ViewUnmap 2 - -typedef NTSTATUS (WINAPI *NtMapViewOfSectionFunction)( - IN HANDLE SectionHandle, - IN HANDLE ProcessHandle, - IN OUT PVOID *BaseAddress, - IN ULONG_PTR ZeroBits, - IN SIZE_T CommitSize, - IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, - IN OUT PSIZE_T ViewSize, - IN SECTION_INHERIT InheritDisposition, - IN ULONG AllocationType, - IN ULONG Win32Protect); - -typedef NTSTATUS (WINAPI *NtUnmapViewOfSectionFunction)( - IN HANDLE ProcessHandle, - IN PVOID BaseAddress); - -typedef enum _SECTION_INFORMATION_CLASS { - SectionBasicInformation = 0, - SectionImageInformation -} SECTION_INFORMATION_CLASS; - -typedef struct _SECTION_BASIC_INFORMATION { - PVOID BaseAddress; - ULONG Attributes; - LARGE_INTEGER Size; -} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; - -typedef NTSTATUS (WINAPI *NtQuerySectionFunction)( - IN HANDLE SectionHandle, - IN SECTION_INFORMATION_CLASS SectionInformationClass, - OUT PVOID SectionInformation, - IN SIZE_T SectionInformationLength, - OUT PSIZE_T ReturnLength OPTIONAL); - -// ----------------------------------------------------------------------- -// Process and Thread - -typedef struct _CLIENT_ID { - PVOID UniqueProcess; - PVOID UniqueThread; -} CLIENT_ID, *PCLIENT_ID; - -typedef NTSTATUS (WINAPI *NtOpenThreadFunction) ( - OUT PHANDLE ThreadHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId); - -typedef NTSTATUS (WINAPI *NtOpenProcessFunction) ( - OUT PHANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId); - -typedef enum _NT_THREAD_INFORMATION_CLASS { - ThreadBasicInformation, - ThreadTimes, - ThreadPriority, - ThreadBasePriority, - ThreadAffinityMask, - ThreadImpersonationToken, - ThreadDescriptorTableEntry, - ThreadEnableAlignmentFaultFixup, - ThreadEventPair, - ThreadQuerySetWin32StartAddress, - ThreadZeroTlsCell, - ThreadPerformanceCount, - ThreadAmILastThread, - ThreadIdealProcessor, - ThreadPriorityBoost, - ThreadSetTlsArrayAddress, - ThreadIsIoPending, - ThreadHideFromDebugger -} NT_THREAD_INFORMATION_CLASS, *PNT_THREAD_INFORMATION_CLASS; - -typedef NTSTATUS (WINAPI *NtSetInformationThreadFunction) ( - IN HANDLE ThreadHandle, - IN NT_THREAD_INFORMATION_CLASS ThreadInformationClass, - IN PVOID ThreadInformation, - IN ULONG ThreadInformationLength); - -// Partial definition only: -typedef enum _PROCESSINFOCLASS { - ProcessBasicInformation = 0, - ProcessExecuteFlags = 0x22 -} PROCESSINFOCLASS; - -typedef PVOID PPEB; -typedef LONG KPRIORITY; - -typedef struct _PROCESS_BASIC_INFORMATION { - union { - NTSTATUS ExitStatus; - PVOID padding_for_x64_0; - }; - PPEB PebBaseAddress; - KAFFINITY AffinityMask; - union { - KPRIORITY BasePriority; - PVOID padding_for_x64_1; - }; - union { - DWORD UniqueProcessId; - PVOID padding_for_x64_2; - }; - union { - DWORD InheritedFromUniqueProcessId; - PVOID padding_for_x64_3; - }; -} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; - -typedef NTSTATUS (WINAPI *NtQueryInformationProcessFunction)( - IN HANDLE ProcessHandle, - IN PROCESSINFOCLASS ProcessInformationClass, - OUT PVOID ProcessInformation, - IN ULONG ProcessInformationLength, - OUT PULONG ReturnLength OPTIONAL); - -typedef NTSTATUS (WINAPI *NtSetInformationProcessFunction)( - HANDLE ProcessHandle, - IN PROCESSINFOCLASS ProcessInformationClass, - IN PVOID ProcessInformation, - IN ULONG ProcessInformationLength); - -typedef NTSTATUS (WINAPI *NtOpenThreadTokenFunction) ( - IN HANDLE ThreadHandle, - IN ACCESS_MASK DesiredAccess, - IN BOOLEAN OpenAsSelf, - OUT PHANDLE TokenHandle); - -typedef NTSTATUS (WINAPI *NtOpenThreadTokenExFunction) ( - IN HANDLE ThreadHandle, - IN ACCESS_MASK DesiredAccess, - IN BOOLEAN OpenAsSelf, - IN ULONG HandleAttributes, - OUT PHANDLE TokenHandle); - -typedef NTSTATUS (WINAPI *NtOpenProcessTokenFunction) ( - IN HANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - OUT PHANDLE TokenHandle); - -typedef NTSTATUS (WINAPI *NtOpenProcessTokenExFunction) ( - IN HANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN ULONG HandleAttributes, - OUT PHANDLE TokenHandle); - -typedef NTSTATUS (WINAPI * RtlCreateUserThreadFunction)( - IN HANDLE Process, - IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, - IN BOOLEAN CreateSuspended, - IN ULONG ZeroBits, - IN SIZE_T MaximumStackSize, - IN SIZE_T CommittedStackSize, - IN LPTHREAD_START_ROUTINE StartAddress, - IN PVOID Parameter, - OUT PHANDLE Thread, - OUT PCLIENT_ID ClientId); - -// ----------------------------------------------------------------------- -// Registry - -typedef NTSTATUS (WINAPI *NtCreateKeyFunction)( - OUT PHANDLE KeyHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG TitleIndex, - IN PUNICODE_STRING Class OPTIONAL, - IN ULONG CreateOptions, - OUT PULONG Disposition OPTIONAL); - -typedef NTSTATUS (WINAPI *NtOpenKeyFunction)( - OUT PHANDLE KeyHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes); - -typedef NTSTATUS (WINAPI *NtOpenKeyExFunction)( - OUT PHANDLE KeyHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN DWORD open_options); - -typedef NTSTATUS (WINAPI *NtDeleteKeyFunction)( - IN HANDLE KeyHandle); - -// ----------------------------------------------------------------------- -// Memory - -// Don't really need this structure right now. -typedef PVOID PRTL_HEAP_PARAMETERS; - -typedef PVOID (WINAPI *RtlCreateHeapFunction)( - IN ULONG Flags, - IN PVOID HeapBase OPTIONAL, - IN SIZE_T ReserveSize OPTIONAL, - IN SIZE_T CommitSize OPTIONAL, - IN PVOID Lock OPTIONAL, - IN PRTL_HEAP_PARAMETERS Parameters OPTIONAL); - -typedef PVOID (WINAPI *RtlDestroyHeapFunction)( - IN PVOID HeapHandle); - -typedef PVOID (WINAPI *RtlAllocateHeapFunction)( - IN PVOID HeapHandle, - IN ULONG Flags, - IN SIZE_T Size); - -typedef BOOLEAN (WINAPI *RtlFreeHeapFunction)( - IN PVOID HeapHandle, - IN ULONG Flags, - IN PVOID HeapBase); - -typedef NTSTATUS (WINAPI *NtAllocateVirtualMemoryFunction) ( - IN HANDLE ProcessHandle, - IN OUT PVOID *BaseAddress, - IN ULONG_PTR ZeroBits, - IN OUT PSIZE_T RegionSize, - IN ULONG AllocationType, - IN ULONG Protect); - -typedef NTSTATUS (WINAPI *NtFreeVirtualMemoryFunction) ( - IN HANDLE ProcessHandle, - IN OUT PVOID *BaseAddress, - IN OUT PSIZE_T RegionSize, - IN ULONG FreeType); - -typedef enum _MEMORY_INFORMATION_CLASS { - MemoryBasicInformation = 0, - MemoryWorkingSetList, - MemorySectionName, - MemoryBasicVlmInformation -} MEMORY_INFORMATION_CLASS; - -typedef struct _MEMORY_SECTION_NAME { // Information Class 2 - UNICODE_STRING SectionFileName; -} MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME; - -typedef NTSTATUS (WINAPI *NtQueryVirtualMemoryFunction)( - IN HANDLE ProcessHandle, - IN PVOID BaseAddress, - IN MEMORY_INFORMATION_CLASS MemoryInformationClass, - OUT PVOID MemoryInformation, - IN SIZE_T MemoryInformationLength, - OUT PSIZE_T ReturnLength OPTIONAL); - -typedef NTSTATUS (WINAPI *NtProtectVirtualMemoryFunction)( - IN HANDLE ProcessHandle, - IN OUT PVOID* BaseAddress, - IN OUT PSIZE_T ProtectSize, - IN ULONG NewProtect, - OUT PULONG OldProtect); - -// ----------------------------------------------------------------------- -// Objects - -typedef enum _OBJECT_INFORMATION_CLASS { - ObjectBasicInformation, - ObjectNameInformation, - ObjectTypeInformation, - ObjectAllInformation, - ObjectDataInformation -} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS; - -typedef struct _OBJDIR_INFORMATION { - UNICODE_STRING ObjectName; - UNICODE_STRING ObjectTypeName; - BYTE Data[1]; -} OBJDIR_INFORMATION; - -typedef struct _PUBLIC_OBJECT_BASIC_INFORMATION { - ULONG Attributes; - ACCESS_MASK GrantedAccess; - ULONG HandleCount; - ULONG PointerCount; - ULONG Reserved[10]; // reserved for internal use -} PUBLIC_OBJECT_BASIC_INFORMATION, *PPUBLIC_OBJECT_BASIC_INFORMATION; - -typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION { - UNICODE_STRING TypeName; - ULONG Reserved[22]; // reserved for internal use -} PUBLIC_OBJECT_TYPE_INFORMATION, *PPUBLIC_OBJECT_TYPE_INFORMATION; - -typedef enum _POOL_TYPE { - NonPagedPool, - PagedPool, - NonPagedPoolMustSucceed, - ReservedType, - NonPagedPoolCacheAligned, - PagedPoolCacheAligned, - NonPagedPoolCacheAlignedMustS -} POOL_TYPE; - -typedef struct _OBJECT_BASIC_INFORMATION { - ULONG Attributes; - ACCESS_MASK GrantedAccess; - ULONG HandleCount; - ULONG PointerCount; - ULONG PagedPoolUsage; - ULONG NonPagedPoolUsage; - ULONG Reserved[3]; - ULONG NameInformationLength; - ULONG TypeInformationLength; - ULONG SecurityDescriptorLength; - LARGE_INTEGER CreateTime; -} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; - -typedef struct _OBJECT_TYPE_INFORMATION { - UNICODE_STRING Name; - ULONG TotalNumberOfObjects; - ULONG TotalNumberOfHandles; - ULONG TotalPagedPoolUsage; - ULONG TotalNonPagedPoolUsage; - ULONG TotalNamePoolUsage; - ULONG TotalHandleTableUsage; - ULONG HighWaterNumberOfObjects; - ULONG HighWaterNumberOfHandles; - ULONG HighWaterPagedPoolUsage; - ULONG HighWaterNonPagedPoolUsage; - ULONG HighWaterNamePoolUsage; - ULONG HighWaterHandleTableUsage; - ULONG InvalidAttributes; - GENERIC_MAPPING GenericMapping; - ULONG ValidAccess; - BOOLEAN SecurityRequired; - BOOLEAN MaintainHandleCount; - USHORT MaintainTypeList; - POOL_TYPE PoolType; - ULONG PagedPoolUsage; - ULONG NonPagedPoolUsage; -} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; - -typedef enum _SYSTEM_INFORMATION_CLASS { - SystemHandleInformation = 16 -} SYSTEM_INFORMATION_CLASS; - -typedef struct _SYSTEM_HANDLE_INFORMATION { - USHORT ProcessId; - USHORT CreatorBackTraceIndex; - UCHAR ObjectTypeNumber; - UCHAR Flags; - USHORT Handle; - PVOID Object; - ACCESS_MASK GrantedAccess; -} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; - -typedef struct _SYSTEM_HANDLE_INFORMATION_EX { - ULONG NumberOfHandles; - SYSTEM_HANDLE_INFORMATION Information[1]; -} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; - -typedef struct _OBJECT_NAME_INFORMATION { - UNICODE_STRING ObjectName; -} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; - -typedef NTSTATUS (WINAPI *NtQueryObjectFunction)( - IN HANDLE Handle, - IN OBJECT_INFORMATION_CLASS ObjectInformationClass, - OUT PVOID ObjectInformation OPTIONAL, - IN ULONG ObjectInformationLength, - OUT PULONG ReturnLength OPTIONAL); - -typedef NTSTATUS (WINAPI *NtDuplicateObjectFunction)( - IN HANDLE SourceProcess, - IN HANDLE SourceHandle, - IN HANDLE TargetProcess, - OUT PHANDLE TargetHandle, - IN ACCESS_MASK DesiredAccess, - IN ULONG Attributes, - IN ULONG Options); - -typedef NTSTATUS (WINAPI *NtSignalAndWaitForSingleObjectFunction)( - IN HANDLE HandleToSignal, - IN HANDLE HandleToWait, - IN BOOLEAN Alertable, - IN PLARGE_INTEGER Timeout OPTIONAL); - -typedef NTSTATUS (WINAPI *NtQuerySystemInformation)( - IN SYSTEM_INFORMATION_CLASS SystemInformationClass, - OUT PVOID SystemInformation, - IN ULONG SystemInformationLength, - OUT PULONG ReturnLength); - -typedef NTSTATUS (WINAPI *NtQueryObject)( - IN HANDLE Handle, - IN OBJECT_INFORMATION_CLASS ObjectInformationClass, - OUT PVOID ObjectInformation, - IN ULONG ObjectInformationLength, - OUT PULONG ReturnLength); - -// ----------------------------------------------------------------------- -// Strings - -typedef int (__cdecl *_strnicmpFunction)( - IN const char* _Str1, - IN const char* _Str2, - IN size_t _MaxCount); - -typedef size_t (__cdecl *strlenFunction)( - IN const char * _Str); - -typedef size_t (__cdecl *wcslenFunction)( - IN const wchar_t* _Str); - -typedef void* (__cdecl *memcpyFunction)( - IN void* dest, - IN const void* src, - IN size_t count); - -typedef NTSTATUS (WINAPI *RtlAnsiStringToUnicodeStringFunction)( - IN OUT PUNICODE_STRING DestinationString, - IN PANSI_STRING SourceString, - IN BOOLEAN AllocateDestinationString); - -typedef LONG (WINAPI *RtlCompareUnicodeStringFunction)( - IN PCUNICODE_STRING String1, - IN PCUNICODE_STRING String2, - IN BOOLEAN CaseInSensitive); - -typedef VOID (WINAPI *RtlInitUnicodeStringFunction) ( - IN OUT PUNICODE_STRING DestinationString, - IN PCWSTR SourceString); - -typedef enum _EVENT_TYPE { - NotificationEvent, - SynchronizationEvent -} EVENT_TYPE, *PEVENT_TYPE; - -typedef NTSTATUS (WINAPI* NtCreateDirectoryObjectFunction) ( - PHANDLE DirectoryHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes); - -typedef NTSTATUS (WINAPI* NtOpenDirectoryObjectFunction) ( - PHANDLE DirectoryHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes); - -typedef NTSTATUS (WINAPI* NtQuerySymbolicLinkObjectFunction) ( - HANDLE LinkHandle, - PUNICODE_STRING LinkTarget, - PULONG ReturnedLength); - -typedef NTSTATUS (WINAPI* NtOpenSymbolicLinkObjectFunction) ( - PHANDLE LinkHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes); - -#define DIRECTORY_QUERY 0x0001 -#define DIRECTORY_TRAVERSE 0x0002 -#define DIRECTORY_CREATE_OBJECT 0x0004 -#define DIRECTORY_CREATE_SUBDIRECTORY 0x0008 -#define DIRECTORY_ALL_ACCESS 0x000F - -typedef NTSTATUS (WINAPI* NtCreateLowBoxToken)( - OUT PHANDLE token, - IN HANDLE original_handle, - IN ACCESS_MASK access, - IN POBJECT_ATTRIBUTES object_attribute, - IN PSID appcontainer_sid, - IN DWORD capabilityCount, - IN PSID_AND_ATTRIBUTES capabilities, - IN DWORD handle_count, - IN PHANDLE handles); - -typedef NTSTATUS(WINAPI *NtSetInformationProcess)( - IN HANDLE process_handle, - IN ULONG info_class, - IN PVOID process_information, - IN ULONG information_length); - -struct PROCESS_ACCESS_TOKEN { - HANDLE token; - HANDLE thread; -}; - -const unsigned int NtProcessInformationAccessToken = 9; - -#endif // SANDBOX_WIN_SRC_NT_INTERNALS_H__ - diff --git a/security/sandbox/chromium/sandbox/win/src/policy_broker.cc b/security/sandbox/chromium/sandbox/win/src/policy_broker.cc deleted file mode 100644 index a946ebc76..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_broker.cc +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> - -#include <map> - -#include "sandbox/win/src/policy_broker.h" - -#include "base/logging.h" -#include "base/win/pe_image.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/policy_target.h" -#include "sandbox/win/src/process_thread_interception.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_nt_types.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/target_process.h" - -// This code executes on the broker side, as a callback from the policy on the -// target side (the child). - -namespace sandbox { - -// This is the list of all imported symbols from ntdll.dll. -SANDBOX_INTERCEPT NtExports g_nt; - -#define INIT_GLOBAL_NT(member) \ - g_nt.member = reinterpret_cast<Nt##member##Function>( \ - ntdll_image.GetProcAddress("Nt" #member)); \ - if (NULL == g_nt.member) \ - return false - -#define INIT_GLOBAL_RTL(member) \ - g_nt.member = reinterpret_cast<member##Function>( \ - ntdll_image.GetProcAddress(#member)); \ - if (NULL == g_nt.member) \ - return false - -bool InitGlobalNt() { - HMODULE ntdll = ::GetModuleHandle(kNtdllName); - base::win::PEImage ntdll_image(ntdll); - - // Bypass purify's interception. - wchar_t* loader_get = reinterpret_cast<wchar_t*>( - ntdll_image.GetProcAddress("LdrGetDllHandle")); - if (loader_get) { - GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - loader_get, &ntdll); - } - - INIT_GLOBAL_NT(AllocateVirtualMemory); - INIT_GLOBAL_NT(Close); - INIT_GLOBAL_NT(DuplicateObject); - INIT_GLOBAL_NT(FreeVirtualMemory); - INIT_GLOBAL_NT(MapViewOfSection); - INIT_GLOBAL_NT(ProtectVirtualMemory); - INIT_GLOBAL_NT(QueryInformationProcess); - INIT_GLOBAL_NT(QueryObject); - INIT_GLOBAL_NT(QuerySection); - INIT_GLOBAL_NT(QueryVirtualMemory); - INIT_GLOBAL_NT(UnmapViewOfSection); - - INIT_GLOBAL_RTL(RtlAllocateHeap); - INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString); - INIT_GLOBAL_RTL(RtlCompareUnicodeString); - INIT_GLOBAL_RTL(RtlCreateHeap); - INIT_GLOBAL_RTL(RtlCreateUserThread); - INIT_GLOBAL_RTL(RtlDestroyHeap); - INIT_GLOBAL_RTL(RtlFreeHeap); - INIT_GLOBAL_RTL(_strnicmp); - INIT_GLOBAL_RTL(strlen); - INIT_GLOBAL_RTL(wcslen); - INIT_GLOBAL_RTL(memcpy); - - return true; -} - -bool SetupNtdllImports(TargetProcess *child) { - if (!InitGlobalNt()) { - return false; - } - -#ifndef NDEBUG - // Verify that the structure is fully initialized. - for (size_t i = 0; i < sizeof(g_nt)/sizeof(void*); i++) - DCHECK(reinterpret_cast<char**>(&g_nt)[i]); -#endif - return (SBOX_ALL_OK == child->TransferVariable("g_nt", &g_nt, sizeof(g_nt))); -} - -#undef INIT_GLOBAL_NT -#undef INIT_GLOBAL_RTL - -bool SetupBasicInterceptions(InterceptionManager* manager) { - // Interceptions provided by process_thread_policy, without actual policy. - if (!INTERCEPT_NT(manager, NtOpenThread, OPEN_TREAD_ID, 20) || - !INTERCEPT_NT(manager, NtOpenProcess, OPEN_PROCESS_ID, 20) || - !INTERCEPT_NT(manager, NtOpenProcessToken, OPEN_PROCESS_TOKEN_ID, 16)) - return false; - - // Interceptions with neither policy nor IPC. - if (!INTERCEPT_NT(manager, NtSetInformationThread, SET_INFORMATION_THREAD_ID, - 20) || - !INTERCEPT_NT(manager, NtOpenThreadToken, OPEN_THREAD_TOKEN_ID, 20)) - return false; - - if (base::win::GetVersion() >= base::win::VERSION_XP) { - // Bug 27218: We don't have dispatch for some x64 syscalls. - // This one is also provided by process_thread_policy. - if (!INTERCEPT_NT(manager, NtOpenProcessTokenEx, OPEN_PROCESS_TOKEN_EX_ID, - 20)) - return false; - - return INTERCEPT_NT(manager, NtOpenThreadTokenEx, OPEN_THREAD_TOKEN_EX_ID, - 24); - } - - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/policy_broker.h b/security/sandbox/chromium/sandbox/win/src/policy_broker.h deleted file mode 100644 index 15d3b21ef..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_broker.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_POLICY_BROKER_H_ -#define SANDBOX_SRC_POLICY_BROKER_H_ - -#include "sandbox/win/src/interception.h" - -namespace sandbox { - -class TargetProcess; - -// Initializes global imported symbols from ntdll. -bool InitGlobalNt(); - -// Sets up interceptions not controlled by explicit policies. -bool SetupBasicInterceptions(InterceptionManager* manager); - -// Sets up imports from NTDLL for the given target process so the interceptions -// can work. -bool SetupNtdllImports(TargetProcess *child); - -} // namespace sandbox - -#endif // SANDBOX_SRC_POLICY_BROKER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc deleted file mode 100644 index 8dca0d9d6..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc +++ /dev/null @@ -1,446 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/policy_engine_opcodes.h" - -#include <stddef.h> -#include <stdint.h> - -#include "sandbox/win/src/sandbox_nt_types.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace { -const unsigned short kMaxUniStrSize = 0xfffc / sizeof(wchar_t); - -bool InitStringUnicode(const wchar_t* source, size_t length, - UNICODE_STRING* ustring) { - if (length > kMaxUniStrSize) { - return false; - } - ustring->Buffer = const_cast<wchar_t*>(source); - ustring->Length = static_cast<USHORT>(length) * sizeof(wchar_t); - ustring->MaximumLength = (NULL != source) ? - ustring->Length + sizeof(wchar_t) : 0; - return true; -} - -} // namespace - -namespace sandbox { - -SANDBOX_INTERCEPT NtExports g_nt; - -// Note: The opcodes are implemented as functions (as opposed to classes derived -// from PolicyOpcode) because you should not add more member variables to the -// PolicyOpcode class since it would cause object slicing on the target. So to -// enforce that (instead of just trusting the developer) the opcodes became -// just functions. -// -// In the code that follows I have keep the evaluation function and the factory -// function together to stress the close relationship between both. For example, -// only the factory method and the evaluation function know the stored argument -// order and meaning. - -template <int> -EvalResult OpcodeEval(PolicyOpcode* opcode, const ParameterSet* pp, - MatchContext* match); - -////////////////////////////////////////////////////////////////////////////// -// Opcode OpAlwaysFalse: -// Does not require input parameter. - -PolicyOpcode* OpcodeFactory::MakeOpAlwaysFalse(uint32_t options) { - return MakeBase(OP_ALWAYS_FALSE, options, -1); -} - -template <> -EvalResult OpcodeEval<OP_ALWAYS_FALSE>(PolicyOpcode* opcode, - const ParameterSet* param, - MatchContext* context) { - return EVAL_FALSE; -} - -////////////////////////////////////////////////////////////////////////////// -// Opcode OpAlwaysTrue: -// Does not require input parameter. - -PolicyOpcode* OpcodeFactory::MakeOpAlwaysTrue(uint32_t options) { - return MakeBase(OP_ALWAYS_TRUE, options, -1); -} - -template <> -EvalResult OpcodeEval<OP_ALWAYS_TRUE>(PolicyOpcode* opcode, - const ParameterSet* param, - MatchContext* context) { - return EVAL_TRUE; -} - -////////////////////////////////////////////////////////////////////////////// -// Opcode OpAction: -// Does not require input parameter. -// Argument 0 contains the actual action to return. - -PolicyOpcode* OpcodeFactory::MakeOpAction(EvalResult action, uint32_t options) { - PolicyOpcode* opcode = MakeBase(OP_ACTION, options, 0); - if (NULL == opcode) return NULL; - opcode->SetArgument(0, action); - return opcode; -} - -template <> -EvalResult OpcodeEval<OP_ACTION>(PolicyOpcode* opcode, - const ParameterSet* param, - MatchContext* context) { - int action = 0; - opcode->GetArgument(0, &action); - return static_cast<EvalResult>(action); -} - -////////////////////////////////////////////////////////////////////////////// -// Opcode OpNumberMatch: -// Requires a uint32_t or void* in selected_param -// Argument 0 is the stored number to match. -// Argument 1 is the C++ type of the 0th argument. - -PolicyOpcode* OpcodeFactory::MakeOpNumberMatch(int16_t selected_param, - uint32_t match, - uint32_t options) { - PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param); - if (NULL == opcode) return NULL; - opcode->SetArgument(0, match); - opcode->SetArgument(1, UINT32_TYPE); - return opcode; -} - -PolicyOpcode* OpcodeFactory::MakeOpVoidPtrMatch(int16_t selected_param, - const void* match, - uint32_t options) { - PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param); - if (NULL == opcode) return NULL; - opcode->SetArgument(0, match); - opcode->SetArgument(1, VOIDPTR_TYPE); - return opcode; -} - -template <> -EvalResult OpcodeEval<OP_NUMBER_MATCH>(PolicyOpcode* opcode, - const ParameterSet* param, - MatchContext* context) { - uint32_t value_uint32 = 0; - if (param->Get(&value_uint32)) { - uint32_t match_uint32 = 0; - opcode->GetArgument(0, &match_uint32); - return (match_uint32 != value_uint32)? EVAL_FALSE : EVAL_TRUE; - } else { - const void* value_ptr = NULL; - if (param->Get(&value_ptr)) { - const void* match_ptr = NULL; - opcode->GetArgument(0, &match_ptr); - return (match_ptr != value_ptr)? EVAL_FALSE : EVAL_TRUE; - } - } - return EVAL_ERROR; -} - -////////////////////////////////////////////////////////////////////////////// -// Opcode OpNumberMatchRange -// Requires a uint32_t in selected_param. -// Argument 0 is the stored lower bound to match. -// Argument 1 is the stored upper bound to match. - -PolicyOpcode* OpcodeFactory::MakeOpNumberMatchRange(int16_t selected_param, - uint32_t lower_bound, - uint32_t upper_bound, - uint32_t options) { - if (lower_bound > upper_bound) { - return NULL; - } - PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH_RANGE, options, - selected_param); - if (NULL == opcode) return NULL; - opcode->SetArgument(0, lower_bound); - opcode->SetArgument(1, upper_bound); - return opcode; -} - -template <> -EvalResult OpcodeEval<OP_NUMBER_MATCH_RANGE>(PolicyOpcode* opcode, - const ParameterSet* param, - MatchContext* context) { - uint32_t value = 0; - if (!param->Get(&value)) return EVAL_ERROR; - - uint32_t lower_bound = 0; - uint32_t upper_bound = 0; - opcode->GetArgument(0, &lower_bound); - opcode->GetArgument(1, &upper_bound); - return((lower_bound <= value) && (upper_bound >= value))? - EVAL_TRUE : EVAL_FALSE; -} - -////////////////////////////////////////////////////////////////////////////// -// Opcode OpNumberAndMatch: -// Requires a uint32_t in selected_param. -// Argument 0 is the stored number to match. - -PolicyOpcode* OpcodeFactory::MakeOpNumberAndMatch(int16_t selected_param, - uint32_t match, - uint32_t options) { - PolicyOpcode* opcode = MakeBase(OP_NUMBER_AND_MATCH, options, selected_param); - if (NULL == opcode) return NULL; - opcode->SetArgument(0, match); - return opcode; -} - -template <> -EvalResult OpcodeEval<OP_NUMBER_AND_MATCH>(PolicyOpcode* opcode, - const ParameterSet* param, - MatchContext* context) { - uint32_t value = 0; - if (!param->Get(&value)) return EVAL_ERROR; - - uint32_t number = 0; - opcode->GetArgument(0, &number); - return (number & value)? EVAL_TRUE : EVAL_FALSE; -} - -////////////////////////////////////////////////////////////////////////////// -// Opcode OpWStringMatch: -// Requires a wchar_t* in selected_param. -// Argument 0 is the byte displacement of the stored string. -// Argument 1 is the lenght in chars of the stored string. -// Argument 2 is the offset to apply on the input string. It has special values. -// as noted in the header file. -// Argument 3 is the string matching options. - -PolicyOpcode* OpcodeFactory::MakeOpWStringMatch(int16_t selected_param, - const wchar_t* match_str, - int start_position, - StringMatchOptions match_opts, - uint32_t options) { - if (NULL == match_str) { - return NULL; - } - if ('\0' == match_str[0]) { - return NULL; - } - - int lenght = lstrlenW(match_str); - - PolicyOpcode* opcode = MakeBase(OP_WSTRING_MATCH, options, selected_param); - if (NULL == opcode) { - return NULL; - } - ptrdiff_t delta_str = AllocRelative(opcode, match_str, wcslen(match_str)+1); - if (0 == delta_str) { - return NULL; - } - opcode->SetArgument(0, delta_str); - opcode->SetArgument(1, lenght); - opcode->SetArgument(2, start_position); - opcode->SetArgument(3, match_opts); - return opcode; -} - -template<> -EvalResult OpcodeEval<OP_WSTRING_MATCH>(PolicyOpcode* opcode, - const ParameterSet* param, - MatchContext* context) { - if (NULL == context) { - return EVAL_ERROR; - } - const wchar_t* source_str = NULL; - if (!param->Get(&source_str)) return EVAL_ERROR; - - int start_position = 0; - int match_len = 0; - unsigned int match_opts = 0; - opcode->GetArgument(1, &match_len); - opcode->GetArgument(2, &start_position); - opcode->GetArgument(3, &match_opts); - - const wchar_t* match_str = opcode->GetRelativeString(0); - // Advance the source string to the last successfully evaluated position - // according to the match context. - source_str = &source_str[context->position]; - int source_len = static_cast<int>(g_nt.wcslen(source_str)); - - if (0 == source_len) { - // If we reached the end of the source string there is nothing we can - // match against. - return EVAL_FALSE; - } - if (match_len > source_len) { - // There can't be a positive match when the target string is bigger than - // the source string - return EVAL_FALSE; - } - - BOOLEAN case_sensitive = (match_opts & CASE_INSENSITIVE) ? TRUE : FALSE; - - // We have three cases, depending on the value of start_pos: - // Case 1. We skip N characters and compare once. - // Case 2: We skip to the end and compare once. - // Case 3: We match the first substring (if we find any). - if (start_position >= 0) { - if (kSeekToEnd == start_position) { - start_position = source_len - match_len; - } else if (match_opts & EXACT_LENGHT) { - // A sub-case of case 3 is when the EXACT_LENGHT flag is on - // the match needs to be not just substring but full match. - if ((match_len + start_position) != source_len) { - return EVAL_FALSE; - } - } - - // Advance start_pos characters. Warning! this does not consider - // utf16 encodings (surrogate pairs) or other Unicode 'features'. - source_str += start_position; - - // Since we skipped, lets reevaluate just the lengths again. - if ((match_len + start_position) > source_len) { - return EVAL_FALSE; - } - - UNICODE_STRING match_ustr; - UNICODE_STRING source_ustr; - if (!InitStringUnicode(match_str, match_len, &match_ustr) || - !InitStringUnicode(source_str, match_len, &source_ustr)) - return EVAL_ERROR; - - if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr, - case_sensitive)) { - // Match! update the match context. - context->position += start_position + match_len; - return EVAL_TRUE; - } else { - return EVAL_FALSE; - } - } else if (start_position < 0) { - UNICODE_STRING match_ustr; - UNICODE_STRING source_ustr; - if (!InitStringUnicode(match_str, match_len, &match_ustr) || - !InitStringUnicode(source_str, match_len, &source_ustr)) - return EVAL_ERROR; - - do { - if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr, - case_sensitive)) { - // Match! update the match context. - context->position += (source_ustr.Buffer - source_str) + match_len; - return EVAL_TRUE; - } - ++source_ustr.Buffer; - --source_len; - } while (source_len >= match_len); - } - return EVAL_FALSE; -} - -////////////////////////////////////////////////////////////////////////////// -// OpcodeMaker (other member functions). - -PolicyOpcode* OpcodeFactory::MakeBase(OpcodeID opcode_id, - uint32_t options, - int16_t selected_param) { - if (memory_size() < sizeof(PolicyOpcode)) { - return NULL; - } - - // Create opcode using placement-new on the buffer memory. - PolicyOpcode* opcode = new(memory_top_) PolicyOpcode(); - - // Fill in the standard fields, that every opcode has. - memory_top_ += sizeof(PolicyOpcode); - opcode->opcode_id_ = opcode_id; - opcode->SetOptions(options); - opcode->parameter_ = selected_param; - return opcode; -} - -ptrdiff_t OpcodeFactory::AllocRelative(void* start, const wchar_t* str, - size_t lenght) { - size_t bytes = lenght * sizeof(wchar_t); - if (memory_size() < bytes) { - return 0; - } - memory_bottom_ -= bytes; - if (reinterpret_cast<UINT_PTR>(memory_bottom_) & 1) { - // TODO(cpu) replace this for something better. - ::DebugBreak(); - } - memcpy(memory_bottom_, str, bytes); - ptrdiff_t delta = memory_bottom_ - reinterpret_cast<char*>(start); - return delta; -} - -////////////////////////////////////////////////////////////////////////////// -// Opcode evaluation dispatchers. - -// This function is the one and only entry for evaluating any opcode. It is -// in charge of applying any relevant opcode options and calling EvaluateInner -// were the actual dispatch-by-id is made. It would seem at first glance that -// the dispatch should be done by virtual function (vtable) calls but you have -// to remember that the opcodes are made in the broker process and copied as -// raw memory to the target process. - -EvalResult PolicyOpcode::Evaluate(const ParameterSet* call_params, - size_t param_count, MatchContext* match) { - if (NULL == call_params) { - return EVAL_ERROR; - } - const ParameterSet* selected_param = NULL; - if (parameter_ >= 0) { - if (static_cast<size_t>(parameter_) >= param_count) { - return EVAL_ERROR; - } - selected_param = &call_params[parameter_]; - } - EvalResult result = EvaluateHelper(selected_param, match); - - // Apply the general options regardless of the particular type of opcode. - if (kPolNone == options_) { - return result; - } - - if (options_ & kPolNegateEval) { - if (EVAL_TRUE == result) { - result = EVAL_FALSE; - } else if (EVAL_FALSE == result) { - result = EVAL_TRUE; - } else if (EVAL_ERROR != result) { - result = EVAL_ERROR; - } - } - if (NULL != match) { - if (options_ & kPolClearContext) { - match->Clear(); - } - if (options_ & kPolUseOREval) { - match->options = kPolUseOREval; - } - } - return result; -} - -#define OPCODE_EVAL(op, x, y, z) case op: return OpcodeEval<op>(x, y, z) - -EvalResult PolicyOpcode::EvaluateHelper(const ParameterSet* parameters, - MatchContext* match) { - switch (opcode_id_) { - OPCODE_EVAL(OP_ALWAYS_FALSE, this, parameters, match); - OPCODE_EVAL(OP_ALWAYS_TRUE, this, parameters, match); - OPCODE_EVAL(OP_NUMBER_MATCH, this, parameters, match); - OPCODE_EVAL(OP_NUMBER_MATCH_RANGE, this, parameters, match); - OPCODE_EVAL(OP_NUMBER_AND_MATCH, this, parameters, match); - OPCODE_EVAL(OP_WSTRING_MATCH, this, parameters, match); - OPCODE_EVAL(OP_ACTION, this, parameters, match); - default: - return EVAL_ERROR; - } -} - -#undef OPCODE_EVAL - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.h b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.h deleted file mode 100644 index 11a9c813e..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.h +++ /dev/null @@ -1,388 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_POLICY_ENGINE_OPCODES_H_ -#define SANDBOX_WIN_SRC_POLICY_ENGINE_OPCODES_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "base/numerics/safe_conversions.h" -#include "sandbox/win/src/policy_engine_params.h" - -// The low-level policy is implemented using the concept of policy 'opcodes'. -// An opcode is a structure that contains enough information to perform one -// comparison against one single input parameter. For example, an opcode can -// encode just one of the following comparison: -// -// - Is input parameter 3 not equal to NULL? -// - Does input parameter 2 start with L"c:\\"? -// - Is input parameter 5, bit 3 is equal 1? -// -// Each opcode is in fact equivalent to a function invocation where all -// the parameters are known by the opcode except one. So say you have a -// function of this form: -// bool fn(a, b, c, d) with 4 arguments -// -// Then an opcode is: -// op(fn, b, c, d) -// Which stores the function to call and its 3 last arguments -// -// Then and opcode evaluation is: -// op.eval(a) ------------------------> fn(a,b,c,d) -// internally calls -// -// The idea is that complex policy rules can be split into streams of -// opcodes which are evaluated in sequence. The evaluation is done in -// groups of opcodes that have N comparison opcodes plus 1 action opcode: -// -// [comparison 1][comparison 2]...[comparison N][action][comparison 1]... -// ----- evaluation order-----------> -// -// Each opcode group encodes one high-level policy rule. The rule applies -// only if all the conditions on the group evaluate to true. The action -// opcode contains the policy outcome for that particular rule. -// -// Note that this header contains the main building blocks of low-level policy -// but not the low level policy class. -namespace sandbox { - -// These are the possible policy outcomes. Note that some of them might -// not apply and can be removed. Also note that The following values only -// specify what to do, not how to do it and it is acceptable given specific -// cases to ignore the policy outcome. -enum EvalResult { - // Comparison opcode values: - EVAL_TRUE, // Opcode condition evaluated true. - EVAL_FALSE, // Opcode condition evaluated false. - EVAL_ERROR, // Opcode condition generated an error while evaluating. - // Action opcode values: - ASK_BROKER, // The target must generate an IPC to the broker. On the broker - // side, this means grant access to the resource. - DENY_ACCESS, // No access granted to the resource. - GIVE_READONLY, // Give readonly access to the resource. - GIVE_ALLACCESS, // Give full access to the resource. - GIVE_CACHED, // IPC is not required. Target can return a cached handle. - GIVE_FIRST, // TODO(cpu) - SIGNAL_ALARM, // Unusual activity. Generate an alarm. - FAKE_SUCCESS, // Do not call original function. Just return 'success'. - FAKE_ACCESS_DENIED, // Do not call original function. Just return 'denied' - // and do not do IPC. - TERMINATE_PROCESS, // Destroy target process. Do IPC as well. -}; - -// The following are the implemented opcodes. -enum OpcodeID { - OP_ALWAYS_FALSE, // Evaluates to false (EVAL_FALSE). - OP_ALWAYS_TRUE, // Evaluates to true (EVAL_TRUE). - OP_NUMBER_MATCH, // Match a 32-bit integer as n == a. - OP_NUMBER_MATCH_RANGE, // Match a 32-bit integer as a <= n <= b. - OP_NUMBER_AND_MATCH, // Match using bitwise AND; as in: n & a != 0. - OP_WSTRING_MATCH, // Match a string for equality. - OP_ACTION // Evaluates to an action opcode. -}; - -// Options that apply to every opcode. They are specified when creating -// each opcode using OpcodeFactory::MakeOpXXXXX() family of functions -// Do nothing special. -const uint32_t kPolNone = 0; - -// Convert EVAL_TRUE into EVAL_FALSE and vice-versa. This allows to express -// negated conditions such as if ( a && !b). -const uint32_t kPolNegateEval = 1; - -// Zero the MatchContext context structure. This happens after the opcode -// is evaluated. -const uint32_t kPolClearContext = 2; - -// Use OR when evaluating this set of opcodes. The policy evaluator by default -// uses AND when evaluating. Very helpful when -// used with kPolNegateEval. For example if you have a condition best expressed -// as if(! (a && b && c)), the use of this flags allows it to be expressed as -// if ((!a) || (!b) || (!c)). -const uint32_t kPolUseOREval = 4; - -// Keeps the evaluation state between opcode evaluations. This is used -// for string matching where the next opcode needs to continue matching -// from the last character position from the current opcode. The match -// context is preserved across opcode evaluation unless an opcode specifies -// as an option kPolClearContext. -struct MatchContext { - size_t position; - uint32_t options; - - MatchContext() { - Clear(); - } - - void Clear() { - position = 0; - options = 0; - } -}; - -// Models a policy opcode; that is a condition evaluation were all the -// arguments but one are stored in objects of this class. Use OpcodeFactory -// to create objects of this type. -// This class is just an implementation artifact and not exposed to the -// API clients or visible in the intercepted service. Internally, an -// opcode is just: -// - An integer that identifies the actual opcode. -// - An index to indicate which one is the input argument -// - An array of arguments. -// While an OO hierarchy of objects would have been a natural choice, the fact -// that 1) this code can execute before the CRT is loaded, presents serious -// problems in terms of guarantees about the actual state of the vtables and -// 2) because the opcode objects are generated in the broker process, we need to -// use plain objects. To preserve some minimal type safety templates are used -// when possible. -class PolicyOpcode { - friend class OpcodeFactory; - public: - // Evaluates the opcode. For a typical comparison opcode the return value - // is EVAL_TRUE or EVAL_FALSE. If there was an error in the evaluation the - // the return is EVAL_ERROR. If the opcode is an action opcode then the - // return can take other values such as ASK_BROKER. - // parameters: An array of all input parameters. This argument is normally - // created by the macros POLPARAMS_BEGIN() POLPARAMS_END. - // count: The number of parameters passed as first argument. - // match: The match context that is persisted across the opcode evaluation - // sequence. - EvalResult Evaluate(const ParameterSet* parameters, size_t count, - MatchContext* match); - - // Retrieves a stored argument by index. Valid index values are - // from 0 to < kArgumentCount. - template <typename T> - void GetArgument(size_t index, T* argument) const { - static_assert(sizeof(T) <= sizeof(arguments_[0]), "invalid size"); - *argument = *reinterpret_cast<const T*>(&arguments_[index].mem); - } - - // Sets a stored argument by index. Valid index values are - // from 0 to < kArgumentCount. - template <typename T> - void SetArgument(size_t index, const T& argument) { - static_assert(sizeof(T) <= sizeof(arguments_[0]), "invalid size"); - *reinterpret_cast<T*>(&arguments_[index].mem) = argument; - } - - // Retrieves the actual address of an string argument. When using - // GetArgument() to retrieve an index that contains a string, the returned - // value is just an offset to the actual string. - // index: the stored string index. Valid values are from 0 - // to < kArgumentCount. - const wchar_t* GetRelativeString(size_t index) const { - ptrdiff_t str_delta = 0; - GetArgument(index, &str_delta); - const char* delta = reinterpret_cast<const char*>(this) + str_delta; - return reinterpret_cast<const wchar_t*>(delta); - } - - // Returns true if this opcode is an action opcode without actually - // evaluating it. Used to do a quick scan forward to the next opcode group. - bool IsAction() const { - return (OP_ACTION == opcode_id_); - }; - - // Returns the opcode type. - OpcodeID GetID() const { - return opcode_id_; - } - - // Returns the stored options such as kPolNegateEval and others. - uint32_t GetOptions() const { return options_; } - - // Sets the stored options such as kPolNegateEval. - void SetOptions(uint32_t options) { - options_ = base::checked_cast<uint16_t>(options); - } - - private: - - static const size_t kArgumentCount = 4; // The number of supported argument. - - struct OpcodeArgument { - UINT_PTR mem; - }; - - // Better define placement new in the class instead of relying on the - // global definition which seems to be fubared. - void* operator new(size_t, void* location) { - return location; - } - - // Helper function to evaluate the opcode. The parameters have the same - // meaning that in Evaluate(). - EvalResult EvaluateHelper(const ParameterSet* parameters, - MatchContext* match); - OpcodeID opcode_id_; - int16_t parameter_; - // TODO(cpu): Making |options_| a uint32_t would avoid casting, but causes - // test failures. Somewhere code is relying on the size of this struct. - // http://crbug.com/420296 - uint16_t options_; - OpcodeArgument arguments_[PolicyOpcode::kArgumentCount]; -}; - -enum StringMatchOptions { - CASE_SENSITIVE = 0, // Pay or Not attention to the case as defined by - CASE_INSENSITIVE = 1, // RtlCompareUnicodeString windows API. - EXACT_LENGHT = 2 // Don't do substring match. Do full string match. -}; - -// Opcodes that do string comparisons take a parameter that is the starting -// position to perform the comparison so we can do substring matching. There -// are two special values: -// -// Start from the current position and compare strings advancing forward until -// a match is found if any. Similar to CRT strstr(). -const int kSeekForward = -1; -// Perform a match with the end of the string. It only does a single comparison. -const int kSeekToEnd = 0xfffff; - - -// A PolicyBuffer is a variable size structure that contains all the opcodes -// that are to be created or evaluated in sequence. -struct PolicyBuffer { - size_t opcode_count; - PolicyOpcode opcodes[1]; -}; - -// Helper class to create any opcode sequence. This class is normally invoked -// only by the high level policy module or when you need to handcraft a special -// policy. -// The factory works by creating the opcodes using a chunk of memory given -// in the constructor. The opcodes themselves are allocated from the beginning -// (top) of the memory, while any string that an opcode needs is allocated from -// the end (bottom) of the memory. -// -// In essence: -// -// low address ---> [opcode 1] -// [opcode 2] -// [opcode 3] -// | | <--- memory_top_ -// | free | -// | | -// | | <--- memory_bottom_ -// [string 1] -// high address --> [string 2] -// -// Note that this class does not keep track of the number of opcodes made and -// it is designed to be a building block for low-level policy. -// -// Note that any of the MakeOpXXXXX member functions below can return NULL on -// failure. When that happens opcode sequence creation must be aborted. -class OpcodeFactory { - public: - // memory: base pointer to a chunk of memory where the opcodes are created. - // memory_size: the size in bytes of the memory chunk. - OpcodeFactory(char* memory, size_t memory_size) - : memory_top_(memory) { - memory_bottom_ = &memory_top_[memory_size]; - } - - // policy: contains the raw memory where the opcodes are created. - // memory_size: contains the actual size of the policy argument. - OpcodeFactory(PolicyBuffer* policy, size_t memory_size) { - memory_top_ = reinterpret_cast<char*>(&policy->opcodes[0]); - memory_bottom_ = &memory_top_[memory_size]; - } - - // Returns the available memory to make opcodes. - size_t memory_size() const { - return memory_bottom_ - memory_top_; - } - - // Creates an OpAlwaysFalse opcode. - PolicyOpcode* MakeOpAlwaysFalse(uint32_t options); - - // Creates an OpAlwaysFalse opcode. - PolicyOpcode* MakeOpAlwaysTrue(uint32_t options); - - // Creates an OpAction opcode. - // action: The action to return when Evaluate() is called. - PolicyOpcode* MakeOpAction(EvalResult action, uint32_t options); - - // Creates an OpNumberMatch opcode. - // selected_param: index of the input argument. It must be a uint32_t or the - // evaluation result will generate a EVAL_ERROR. - // match: the number to compare against the selected_param. - PolicyOpcode* MakeOpNumberMatch(int16_t selected_param, - uint32_t match, - uint32_t options); - - // Creates an OpNumberMatch opcode (void pointers are cast to numbers). - // selected_param: index of the input argument. It must be an void* or the - // evaluation result will generate a EVAL_ERROR. - // match: the pointer numeric value to compare against selected_param. - PolicyOpcode* MakeOpVoidPtrMatch(int16_t selected_param, - const void* match, - uint32_t options); - - // Creates an OpNumberMatchRange opcode using the memory passed in the ctor. - // selected_param: index of the input argument. It must be a uint32_t or the - // evaluation result will generate a EVAL_ERROR. - // lower_bound, upper_bound: the range to compare against selected_param. - PolicyOpcode* MakeOpNumberMatchRange(int16_t selected_param, - uint32_t lower_bound, - uint32_t upper_bound, - uint32_t options); - - // Creates an OpWStringMatch opcode using the raw memory passed in the ctor. - // selected_param: index of the input argument. It must be a wide string - // pointer or the evaluation result will generate a EVAL_ERROR. - // match_str: string to compare against selected_param. - // start_position: when its value is from 0 to < 0x7fff it indicates an - // offset from the selected_param string where to perform the comparison. If - // the value is SeekForward then a substring search is performed. If the - // value is SeekToEnd the comparison is performed against the last part of - // the selected_param string. - // Note that the range in the position (0 to 0x7fff) is dictated by the - // current implementation. - // match_opts: Indicates additional matching flags. Currently CaseInsensitive - // is supported. - PolicyOpcode* MakeOpWStringMatch(int16_t selected_param, - const wchar_t* match_str, - int start_position, - StringMatchOptions match_opts, - uint32_t options); - - // Creates an OpNumberAndMatch opcode using the raw memory passed in the ctor. - // selected_param: index of the input argument. It must be uint32_t or the - // evaluation result will generate a EVAL_ERROR. - // match: the value to bitwise AND against selected_param. - PolicyOpcode* MakeOpNumberAndMatch(int16_t selected_param, - uint32_t match, - uint32_t options); - - private: - // Constructs the common part of every opcode. selected_param is the index - // of the input param to use when evaluating the opcode. Pass -1 in - // selected_param to indicate that no input parameter is required. - PolicyOpcode* MakeBase(OpcodeID opcode_id, - uint32_t options, - int16_t selected_param); - - // Allocates (and copies) a string (of size length) inside the buffer and - // returns the displacement with respect to start. - ptrdiff_t AllocRelative(void* start, const wchar_t* str, size_t lenght); - - // Points to the lowest currently available address of the memory - // used to make the opcodes. This pointer increments as opcodes are made. - char* memory_top_; - - // Points to the highest currently available address of the memory - // used to make the opcodes. This pointer decrements as opcode strings are - // allocated. - char* memory_bottom_; - - DISALLOW_COPY_AND_ASSIGN(OpcodeFactory); -}; - -} // namespace sandbox - -#endif // SANDBOX_WIN_SRC_POLICY_ENGINE_OPCODES_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_params.h b/security/sandbox/chromium/sandbox/win/src/policy_engine_params.h deleted file mode 100644 index fb4c00e3d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_engine_params.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_POLICY_ENGINE_PARAMS_H__ -#define SANDBOX_SRC_POLICY_ENGINE_PARAMS_H__ - -#include <stdint.h> - -#include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_nt_util.h" - -// This header defines the classes that allow the low level policy to select -// the input parameters. In order to better make sense of this header is -// recommended that you check policy_engine_opcodes.h first. - -namespace sandbox { - -// Models the set of interesting parameters of an intercepted system call -// normally you don't create objects of this class directly, instead you -// use the POLPARAMS_XXX macros. -// For example, if an intercepted function has the following signature: -// -// NTSTATUS NtOpenFileFunction (PHANDLE FileHandle, -// ACCESS_MASK DesiredAccess, -// POBJECT_ATTRIBUTES ObjectAttributes, -// PIO_STATUS_BLOCK IoStatusBlock, -// ULONG ShareAccess, -// ULONG OpenOptions); -// -// You could say that the following parameters are of interest to policy: -// -// POLPARAMS_BEGIN(open_params) -// POLPARAM(DESIRED_ACCESS) -// POLPARAM(OBJECT_NAME) -// POLPARAM(SECURITY_DESCRIPTOR) -// POLPARAM(IO_STATUS) -// POLPARAM(OPEN_OPTIONS) -// POLPARAMS_END; -// -// and the actual code will use this for defining the parameters: -// -// CountedParameterSet<open_params> p; -// p[open_params::DESIRED_ACCESS] = ParamPickerMake(DesiredAccess); -// p[open_params::OBJECT_NAME] = -// ParamPickerMake(ObjectAttributes->ObjectName); -// p[open_params::SECURITY_DESCRIPTOR] = -// ParamPickerMake(ObjectAttributes->SecurityDescriptor); -// p[open_params::IO_STATUS] = ParamPickerMake(IoStatusBlock); -// p[open_params::OPEN_OPTIONS] = ParamPickerMake(OpenOptions); -// -// These will create an stack-allocated array of ParameterSet objects which -// have each 1) the address of the parameter 2) a numeric id that encodes the -// original C++ type. This allows the policy to treat any set of supported -// argument types uniformily and with some type safety. -// -// TODO(cpu): support not fully implemented yet for unicode string and will -// probably add other types as well. -class ParameterSet { - public: - ParameterSet() : real_type_(INVALID_TYPE), address_(NULL) {} - - // Retrieve the stored parameter. If the type does not match ulong fail. - bool Get(uint32_t* destination) const { - if (real_type_ != UINT32_TYPE) { - return false; - } - *destination = Void2TypePointerCopy<uint32_t>(); - return true; - } - - // Retrieve the stored parameter. If the type does not match void* fail. - bool Get(const void** destination) const { - if (real_type_ != VOIDPTR_TYPE) { - return false; - } - *destination = Void2TypePointerCopy<void*>(); - return true; - } - - // Retrieve the stored parameter. If the type does not match wchar_t* fail. - bool Get(const wchar_t** destination) const { - if (real_type_ != WCHAR_TYPE) { - return false; - } - *destination = Void2TypePointerCopy<const wchar_t*>(); - return true; - } - - // False if the parameter is not properly initialized. - bool IsValid() const { - return real_type_ != INVALID_TYPE; - } - - protected: - // The constructor can only be called by derived types, which should - // safely provide the real_type and the address of the argument. - ParameterSet(ArgType real_type, const void* address) - : real_type_(real_type), address_(address) { - } - - private: - // This template provides the same functionality as bits_cast but - // it works with pointer while the former works only with references. - template <typename T> - T Void2TypePointerCopy() const { - return *(reinterpret_cast<const T*>(address_)); - } - - ArgType real_type_; - const void* address_; -}; - -// To safely infer the type, we use a set of template specializations -// in ParameterSetEx with a template function ParamPickerMake to do the -// parameter type deduction. - -// Base template class. Not implemented so using unsupported types should -// fail to compile. -template <typename T> -class ParameterSetEx : public ParameterSet { - public: - ParameterSetEx(const void* address); -}; - -template<> -class ParameterSetEx<void const*> : public ParameterSet { - public: - ParameterSetEx(const void* address) - : ParameterSet(VOIDPTR_TYPE, address) {} -}; - -template<> -class ParameterSetEx<void*> : public ParameterSet { - public: - ParameterSetEx(const void* address) - : ParameterSet(VOIDPTR_TYPE, address) {} -}; - - -template<> -class ParameterSetEx<wchar_t*> : public ParameterSet { - public: - ParameterSetEx(const void* address) - : ParameterSet(WCHAR_TYPE, address) {} -}; - -template<> -class ParameterSetEx<wchar_t const*> : public ParameterSet { - public: - ParameterSetEx(const void* address) - : ParameterSet(WCHAR_TYPE, address) {} -}; - -template <> -class ParameterSetEx<uint32_t> : public ParameterSet { - public: - ParameterSetEx(const void* address) - : ParameterSet(UINT32_TYPE, address) {} -}; - -template<> -class ParameterSetEx<UNICODE_STRING> : public ParameterSet { - public: - ParameterSetEx(const void* address) - : ParameterSet(UNISTR_TYPE, address) {} -}; - -template <typename T> -ParameterSet ParamPickerMake(T& parameter) { - return ParameterSetEx<T>(¶meter); -}; - -struct CountedParameterSetBase { - int count; - ParameterSet parameters[1]; -}; - -// This template defines the actual list of policy parameters for a given -// interception. -// Warning: This template stores the address to the actual variables, in -// other words, the values are not copied. -template <typename T> -struct CountedParameterSet { - CountedParameterSet() : count(T::PolParamLast) {} - - ParameterSet& operator[](typename T::Args n) { - return parameters[n]; - } - - CountedParameterSetBase* GetBase() { - return reinterpret_cast<CountedParameterSetBase*>(this); - } - - int count; - ParameterSet parameters[T::PolParamLast]; -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_POLICY_ENGINE_PARAMS_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_processor.cc b/security/sandbox/chromium/sandbox/win/src/policy_engine_processor.cc deleted file mode 100644 index 960db085c..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_engine_processor.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "sandbox/win/src/policy_engine_processor.h" - -namespace sandbox { - -void PolicyProcessor::SetInternalState(size_t index, EvalResult result) { - state_.current_index_ = index; - state_.current_result_ = result; -} - -EvalResult PolicyProcessor::GetAction() const { - return state_.current_result_; -} - -// Decides if an opcode can be skipped (not evaluated) or not. The function -// takes as inputs the opcode and the current evaluation context and returns -// true if the opcode should be skipped or not and also can set keep_skipping -// to false to signal that the current instruction should be skipped but not -// the next after the current one. -bool SkipOpcode(const PolicyOpcode& opcode, MatchContext* context, - bool* keep_skipping) { - if (opcode.IsAction()) { - uint32_t options = context->options; - context->Clear(); - *keep_skipping = false; - return (kPolUseOREval != options); - } - *keep_skipping = true; - return true; -} - -PolicyResult PolicyProcessor::Evaluate(uint32_t options, - ParameterSet* parameters, - size_t param_count) { - if (NULL == policy_) { - return NO_POLICY_MATCH; - } - if (0 == policy_->opcode_count) { - return NO_POLICY_MATCH; - } - if (!(kShortEval & options)) { - return POLICY_ERROR; - } - - MatchContext context; - bool evaluation = false; - bool skip_group = false; - SetInternalState(0, EVAL_FALSE); - size_t count = policy_->opcode_count; - - // Loop over all the opcodes Evaluating in sequence. Since we only support - // short circuit evaluation, we stop as soon as we find an 'action' opcode - // and the current evaluation is true. - // - // Skipping opcodes can happen when we are in AND mode (!kPolUseOREval) and - // have got EVAL_FALSE or when we are in OR mode (kPolUseOREval) and got - // EVAL_TRUE. Skipping will stop at the next action opcode or at the opcode - // after the action depending on kPolUseOREval. - - for (size_t ix = 0; ix != count; ++ix) { - PolicyOpcode& opcode = policy_->opcodes[ix]; - // Skipping block. - if (skip_group) { - if (SkipOpcode(opcode, &context, &skip_group)) { - continue; - } - } - // Evaluation block. - EvalResult result = opcode.Evaluate(parameters, param_count, &context); - switch (result) { - case EVAL_FALSE: - evaluation = false; - if (kPolUseOREval != context.options) { - skip_group = true; - } - break; - case EVAL_ERROR: - if (kStopOnErrors & options) { - return POLICY_ERROR; - } - break; - case EVAL_TRUE: - evaluation = true; - if (kPolUseOREval == context.options) { - skip_group = true; - } - break; - default: - // We have evaluated an action. - SetInternalState(ix, result); - return POLICY_MATCH; - } - } - - if (evaluation) { - // Reaching the end of the policy with a positive evaluation is probably - // an error: we did not find a final action opcode? - return POLICY_ERROR; - } - return NO_POLICY_MATCH; -} - - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_processor.h b/security/sandbox/chromium/sandbox/win/src/policy_engine_processor.h deleted file mode 100644 index 0d5689604..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_engine_processor.h +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__ -#define SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__ - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_engine_params.h" - -namespace sandbox { - -// This header contains the core policy evaluator. In its simplest form -// it evaluates a stream of opcodes assuming that they are laid out in -// memory as opcode groups. -// -// An opcode group has N comparison opcodes plus 1 action opcode. For -// example here we have 3 opcode groups (A, B,C): -// -// [comparison 1] <-- group A start -// [comparison 2] -// [comparison 3] -// [action A ] -// [comparison 1] <-- group B start -// [action B ] -// [comparison 1] <-- group C start -// [comparison 2] -// [action C ] -// -// The opcode evaluator proceeds from the top, evaluating each opcode in -// sequence. An opcode group is evaluated until the first comparison that -// returns false. At that point the rest of the group is skipped and evaluation -// resumes with the first comparison of the next group. When all the comparisons -// in a group have evaluated to true and the action is reached. The group is -// considered a matching group. -// -// In the 'ShortEval' mode evaluation stops when it reaches the end or the first -// matching group. The action opcode from this group is the resulting policy -// action. -// -// In the 'RankedEval' mode evaluation stops only when it reaches the end of the -// the opcode stream. In the process all matching groups are saved and at the -// end the 'best' group is selected (what makes the best is TBD) and the action -// from this group is the resulting policy action. -// -// As explained above, the policy evaluation of a group is a logical AND of -// the evaluation of each opcode. However an opcode can request kPolUseOREval -// which makes the evaluation to use logical OR. Given that each opcode can -// request its evaluation result to be negated with kPolNegateEval you can -// achieve the negation of the total group evaluation. This means that if you -// need to express: -// if (!(c1 && c2 && c3)) -// You can do it by: -// if ((!c1) || (!c2) || (!c3)) -// - -// Possible outcomes of policy evaluation. -enum PolicyResult { - NO_POLICY_MATCH, - POLICY_MATCH, - POLICY_ERROR -}; - -// Policy evaluation flags -// TODO(cpu): implement the options kStopOnErrors & kRankedEval. -// -// Stop evaluating as soon as an error is encountered. -const uint32_t kStopOnErrors = 1; -// Ignore all non fatal opcode evaluation errors. -const uint32_t kIgnoreErrors = 2; -// Short-circuit evaluation: Only evaluate until opcode group that -// evaluated to true has been found. -const uint32_t kShortEval = 4; -// Discussed briefly at the policy design meeting. It will evaluate -// all rules and then return the 'best' rule that evaluated true. -const uint32_t kRankedEval = 8; - -// This class evaluates a policy-opcode stream given the memory where the -// opcodes are and an input 'parameter set'. -// -// This class is designed to be callable from interception points -// as low as the NtXXXX service level (it is not currently safe, but -// it is designed to be made safe). -// -// Its usage in an interception is: -// -// POLPARAMS_BEGIN(eval_params) -// POLPARAM(param1) -// POLPARAM(param2) -// POLPARAM(param3) -// POLPARAM(param4) -// POLPARAM(param5) -// POLPARAMS_END; -// -// PolicyProcessor pol_evaluator(policy_memory); -// PolicyResult pr = pol_evaluator.Evaluate(ShortEval, eval_params, -// _countof(eval_params)); -// if (NO_POLICY_MATCH == pr) { -// EvalResult policy_action = pol_evaluator.GetAction(); -// // apply policy here... -// } -// -// Where the POLPARAM() arguments are derived from the intercepted function -// arguments, and represent all the 'interesting' policy inputs, and -// policy_memory is a memory buffer containing the opcode stream that is the -// relevant policy for this intercept. -class PolicyProcessor { - public: - // policy_buffer contains opcodes made with OpcodeFactory. They are usually - // created in the broker process and evaluated in the target process. - - // This constructor is just a variant of the previous constructor. - explicit PolicyProcessor(PolicyBuffer* policy) - : policy_(policy) { - SetInternalState(0, EVAL_FALSE); - } - - // Evaluates a policy-opcode stream. See the comments at the top of this - // class for more info. Returns POLICY_MATCH if a rule set was found that - // matches an active policy. - PolicyResult Evaluate(uint32_t options, - ParameterSet* parameters, - size_t parameter_count); - - // If the result of Evaluate() was POLICY_MATCH, calling this function returns - // the recommended policy action. - EvalResult GetAction() const; - - private: - struct { - size_t current_index_; - EvalResult current_result_; - } state_; - - // Sets the currently matching action result. - void SetInternalState(size_t index, EvalResult result); - - PolicyBuffer* policy_; - DISALLOW_COPY_AND_ASSIGN(PolicyProcessor); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_unittest.cc b/security/sandbox/chromium/sandbox/win/src/policy_engine_unittest.cc deleted file mode 100644 index 5572bdcd3..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_engine_unittest.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "sandbox/win/src/policy_engine_params.h" -#include "sandbox/win/src/policy_engine_processor.h" -#include "testing/gtest/include/gtest/gtest.h" - -#define POLPARAMS_BEGIN(x) sandbox::ParameterSet x[] = { -#define POLPARAM(p) sandbox::ParamPickerMake(p), -#define POLPARAMS_END } - -namespace sandbox { - -bool SetupNtdllImports(); - -TEST(PolicyEngineTest, Rules1) { - SetupNtdllImports(); - - // Construct two policy rules that say: - // - // #1 - // If the path is c:\\documents and settings\\* AND - // If the creation mode is 'open existing' AND - // If the security descriptor is null THEN - // Ask the broker. - // - // #2 - // If the security descriptor is null AND - // If the path ends with *.txt AND - // If the creation mode is not 'create new' THEN - // return Access Denied. - - enum FileCreateArgs { - FileNameArg, - CreationDispositionArg, - FlagsAndAttributesArg, - SecurityAttributes - }; - - const size_t policy_sz = 1024; - PolicyBuffer* policy = reinterpret_cast<PolicyBuffer*>(new char[policy_sz]); - OpcodeFactory opcode_maker(policy, policy_sz - 0x40); - - // Add rule set #1 - opcode_maker.MakeOpWStringMatch(FileNameArg, - L"c:\\documents and settings\\", - 0, CASE_INSENSITIVE, kPolNone); - opcode_maker.MakeOpNumberMatch(CreationDispositionArg, OPEN_EXISTING, - kPolNone); - opcode_maker.MakeOpVoidPtrMatch(SecurityAttributes, (void*)NULL, - kPolNone); - opcode_maker.MakeOpAction(ASK_BROKER, kPolNone); - - // Add rule set #2 - opcode_maker.MakeOpWStringMatch(FileNameArg, L".TXT", - kSeekToEnd, CASE_INSENSITIVE, kPolNone); - opcode_maker.MakeOpNumberMatch(CreationDispositionArg, CREATE_NEW, - kPolNegateEval); - opcode_maker.MakeOpAction(FAKE_ACCESS_DENIED, kPolNone); - policy->opcode_count = 7; - - const wchar_t* filename = L"c:\\Documents and Settings\\Microsoft\\BLAH.txt"; - uint32_t creation_mode = OPEN_EXISTING; - uint32_t flags = FILE_ATTRIBUTE_NORMAL; - void* security_descriptor = NULL; - - POLPARAMS_BEGIN(eval_params) - POLPARAM(filename) - POLPARAM(creation_mode) - POLPARAM(flags) - POLPARAM(security_descriptor) - POLPARAMS_END; - - PolicyResult pr; - PolicyProcessor pol_ev(policy); - - // Test should match the first rule set. - pr = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, pr); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - // Test should still match the first rule set. - pr = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, pr); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - // Changing creation_mode such that evaluation should not match any rule. - creation_mode = CREATE_NEW; - pr = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, pr); - - // Changing creation_mode such that evaluation should match rule #2. - creation_mode = OPEN_ALWAYS; - pr = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, pr); - EXPECT_EQ(FAKE_ACCESS_DENIED, pol_ev.GetAction()); - - delete [] reinterpret_cast<char*>(policy); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/policy_low_level.cc b/security/sandbox/chromium/sandbox/win/src/policy_low_level.cc deleted file mode 100644 index 526b23d6b..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_low_level.cc +++ /dev/null @@ -1,360 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/policy_low_level.h" - -#include <stddef.h> -#include <stdint.h> - -#include <map> -#include <string> - -namespace { - - // A single rule can use at most this amount of memory. - const size_t kRuleBufferSize = 1024*4; - - // The possible states of the string matching opcode generator. - enum { - PENDING_NONE, - PENDING_ASTERISK, // Have seen an '*' but have not generated an opcode. - PENDING_QMARK, // Have seen an '?' but have not generated an opcode. - }; - - // The category of the last character seen by the string matching opcode - // generator. - const uint32_t kLastCharIsNone = 0; - const uint32_t kLastCharIsAlpha = 1; - const uint32_t kLastCharIsWild = 2; - const uint32_t kLastCharIsAsterisk = kLastCharIsWild + 4; - const uint32_t kLastCharIsQuestionM = kLastCharIsWild + 8; -} - -namespace sandbox { - -LowLevelPolicy::LowLevelPolicy(PolicyGlobal* policy_store) - : policy_store_(policy_store) { -} - -// Adding a rule is nothing more than pushing it into an stl container. Done() -// is called for the rule in case the code that made the rule in the first -// place has not done it. -bool LowLevelPolicy::AddRule(int service, PolicyRule* rule) { - if (!rule->Done()) { - return false; - } - - PolicyRule* local_rule = new PolicyRule(*rule); - RuleNode node = {local_rule, service}; - rules_.push_back(node); - return true; -} - -LowLevelPolicy::~LowLevelPolicy() { - // Delete all the rules. - typedef std::list<RuleNode> RuleNodes; - for (RuleNodes::iterator it = rules_.begin(); it != rules_.end(); ++it) { - delete it->rule; - } -} - -// Here is where the heavy byte shuffling is done. We take all the rules and -// 'compile' them into a single memory region. Now, the rules are in random -// order so the first step is to reorganize them into a stl map that is keyed -// by the service id and as a value contains a list with all the rules that -// belong to that service. Then we enter the big for-loop where we carve a -// memory zone for the opcodes and the data and call RebindCopy on each rule -// so they all end up nicely packed in the policy_store_. -bool LowLevelPolicy::Done() { - typedef std::list<RuleNode> RuleNodes; - typedef std::list<const PolicyRule*> RuleList; - typedef std::map<uint32_t, RuleList> Mmap; - Mmap mmap; - - for (RuleNodes::iterator it = rules_.begin(); it != rules_.end(); ++it) { - mmap[it->service].push_back(it->rule); - } - - PolicyBuffer* current_buffer = &policy_store_->data[0]; - char* buffer_end = reinterpret_cast<char*>(current_buffer) + - policy_store_->data_size; - size_t avail_size = policy_store_->data_size; - - for (Mmap::iterator it = mmap.begin(); it != mmap.end(); ++it) { - uint32_t service = (*it).first; - if (service >= kMaxServiceCount) { - return false; - } - policy_store_->entry[service] = current_buffer; - - RuleList::iterator rules_it = (*it).second.begin(); - RuleList::iterator rules_it_end = (*it).second.end(); - - size_t svc_opcode_count = 0; - - for (; rules_it != rules_it_end; ++rules_it) { - const PolicyRule* rule = (*rules_it); - size_t op_count = rule->GetOpcodeCount(); - - size_t opcodes_size = op_count * sizeof(PolicyOpcode); - if (avail_size < opcodes_size) { - return false; - } - size_t data_size = avail_size - opcodes_size; - PolicyOpcode* opcodes_start = ¤t_buffer->opcodes[svc_opcode_count]; - if (!rule->RebindCopy(opcodes_start, opcodes_size, - buffer_end, &data_size)) { - return false; - } - size_t used = avail_size - data_size; - buffer_end -= used; - avail_size -= used; - svc_opcode_count += op_count; - } - - current_buffer->opcode_count += svc_opcode_count; - size_t policy_byte_count = (svc_opcode_count * sizeof(PolicyOpcode)) - / sizeof(current_buffer[0]); - current_buffer = ¤t_buffer[policy_byte_count + 1]; - } - - return true; -} - -PolicyRule::PolicyRule(EvalResult action) - : action_(action), done_(false) { - char* memory = new char[sizeof(PolicyBuffer) + kRuleBufferSize]; - buffer_ = reinterpret_cast<PolicyBuffer*>(memory); - buffer_->opcode_count = 0; - opcode_factory_ = new OpcodeFactory(buffer_, - kRuleBufferSize + sizeof(PolicyOpcode)); -} - -PolicyRule::PolicyRule(const PolicyRule& other) { - if (this == &other) - return; - action_ = other.action_; - done_ = other.done_; - size_t buffer_size = sizeof(PolicyBuffer) + kRuleBufferSize; - char* memory = new char[buffer_size]; - buffer_ = reinterpret_cast<PolicyBuffer*>(memory); - memcpy(buffer_, other.buffer_, buffer_size); - - char* opcode_buffer = reinterpret_cast<char*>(&buffer_->opcodes[0]); - char* next_opcode = &opcode_buffer[GetOpcodeCount() * sizeof(PolicyOpcode)]; - opcode_factory_ = - new OpcodeFactory(next_opcode, other.opcode_factory_->memory_size()); -} - -// This function get called from a simple state machine implemented in -// AddStringMatch() which passes the current state (in state) and it passes -// true in last_call if AddStringMatch() has finished processing the input -// pattern string and this would be the last call to generate any pending -// opcode. The skip_count is the currently accumulated number of '?' seen so -// far and once the associated opcode is generated this function sets it back -// to zero. -bool PolicyRule::GenStringOpcode(RuleType rule_type, - StringMatchOptions match_opts, - uint16_t parameter, - int state, - bool last_call, - int* skip_count, - base::string16* fragment) { - // The last opcode must: - // 1) Always clear the context. - // 2) Preserve the negation. - // 3) Remove the 'OR' mode flag. - uint32_t options = kPolNone; - if (last_call) { - if (IF_NOT == rule_type) { - options = kPolClearContext | kPolNegateEval; - } else { - options = kPolClearContext; - } - } else if (IF_NOT == rule_type) { - options = kPolUseOREval | kPolNegateEval; - } - - PolicyOpcode* op = NULL; - - // The fragment string contains the accumulated characters to match with, it - // never contains wildcards (unless they have been escaped) and while there - // is no fragment there is no new string match opcode to generate. - if (fragment->empty()) { - // There is no new opcode to generate but in the last call we have to fix - // the previous opcode because it was really the last but we did not know - // it at that time. - if (last_call && (buffer_->opcode_count > 0)) { - op = &buffer_->opcodes[buffer_->opcode_count - 1]; - op->SetOptions(options); - } - return true; - } - - if (PENDING_ASTERISK == state) { - if (last_call) { - op = opcode_factory_->MakeOpWStringMatch(parameter, fragment->c_str(), - kSeekToEnd, match_opts, - options); - } else { - op = opcode_factory_->MakeOpWStringMatch(parameter, fragment->c_str(), - kSeekForward, match_opts, - options); - } - - } else if (PENDING_QMARK == state) { - op = opcode_factory_->MakeOpWStringMatch(parameter, fragment->c_str(), - *skip_count, match_opts, options); - *skip_count = 0; - } else { - if (last_call) { - match_opts = static_cast<StringMatchOptions>(EXACT_LENGHT | match_opts); - } - op = opcode_factory_->MakeOpWStringMatch(parameter, fragment->c_str(), 0, - match_opts, options); - } - if (NULL == op) { - return false; - } - ++buffer_->opcode_count; - fragment->clear(); - return true; -} - -bool PolicyRule::AddStringMatch(RuleType rule_type, - int16_t parameter, - const wchar_t* string, - StringMatchOptions match_opts) { - if (done_) { - // Do not allow to add more rules after generating the action opcode. - return false; - } - - const wchar_t* current_char = string; - uint32_t last_char = kLastCharIsNone; - int state = PENDING_NONE; - int skip_count = 0; // counts how many '?' we have seen in a row. - base::string16 fragment; // accumulates the non-wildcard part. - - while (L'\0' != *current_char) { - switch (*current_char) { - case L'*': - if (kLastCharIsWild & last_char) { - // '**' and '&*' is an error. - return false; - } - if (!GenStringOpcode(rule_type, match_opts, parameter, - state, false, &skip_count, &fragment)) { - return false; - } - last_char = kLastCharIsAsterisk; - state = PENDING_ASTERISK; - break; - case L'?': - if (kLastCharIsAsterisk == last_char) { - // '*?' is an error. - return false; - } - if (!GenStringOpcode(rule_type, match_opts, parameter, - state, false, &skip_count, &fragment)) { - return false; - } - ++skip_count; - last_char = kLastCharIsQuestionM; - state = PENDING_QMARK; - break; - case L'/': - // Note: "/?" is an escaped '?'. Eat the slash and fall through. - if (L'?' == current_char[1]) { - ++current_char; - } - default: - fragment += *current_char; - last_char = kLastCharIsAlpha; - } - ++current_char; - } - - if (!GenStringOpcode(rule_type, match_opts, parameter, - state, true, &skip_count, &fragment)) { - return false; - } - return true; -} - -bool PolicyRule::AddNumberMatch(RuleType rule_type, - int16_t parameter, - uint32_t number, - RuleOp comparison_op) { - if (done_) { - // Do not allow to add more rules after generating the action opcode. - return false; - } - uint32_t opts = (rule_type == IF_NOT) ? kPolNegateEval : kPolNone; - - if (EQUAL == comparison_op) { - if (NULL == opcode_factory_->MakeOpNumberMatch(parameter, number, opts)) { - return false; - } - } else if (AND == comparison_op) { - if (NULL == opcode_factory_->MakeOpNumberAndMatch(parameter, number, - opts)) { - return false; - } - } - ++buffer_->opcode_count; - return true; -} - -bool PolicyRule::Done() { - if (done_) { - return true; - } - if (NULL == opcode_factory_->MakeOpAction(action_, kPolNone)) { - return false; - } - ++buffer_->opcode_count; - done_ = true; - return true; -} - -bool PolicyRule::RebindCopy(PolicyOpcode* opcode_start, size_t opcode_size, - char* data_start, size_t* data_size) const { - size_t count = buffer_->opcode_count; - for (size_t ix = 0; ix != count; ++ix) { - if (opcode_size < sizeof(PolicyOpcode)) { - return false; - } - PolicyOpcode& opcode = buffer_->opcodes[ix]; - *opcode_start = opcode; - if (OP_WSTRING_MATCH == opcode.GetID()) { - // For this opcode argument 0 is a delta to the string and argument 1 - // is the length (in chars) of the string. - const wchar_t* str = opcode.GetRelativeString(0); - size_t str_len; - opcode.GetArgument(1, &str_len); - str_len = str_len * sizeof(wchar_t); - if ((*data_size) < str_len) { - return false; - } - *data_size -= str_len; - data_start -= str_len; - memcpy(data_start, str, str_len); - // Recompute the string displacement - ptrdiff_t delta = data_start - reinterpret_cast<char*>(opcode_start); - opcode_start->SetArgument(0, delta); - } - ++opcode_start; - opcode_size -= sizeof(PolicyOpcode); - } - - return true; -} - -PolicyRule::~PolicyRule() { - delete [] reinterpret_cast<char*>(buffer_); - delete opcode_factory_; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/policy_low_level.h b/security/sandbox/chromium/sandbox/win/src/policy_low_level.h deleted file mode 100644 index f77787c77..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_low_level.h +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_POLICY_LOW_LEVEL_H__ -#define SANDBOX_SRC_POLICY_LOW_LEVEL_H__ - -#include <stddef.h> -#include <stdint.h> - -#include <list> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_engine_params.h" - -// Low level policy classes. -// Built on top of the PolicyOpcode and OpcodeFatory, the low level policy -// provides a way to define rules on strings and numbers but it is unaware -// of Windows specific details or how the Interceptions must be set up. -// To use these classes you construct one or more rules and add them to the -// LowLevelPolicy object like this: -// -// PolicyRule rule1(ASK_BROKER); -// rule1.AddStringMatch(IF, 0, L"\\\\/?/?\\c:\\*Microsoft*\\*.exe", true); -// rule1.AddNumberMatch(IF_NOT, 1, CREATE_ALWAYS, EQUAL); -// rule1.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL); -// -// PolicyRule rule2(FAKE_SUCCESS); -// rule2.AddStringMatch(IF, 0, L"\\\\/?/?\\Pipe\\Chrome.*", false)); -// rule2.AddNumberMatch(IF, 1, OPEN_EXISTING, EQUAL)); -// -// LowLevelPolicy policyGen(*policy_memory); -// policyGen.AddRule(kNtCreateFileSvc, &rule1); -// policyGen.AddRule(kNtCreateFileSvc, &rule2); -// policyGen.Done(); -// -// At this point (error checking omitted) the policy_memory can be copied -// to the target process where it can be evaluated. - -namespace sandbox { - -// TODO(cpu): Move this constant to crosscall_client.h. -const size_t kMaxServiceCount = 32; -static_assert(IPC_LAST_TAG <= kMaxServiceCount, - "kMaxServiceCount is too low"); - -// Defines the memory layout of the policy. This memory is filled by -// LowLevelPolicy object. -// For example: -// -// [Service 0] --points to---\ -// [Service 1] --------------|-----\ -// ...... | | -// [Service N] | | -// [data_size] | | -// [Policy Buffer 0] <-------/ | -// [opcodes of] | -// ....... | -// [Policy Buffer 1] <-------------/ -// [opcodes] -// ....... -// ....... -// [Policy Buffer N] -// [opcodes] -// ....... -// <possibly unused space here> -// ....... -// [opcode string ] -// [opcode string ] -// ....... -// [opcode string ] -struct PolicyGlobal { - PolicyBuffer* entry[kMaxServiceCount]; - size_t data_size; - PolicyBuffer data[1]; -}; - -class PolicyRule; - -// Provides the means to collect rules into a policy store (memory) -class LowLevelPolicy { - public: - // policy_store: must contain allocated memory and the internal - // size fields set to correct values. - explicit LowLevelPolicy(PolicyGlobal* policy_store); - - // Destroys all the policy rules. - ~LowLevelPolicy(); - - // Adds a rule to be generated when Done() is called. - // service: The id of the service that this rule is associated with, - // for example the 'Open Thread' service or the "Create File" service. - // returns false on error. - bool AddRule(int service, PolicyRule* rule); - - // Generates all the rules added with AddRule() into the memory area - // passed on the constructor. Returns false on error. - bool Done(); - - private: - struct RuleNode { - const PolicyRule* rule; - int service; - }; - std::list<RuleNode> rules_; - PolicyGlobal* policy_store_; - DISALLOW_IMPLICIT_CONSTRUCTORS(LowLevelPolicy); -}; - -// There are 'if' rules and 'if not' comparisons -enum RuleType { - IF = 0, - IF_NOT = 1, -}; - -// Possible comparisons for numbers -enum RuleOp { - EQUAL, - AND, - RANGE // TODO(cpu): Implement this option. -}; - -// Provides the means to collect a set of comparisons into a single -// rule and its associated action. -class PolicyRule { - friend class LowLevelPolicy; - - public: - explicit PolicyRule(EvalResult action); - PolicyRule(const PolicyRule& other); - ~PolicyRule(); - - // Adds a string comparison to the rule. - // rule_type: possible values are IF and IF_NOT. - // parameter: the expected index of the argument for this rule. For example - // in a 'create file' service the file name argument can be at index 0. - // string: is the desired matching pattern. - // match_opts: if the pattern matching is case sensitive or not. - bool AddStringMatch(RuleType rule_type, - int16_t parameter, - const wchar_t* string, - StringMatchOptions match_opts); - - // Adds a number match comparison to the rule. - // rule_type: possible values are IF and IF_NOT. - // parameter: the expected index of the argument for this rule. - // number: the value to compare the input to. - // comparison_op: the comparison kind (equal, logical and, etc). - bool AddNumberMatch(RuleType rule_type, - int16_t parameter, - uint32_t number, - RuleOp comparison_op); - - // Returns the number of opcodes generated so far. - size_t GetOpcodeCount() const { - return buffer_->opcode_count; - } - - // Called when there is no more comparisons to add. Internally it generates - // the last opcode (the action opcode). Returns false if this operation fails. - bool Done(); - - private: - void operator=(const PolicyRule&); - // Called in a loop from AddStringMatch to generate the required string - // match opcodes. rule_type, match_opts and parameter are the same as - // in AddStringMatch. - bool GenStringOpcode(RuleType rule_type, - StringMatchOptions match_opts, - uint16_t parameter, - int state, - bool last_call, - int* skip_count, - base::string16* fragment); - - // Loop over all generated opcodes and copy them to increasing memory - // addresses from opcode_start and copy the extra data (strings usually) into - // decreasing addresses from data_start. Extra data is only present in the - // string evaluation opcodes. - bool RebindCopy(PolicyOpcode* opcode_start, size_t opcode_size, - char* data_start, size_t* data_size) const; - PolicyBuffer* buffer_; - OpcodeFactory* opcode_factory_; - EvalResult action_; - bool done_; -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_POLICY_LOW_LEVEL_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/policy_low_level_unittest.cc b/security/sandbox/chromium/sandbox/win/src/policy_low_level_unittest.cc deleted file mode 100644 index fd67469f7..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_low_level_unittest.cc +++ /dev/null @@ -1,621 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "sandbox/win/src/policy_engine_params.h" -#include "sandbox/win/src/policy_engine_processor.h" -#include "sandbox/win/src/policy_low_level.h" -#include "testing/gtest/include/gtest/gtest.h" - -#define POLPARAMS_BEGIN(x) sandbox::ParameterSet x[] = { -#define POLPARAM(p) sandbox::ParamPickerMake(p), -#define POLPARAMS_END } - -namespace sandbox { - -bool SetupNtdllImports(); - -// Testing that we allow opcode generation on valid string patterns. -TEST(PolicyEngineTest, StringPatternsOK) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"c:\\adobe\\ver??\\", CASE_SENSITIVE)); - EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"*.tmp", CASE_SENSITIVE)); - EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"c:\\*.doc", CASE_SENSITIVE)); - EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"c:\\windows\\*", CASE_SENSITIVE)); - EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"d:\\adobe\\acrobat.exe", - CASE_SENSITIVE)); -} - -// Testing that we signal invalid string patterns. -TEST(PolicyEngineTest, StringPatternsBAD) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_FALSE(pr.AddStringMatch(IF, 0, L"one**two", CASE_SENSITIVE)); - EXPECT_FALSE(pr.AddStringMatch(IF, 0, L"**three", CASE_SENSITIVE)); - EXPECT_FALSE(pr.AddStringMatch(IF, 0, L"five?six*?seven", CASE_SENSITIVE)); - EXPECT_FALSE(pr.AddStringMatch(IF, 0, L"eight?*nine", CASE_SENSITIVE)); -} - -// Helper function to allocate space (on the heap) for policy. -PolicyGlobal* MakePolicyMemory() { - const size_t kTotalPolicySz = 4096*8; - char* mem = new char[kTotalPolicySz]; - memset(mem, 0, kTotalPolicySz); - PolicyGlobal* policy = reinterpret_cast<PolicyGlobal*>(mem); - policy->data_size = kTotalPolicySz - sizeof(PolicyGlobal); - return policy; -} - -// The simplest test using LowLevelPolicy it should test a single opcode which -// does a exact string comparison. -TEST(PolicyEngineTest, SimpleStrMatch) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"z:\\Directory\\domo.txt", - CASE_INSENSITIVE)); - - PolicyGlobal* policy = MakePolicyMemory(); - const uint32_t kFakeService = 2; - - LowLevelPolicy policyGen(policy); - EXPECT_TRUE(policyGen.AddRule(kFakeService, &pr)); - EXPECT_TRUE(policyGen.Done()); - - const wchar_t* filename = L"Z:\\Directory\\domo.txt"; - - POLPARAMS_BEGIN(eval_params) - POLPARAM(filename) // Argument 0 - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor pol_ev(policy->entry[kFakeService]); - - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - filename = L"Z:\\Directory\\domo.txt.tmp"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - delete [] reinterpret_cast<char*>(policy); -} - -TEST(PolicyEngineTest, SimpleIfNotStrMatch) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_TRUE(pr.AddStringMatch(IF_NOT, 0, L"c:\\Microsoft\\", - CASE_SENSITIVE)); - - PolicyGlobal* policy = MakePolicyMemory(); - const uint32_t kFakeService = 2; - LowLevelPolicy policyGen(policy); - - EXPECT_TRUE(policyGen.AddRule(kFakeService, &pr)); - EXPECT_TRUE(policyGen.Done()); - - const wchar_t* filename = NULL; - POLPARAMS_BEGIN(eval_params) - POLPARAM(filename) // Argument 0 - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor pol_ev(policy->entry[kFakeService]); - - filename = L"c:\\Microsoft\\"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\MicroNerd\\"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - filename = L"c:\\Microsoft\\domo.txt"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - delete [] reinterpret_cast<char*>(policy); -} - -TEST(PolicyEngineTest, SimpleIfNotStrMatchWild1) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_TRUE(pr.AddStringMatch(IF_NOT, 0, L"c:\\Microsoft\\*", - CASE_SENSITIVE)); - - PolicyGlobal* policy = MakePolicyMemory(); - const uint32_t kFakeService = 3; - LowLevelPolicy policyGen(policy); - - EXPECT_TRUE(policyGen.AddRule(kFakeService, &pr)); - EXPECT_TRUE(policyGen.Done()); - - const wchar_t* filename = NULL; - POLPARAMS_BEGIN(eval_params) - POLPARAM(filename) // Argument 0 - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor pol_ev(policy->entry[kFakeService]); - - filename = L"c:\\Microsoft\\domo.txt"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\MicroNerd\\domo.txt"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - delete [] reinterpret_cast<char*>(policy); -} - -TEST(PolicyEngineTest, SimpleIfNotStrMatchWild2) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_TRUE(pr.AddStringMatch(IF_NOT, 0, L"c:\\Microsoft\\*.txt", - CASE_SENSITIVE)); - - PolicyGlobal* policy = MakePolicyMemory(); - const uint32_t kFakeService = 3; - LowLevelPolicy policyGen(policy); - - EXPECT_TRUE(policyGen.AddRule(kFakeService, &pr)); - EXPECT_TRUE(policyGen.Done()); - - const wchar_t* filename = NULL; - POLPARAMS_BEGIN(eval_params) - POLPARAM(filename) // Argument 0 - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor pol_ev(policy->entry[kFakeService]); - - filename = L"c:\\Microsoft\\domo.txt"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\MicroNerd\\domo.txt"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - filename = L"c:\\Microsoft\\domo.bmp"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - delete [] reinterpret_cast<char*>(policy); -} - -TEST(PolicyEngineTest, IfNotStrMatchTwoRulesWild1) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_TRUE(pr.AddStringMatch(IF_NOT, 0, L"c:\\Microsoft\\*", - CASE_SENSITIVE)); - EXPECT_TRUE(pr.AddNumberMatch(IF, 1, 24, EQUAL)); - - PolicyGlobal* policy = MakePolicyMemory(); - const uint32_t kFakeService = 3; - LowLevelPolicy policyGen(policy); - - EXPECT_TRUE(policyGen.AddRule(kFakeService, &pr)); - EXPECT_TRUE(policyGen.Done()); - - const wchar_t* filename = NULL; - uint32_t access = 0; - POLPARAMS_BEGIN(eval_params) - POLPARAM(filename) // Argument 0 - POLPARAM(access) // Argument 1 - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor pol_ev(policy->entry[kFakeService]); - - filename = L"c:\\Microsoft\\domo.txt"; - access = 24; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\Microsoft\\domo.txt"; - access = 42; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\MicroNerd\\domo.txt"; - access = 24; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - filename = L"c:\\Micronesia\\domo.txt"; - access = 42; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - delete [] reinterpret_cast<char*>(policy); -} - -TEST(PolicyEngineTest, IfNotStrMatchTwoRulesWild2) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_TRUE(pr.AddNumberMatch(IF, 1, 24, EQUAL)); - EXPECT_TRUE(pr.AddStringMatch(IF_NOT, 0, L"c:\\GoogleV?\\*.txt", - CASE_SENSITIVE)); - EXPECT_TRUE(pr.AddNumberMatch(IF, 2, 66, EQUAL)); - - PolicyGlobal* policy = MakePolicyMemory(); - const uint32_t kFakeService = 3; - LowLevelPolicy policyGen(policy); - - EXPECT_TRUE(policyGen.AddRule(kFakeService, &pr)); - EXPECT_TRUE(policyGen.Done()); - - const wchar_t* filename = NULL; - uint32_t access = 0; - uint32_t sharing = 66; - - POLPARAMS_BEGIN(eval_params) - POLPARAM(filename) // Argument 0 - POLPARAM(access) // Argument 1 - POLPARAM(sharing) // Argument 2 - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor pol_ev(policy->entry[kFakeService]); - - filename = L"c:\\GoogleV2\\domo.txt"; - access = 24; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\GoogleV2\\domo.bmp"; - access = 24; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - filename = L"c:\\GoogleV23\\domo.txt"; - access = 24; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - - filename = L"c:\\GoogleV2\\domo.txt"; - access = 42; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\Google\\domo.txt"; - access = 24; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - filename = L"c:\\Micronesia\\domo.txt"; - access = 42; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\GoogleV2\\domo.bmp"; - access = 24; - sharing = 0; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - delete [] reinterpret_cast<char*>(policy); -} - -// Testing one single rule in one single service. The service is made to -// resemble NtCreateFile. -TEST(PolicyEngineTest, OneRuleTest) { - SetupNtdllImports(); - PolicyRule pr(ASK_BROKER); - EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"c:\\*Microsoft*\\*.txt", - CASE_SENSITIVE)); - EXPECT_TRUE(pr.AddNumberMatch(IF_NOT, 1, CREATE_ALWAYS, EQUAL)); - EXPECT_TRUE(pr.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL)); - - PolicyGlobal* policy = MakePolicyMemory(); - - const uint32_t kNtFakeCreateFile = 7; - - LowLevelPolicy policyGen(policy); - EXPECT_TRUE(policyGen.AddRule(kNtFakeCreateFile, &pr)); - EXPECT_TRUE(policyGen.Done()); - - const wchar_t* filename = L"c:\\Documents and Settings\\Microsoft\\BLAH.txt"; - uint32_t creation_mode = OPEN_EXISTING; - uint32_t flags = FILE_ATTRIBUTE_NORMAL; - void* security_descriptor = NULL; - - POLPARAMS_BEGIN(eval_params) - POLPARAM(filename) // Argument 0 - POLPARAM(creation_mode) // Argument 1 - POLPARAM(flags) // Argument 2 - POLPARAM(security_descriptor) - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor pol_ev(policy->entry[kNtFakeCreateFile]); - - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - creation_mode = CREATE_ALWAYS; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - creation_mode = OPEN_EXISTING; - filename = L"c:\\Other\\Path\\Microsoft\\Another file.txt"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - filename = L"c:\\Other\\Path\\Microsoft\\Another file.txt.tmp"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - flags = FILE_ATTRIBUTE_DEVICE; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\Other\\Macrosoft\\Another file.txt"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\Microsoft\\1.txt"; - flags = FILE_ATTRIBUTE_NORMAL; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev.GetAction()); - - filename = L"c:\\Microsoft\\1.ttt"; - result = pol_ev.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - delete [] reinterpret_cast<char*>(policy); -} - -// Testing 3 rules in 3 services. Two of the services resemble File services. -TEST(PolicyEngineTest, ThreeRulesTest) { - SetupNtdllImports(); - PolicyRule pr_pipe(FAKE_SUCCESS); - EXPECT_TRUE(pr_pipe.AddStringMatch(IF, 0, L"\\\\/?/?\\Pipe\\Chrome.*", - CASE_INSENSITIVE)); - EXPECT_TRUE(pr_pipe.AddNumberMatch(IF, 1, OPEN_EXISTING, EQUAL)); - EXPECT_TRUE(pr_pipe.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL)); - - size_t opc1 = pr_pipe.GetOpcodeCount(); - EXPECT_EQ(3u, opc1); - - PolicyRule pr_dump(ASK_BROKER); - EXPECT_TRUE(pr_dump.AddStringMatch(IF, 0, L"\\\\/?/?\\*\\Crash Reports\\*", - CASE_INSENSITIVE)); - EXPECT_TRUE(pr_dump.AddNumberMatch(IF, 1, CREATE_ALWAYS, EQUAL)); - EXPECT_TRUE(pr_dump.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL)); - - size_t opc2 = pr_dump.GetOpcodeCount(); - EXPECT_EQ(4u, opc2); - - PolicyRule pr_winexe(SIGNAL_ALARM); - EXPECT_TRUE(pr_winexe.AddStringMatch(IF, 0, L"\\\\/?/?\\C:\\Windows\\*.exe", - CASE_INSENSITIVE)); - EXPECT_TRUE(pr_winexe.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL)); - - size_t opc3 = pr_winexe.GetOpcodeCount(); - EXPECT_EQ(3u, opc3); - - PolicyRule pr_adobe(GIVE_CACHED); - EXPECT_TRUE(pr_adobe.AddStringMatch(IF, 0, L"c:\\adobe\\ver?.?\\", - CASE_SENSITIVE)); - EXPECT_TRUE(pr_adobe.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL)); - - size_t opc4 = pr_adobe.GetOpcodeCount(); - EXPECT_EQ(4u, opc4); - - PolicyRule pr_none(GIVE_FIRST); - EXPECT_TRUE(pr_none.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_READONLY, AND)); - EXPECT_TRUE(pr_none.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_SYSTEM, AND)); - - size_t opc5 = pr_none.GetOpcodeCount(); - EXPECT_EQ(2u, opc5); - - PolicyGlobal* policy = MakePolicyMemory(); - - const uint32_t kNtFakeNone = 4; - const uint32_t kNtFakeCreateFile = 5; - const uint32_t kNtFakeOpenFile = 6; - - LowLevelPolicy policyGen(policy); - EXPECT_TRUE(policyGen.AddRule(kNtFakeCreateFile, &pr_pipe)); - EXPECT_TRUE(policyGen.AddRule(kNtFakeCreateFile, &pr_dump)); - EXPECT_TRUE(policyGen.AddRule(kNtFakeCreateFile, &pr_winexe)); - - EXPECT_TRUE(policyGen.AddRule(kNtFakeOpenFile, &pr_adobe)); - EXPECT_TRUE(policyGen.AddRule(kNtFakeOpenFile, &pr_pipe)); - - EXPECT_TRUE(policyGen.AddRule(kNtFakeNone, &pr_none)); - - EXPECT_TRUE(policyGen.Done()); - - // Inspect the policy structure manually. - EXPECT_TRUE(NULL == policy->entry[0]); - EXPECT_TRUE(NULL == policy->entry[1]); - EXPECT_TRUE(NULL == policy->entry[2]); - EXPECT_TRUE(NULL == policy->entry[3]); - EXPECT_TRUE(NULL != policy->entry[4]); // kNtFakeNone. - EXPECT_TRUE(NULL != policy->entry[5]); // kNtFakeCreateFile. - EXPECT_TRUE(NULL != policy->entry[6]); // kNtFakeOpenFile. - EXPECT_TRUE(NULL == policy->entry[7]); - - // The total per service opcode counts now must take in account one - // extra opcode (action opcode) per rule. - ++opc1; - ++opc2; - ++opc3; - ++opc4; - ++opc5; - - size_t tc1 = policy->entry[kNtFakeNone]->opcode_count; - size_t tc2 = policy->entry[kNtFakeCreateFile]->opcode_count; - size_t tc3 = policy->entry[kNtFakeOpenFile]->opcode_count; - - EXPECT_EQ(opc5, tc1); - EXPECT_EQ((opc1 + opc2 + opc3), tc2); - EXPECT_EQ((opc1 + opc4), tc3); - - // Check the type of the first and last opcode of each service. - - EXPECT_EQ(OP_NUMBER_AND_MATCH, - policy->entry[kNtFakeNone]->opcodes[0].GetID()); - EXPECT_EQ(OP_ACTION, policy->entry[kNtFakeNone]->opcodes[tc1-1].GetID()); - EXPECT_EQ(OP_WSTRING_MATCH, - policy->entry[kNtFakeCreateFile]->opcodes[0].GetID()); - EXPECT_EQ(OP_ACTION, - policy->entry[kNtFakeCreateFile]->opcodes[tc2-1].GetID()); - EXPECT_EQ(OP_WSTRING_MATCH, - policy->entry[kNtFakeOpenFile]->opcodes[0].GetID()); - EXPECT_EQ(OP_ACTION, policy->entry[kNtFakeOpenFile]->opcodes[tc3-1].GetID()); - - // Test the policy evaluation. - - const wchar_t* filename = L""; - uint32_t creation_mode = OPEN_EXISTING; - uint32_t flags = FILE_ATTRIBUTE_NORMAL; - void* security_descriptor = NULL; - - POLPARAMS_BEGIN(params) - POLPARAM(filename) // Argument 0 - POLPARAM(creation_mode) // Argument 1 - POLPARAM(flags) // Argument 2 - POLPARAM(security_descriptor) - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor eval_CreateFile(policy->entry[kNtFakeCreateFile]); - PolicyProcessor eval_OpenFile(policy->entry[kNtFakeOpenFile]); - PolicyProcessor eval_None(policy->entry[kNtFakeNone]); - - result = eval_CreateFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_OpenFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_None.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"\\\\??\\c:\\Windows\\System32\\calc.exe"; - flags = FILE_ATTRIBUTE_SYSTEM; - result = eval_CreateFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_None.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_OpenFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - flags += FILE_ATTRIBUTE_READONLY; - result = eval_CreateFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_None.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(GIVE_FIRST, eval_None.GetAction()); - result = eval_OpenFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - flags = FILE_ATTRIBUTE_NORMAL; - result = eval_CreateFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(SIGNAL_ALARM, eval_CreateFile.GetAction()); - result = eval_None.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_OpenFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"c:\\adobe\\ver3.2\\temp"; - result = eval_CreateFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_None.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_OpenFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(GIVE_CACHED, eval_OpenFile.GetAction()); - - filename = L"c:\\adobe\\ver3.22\\temp"; - result = eval_OpenFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"\\\\??\\c:\\some path\\other path\\crash reports\\some path"; - creation_mode = CREATE_ALWAYS; - result = eval_CreateFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, eval_CreateFile.GetAction()); - result = eval_None.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_OpenFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - filename = L"\\\\??\\Pipe\\Chrome.12345"; - creation_mode = OPEN_EXISTING; - result = eval_CreateFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(FAKE_SUCCESS, eval_CreateFile.GetAction()); - result = eval_None.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - result = eval_OpenFile.Evaluate(kShortEval, params, _countof(params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(FAKE_SUCCESS, eval_OpenFile.GetAction()); - - delete [] reinterpret_cast<char*>(policy); -} - -TEST(PolicyEngineTest, PolicyRuleCopyConstructorTwoStrings) { - SetupNtdllImports(); - // Both pr_orig and pr_copy should allow hello.* but not *.txt files. - PolicyRule pr_orig(ASK_BROKER); - EXPECT_TRUE(pr_orig.AddStringMatch(IF, 0, L"hello.*", CASE_SENSITIVE)); - - PolicyRule pr_copy(pr_orig); - EXPECT_TRUE(pr_orig.AddStringMatch(IF_NOT, 0, L"*.txt", CASE_SENSITIVE)); - EXPECT_TRUE(pr_copy.AddStringMatch(IF_NOT, 0, L"*.txt", CASE_SENSITIVE)); - - PolicyGlobal* policy = MakePolicyMemory(); - LowLevelPolicy policyGen(policy); - EXPECT_TRUE(policyGen.AddRule(1, &pr_orig)); - EXPECT_TRUE(policyGen.AddRule(2, &pr_copy)); - EXPECT_TRUE(policyGen.Done()); - - const wchar_t* name = NULL; - POLPARAMS_BEGIN(eval_params) - POLPARAM(name) - POLPARAMS_END; - - PolicyResult result; - PolicyProcessor pol_ev_orig(policy->entry[1]); - name = L"domo.txt"; - result = pol_ev_orig.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - name = L"hello.bmp"; - result = pol_ev_orig.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev_orig.GetAction()); - - PolicyProcessor pol_ev_copy(policy->entry[2]); - name = L"domo.txt"; - result = pol_ev_copy.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(NO_POLICY_MATCH, result); - - name = L"hello.bmp"; - result = pol_ev_copy.Evaluate(kShortEval, eval_params, _countof(eval_params)); - EXPECT_EQ(POLICY_MATCH, result); - EXPECT_EQ(ASK_BROKER, pol_ev_copy.GetAction()); -} -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/policy_opcodes_unittest.cc b/security/sandbox/chromium/sandbox/win/src/policy_opcodes_unittest.cc deleted file mode 100644 index f8c210e87..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_opcodes_unittest.cc +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_engine_params.h" -#include "sandbox/win/src/sandbox_nt_types.h" -#include "sandbox/win/src/sandbox_types.h" -#include "testing/gtest/include/gtest/gtest.h" - - -#define INIT_GLOBAL_RTL(member) \ - g_nt.member = reinterpret_cast<member##Function>( \ - ::GetProcAddress(ntdll, #member)); \ - if (NULL == g_nt.member) \ - return false - -namespace sandbox { - -const size_t kOpcodeMemory = 1024; - -SANDBOX_INTERCEPT NtExports g_nt; - -bool SetupNtdllImports() { - HMODULE ntdll = ::GetModuleHandle(kNtdllName); - - INIT_GLOBAL_RTL(RtlAllocateHeap); - INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString); - INIT_GLOBAL_RTL(RtlCompareUnicodeString); - INIT_GLOBAL_RTL(RtlCreateHeap); - INIT_GLOBAL_RTL(RtlDestroyHeap); - INIT_GLOBAL_RTL(RtlFreeHeap); - INIT_GLOBAL_RTL(_strnicmp); - INIT_GLOBAL_RTL(strlen); - INIT_GLOBAL_RTL(wcslen); - - return true; -} - -TEST(PolicyEngineTest, ParameterSetTest) { - void* pv1 = reinterpret_cast<void*>(0x477EAA5); - const void* pv2 = reinterpret_cast<void*>(0x987654); - ParameterSet pset1 = ParamPickerMake(pv1); - ParameterSet pset2 = ParamPickerMake(pv2); - - // Test that we can store and retrieve a void pointer: - const void* result1 =0; - uint32_t result2 = 0; - EXPECT_TRUE(pset1.Get(&result1)); - EXPECT_TRUE(pv1 == result1); - EXPECT_FALSE(pset1.Get(&result2)); - EXPECT_TRUE(pset2.Get(&result1)); - EXPECT_TRUE(pv2 == result1); - EXPECT_FALSE(pset2.Get(&result2)); - - // Test that we can store and retrieve a uint32_t: - uint32_t number = 12747; - ParameterSet pset3 = ParamPickerMake(number); - EXPECT_FALSE(pset3.Get(&result1)); - EXPECT_TRUE(pset3.Get(&result2)); - EXPECT_EQ(number, result2); - - // Test that we can store and retrieve a string: - const wchar_t* txt = L"S231L"; - ParameterSet pset4 = ParamPickerMake(txt); - const wchar_t* result3 = NULL; - EXPECT_TRUE(pset4.Get(&result3)); - EXPECT_EQ(0, wcscmp(txt, result3)); -} - -TEST(PolicyEngineTest, OpcodeConstraints) { - // Test that PolicyOpcode has no virtual functions - // because these objects are copied over to other processes - // so they cannot have vtables. - EXPECT_FALSE(__is_polymorphic(PolicyOpcode)); - // Keep developers from adding smarts to the opcodes which should - // be pretty much a bag of bytes with a OO interface. - EXPECT_TRUE(__has_trivial_destructor(PolicyOpcode)); - EXPECT_TRUE(__has_trivial_constructor(PolicyOpcode)); - EXPECT_TRUE(__has_trivial_copy(PolicyOpcode)); -} - -TEST(PolicyEngineTest, TrueFalseOpcodes) { - void* dummy = NULL; - ParameterSet ppb1 = ParamPickerMake(dummy); - char memory[kOpcodeMemory]; - OpcodeFactory opcode_maker(memory, sizeof(memory)); - - // This opcode always evaluates to true. - PolicyOpcode* op1 = opcode_maker.MakeOpAlwaysFalse(kPolNone); - ASSERT_NE(nullptr, op1); - EXPECT_EQ(EVAL_FALSE, op1->Evaluate(&ppb1, 1, NULL)); - EXPECT_FALSE(op1->IsAction()); - - // This opcode always evaluates to false. - PolicyOpcode* op2 = opcode_maker.MakeOpAlwaysTrue(kPolNone); - ASSERT_NE(nullptr, op2); - EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 1, NULL)); - - // Nulls not allowed on the params. - EXPECT_EQ(EVAL_ERROR, op2->Evaluate(NULL, 0, NULL)); - EXPECT_EQ(EVAL_ERROR, op2->Evaluate(NULL, 1, NULL)); - - // True and False opcodes do not 'require' a number of parameters - EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 0, NULL)); - EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 1, NULL)); - - // Test Inverting the logic. Note that inversion is done outside - // any particular opcode evaluation so no need to repeat for all - // opcodes. - PolicyOpcode* op3 = opcode_maker.MakeOpAlwaysFalse(kPolNegateEval); - ASSERT_NE(nullptr, op3); - EXPECT_EQ(EVAL_TRUE, op3->Evaluate(&ppb1, 1, NULL)); - PolicyOpcode* op4 = opcode_maker.MakeOpAlwaysTrue(kPolNegateEval); - ASSERT_NE(nullptr, op4); - EXPECT_EQ(EVAL_FALSE, op4->Evaluate(&ppb1, 1, NULL)); - - // Test that we clear the match context - PolicyOpcode* op5 = opcode_maker.MakeOpAlwaysTrue(kPolClearContext); - ASSERT_NE(nullptr, op5); - MatchContext context; - context.position = 1; - context.options = kPolUseOREval; - EXPECT_EQ(EVAL_TRUE, op5->Evaluate(&ppb1, 1, &context)); - EXPECT_EQ(0u, context.position); - MatchContext context2; - EXPECT_EQ(context2.options, context.options); -} - -TEST(PolicyEngineTest, OpcodeMakerCase1) { - // Testing that the opcode maker does not overrun the - // supplied buffer. It should only be able to make 'count' opcodes. - void* dummy = NULL; - ParameterSet ppb1 = ParamPickerMake(dummy); - - char memory[kOpcodeMemory]; - OpcodeFactory opcode_maker(memory, sizeof(memory)); - size_t count = sizeof(memory) / sizeof(PolicyOpcode); - - for (size_t ix =0; ix != count; ++ix) { - PolicyOpcode* op = opcode_maker.MakeOpAlwaysFalse(kPolNone); - ASSERT_NE(nullptr, op); - EXPECT_EQ(EVAL_FALSE, op->Evaluate(&ppb1, 1, NULL)); - } - // There should be no room more another opcode: - PolicyOpcode* op1 = opcode_maker.MakeOpAlwaysFalse(kPolNone); - ASSERT_EQ(nullptr, op1); -} - -TEST(PolicyEngineTest, OpcodeMakerCase2) { - SetupNtdllImports(); - // Testing that the opcode maker does not overrun the - // supplied buffer. It should only be able to make 'count' opcodes. - // The difference with the previous test is that this opcodes allocate - // the string 'txt2' inside the same buffer. - const wchar_t* txt1 = L"1234"; - const wchar_t txt2[] = L"123"; - - ParameterSet ppb1 = ParamPickerMake(txt1); - MatchContext mc1; - - char memory[kOpcodeMemory]; - OpcodeFactory opcode_maker(memory, sizeof(memory)); - size_t count = sizeof(memory) / (sizeof(PolicyOpcode) + sizeof(txt2)); - - // Test that it does not overrun the buffer. - for (size_t ix =0; ix != count; ++ix) { - PolicyOpcode* op = opcode_maker.MakeOpWStringMatch(0, txt2, 0, - CASE_SENSITIVE, - kPolClearContext); - ASSERT_NE(nullptr, op); - EXPECT_EQ(EVAL_TRUE, op->Evaluate(&ppb1, 1, &mc1)); - } - - // There should be no room more another opcode: - PolicyOpcode* op1 = opcode_maker.MakeOpWStringMatch(0, txt2, 0, - CASE_SENSITIVE, - kPolNone); - ASSERT_EQ(nullptr, op1); -} - -TEST(PolicyEngineTest, IntegerOpcodes) { - const wchar_t* txt = L"abcdef"; - uint32_t num1 = 42; - uint32_t num2 = 113377; - - ParameterSet pp_wrong1 = ParamPickerMake(txt); - ParameterSet pp_num1 = ParamPickerMake(num1); - ParameterSet pp_num2 = ParamPickerMake(num2); - - char memory[kOpcodeMemory]; - OpcodeFactory opcode_maker(memory, sizeof(memory)); - - // Test basic match for uint32s 42 == 42 and 42 != 113377. - PolicyOpcode* op_m42 = opcode_maker.MakeOpNumberMatch(0, 42UL, kPolNone); - ASSERT_NE(nullptr, op_m42); - EXPECT_EQ(EVAL_TRUE, op_m42->Evaluate(&pp_num1, 1, NULL)); - EXPECT_EQ(EVAL_FALSE, op_m42->Evaluate(&pp_num2, 1, NULL)); - EXPECT_EQ(EVAL_ERROR, op_m42->Evaluate(&pp_wrong1, 1, NULL)); - - // Test basic match for void pointers. - const void* vp = NULL; - ParameterSet pp_num3 = ParamPickerMake(vp); - PolicyOpcode* op_vp_null = opcode_maker.MakeOpVoidPtrMatch(0, NULL, - kPolNone); - ASSERT_NE(nullptr, op_vp_null); - EXPECT_EQ(EVAL_TRUE, op_vp_null->Evaluate(&pp_num3, 1, NULL)); - EXPECT_EQ(EVAL_FALSE, op_vp_null->Evaluate(&pp_num1, 1, NULL)); - EXPECT_EQ(EVAL_ERROR, op_vp_null->Evaluate(&pp_wrong1, 1, NULL)); - - // Basic range test [41 43] (inclusive). - PolicyOpcode* op_range1 = - opcode_maker.MakeOpNumberMatchRange(0, 41, 43, kPolNone); - ASSERT_NE(nullptr, op_range1); - EXPECT_EQ(EVAL_TRUE, op_range1->Evaluate(&pp_num1, 1, NULL)); - EXPECT_EQ(EVAL_FALSE, op_range1->Evaluate(&pp_num2, 1, NULL)); - EXPECT_EQ(EVAL_ERROR, op_range1->Evaluate(&pp_wrong1, 1, NULL)); -} - -TEST(PolicyEngineTest, LogicalOpcodes) { - char memory[kOpcodeMemory]; - OpcodeFactory opcode_maker(memory, sizeof(memory)); - - uint32_t num1 = 0x10100702; - ParameterSet pp_num1 = ParamPickerMake(num1); - - PolicyOpcode* op_and1 = - opcode_maker.MakeOpNumberAndMatch(0, 0x00100000, kPolNone); - ASSERT_NE(nullptr, op_and1); - EXPECT_EQ(EVAL_TRUE, op_and1->Evaluate(&pp_num1, 1, NULL)); - PolicyOpcode* op_and2 = - opcode_maker.MakeOpNumberAndMatch(0, 0x00000001, kPolNone); - ASSERT_NE(nullptr, op_and2); - EXPECT_EQ(EVAL_FALSE, op_and2->Evaluate(&pp_num1, 1, NULL)); -} - -TEST(PolicyEngineTest, WCharOpcodes1) { - SetupNtdllImports(); - - const wchar_t* txt1 = L"the quick fox jumps over the lazy dog"; - const wchar_t txt2[] = L"the quick"; - const wchar_t txt3[] = L" fox jumps"; - const wchar_t txt4[] = L"the lazy dog"; - const wchar_t txt5[] = L"jumps over"; - const wchar_t txt6[] = L"g"; - - ParameterSet pp_tc1 = ParamPickerMake(txt1); - char memory[kOpcodeMemory]; - OpcodeFactory opcode_maker(memory, sizeof(memory)); - - PolicyOpcode* op1 = opcode_maker.MakeOpWStringMatch(0, txt2, 0, - CASE_SENSITIVE, - kPolNone); - ASSERT_NE(nullptr, op1); - - // Simplest substring match from pos 0. It should be a successful match - // and the match context should be updated. - MatchContext mc1; - EXPECT_EQ(EVAL_TRUE, op1->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_TRUE(_countof(txt2) == mc1.position + 1); - - // Matching again should fail and the context should be unmodified. - EXPECT_EQ(EVAL_FALSE, op1->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_TRUE(_countof(txt2) == mc1.position + 1); - - // Using the same match context we should continue where we left - // in the previous successful match, - PolicyOpcode* op3 = opcode_maker.MakeOpWStringMatch(0, txt3, 0, - CASE_SENSITIVE, - kPolNone); - ASSERT_NE(nullptr, op3); - EXPECT_EQ(EVAL_TRUE, op3->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_TRUE(_countof(txt3) + _countof(txt2) == mc1.position + 2); - - // We now keep on matching but now we skip 6 characters which means - // we skip the string ' over '. And we zero the match context. This is - // the primitive that we use to build '??'. - PolicyOpcode* op4 = opcode_maker.MakeOpWStringMatch(0, txt4, 6, - CASE_SENSITIVE, - kPolClearContext); - ASSERT_NE(nullptr, op4); - EXPECT_EQ(EVAL_TRUE, op4->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_EQ(0u, mc1.position); - - // Test that we can properly match the last part of the string - PolicyOpcode* op4b = opcode_maker.MakeOpWStringMatch(0, txt4, kSeekToEnd, - CASE_SENSITIVE, - kPolClearContext); - ASSERT_NE(nullptr, op4b); - EXPECT_EQ(EVAL_TRUE, op4b->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_EQ(0u, mc1.position); - - // Test matching 'jumps over' over the entire string. This is the - // primitive we build '*' from. - PolicyOpcode* op5 = opcode_maker.MakeOpWStringMatch(0, txt5, kSeekForward, - CASE_SENSITIVE, kPolNone); - ASSERT_NE(nullptr, op5); - EXPECT_EQ(EVAL_TRUE, op5->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_EQ(24u, mc1.position); - - // Test that we don't match because it is not at the end of the string - PolicyOpcode* op5b = opcode_maker.MakeOpWStringMatch(0, txt5, kSeekToEnd, - CASE_SENSITIVE, - kPolNone); - ASSERT_NE(nullptr, op5b); - EXPECT_EQ(EVAL_FALSE, op5b->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_EQ(24u, mc1.position); - - // Test that we function if the string does not fit. In this case we - // try to match 'the lazy dog' against 'he lazy dog'. - PolicyOpcode* op6 = opcode_maker.MakeOpWStringMatch(0, txt4, 2, - CASE_SENSITIVE, kPolNone); - ASSERT_NE(nullptr, op6); - EXPECT_EQ(EVAL_FALSE, op6->Evaluate(&pp_tc1, 1, &mc1)); - - // Testing matching against 'g' which should be the last char. - MatchContext mc2; - PolicyOpcode* op7 = opcode_maker.MakeOpWStringMatch(0, txt6, kSeekForward, - CASE_SENSITIVE, kPolNone); - ASSERT_NE(nullptr, op7); - EXPECT_EQ(EVAL_TRUE, op7->Evaluate(&pp_tc1, 1, &mc2)); - EXPECT_EQ(37u, mc2.position); - - // Trying to match again should fail since we are in the last char. - // This also covers a couple of boundary conditions. - EXPECT_EQ(EVAL_FALSE, op7->Evaluate(&pp_tc1, 1, &mc2)); - EXPECT_EQ(37u, mc2.position); -} - -TEST(PolicyEngineTest, WCharOpcodes2) { - SetupNtdllImports(); - - const wchar_t* path1 = L"c:\\documents and settings\\Microsoft\\BLAH.txt"; - const wchar_t txt1[] = L"Settings\\microsoft"; - ParameterSet pp_tc1 = ParamPickerMake(path1); - - char memory[kOpcodeMemory]; - OpcodeFactory opcode_maker(memory, sizeof(memory)); - MatchContext mc1; - - // Testing case-insensitive does not buy us much since it this option - // is just passed to the Microsoft API that we use normally, but just for - // coverage, here it is: - PolicyOpcode* op1s = opcode_maker.MakeOpWStringMatch(0, txt1, kSeekForward, - CASE_SENSITIVE, kPolNone); - ASSERT_NE(nullptr, op1s); - PolicyOpcode* op1i = opcode_maker.MakeOpWStringMatch(0, txt1, kSeekForward, - CASE_INSENSITIVE, - kPolNone); - ASSERT_NE(nullptr, op1i); - EXPECT_EQ(EVAL_FALSE, op1s->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_EQ(EVAL_TRUE, op1i->Evaluate(&pp_tc1, 1, &mc1)); - EXPECT_EQ(35u, mc1.position); -} - -TEST(PolicyEngineTest, ActionOpcodes) { - char memory[kOpcodeMemory]; - OpcodeFactory opcode_maker(memory, sizeof(memory)); - MatchContext mc1; - void* dummy = NULL; - ParameterSet ppb1 = ParamPickerMake(dummy); - - PolicyOpcode* op1 = opcode_maker.MakeOpAction(ASK_BROKER, kPolNone); - ASSERT_NE(nullptr, op1); - EXPECT_TRUE(op1->IsAction()); - EXPECT_EQ(ASK_BROKER, op1->Evaluate(&ppb1, 1, &mc1)); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/policy_params.h b/security/sandbox/chromium/sandbox/win/src/policy_params.h deleted file mode 100644 index e051d2b59..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_params.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_POLICY_PARAMS_H__ -#define SANDBOX_SRC_POLICY_PARAMS_H__ - -#include "sandbox/win/src/policy_engine_params.h" - -namespace sandbox { - -class ParameterSet; - -// Warning: The following macros store the address to the actual variables, in -// other words, the values are not copied. -#define POLPARAMS_BEGIN(type) class type { public: enum Args { -#define POLPARAM(arg) arg, -#define POLPARAMS_END(type) PolParamLast }; }; \ - typedef sandbox::ParameterSet type##Array [type::PolParamLast]; - -// Policy parameters for file open / create. -POLPARAMS_BEGIN(OpenFile) - POLPARAM(NAME) - POLPARAM(BROKER) // TRUE if called from the broker. - POLPARAM(ACCESS) - POLPARAM(DISPOSITION) - POLPARAM(OPTIONS) -POLPARAMS_END(OpenFile) - -// Policy parameter for name-based policies. -POLPARAMS_BEGIN(FileName) - POLPARAM(NAME) - POLPARAM(BROKER) // TRUE if called from the broker. -POLPARAMS_END(FileName) - -static_assert(OpenFile::NAME == static_cast<int>(FileName::NAME), - "to simplify fs policies"); -static_assert(OpenFile::BROKER == static_cast<int>(FileName::BROKER), - "to simplify fs policies"); - -// Policy parameter for name-based policies. -POLPARAMS_BEGIN(NameBased) - POLPARAM(NAME) -POLPARAMS_END(NameBased) - -// Policy parameters for open event. -POLPARAMS_BEGIN(OpenEventParams) - POLPARAM(NAME) - POLPARAM(ACCESS) -POLPARAMS_END(OpenEventParams) - -// Policy Parameters for reg open / create. -POLPARAMS_BEGIN(OpenKey) - POLPARAM(NAME) - POLPARAM(ACCESS) -POLPARAMS_END(OpenKey) - -// Policy parameter for name-based policies. -POLPARAMS_BEGIN(HandleTarget) - POLPARAM(NAME) - POLPARAM(TARGET) -POLPARAMS_END(HandleTarget) - - -} // namespace sandbox - -#endif // SANDBOX_SRC_POLICY_PARAMS_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/policy_target.cc b/security/sandbox/chromium/sandbox/win/src/policy_target.cc deleted file mode 100644 index 800302805..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_target.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/policy_target.h" - -#include <stddef.h> - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_engine_processor.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/target_services.h" - -namespace sandbox { - -// Handle for our private heap. -extern void* g_heap; - -// This is the list of all imported symbols from ntdll.dll. -SANDBOX_INTERCEPT NtExports g_nt; - -// Policy data. -extern void* volatile g_shared_policy_memory; -SANDBOX_INTERCEPT size_t g_shared_policy_size; - -bool QueryBroker(int ipc_id, CountedParameterSetBase* params) { - DCHECK_NT(static_cast<size_t>(ipc_id) < kMaxServiceCount); - DCHECK_NT(g_shared_policy_memory); - DCHECK_NT(g_shared_policy_size > 0); - - if (static_cast<size_t>(ipc_id) >= kMaxServiceCount) - return false; - - PolicyGlobal* global_policy = - reinterpret_cast<PolicyGlobal*>(g_shared_policy_memory); - - if (!global_policy->entry[ipc_id]) - return false; - - PolicyBuffer* policy = reinterpret_cast<PolicyBuffer*>( - reinterpret_cast<char*>(g_shared_policy_memory) + - reinterpret_cast<size_t>(global_policy->entry[ipc_id])); - - if ((reinterpret_cast<size_t>(global_policy->entry[ipc_id]) > - global_policy->data_size) || - (g_shared_policy_size < global_policy->data_size)) { - NOTREACHED_NT(); - return false; - } - - for (int i = 0; i < params->count; i++) { - if (!params->parameters[i].IsValid()) { - NOTREACHED_NT(); - return false; - } - } - - PolicyProcessor processor(policy); - PolicyResult result = processor.Evaluate(kShortEval, params->parameters, - params->count); - DCHECK_NT(POLICY_ERROR != result); - - return POLICY_MATCH == result && ASK_BROKER == processor.GetAction(); -} - -// ----------------------------------------------------------------------- - -// Hooks NtSetInformationThread to block RevertToSelf from being -// called before the actual call to LowerToken. -NTSTATUS WINAPI TargetNtSetInformationThread( - NtSetInformationThreadFunction orig_SetInformationThread, HANDLE thread, - NT_THREAD_INFORMATION_CLASS thread_info_class, PVOID thread_information, - ULONG thread_information_bytes) { - do { - if (SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) - break; - if (ThreadImpersonationToken != thread_info_class) - break; - if (!thread_information) - break; - HANDLE token; - if (sizeof(token) > thread_information_bytes) - break; - - NTSTATUS ret = CopyData(&token, thread_information, sizeof(token)); - if (!NT_SUCCESS(ret) || NULL != token) - break; - - // This is a revert to self. - return STATUS_SUCCESS; - } while (false); - - return orig_SetInformationThread(thread, thread_info_class, - thread_information, - thread_information_bytes); -} - -// Hooks NtOpenThreadToken to force the open_as_self parameter to be set to -// FALSE if we are still running with the impersonation token. open_as_self set -// to TRUE means that the token will be open using the process token instead of -// the impersonation token. This is bad because the process token does not have -// access to open the thread token. -NTSTATUS WINAPI TargetNtOpenThreadToken( - NtOpenThreadTokenFunction orig_OpenThreadToken, HANDLE thread, - ACCESS_MASK desired_access, BOOLEAN open_as_self, PHANDLE token) { - if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) - open_as_self = FALSE; - - return orig_OpenThreadToken(thread, desired_access, open_as_self, token); -} - -// See comment for TargetNtOpenThreadToken -NTSTATUS WINAPI TargetNtOpenThreadTokenEx( - NtOpenThreadTokenExFunction orig_OpenThreadTokenEx, HANDLE thread, - ACCESS_MASK desired_access, BOOLEAN open_as_self, ULONG handle_attributes, - PHANDLE token) { - if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) - open_as_self = FALSE; - - return orig_OpenThreadTokenEx(thread, desired_access, open_as_self, - handle_attributes, token); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/policy_target.h b/security/sandbox/chromium/sandbox/win/src/policy_target.h deleted file mode 100644 index 8a2b43709..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_target.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_POLICY_TARGET_H__ -#define SANDBOX_SRC_POLICY_TARGET_H__ - -namespace sandbox { - -struct CountedParameterSetBase; - -// Performs a policy lookup and returns true if the request should be passed to -// the broker process. -bool QueryBroker(int ipc_id, CountedParameterSetBase* params); - -extern "C" { - -// Interception of NtSetInformationThread on the child process. -// It should never be called directly. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationThread( - NtSetInformationThreadFunction orig_SetInformationThread, HANDLE thread, - NT_THREAD_INFORMATION_CLASS thread_info_class, PVOID thread_information, - ULONG thread_information_bytes); - -// Interception of NtOpenThreadToken on the child process. -// It should never be called directly -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadToken( - NtOpenThreadTokenFunction orig_OpenThreadToken, HANDLE thread, - ACCESS_MASK desired_access, BOOLEAN open_as_self, PHANDLE token); - -// Interception of NtOpenThreadTokenEx on the child process. -// It should never be called directly -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadTokenEx( - NtOpenThreadTokenExFunction orig_OpenThreadTokenEx, HANDLE thread, - ACCESS_MASK desired_access, BOOLEAN open_as_self, ULONG handle_attributes, - PHANDLE token); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_POLICY_TARGET_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/policy_target_test.cc b/security/sandbox/chromium/sandbox/win/src/policy_target_test.cc deleted file mode 100644 index d1a82e54d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/policy_target_test.cc +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/shared_memory.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "base/win/scoped_process_information.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_utils.h" -#include "sandbox/win/src/target_services.h" -#include "sandbox/win/tests/common/controller.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#include "base/win/win_util.h" -#endif - -namespace sandbox { - -#define BINDNTDLL(name) \ - name ## Function name = reinterpret_cast<name ## Function>( \ - ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name)) - -// Reverts to self and verify that SetInformationToken was faked. Returns -// SBOX_TEST_SUCCEEDED if faked and SBOX_TEST_FAILED if not faked. -SBOX_TESTS_COMMAND int PolicyTargetTest_token(int argc, wchar_t **argv) { - HANDLE thread_token; - // Get the thread token, using impersonation. - if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | - TOKEN_DUPLICATE, FALSE, &thread_token)) - return ::GetLastError(); - - ::RevertToSelf(); - ::CloseHandle(thread_token); - - int ret = SBOX_TEST_FAILED; - if (::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE, - FALSE, &thread_token)) { - ret = SBOX_TEST_SUCCEEDED; - ::CloseHandle(thread_token); - } - return ret; -} - -// Stores the high privilege token on a static variable, change impersonation -// again to that one and verify that we are not interfering anymore with -// RevertToSelf. -SBOX_TESTS_COMMAND int PolicyTargetTest_steal(int argc, wchar_t **argv) { - static HANDLE thread_token; - if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) { - if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | - TOKEN_DUPLICATE, FALSE, &thread_token)) - return ::GetLastError(); - } else { - if (!::SetThreadToken(NULL, thread_token)) - return ::GetLastError(); - - // See if we fake the call again. - int ret = PolicyTargetTest_token(argc, argv); - ::CloseHandle(thread_token); - return ret; - } - return 0; -} - -// Opens the thread token with and without impersonation. -SBOX_TESTS_COMMAND int PolicyTargetTest_token2(int argc, wchar_t **argv) { - HANDLE thread_token; - // Get the thread token, using impersonation. - if (!::OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | - TOKEN_DUPLICATE, FALSE, &thread_token)) - return ::GetLastError(); - ::CloseHandle(thread_token); - - // Get the thread token, without impersonation. - if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_DUPLICATE, - TRUE, &thread_token)) - return ::GetLastError(); - ::CloseHandle(thread_token); - return SBOX_TEST_SUCCEEDED; -} - -// Opens the thread token with and without impersonation, using -// NtOpenThreadTokenEX. -SBOX_TESTS_COMMAND int PolicyTargetTest_token3(int argc, wchar_t **argv) { - BINDNTDLL(NtOpenThreadTokenEx); - if (!NtOpenThreadTokenEx) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - HANDLE thread_token; - // Get the thread token, using impersonation. - NTSTATUS status = NtOpenThreadTokenEx(GetCurrentThread(), - TOKEN_IMPERSONATE | TOKEN_DUPLICATE, - FALSE, 0, &thread_token); - if (status == STATUS_NO_TOKEN) - return ERROR_NO_TOKEN; - if (!NT_SUCCESS(status)) - return SBOX_TEST_FAILED; - - ::CloseHandle(thread_token); - - // Get the thread token, without impersonation. - status = NtOpenThreadTokenEx(GetCurrentThread(), - TOKEN_IMPERSONATE | TOKEN_DUPLICATE, TRUE, 0, - &thread_token); - if (!NT_SUCCESS(status)) - return SBOX_TEST_FAILED; - - ::CloseHandle(thread_token); - return SBOX_TEST_SUCCEEDED; -} - -// Tests that we can open the current thread. -SBOX_TESTS_COMMAND int PolicyTargetTest_thread(int argc, wchar_t **argv) { - DWORD thread_id = ::GetCurrentThreadId(); - HANDLE thread = ::OpenThread(SYNCHRONIZE, FALSE, thread_id); - if (!thread) - return ::GetLastError(); - if (!::CloseHandle(thread)) - return ::GetLastError(); - - return SBOX_TEST_SUCCEEDED; -} - -// New thread entry point: do nothing. -DWORD WINAPI PolicyTargetTest_thread_main(void* param) { - ::Sleep(INFINITE); - return 0; -} - -// Tests that we can create a new thread, and open it. -SBOX_TESTS_COMMAND int PolicyTargetTest_thread2(int argc, wchar_t **argv) { - // Use default values to create a new thread. - DWORD thread_id; - HANDLE thread = ::CreateThread(NULL, 0, &PolicyTargetTest_thread_main, 0, 0, - &thread_id); - if (!thread) - return ::GetLastError(); - if (!::CloseHandle(thread)) - return ::GetLastError(); - - thread = ::OpenThread(SYNCHRONIZE, FALSE, thread_id); - if (!thread) - return ::GetLastError(); - - if (!::CloseHandle(thread)) - return ::GetLastError(); - - return SBOX_TEST_SUCCEEDED; -} - -// Tests that we can call CreateProcess. -SBOX_TESTS_COMMAND int PolicyTargetTest_process(int argc, wchar_t **argv) { - // Use default values to create a new process. - STARTUPINFO startup_info = {0}; - startup_info.cb = sizeof(startup_info); - PROCESS_INFORMATION temp_process_info = {}; - // Note: CreateProcessW() can write to its lpCommandLine, don't pass a - // raw string literal. - base::string16 writable_cmdline_str(L"foo.exe"); - if (!::CreateProcessW(L"foo.exe", &writable_cmdline_str[0], NULL, NULL, FALSE, - 0, NULL, NULL, &startup_info, &temp_process_info)) - return SBOX_TEST_SUCCEEDED; - base::win::ScopedProcessInformation process_info(temp_process_info); - return SBOX_TEST_FAILED; -} - -TEST(PolicyTargetTest, SetInformationThread) { - TestRunner runner; - if (base::win::GetVersion() >= base::win::VERSION_XP) { - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token")); - } - - runner.SetTestState(AFTER_REVERT); - EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token")); - - runner.SetTestState(EVERY_STATE); - if (base::win::GetVersion() >= base::win::VERSION_XP) - EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"PolicyTargetTest_steal")); -} - -TEST(PolicyTargetTest, OpenThreadToken) { - TestRunner runner; - if (base::win::GetVersion() >= base::win::VERSION_XP) { - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token2")); - } - - runner.SetTestState(AFTER_REVERT); - EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token2")); -} - -TEST(PolicyTargetTest, OpenThreadTokenEx) { - TestRunner runner; - if (base::win::GetVersion() < base::win::VERSION_XP) - return; - - runner.SetTestState(BEFORE_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token3")); - - runner.SetTestState(AFTER_REVERT); - EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token3")); -} - -TEST(PolicyTargetTest, OpenThread) { - TestRunner runner; - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread")) << - "Opens the current thread"; - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread2")) << - "Creates a new thread and opens it"; -} - -TEST(PolicyTargetTest, OpenProcess) { - TestRunner runner; - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_process")) << - "Opens a process"; -} - -// Launches the app in the sandbox and ask it to wait in an -// infinite loop. Waits for 2 seconds and then check if the -// desktop associated with the app thread is not the same as the -// current desktop. -TEST(PolicyTargetTest, DesktopPolicy) { - BrokerServices* broker = GetBroker(); - - // Precreate the desktop. - TargetPolicy* temp_policy = broker->CreatePolicy(); - temp_policy->CreateAlternateDesktop(false); - temp_policy->Release(); - - ASSERT_TRUE(broker != NULL); - - // Get the path to the sandboxed app. - wchar_t prog_name[MAX_PATH]; - GetModuleFileNameW(NULL, prog_name, MAX_PATH); - - base::string16 arguments(L"\""); - arguments += prog_name; - arguments += L"\" -child 0 wait"; // Don't care about the "state" argument. - - // Launch the app. - ResultCode result = SBOX_ALL_OK; - base::win::ScopedProcessInformation target; - - TargetPolicy* policy = broker->CreatePolicy(); - policy->SetAlternateDesktop(false); - policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); - PROCESS_INFORMATION temp_process_info = {}; - result = broker->SpawnTarget(prog_name, arguments.c_str(), policy, - &temp_process_info); - base::string16 desktop_name = policy->GetAlternateDesktop(); - policy->Release(); - - EXPECT_EQ(SBOX_ALL_OK, result); - if (result == SBOX_ALL_OK) - target.Set(temp_process_info); - - EXPECT_EQ(1u, ::ResumeThread(target.thread_handle())); - - EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT), - ::WaitForSingleObject(target.process_handle(), 2000)); - - EXPECT_NE(::GetThreadDesktop(target.thread_id()), - ::GetThreadDesktop(::GetCurrentThreadId())); - - HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE); - EXPECT_TRUE(NULL != desk); - EXPECT_TRUE(::CloseDesktop(desk)); - EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0)); - - ::WaitForSingleObject(target.process_handle(), INFINITE); - - // Close the desktop handle. - temp_policy = broker->CreatePolicy(); - temp_policy->DestroyAlternateDesktop(); - temp_policy->Release(); - - // Make sure the desktop does not exist anymore. - desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE); - EXPECT_TRUE(NULL == desk); -} - -// Launches the app in the sandbox and ask it to wait in an -// infinite loop. Waits for 2 seconds and then check if the -// winstation associated with the app thread is not the same as the -// current desktop. -TEST(PolicyTargetTest, WinstaPolicy) { - BrokerServices* broker = GetBroker(); - - // Precreate the desktop. - TargetPolicy* temp_policy = broker->CreatePolicy(); - temp_policy->CreateAlternateDesktop(true); - temp_policy->Release(); - - ASSERT_TRUE(broker != NULL); - - // Get the path to the sandboxed app. - wchar_t prog_name[MAX_PATH]; - GetModuleFileNameW(NULL, prog_name, MAX_PATH); - - base::string16 arguments(L"\""); - arguments += prog_name; - arguments += L"\" -child 0 wait"; // Don't care about the "state" argument. - - // Launch the app. - ResultCode result = SBOX_ALL_OK; - base::win::ScopedProcessInformation target; - - TargetPolicy* policy = broker->CreatePolicy(); - policy->SetAlternateDesktop(true); - policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); - PROCESS_INFORMATION temp_process_info = {}; - result = broker->SpawnTarget(prog_name, arguments.c_str(), policy, - &temp_process_info); - base::string16 desktop_name = policy->GetAlternateDesktop(); - policy->Release(); - - EXPECT_EQ(SBOX_ALL_OK, result); - if (result == SBOX_ALL_OK) - target.Set(temp_process_info); - - EXPECT_EQ(1u, ::ResumeThread(target.thread_handle())); - - EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT), - ::WaitForSingleObject(target.process_handle(), 2000)); - - EXPECT_NE(::GetThreadDesktop(target.thread_id()), - ::GetThreadDesktop(::GetCurrentThreadId())); - - ASSERT_FALSE(desktop_name.empty()); - - // Make sure there is a backslash, for the window station name. - EXPECT_NE(desktop_name.find_first_of(L'\\'), base::string16::npos); - - // Isolate the desktop name. - desktop_name = desktop_name.substr(desktop_name.find_first_of(L'\\') + 1); - - HDESK desk = ::OpenDesktop(desktop_name.c_str(), 0, FALSE, DESKTOP_ENUMERATE); - // This should fail if the desktop is really on another window station. - EXPECT_FALSE(NULL != desk); - EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0)); - - ::WaitForSingleObject(target.process_handle(), INFINITE); - - // Close the desktop handle. - temp_policy = broker->CreatePolicy(); - temp_policy->DestroyAlternateDesktop(); - temp_policy->Release(); -} - -// Launches the app in the sandbox and share a handle with it. The app should -// be able to use the handle. -TEST(PolicyTargetTest, ShareHandleTest) { - // The way we share handles via STARTUPINFOEX does not work on XP. - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return; - - BrokerServices* broker = GetBroker(); - ASSERT_TRUE(broker != NULL); - - base::StringPiece contents = "Hello World"; - std::string name = "TestSharedMemory"; - base::SharedMemoryCreateOptions options; - options.size = contents.size(); - options.share_read_only = true; - options.name_deprecated = &name; - base::SharedMemory writable_shmem; - ASSERT_TRUE(writable_shmem.Create(options)); - ASSERT_TRUE(writable_shmem.Map(options.size)); - memcpy(writable_shmem.memory(), contents.data(), contents.size()); - - base::SharedMemory read_only_view; - ASSERT_TRUE(read_only_view.Open(name, true)); - - // Get the path to the sandboxed app. - wchar_t prog_name[MAX_PATH]; - GetModuleFileNameW(NULL, prog_name, MAX_PATH); - - TargetPolicy* policy = broker->CreatePolicy(); - void* shared_handle = - policy->AddHandleToShare(read_only_view.handle().GetHandle()); - - base::string16 arguments(L"\""); - arguments += prog_name; - arguments += L"\" -child 0 shared_memory_handle "; - arguments += base::UintToString16(base::win::HandleToUint32(shared_handle)); - - // Launch the app. - ResultCode result = SBOX_ALL_OK; - base::win::ScopedProcessInformation target; - - policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); - PROCESS_INFORMATION temp_process_info = {}; - result = broker->SpawnTarget(prog_name, arguments.c_str(), policy, - &temp_process_info); - policy->Release(); - - EXPECT_EQ(SBOX_ALL_OK, result); - if (result == SBOX_ALL_OK) - target.Set(temp_process_info); - - EXPECT_EQ(1u, ::ResumeThread(target.thread_handle())); - - EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT), - ::WaitForSingleObject(target.process_handle(), 2000)); - - EXPECT_TRUE(::TerminateProcess(target.process_handle(), 0)); - - ::WaitForSingleObject(target.process_handle(), INFINITE); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc b/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc deleted file mode 100644 index 6ca8a8d7e..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/process_mitigations.h" - -#include <stddef.h> - -#include <algorithm> - -#include "base/win/windows_version.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/restricted_token_utils.h" -#include "sandbox/win/src/sandbox_rand.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -// Functions for enabling policies. -typedef BOOL (WINAPI *SetProcessDEPPolicyFunction)(DWORD dwFlags); - -typedef BOOL (WINAPI *SetProcessMitigationPolicyFunction)( - PROCESS_MITIGATION_POLICY mitigation_policy, - PVOID buffer, - SIZE_T length); - -typedef BOOL (WINAPI *SetDefaultDllDirectoriesFunction)( - DWORD DirectoryFlags); - -} // namespace - -namespace sandbox { - -bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags) { - if (!CanSetProcessMitigationsPostStartup(flags)) - return false; - - base::win::Version version = base::win::GetVersion(); - HMODULE module = ::GetModuleHandleA("kernel32.dll"); - - if (version >= base::win::VERSION_VISTA && - (flags & MITIGATION_DLL_SEARCH_ORDER)) { - SetDefaultDllDirectoriesFunction set_default_dll_directories = - reinterpret_cast<SetDefaultDllDirectoriesFunction>( - ::GetProcAddress(module, "SetDefaultDllDirectories")); - - // Check for SetDefaultDllDirectories since it requires KB2533623. - if (set_default_dll_directories) { - if (!set_default_dll_directories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) && - ERROR_ACCESS_DENIED != ::GetLastError()) { - return false; - } - } - } - - // Set the heap to terminate on corruption - if (version >= base::win::VERSION_VISTA && - (flags & MITIGATION_HEAP_TERMINATE)) { - if (!::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, - NULL, 0) && - ERROR_ACCESS_DENIED != ::GetLastError()) { - return false; - } - } - - if (version >= base::win::VERSION_WIN7 && - (flags & MITIGATION_HARDEN_TOKEN_IL_POLICY)) { - DWORD error = HardenProcessIntegrityLevelPolicy(); - if ((error != ERROR_SUCCESS) && (error != ERROR_ACCESS_DENIED)) - return false; - } - -#if !defined(_WIN64) // DEP is always enabled on 64-bit. - if (flags & MITIGATION_DEP) { - DWORD dep_flags = PROCESS_DEP_ENABLE; - // DEP support is quirky on XP, so don't force a failure in that case. - const bool return_on_fail = version >= base::win::VERSION_VISTA; - - if (flags & MITIGATION_DEP_NO_ATL_THUNK) - dep_flags |= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION; - - SetProcessDEPPolicyFunction set_process_dep_policy = - reinterpret_cast<SetProcessDEPPolicyFunction>( - ::GetProcAddress(module, "SetProcessDEPPolicy")); - if (set_process_dep_policy) { - if (!set_process_dep_policy(dep_flags) && - ERROR_ACCESS_DENIED != ::GetLastError() && return_on_fail) { - return false; - } - } else { - // We're on XP sp2, so use the less standard approach. - // For reference: http://www.uninformed.org/?v=2&a=4 - static const int MEM_EXECUTE_OPTION_DISABLE = 2; - static const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4; - static const int MEM_EXECUTE_OPTION_PERMANENT = 8; - - NtSetInformationProcessFunction set_information_process = NULL; - ResolveNTFunctionPtr("NtSetInformationProcess", - &set_information_process); - if (!set_information_process) - return false; - ULONG dep = MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_PERMANENT; - if (!(dep_flags & PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION)) - dep |= MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION; - if (!SUCCEEDED(set_information_process(GetCurrentProcess(), - ProcessExecuteFlags, - &dep, sizeof(dep))) && - ERROR_ACCESS_DENIED != ::GetLastError() && return_on_fail) { - return false; - } - } - } -#endif - - // This is all we can do in Win7 and below. - if (version < base::win::VERSION_WIN8) - return true; - - SetProcessMitigationPolicyFunction set_process_mitigation_policy = - reinterpret_cast<SetProcessMitigationPolicyFunction>( - ::GetProcAddress(module, "SetProcessMitigationPolicy")); - if (!set_process_mitigation_policy) - return false; - - // Enable ASLR policies. - if (flags & MITIGATION_RELOCATE_IMAGE) { - PROCESS_MITIGATION_ASLR_POLICY policy = {}; - policy.EnableForceRelocateImages = true; - policy.DisallowStrippedImages = (flags & - MITIGATION_RELOCATE_IMAGE_REQUIRED) == - MITIGATION_RELOCATE_IMAGE_REQUIRED; - - if (!set_process_mitigation_policy(ProcessASLRPolicy, &policy, - sizeof(policy)) && - ERROR_ACCESS_DENIED != ::GetLastError()) { - return false; - } - } - - // Enable strict handle policies. - if (flags & MITIGATION_STRICT_HANDLE_CHECKS) { - PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy = {}; - policy.HandleExceptionsPermanentlyEnabled = - policy.RaiseExceptionOnInvalidHandleReference = true; - - if (!set_process_mitigation_policy(ProcessStrictHandleCheckPolicy, &policy, - sizeof(policy)) && - ERROR_ACCESS_DENIED != ::GetLastError()) { - return false; - } - } - - // Enable system call policies. - if (flags & MITIGATION_WIN32K_DISABLE) { - PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; - policy.DisallowWin32kSystemCalls = true; - - if (!set_process_mitigation_policy(ProcessSystemCallDisablePolicy, &policy, - sizeof(policy)) && - ERROR_ACCESS_DENIED != ::GetLastError()) { - return false; - } - } - - // Enable system call policies. - if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { - PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; - policy.DisableExtensionPoints = true; - - if (!set_process_mitigation_policy(ProcessExtensionPointDisablePolicy, - &policy, sizeof(policy)) && - ERROR_ACCESS_DENIED != ::GetLastError()) { - return false; - } - } - - return true; -} - -void ConvertProcessMitigationsToPolicy(MitigationFlags flags, - DWORD64* policy_flags, size_t* size) { - base::win::Version version = base::win::GetVersion(); - - *policy_flags = 0; -#if defined(_WIN64) - *size = sizeof(*policy_flags); -#elif defined(_M_IX86) - // A 64-bit flags attribute is illegal on 32-bit Win 7 and below. - if (version < base::win::VERSION_WIN8) - *size = sizeof(DWORD); - else - *size = sizeof(*policy_flags); -#else -#error This platform is not supported. -#endif - - // Nothing for Win XP or Vista. - if (version <= base::win::VERSION_VISTA) - return; - - // DEP and SEHOP are not valid for 64-bit Windows -#if !defined(_WIN64) - if (flags & MITIGATION_DEP) { - *policy_flags |= PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE; - if (!(flags & MITIGATION_DEP_NO_ATL_THUNK)) - *policy_flags |= PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE; - } - - if (flags & MITIGATION_SEHOP) - *policy_flags |= PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE; -#endif - - // Win 7 - if (version < base::win::VERSION_WIN8) - return; - - if (flags & MITIGATION_RELOCATE_IMAGE) { - *policy_flags |= - PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON; - if (flags & MITIGATION_RELOCATE_IMAGE_REQUIRED) { - *policy_flags |= - PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON_REQ_RELOCS; - } - } - - if (flags & MITIGATION_HEAP_TERMINATE) { - *policy_flags |= - PROCESS_CREATION_MITIGATION_POLICY_HEAP_TERMINATE_ALWAYS_ON; - } - - if (flags & MITIGATION_BOTTOM_UP_ASLR) { - *policy_flags |= - PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_ON; - } - - if (flags & MITIGATION_HIGH_ENTROPY_ASLR) { - *policy_flags |= - PROCESS_CREATION_MITIGATION_POLICY_HIGH_ENTROPY_ASLR_ALWAYS_ON; - } - - if (flags & MITIGATION_STRICT_HANDLE_CHECKS) { - *policy_flags |= - PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON; - } - - if (flags & MITIGATION_WIN32K_DISABLE) { - *policy_flags |= - PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON; - } - - if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { - *policy_flags |= - PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; - } -} - -MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags) { - base::win::Version version = base::win::GetVersion(); - - // Windows XP SP2+. - if (version < base::win::VERSION_VISTA) { - return flags & (MITIGATION_DEP | - MITIGATION_DEP_NO_ATL_THUNK); - } - - // Windows Vista - if (version < base::win::VERSION_WIN7) { - return flags & (MITIGATION_BOTTOM_UP_ASLR | - MITIGATION_DLL_SEARCH_ORDER | - MITIGATION_HEAP_TERMINATE); - } - - // Windows 7. - if (version < base::win::VERSION_WIN8) { - return flags & (MITIGATION_BOTTOM_UP_ASLR | - MITIGATION_DLL_SEARCH_ORDER | - MITIGATION_HEAP_TERMINATE); - } - - // Windows 8 and above. - return flags & (MITIGATION_BOTTOM_UP_ASLR | - MITIGATION_DLL_SEARCH_ORDER); -} - -bool ApplyProcessMitigationsToSuspendedProcess(HANDLE process, - MitigationFlags flags) { -// This is a hack to fake a weak bottom-up ASLR on 32-bit Windows. -#if !defined(_WIN64) - if (flags & MITIGATION_BOTTOM_UP_ASLR) { - unsigned int limit; - GetRandom(&limit); - char* ptr = 0; - const size_t kMask64k = 0xFFFF; - // Random range (512k-16.5mb) in 64k steps. - const char* end = ptr + ((((limit % 16384) + 512) * 1024) & ~kMask64k); - while (ptr < end) { - MEMORY_BASIC_INFORMATION memory_info; - if (!::VirtualQueryEx(process, ptr, &memory_info, sizeof(memory_info))) - break; - size_t size = std::min((memory_info.RegionSize + kMask64k) & ~kMask64k, - static_cast<SIZE_T>(end - ptr)); - if (ptr && memory_info.State == MEM_FREE) - ::VirtualAllocEx(process, ptr, size, MEM_RESERVE, PAGE_NOACCESS); - ptr += size; - } - } -#endif - - return true; -} - -bool CanSetProcessMitigationsPostStartup(MitigationFlags flags) { - // All of these mitigations can be enabled after startup. - return !(flags & ~(MITIGATION_HEAP_TERMINATE | - MITIGATION_DEP | - MITIGATION_DEP_NO_ATL_THUNK | - MITIGATION_RELOCATE_IMAGE | - MITIGATION_RELOCATE_IMAGE_REQUIRED | - MITIGATION_BOTTOM_UP_ASLR | - MITIGATION_STRICT_HANDLE_CHECKS | - MITIGATION_EXTENSION_DLL_DISABLE | - MITIGATION_DLL_SEARCH_ORDER | - MITIGATION_HARDEN_TOKEN_IL_POLICY)); -} - -bool CanSetProcessMitigationsPreStartup(MitigationFlags flags) { - // These mitigations cannot be enabled prior to startup. - return !(flags & (MITIGATION_STRICT_HANDLE_CHECKS | - MITIGATION_DLL_SEARCH_ORDER)); -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations.h b/security/sandbox/chromium/sandbox/win/src/process_mitigations.h deleted file mode 100644 index 8bee0245a..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_WIN_PROCESS_MITIGATIONS_H_ -#define SANDBOX_SRC_WIN_PROCESS_MITIGATIONS_H_ - -#include <windows.h> -#include <stddef.h> - -#include "sandbox/win/src/security_level.h" - -namespace sandbox { - -// Sets the mitigation policy for the current process, ignoring any settings -// that are invalid for the current version of Windows. -bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags); - -// Returns the flags that must be enforced after startup for the current OS -// version. -MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags); - -// Converts sandbox flags to the PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES -// policy flags used by UpdateProcThreadAttribute(). The size field varies -// between a 32-bit and a 64-bit type based on the exact build and version of -// Windows, so the returned size must be passed to UpdateProcThreadAttribute(). -void ConvertProcessMitigationsToPolicy(MitigationFlags flags, - DWORD64* policy_flags, size_t* size); - -// Adds mitigations that need to be performed on the suspended target process -// before execution begins. -bool ApplyProcessMitigationsToSuspendedProcess(HANDLE process, - MitigationFlags flags); - -// Returns true if all the supplied flags can be set after a process starts. -bool CanSetProcessMitigationsPostStartup(MitigationFlags flags); - -// Returns true if all the supplied flags can be set before a process starts. -bool CanSetProcessMitigationsPreStartup(MitigationFlags flags); - -} // namespace sandbox - -#endif // SANDBOX_SRC_WIN_PROCESS_MITIGATIONS_H_ - diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations_test.cc b/security/sandbox/chromium/sandbox/win/src/process_mitigations_test.cc deleted file mode 100644 index 080d8eca3..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations_test.cc +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/stringprintf.h" -#include "base/win/scoped_handle.h" - -#include "base/win/windows_version.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/process_mitigations.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/target_services.h" -#include "sandbox/win/src/win_utils.h" -#include "sandbox/win/tests/common/controller.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -typedef BOOL (WINAPI *GetProcessDEPPolicyFunction)( - HANDLE process, - LPDWORD flags, - PBOOL permanent); - -typedef BOOL (WINAPI *GetProcessMitigationPolicyFunction)( - HANDLE process, - PROCESS_MITIGATION_POLICY mitigation_policy, - PVOID buffer, - SIZE_T length); - -GetProcessMitigationPolicyFunction get_process_mitigation_policy; - -#if !defined(_WIN64) -bool CheckWin8DepPolicy() { - PROCESS_MITIGATION_DEP_POLICY policy = {}; - if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, - &policy, sizeof(policy))) { - return false; - } - return policy.Enable && policy.Permanent; -} -#endif // !defined(_WIN64) - -#if defined(NDEBUG) -bool CheckWin8AslrPolicy() { - PROCESS_MITIGATION_ASLR_POLICY policy = {}; - if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy, - &policy, sizeof(policy))) { - return false; - } - return policy.EnableForceRelocateImages && policy.DisallowStrippedImages; -} -#endif // defined(NDEBUG) - -bool CheckWin8StrictHandlePolicy() { - PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy = {}; - if (!get_process_mitigation_policy(::GetCurrentProcess(), - ProcessStrictHandleCheckPolicy, - &policy, sizeof(policy))) { - return false; - } - return policy.RaiseExceptionOnInvalidHandleReference && - policy.HandleExceptionsPermanentlyEnabled; -} - -bool CheckWin8Win32CallPolicy() { - PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; - if (!get_process_mitigation_policy(::GetCurrentProcess(), - ProcessSystemCallDisablePolicy, - &policy, sizeof(policy))) { - return false; - } - return policy.DisallowWin32kSystemCalls; -} - -bool CheckWin8DllExtensionPolicy() { - PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; - if (!get_process_mitigation_policy(::GetCurrentProcess(), - ProcessExtensionPointDisablePolicy, - &policy, sizeof(policy))) { - return false; - } - return policy.DisableExtensionPoints; -} - -} // namespace - -namespace sandbox { - -SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { - get_process_mitigation_policy = - reinterpret_cast<GetProcessMitigationPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessMitigationPolicy")); - if (!get_process_mitigation_policy) - return SBOX_TEST_NOT_FOUND; - -#if !defined(_WIN64) // DEP is always enabled on 64-bit. - if (!CheckWin8DepPolicy()) - return SBOX_TEST_FIRST_ERROR; -#endif - -#if defined(NDEBUG) // ASLR cannot be forced in debug builds. - if (!CheckWin8AslrPolicy()) - return SBOX_TEST_SECOND_ERROR; -#endif - - if (!CheckWin8StrictHandlePolicy()) - return SBOX_TEST_THIRD_ERROR; - - if (!CheckWin8DllExtensionPolicy()) - return SBOX_TEST_FIFTH_ERROR; - - return SBOX_TEST_SUCCEEDED; -} - -TEST(ProcessMitigationsTest, CheckWin8) { - if (base::win::GetVersion() < base::win::VERSION_WIN8) - return; - - TestRunner runner; - sandbox::TargetPolicy* policy = runner.GetPolicy(); - - sandbox::MitigationFlags mitigations = MITIGATION_DEP | - MITIGATION_DEP_NO_ATL_THUNK | - MITIGATION_EXTENSION_DLL_DISABLE; -#if defined(NDEBUG) // ASLR cannot be forced in debug builds. - mitigations |= MITIGATION_RELOCATE_IMAGE | - MITIGATION_RELOCATE_IMAGE_REQUIRED; -#endif - - EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); - - mitigations |= MITIGATION_STRICT_HANDLE_CHECKS; - - EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8")); -} - - -SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) { - GetProcessDEPPolicyFunction get_process_dep_policy = - reinterpret_cast<GetProcessDEPPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessDEPPolicy")); - if (get_process_dep_policy) { - BOOL is_permanent = FALSE; - DWORD dep_flags = 0; - - if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags, - &is_permanent)) { - return SBOX_TEST_FIRST_ERROR; - } - - if (!(dep_flags & PROCESS_DEP_ENABLE) || !is_permanent) - return SBOX_TEST_SECOND_ERROR; - - } else { - NtQueryInformationProcessFunction query_information_process = NULL; - ResolveNTFunctionPtr("NtQueryInformationProcess", - &query_information_process); - if (!query_information_process) - return SBOX_TEST_NOT_FOUND; - - ULONG size = 0; - ULONG dep_flags = 0; - if (!SUCCEEDED(query_information_process(::GetCurrentProcess(), - ProcessExecuteFlags, &dep_flags, - sizeof(dep_flags), &size))) { - return SBOX_TEST_THIRD_ERROR; - } - - static const int MEM_EXECUTE_OPTION_DISABLE = 2; - static const int MEM_EXECUTE_OPTION_PERMANENT = 8; - dep_flags &= 0xff; - - if (dep_flags != (MEM_EXECUTE_OPTION_DISABLE | - MEM_EXECUTE_OPTION_PERMANENT)) { - return SBOX_TEST_FOURTH_ERROR; - } - } - - return SBOX_TEST_SUCCEEDED; -} - -#if !defined(_WIN64) // DEP is always enabled on 64-bit. -TEST(ProcessMitigationsTest, CheckDep) { - if (base::win::GetVersion() > base::win::VERSION_WIN7) - return; - - TestRunner runner; - sandbox::TargetPolicy* policy = runner.GetPolicy(); - - EXPECT_EQ(policy->SetProcessMitigations( - MITIGATION_DEP | - MITIGATION_DEP_NO_ATL_THUNK | - MITIGATION_SEHOP), - SBOX_ALL_OK); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep")); -} -#endif - -SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t **argv) { - get_process_mitigation_policy = - reinterpret_cast<GetProcessMitigationPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessMitigationPolicy")); - if (!get_process_mitigation_policy) - return SBOX_TEST_NOT_FOUND; - - if (!CheckWin8Win32CallPolicy()) - return SBOX_TEST_FIRST_ERROR; - return SBOX_TEST_SUCCEEDED; -} - -// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation on -// the target process causes the launch to fail in process initialization. -// The test process itself links against user32/gdi32. -TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownFailure) { - if (base::win::GetVersion() < base::win::VERSION_WIN8) - return; - - TestRunner runner; - sandbox::TargetPolicy* policy = runner.GetPolicy(); - - EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), - SBOX_ALL_OK); - EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); -} - -// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation -// along with the policy to fake user32 and gdi32 initialization successfully -// launches the target process. -// The test process itself links against user32/gdi32. -TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownSuccess) { - if (base::win::GetVersion() < base::win::VERSION_WIN8) - return; - - TestRunner runner; - sandbox::TargetPolicy* policy = runner.GetPolicy(); - - EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), - SBOX_ALL_OK); - EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, - sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL), - sandbox::SBOX_ALL_OK); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_dispatcher.cc deleted file mode 100644 index e426084f8..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_dispatcher.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/process_mitigations_win32k_interception.h" - -namespace sandbox { - -ProcessMitigationsWin32KDispatcher::ProcessMitigationsWin32KDispatcher( - PolicyBase* policy_base) - : policy_base_(policy_base) { -} - -bool ProcessMitigationsWin32KDispatcher::SetupService( - InterceptionManager* manager, int service) { - if (!(policy_base_->GetProcessMitigations() & - sandbox::MITIGATION_WIN32K_DISABLE)) { - return false; - } - - switch (service) { - case IPC_GDI_GDIDLLINITIALIZE_TAG: { - if (!INTERCEPT_EAT(manager, L"gdi32.dll", GdiDllInitialize, - GDIINITIALIZE_ID, 12)) { - return false; - } - return true; - } - - case IPC_GDI_GETSTOCKOBJECT_TAG: { - if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetStockObject, - GETSTOCKOBJECT_ID, 8)) { - return false; - } - return true; - } - - case IPC_USER_REGISTERCLASSW_TAG: { - if (!INTERCEPT_EAT(manager, L"user32.dll", RegisterClassW, - REGISTERCLASSW_ID, 8)) { - return false; - } - return true; - } - - default: - break; - } - return false; -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_dispatcher.h deleted file mode 100644 index 55a84a76e..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_dispatcher.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_ -#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_ - -#include "base/macros.h" -#include "sandbox/win/src/sandbox_policy_base.h" - -namespace sandbox { - -// This class sets up intercepts for the Win32K lockdown policy which is set -// on Windows 8 and beyond. -class ProcessMitigationsWin32KDispatcher : public Dispatcher { - public: - explicit ProcessMitigationsWin32KDispatcher(PolicyBase* policy_base); - ~ProcessMitigationsWin32KDispatcher() override {} - - // Dispatcher interface. - bool SetupService(InterceptionManager* manager, int service) override; - - private: - PolicyBase* policy_base_; - - DISALLOW_COPY_AND_ASSIGN(ProcessMitigationsWin32KDispatcher); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_interception.cc b/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_interception.cc deleted file mode 100644 index ee24fbf43..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_interception.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/process_mitigations_win32k_interception.h" - -namespace sandbox { - -BOOL WINAPI TargetGdiDllInitialize( - GdiDllInitializeFunction orig_gdi_dll_initialize, - HANDLE dll, - DWORD reason) { - return TRUE; -} - -HGDIOBJ WINAPI TargetGetStockObject( - GetStockObjectFunction orig_get_stock_object, - int object) { - return reinterpret_cast<HGDIOBJ>(NULL); -} - -ATOM WINAPI TargetRegisterClassW( - RegisterClassWFunction orig_register_class_function, - const WNDCLASS* wnd_class) { - return TRUE; -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_interception.h b/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_interception.h deleted file mode 100644 index 0b295eacd..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_interception.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_ -#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_ - -#include <windows.h> -#include "sandbox/win/src/sandbox_types.h" - -namespace sandbox { - -extern "C" { - -typedef BOOL (WINAPI* GdiDllInitializeFunction) ( - HANDLE dll, - DWORD reason, - LPVOID reserved); - -typedef HGDIOBJ (WINAPI *GetStockObjectFunction) (int object); - -typedef ATOM (WINAPI *RegisterClassWFunction) (const WNDCLASS* wnd_class); - -// Interceptor for the GdiDllInitialize function. -SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize( - GdiDllInitializeFunction orig_gdi_dll_initialize, - HANDLE dll, - DWORD reason); - -// Interceptor for the GetStockObject function. -SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject( - GetStockObjectFunction orig_get_stock_object, - int object); - -// Interceptor for the RegisterClassW function. -SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW( - RegisterClassWFunction orig_register_class_function, - const WNDCLASS* wnd_class); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_ - diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_policy.cc b/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_policy.cc deleted file mode 100644 index af18c5413..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_policy.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/process_mitigations_win32k_policy.h" - -namespace sandbox { - -bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( - const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy) { - PolicyRule rule(FAKE_SUCCESS); - if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule)) - return false; - if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule)) - return false; - if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule)) - return false; - return true; -} - -} // namespace sandbox - diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_policy.h b/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_policy.h deleted file mode 100644 index 32af16864..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_mitigations_win32k_policy.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_ -#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_ - -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/sandbox_policy.h" - -namespace sandbox { - -enum EvalResult; - -// This class centralizes most of the knowledge related to the process -// mitigations Win32K lockdown policy. -class ProcessMitigationsWin32KLockdownPolicy { - public: - // Creates the required low-level policy rules to evaluate a high-level - // policy rule for the Win32K process mitigation policy. - // name is the object name, semantics is the desired semantics for the - // open or create and policy is the policy generator to which the rules are - // going to be added. - static bool GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_ - - diff --git a/security/sandbox/chromium/sandbox/win/src/process_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/process_policy_test.cc deleted file mode 100644 index 44effa363..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_policy_test.cc +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> -#include <string> - -#include "base/strings/string16.h" -#include "base/strings/sys_string_conversions.h" -#include "base/win/scoped_handle.h" -#include "base/win/scoped_process_information.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/tests/common/controller.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -// While the shell API provides better calls than this home brew function -// we use GetSystemWindowsDirectoryW which does not query the registry so -// it is safe to use after revert. -base::string16 MakeFullPathToSystem32(const wchar_t* name) { - wchar_t windows_path[MAX_PATH] = {0}; - ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH); - base::string16 full_path(windows_path); - if (full_path.empty()) { - return full_path; - } - full_path += L"\\system32\\"; - full_path += name; - return full_path; -} - -// Creates a process with the |exe| and |command| parameter using the -// unicode and ascii version of the api. -sandbox::SboxTestResult CreateProcessHelper(const base::string16& exe, - const base::string16& command) { - base::win::ScopedProcessInformation pi; - STARTUPINFOW si = {sizeof(si)}; - - const wchar_t *exe_name = NULL; - if (!exe.empty()) - exe_name = exe.c_str(); - - base::string16 writable_command = command; - - // Create the process with the unicode version of the API. - sandbox::SboxTestResult ret1 = sandbox::SBOX_TEST_FAILED; - PROCESS_INFORMATION temp_process_info = {}; - if (::CreateProcessW(exe_name, - command.empty() ? NULL : &writable_command[0], - NULL, - NULL, - FALSE, - 0, - NULL, - NULL, - &si, - &temp_process_info)) { - pi.Set(temp_process_info); - ret1 = sandbox::SBOX_TEST_SUCCEEDED; - } else { - DWORD last_error = GetLastError(); - if ((ERROR_NOT_ENOUGH_QUOTA == last_error) || - (ERROR_ACCESS_DENIED == last_error) || - (ERROR_FILE_NOT_FOUND == last_error)) { - ret1 = sandbox::SBOX_TEST_DENIED; - } else { - ret1 = sandbox::SBOX_TEST_FAILED; - } - } - - pi.Close(); - - // Do the same with the ansi version of the api - STARTUPINFOA sia = {sizeof(sia)}; - sandbox::SboxTestResult ret2 = sandbox::SBOX_TEST_FAILED; - - std::string narrow_cmd_line = - base::SysWideToMultiByte(command.c_str(), CP_UTF8); - if (::CreateProcessA( - exe_name ? base::SysWideToMultiByte(exe_name, CP_UTF8).c_str() : NULL, - command.empty() ? NULL : &narrow_cmd_line[0], - NULL, NULL, FALSE, 0, NULL, NULL, &sia, &temp_process_info)) { - pi.Set(temp_process_info); - ret2 = sandbox::SBOX_TEST_SUCCEEDED; - } else { - DWORD last_error = GetLastError(); - if ((ERROR_NOT_ENOUGH_QUOTA == last_error) || - (ERROR_ACCESS_DENIED == last_error) || - (ERROR_FILE_NOT_FOUND == last_error)) { - ret2 = sandbox::SBOX_TEST_DENIED; - } else { - ret2 = sandbox::SBOX_TEST_FAILED; - } - } - - if (ret1 == ret2) - return ret1; - - return sandbox::SBOX_TEST_FAILED; -} - -} // namespace - -namespace sandbox { - -SBOX_TESTS_COMMAND int Process_RunApp1(int argc, wchar_t **argv) { - if (argc != 1) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - if ((NULL == argv) || (NULL == argv[0])) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - base::string16 path = MakeFullPathToSystem32(argv[0]); - - // TEST 1: Try with the path in the app_name. - return CreateProcessHelper(path, base::string16()); -} - -SBOX_TESTS_COMMAND int Process_RunApp2(int argc, wchar_t **argv) { - if (argc != 1) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - if ((NULL == argv) || (NULL == argv[0])) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - base::string16 path = MakeFullPathToSystem32(argv[0]); - - // TEST 2: Try with the path in the cmd_line. - base::string16 cmd_line = L"\""; - cmd_line += path; - cmd_line += L"\""; - return CreateProcessHelper(base::string16(), cmd_line); -} - -SBOX_TESTS_COMMAND int Process_RunApp3(int argc, wchar_t **argv) { - if (argc != 1) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - if ((NULL == argv) || (NULL == argv[0])) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - - // TEST 3: Try file name in the cmd_line. - return CreateProcessHelper(base::string16(), argv[0]); -} - -SBOX_TESTS_COMMAND int Process_RunApp4(int argc, wchar_t **argv) { - if (argc != 1) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - if ((NULL == argv) || (NULL == argv[0])) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - - // TEST 4: Try file name in the app_name and current directory sets correctly. - base::string16 system32 = MakeFullPathToSystem32(L""); - wchar_t current_directory[MAX_PATH + 1]; - DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory); - if (!ret) - return SBOX_TEST_FIRST_ERROR; - if (ret >= MAX_PATH) - return SBOX_TEST_FAILED; - - current_directory[ret] = L'\\'; - current_directory[ret+1] = L'\0'; - if (!::SetCurrentDirectory(system32.c_str())) { - return SBOX_TEST_SECOND_ERROR; - } - - const int result4 = CreateProcessHelper(argv[0], base::string16()); - return ::SetCurrentDirectory(current_directory) ? result4 : SBOX_TEST_FAILED; -} - -SBOX_TESTS_COMMAND int Process_RunApp5(int argc, wchar_t **argv) { - if (argc != 1) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - if ((NULL == argv) || (NULL == argv[0])) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - base::string16 path = MakeFullPathToSystem32(argv[0]); - - // TEST 5: Try with the path in the cmd_line and arguments. - base::string16 cmd_line = L"\""; - cmd_line += path; - cmd_line += L"\" /I"; - return CreateProcessHelper(base::string16(), cmd_line); -} - -SBOX_TESTS_COMMAND int Process_RunApp6(int argc, wchar_t **argv) { - if (argc != 1) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - if ((NULL == argv) || (NULL == argv[0])) { - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - } - - // TEST 6: Try with the file_name in the cmd_line and arguments. - base::string16 cmd_line = argv[0]; - cmd_line += L" /I"; - return CreateProcessHelper(base::string16(), cmd_line); -} - -// Creates a process and checks if it's possible to get a handle to it's token. -SBOX_TESTS_COMMAND int Process_GetChildProcessToken(int argc, wchar_t **argv) { - if (argc != 1) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - if ((NULL == argv) || (NULL == argv[0])) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - base::string16 path = MakeFullPathToSystem32(argv[0]); - - STARTUPINFOW si = {sizeof(si)}; - - PROCESS_INFORMATION temp_process_info = {}; - if (!::CreateProcessW(path.c_str(), NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, - NULL, NULL, &si, &temp_process_info)) { - return SBOX_TEST_FAILED; - } - base::win::ScopedProcessInformation pi(temp_process_info); - - HANDLE token = NULL; - BOOL result = - ::OpenProcessToken(pi.process_handle(), TOKEN_IMPERSONATE, &token); - DWORD error = ::GetLastError(); - - base::win::ScopedHandle token_handle(token); - - if (!::TerminateProcess(pi.process_handle(), 0)) - return SBOX_TEST_FAILED; - - if (result && token) - return SBOX_TEST_SUCCEEDED; - - if (ERROR_ACCESS_DENIED == error) - return SBOX_TEST_DENIED; - - return SBOX_TEST_FAILED; -} - - -SBOX_TESTS_COMMAND int Process_OpenToken(int argc, wchar_t **argv) { - HANDLE token; - if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)) { - if (ERROR_ACCESS_DENIED == ::GetLastError()) { - return SBOX_TEST_DENIED; - } - } else { - ::CloseHandle(token); - return SBOX_TEST_SUCCEEDED; - } - - return SBOX_TEST_FAILED; -} - -TEST(ProcessPolicyTest, TestAllAccess) { - // Check if the "all access" rule fails to be added when the token is too - // powerful. - TestRunner runner; - - // Check the failing case. - runner.GetPolicy()->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); - EXPECT_EQ(SBOX_ERROR_UNSUPPORTED, - runner.GetPolicy()->AddRule(TargetPolicy::SUBSYS_PROCESS, - TargetPolicy::PROCESS_ALL_EXEC, - L"this is not important")); - - // Check the working case. - runner.GetPolicy()->SetTokenLevel(USER_INTERACTIVE, USER_INTERACTIVE); - - EXPECT_EQ(SBOX_ALL_OK, - runner.GetPolicy()->AddRule(TargetPolicy::SUBSYS_PROCESS, - TargetPolicy::PROCESS_ALL_EXEC, - L"this is not important")); -} - -TEST(ProcessPolicyTest, CreateProcessAW) { - TestRunner runner; - base::string16 exe_path = MakeFullPathToSystem32(L"findstr.exe"); - base::string16 system32 = MakeFullPathToSystem32(L""); - ASSERT_TRUE(!exe_path.empty()); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, - TargetPolicy::PROCESS_MIN_EXEC, - exe_path.c_str())); - - // Need to add directory rules for the directories that we use in - // SetCurrentDirectory. - EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_DIR_ANY, - system32.c_str())); - - wchar_t current_directory[MAX_PATH]; - DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory); - ASSERT_TRUE(0 != ret && ret < MAX_PATH); - - wcscat_s(current_directory, MAX_PATH, L"\\"); - EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_DIR_ANY, - current_directory)); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp1 calc.exe")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp2 calc.exe")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp3 calc.exe")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp5 calc.exe")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp6 calc.exe")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"Process_RunApp1 findstr.exe")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"Process_RunApp2 findstr.exe")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"Process_RunApp3 findstr.exe")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"Process_RunApp5 findstr.exe")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"Process_RunApp6 findstr.exe")); - -#if !defined(_WIN64) - if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { - // WinXP results are not reliable. - EXPECT_EQ(SBOX_TEST_SECOND_ERROR, - runner.RunTest(L"Process_RunApp4 calc.exe")); - EXPECT_EQ(SBOX_TEST_SECOND_ERROR, - runner.RunTest(L"Process_RunApp4 findstr.exe")); - } -#endif -} - -TEST(ProcessPolicyTest, OpenToken) { - TestRunner runner; - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_OpenToken")); -} - -TEST(ProcessPolicyTest, TestGetProcessTokenMinAccess) { - TestRunner runner; - base::string16 exe_path = MakeFullPathToSystem32(L"findstr.exe"); - ASSERT_TRUE(!exe_path.empty()); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, - TargetPolicy::PROCESS_MIN_EXEC, - exe_path.c_str())); - - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); -} - -TEST(ProcessPolicyTest, TestGetProcessTokenMaxAccess) { - TestRunner runner(JOB_UNPROTECTED, USER_INTERACTIVE, USER_INTERACTIVE); - base::string16 exe_path = MakeFullPathToSystem32(L"findstr.exe"); - ASSERT_TRUE(!exe_path.empty()); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, - TargetPolicy::PROCESS_ALL_EXEC, - exe_path.c_str())); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); -} - -TEST(ProcessPolicyTest, TestGetProcessTokenMinAccessNoJob) { - TestRunner runner(JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN); - base::string16 exe_path = MakeFullPathToSystem32(L"findstr.exe"); - ASSERT_TRUE(!exe_path.empty()); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, - TargetPolicy::PROCESS_MIN_EXEC, - exe_path.c_str())); - - EXPECT_EQ(SBOX_TEST_DENIED, - runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); -} - -TEST(ProcessPolicyTest, TestGetProcessTokenMaxAccessNoJob) { - TestRunner runner(JOB_NONE, USER_INTERACTIVE, USER_INTERACTIVE); - base::string16 exe_path = MakeFullPathToSystem32(L"findstr.exe"); - ASSERT_TRUE(!exe_path.empty()); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, - TargetPolicy::PROCESS_ALL_EXEC, - exe_path.c_str())); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/process_thread_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/process_thread_dispatcher.cc deleted file mode 100644 index 8debd1e0f..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_thread_dispatcher.cc +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/process_thread_dispatcher.h" - -#include <stddef.h> -#include <stdint.h> - -#include "base/logging.h" -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_broker.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/process_thread_interception.h" -#include "sandbox/win/src/process_thread_policy.h" -#include "sandbox/win/src/sandbox.h" - -namespace { - -// Extracts the application name from a command line. -// -// The application name is the first element of the command line. If -// there is no quotes, the first element is delimited by the first space. -// If there are quotes, the first element is delimited by the quotes. -// -// The create process call is smarter than us. It tries really hard to launch -// the process even if the command line is wrong. For example: -// "c:\program files\test param" will first try to launch c:\program.exe then -// c:\program files\test.exe. We don't do that, we stop after at the first -// space when there is no quotes. -base::string16 GetPathFromCmdLine(const base::string16 &cmd_line) { - base::string16 exe_name; - // Check if it starts with '"'. - if (cmd_line[0] == L'\"') { - // Find the position of the second '"', this terminates the path. - base::string16::size_type pos = cmd_line.find(L'\"', 1); - if (base::string16::npos == pos) - return cmd_line; - exe_name = cmd_line.substr(1, pos - 1); - } else { - // There is no '"', that means that the appname is terminated at the - // first space. - base::string16::size_type pos = cmd_line.find(L' '); - if (base::string16::npos == pos) { - // There is no space, the cmd_line contains only the app_name - exe_name = cmd_line; - } else { - exe_name = cmd_line.substr(0, pos); - } - } - - return exe_name; -} - -// Returns true is the path in parameter is relative. False if it's -// absolute. -bool IsPathRelative(const base::string16 &path) { - // A path is Relative if it's not a UNC path beginnning with \\ or a - // path beginning with a drive. (i.e. X:\) - if (path.find(L"\\\\") == 0 || path.find(L":\\") == 1) - return false; - return true; -} - -// Converts a relative path to an absolute path. -bool ConvertToAbsolutePath(const base::string16& child_current_directory, - bool use_env_path, base::string16 *path) { - wchar_t file_buffer[MAX_PATH]; - wchar_t *file_part = NULL; - - // Here we should start by looking at the path where the child application was - // started. We don't have this information yet. - DWORD result = 0; - if (use_env_path) { - // Try with the complete path - result = ::SearchPath(NULL, path->c_str(), NULL, MAX_PATH, file_buffer, - &file_part); - } - - if (0 == result) { - // Try with the current directory of the child - result = ::SearchPath(child_current_directory.c_str(), path->c_str(), NULL, - MAX_PATH, file_buffer, &file_part); - } - - if (0 == result || result >= MAX_PATH) - return false; - - *path = file_buffer; - return true; -} - -} // namespace -namespace sandbox { - -ThreadProcessDispatcher::ThreadProcessDispatcher(PolicyBase* policy_base) - : policy_base_(policy_base) { - static const IPCCall open_thread = { - {IPC_NTOPENTHREAD_TAG, {UINT32_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &ThreadProcessDispatcher::NtOpenThread)}; - - static const IPCCall open_process = { - {IPC_NTOPENPROCESS_TAG, {UINT32_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &ThreadProcessDispatcher::NtOpenProcess)}; - - static const IPCCall process_token = { - {IPC_NTOPENPROCESSTOKEN_TAG, {VOIDPTR_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &ThreadProcessDispatcher::NtOpenProcessToken)}; - - static const IPCCall process_tokenex = { - {IPC_NTOPENPROCESSTOKENEX_TAG, {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &ThreadProcessDispatcher::NtOpenProcessTokenEx)}; - - static const IPCCall create_params = { - {IPC_CREATEPROCESSW_TAG, - {WCHAR_TYPE, WCHAR_TYPE, WCHAR_TYPE, INOUTPTR_TYPE}}, - reinterpret_cast<CallbackGeneric>( - &ThreadProcessDispatcher::CreateProcessW)}; - - ipc_calls_.push_back(open_thread); - ipc_calls_.push_back(open_process); - ipc_calls_.push_back(process_token); - ipc_calls_.push_back(process_tokenex); - ipc_calls_.push_back(create_params); -} - -bool ThreadProcessDispatcher::SetupService(InterceptionManager* manager, - int service) { - switch (service) { - case IPC_NTOPENTHREAD_TAG: - case IPC_NTOPENPROCESS_TAG: - case IPC_NTOPENPROCESSTOKEN_TAG: - case IPC_NTOPENPROCESSTOKENEX_TAG: - // There is no explicit policy for these services. - NOTREACHED(); - return false; - - case IPC_CREATEPROCESSW_TAG: - return INTERCEPT_EAT(manager, kKerneldllName, CreateProcessW, - CREATE_PROCESSW_ID, 44) && - INTERCEPT_EAT(manager, L"kernel32.dll", CreateProcessA, - CREATE_PROCESSA_ID, 44); - - default: - return false; - } -} - -bool ThreadProcessDispatcher::NtOpenThread(IPCInfo* ipc, - uint32_t desired_access, - uint32_t thread_id) { - HANDLE handle; - NTSTATUS ret = ProcessPolicy::OpenThreadAction(*ipc->client_info, - desired_access, thread_id, - &handle); - ipc->return_info.nt_status = ret; - ipc->return_info.handle = handle; - return true; -} - -bool ThreadProcessDispatcher::NtOpenProcess(IPCInfo* ipc, - uint32_t desired_access, - uint32_t process_id) { - HANDLE handle; - NTSTATUS ret = ProcessPolicy::OpenProcessAction(*ipc->client_info, - desired_access, process_id, - &handle); - ipc->return_info.nt_status = ret; - ipc->return_info.handle = handle; - return true; -} - -bool ThreadProcessDispatcher::NtOpenProcessToken(IPCInfo* ipc, - HANDLE process, - uint32_t desired_access) { - HANDLE handle; - NTSTATUS ret = ProcessPolicy::OpenProcessTokenAction(*ipc->client_info, - process, desired_access, - &handle); - ipc->return_info.nt_status = ret; - ipc->return_info.handle = handle; - return true; -} - -bool ThreadProcessDispatcher::NtOpenProcessTokenEx(IPCInfo* ipc, - HANDLE process, - uint32_t desired_access, - uint32_t attributes) { - HANDLE handle; - NTSTATUS ret = ProcessPolicy::OpenProcessTokenExAction(*ipc->client_info, - process, - desired_access, - attributes, &handle); - ipc->return_info.nt_status = ret; - ipc->return_info.handle = handle; - return true; -} - -bool ThreadProcessDispatcher::CreateProcessW(IPCInfo* ipc, base::string16* name, - base::string16* cmd_line, - base::string16* cur_dir, - CountedBuffer* info) { - if (sizeof(PROCESS_INFORMATION) != info->Size()) - return false; - - // Check if there is an application name. - base::string16 exe_name; - if (!name->empty()) - exe_name = *name; - else - exe_name = GetPathFromCmdLine(*cmd_line); - - if (IsPathRelative(exe_name)) { - if (!ConvertToAbsolutePath(*cur_dir, name->empty(), &exe_name)) { - // Cannot find the path. Maybe the file does not exist. - ipc->return_info.win32_result = ERROR_FILE_NOT_FOUND; - return true; - } - } - - const wchar_t* const_exe_name = exe_name.c_str(); - CountedParameterSet<NameBased> params; - params[NameBased::NAME] = ParamPickerMake(const_exe_name); - - EvalResult eval = policy_base_->EvalPolicy(IPC_CREATEPROCESSW_TAG, - params.GetBase()); - - PROCESS_INFORMATION* proc_info = - reinterpret_cast<PROCESS_INFORMATION*>(info->Buffer()); - // Here we force the app_name to be the one we used for the policy lookup. - // If our logic was wrong, at least we wont allow create a random process. - DWORD ret = ProcessPolicy::CreateProcessWAction(eval, *ipc->client_info, - exe_name, *cmd_line, - proc_info); - - ipc->return_info.win32_result = ret; - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/process_thread_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/process_thread_dispatcher.h deleted file mode 100644 index 008385f42..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_thread_dispatcher.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H_ -#define SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox_policy_base.h" - -namespace sandbox { - -// This class handles process and thread-related IPC calls. -class ThreadProcessDispatcher : public Dispatcher { - public: - explicit ThreadProcessDispatcher(PolicyBase* policy_base); - ~ThreadProcessDispatcher() override {} - - // Dispatcher interface. - bool SetupService(InterceptionManager* manager, int service) override; - - private: - // Processes IPC requests coming from calls to NtOpenThread() in the target. - bool NtOpenThread(IPCInfo* ipc, uint32_t desired_access, uint32_t thread_id); - - // Processes IPC requests coming from calls to NtOpenProcess() in the target. - bool NtOpenProcess(IPCInfo* ipc, - uint32_t desired_access, - uint32_t process_id); - - // Processes IPC requests from calls to NtOpenProcessToken() in the target. - bool NtOpenProcessToken(IPCInfo* ipc, - HANDLE process, - uint32_t desired_access); - - // Processes IPC requests from calls to NtOpenProcessTokenEx() in the target. - bool NtOpenProcessTokenEx(IPCInfo* ipc, - HANDLE process, - uint32_t desired_access, - uint32_t attributes); - - // Processes IPC requests coming from calls to CreateProcessW() in the target. - bool CreateProcessW(IPCInfo* ipc, - base::string16* name, - base::string16* cmd_line, - base::string16* cur_dir, - CountedBuffer* info); - - PolicyBase* policy_base_; - DISALLOW_COPY_AND_ASSIGN(ThreadProcessDispatcher); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc b/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc deleted file mode 100644 index 6507da3f7..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/process_thread_interception.h" - -#include <stdint.h> - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/policy_target.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/target_services.h" -#include "mozilla/sandboxing/sandboxLogging.h" - -namespace sandbox { - -SANDBOX_INTERCEPT NtExports g_nt; - -// Hooks NtOpenThread and proxy the call to the broker if it's trying to -// open a thread in the same process. -NTSTATUS WINAPI TargetNtOpenThread(NtOpenThreadFunction orig_OpenThread, - PHANDLE thread, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, - PCLIENT_ID client_id) { - NTSTATUS status = orig_OpenThread(thread, desired_access, object_attributes, - client_id); - if (NT_SUCCESS(status)) - return status; - - mozilla::sandboxing::LogBlocked("NtOpenThread"); - do { - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - break; - if (!client_id) - break; - - uint32_t thread_id = 0; - bool should_break = false; - __try { - // We support only the calls for the current process - if (NULL != client_id->UniqueProcess) - should_break = true; - - // Object attributes should be NULL or empty. - if (!should_break && NULL != object_attributes) { - if (0 != object_attributes->Attributes || - NULL != object_attributes->ObjectName || - NULL != object_attributes->RootDirectory || - NULL != object_attributes->SecurityDescriptor || - NULL != object_attributes->SecurityQualityOfService) { - should_break = true; - } - } - - thread_id = static_cast<uint32_t>( - reinterpret_cast<ULONG_PTR>(client_id->UniqueThread)); - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - - if (should_break) - break; - - if (!ValidParameter(thread, sizeof(HANDLE), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTOPENTHREAD_TAG, desired_access, - thread_id, &answer); - if (SBOX_ALL_OK != code) - break; - - if (!NT_SUCCESS(answer.nt_status)) - // The nt_status here is most likely STATUS_INVALID_CID because - // in the broker we set the process id in the CID (client ID) param - // to be the current process. If you try to open a thread from another - // process you will get this INVALID_CID error. On the other hand, if you - // try to open a thread in your own process, it should return success. - // We don't want to return STATUS_INVALID_CID here, so we return the - // return of the original open thread status, which is most likely - // STATUS_ACCESS_DENIED. - break; - - __try { - // Write the output parameters. - *thread = answer.handle; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - - mozilla::sandboxing::LogAllowed("NtOpenThread"); - return answer.nt_status; - } while (false); - - return status; -} - -// Hooks NtOpenProcess and proxy the call to the broker if it's trying to -// open the current process. -NTSTATUS WINAPI TargetNtOpenProcess(NtOpenProcessFunction orig_OpenProcess, - PHANDLE process, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, - PCLIENT_ID client_id) { - NTSTATUS status = orig_OpenProcess(process, desired_access, object_attributes, - client_id); - if (NT_SUCCESS(status)) - return status; - - do { - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - break; - if (!client_id) - break; - - uint32_t process_id = 0; - bool should_break = false; - __try { - // Object attributes should be NULL or empty. - if (!should_break && NULL != object_attributes) { - if (0 != object_attributes->Attributes || - NULL != object_attributes->ObjectName || - NULL != object_attributes->RootDirectory || - NULL != object_attributes->SecurityDescriptor || - NULL != object_attributes->SecurityQualityOfService) { - should_break = true; - } - } - - process_id = static_cast<uint32_t>( - reinterpret_cast<ULONG_PTR>(client_id->UniqueProcess)); - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - - if (should_break) - break; - - if (!ValidParameter(process, sizeof(HANDLE), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTOPENPROCESS_TAG, desired_access, - process_id, &answer); - if (SBOX_ALL_OK != code) - break; - - if (!NT_SUCCESS(answer.nt_status)) - return answer.nt_status; - - __try { - // Write the output parameters. - *process = answer.handle; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - - return answer.nt_status; - } while (false); - - return status; -} - - -NTSTATUS WINAPI TargetNtOpenProcessToken( - NtOpenProcessTokenFunction orig_OpenProcessToken, HANDLE process, - ACCESS_MASK desired_access, PHANDLE token) { - NTSTATUS status = orig_OpenProcessToken(process, desired_access, token); - if (NT_SUCCESS(status)) - return status; - - mozilla::sandboxing::LogBlocked("NtOpenProcessToken"); - do { - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - break; - - if (CURRENT_PROCESS != process) - break; - - if (!ValidParameter(token, sizeof(HANDLE), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTOPENPROCESSTOKEN_TAG, process, - desired_access, &answer); - if (SBOX_ALL_OK != code) - break; - - if (!NT_SUCCESS(answer.nt_status)) - return answer.nt_status; - - __try { - // Write the output parameters. - *token = answer.handle; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - - mozilla::sandboxing::LogAllowed("NtOpenProcessToken"); - return answer.nt_status; - } while (false); - - return status; -} - -NTSTATUS WINAPI TargetNtOpenProcessTokenEx( - NtOpenProcessTokenExFunction orig_OpenProcessTokenEx, HANDLE process, - ACCESS_MASK desired_access, ULONG handle_attributes, PHANDLE token) { - NTSTATUS status = orig_OpenProcessTokenEx(process, desired_access, - handle_attributes, token); - if (NT_SUCCESS(status)) - return status; - - mozilla::sandboxing::LogBlocked("NtOpenProcessTokenEx"); - do { - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - break; - - if (CURRENT_PROCESS != process) - break; - - if (!ValidParameter(token, sizeof(HANDLE), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTOPENPROCESSTOKENEX_TAG, process, - desired_access, handle_attributes, &answer); - if (SBOX_ALL_OK != code) - break; - - if (!NT_SUCCESS(answer.nt_status)) - return answer.nt_status; - - __try { - // Write the output parameters. - *token = answer.handle; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - - mozilla::sandboxing::LogAllowed("NtOpenProcessTokenEx"); - return answer.nt_status; - } while (false); - - return status; -} - -BOOL WINAPI TargetCreateProcessW(CreateProcessWFunction orig_CreateProcessW, - LPCWSTR application_name, LPWSTR command_line, - LPSECURITY_ATTRIBUTES process_attributes, - LPSECURITY_ATTRIBUTES thread_attributes, - BOOL inherit_handles, DWORD flags, - LPVOID environment, LPCWSTR current_directory, - LPSTARTUPINFOW startup_info, - LPPROCESS_INFORMATION process_information) { - if (SandboxFactory::GetTargetServices()->GetState()->IsCsrssConnected() && - orig_CreateProcessW(application_name, command_line, process_attributes, - thread_attributes, inherit_handles, flags, - environment, current_directory, startup_info, - process_information)) { - return TRUE; - } - - mozilla::sandboxing::LogBlocked("CreateProcessW", application_name); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return FALSE; - - // Don't call GetLastError before InitCalled() succeeds because kernel32 may - // not be mapped yet. - DWORD original_error = ::GetLastError(); - - do { - if (!ValidParameter(process_information, sizeof(PROCESS_INFORMATION), - WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - const wchar_t* cur_dir = NULL; - - wchar_t current_directory[MAX_PATH]; - DWORD result = ::GetCurrentDirectory(MAX_PATH, current_directory); - if (0 != result && result < MAX_PATH) - cur_dir = current_directory; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - - InOutCountedBuffer proc_info(process_information, - sizeof(PROCESS_INFORMATION)); - - ResultCode code = CrossCall(ipc, IPC_CREATEPROCESSW_TAG, application_name, - command_line, cur_dir, proc_info, &answer); - if (SBOX_ALL_OK != code) - break; - - ::SetLastError(answer.win32_result); - if (ERROR_SUCCESS != answer.win32_result) - return FALSE; - - mozilla::sandboxing::LogAllowed("CreateProcessW", application_name); - return TRUE; - } while (false); - - ::SetLastError(original_error); - return FALSE; -} - -BOOL WINAPI TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA, - LPCSTR application_name, LPSTR command_line, - LPSECURITY_ATTRIBUTES process_attributes, - LPSECURITY_ATTRIBUTES thread_attributes, - BOOL inherit_handles, DWORD flags, - LPVOID environment, LPCSTR current_directory, - LPSTARTUPINFOA startup_info, - LPPROCESS_INFORMATION process_information) { - if (orig_CreateProcessA(application_name, command_line, process_attributes, - thread_attributes, inherit_handles, flags, - environment, current_directory, startup_info, - process_information)) { - return TRUE; - } - - mozilla::sandboxing::LogBlocked("CreateProcessA", application_name); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return FALSE; - - // Don't call GetLastError before InitCalled() succeeds because kernel32 may - // not be mapped yet. - DWORD original_error = ::GetLastError(); - - do { - if (!ValidParameter(process_information, sizeof(PROCESS_INFORMATION), - WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - // Convert the input params to unicode. - UNICODE_STRING *cmd_unicode = NULL; - UNICODE_STRING *app_unicode = NULL; - if (command_line) { - cmd_unicode = AnsiToUnicode(command_line); - if (!cmd_unicode) - break; - } - - if (application_name) { - app_unicode = AnsiToUnicode(application_name); - if (!app_unicode) { - operator delete(cmd_unicode, NT_ALLOC); - break; - } - } - - const wchar_t* cmd_line = cmd_unicode ? cmd_unicode->Buffer : NULL; - const wchar_t* app_name = app_unicode ? app_unicode->Buffer : NULL; - const wchar_t* cur_dir = NULL; - - wchar_t current_directory[MAX_PATH]; - DWORD result = ::GetCurrentDirectory(MAX_PATH, current_directory); - if (0 != result && result < MAX_PATH) - cur_dir = current_directory; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - - InOutCountedBuffer proc_info(process_information, - sizeof(PROCESS_INFORMATION)); - - ResultCode code = CrossCall(ipc, IPC_CREATEPROCESSW_TAG, app_name, - cmd_line, cur_dir, proc_info, &answer); - - operator delete(cmd_unicode, NT_ALLOC); - operator delete(app_unicode, NT_ALLOC); - - if (SBOX_ALL_OK != code) - break; - - ::SetLastError(answer.win32_result); - if (ERROR_SUCCESS != answer.win32_result) - return FALSE; - - mozilla::sandboxing::LogAllowed("CreateProcessA", application_name); - return TRUE; - } while (false); - - ::SetLastError(original_error); - return FALSE; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/process_thread_interception.h b/security/sandbox/chromium/sandbox/win/src/process_thread_interception.h deleted file mode 100644 index 31dc23154..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_thread_interception.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_PROCESS_THREAD_INTERCEPTION_H__ -#define SANDBOX_SRC_PROCESS_THREAD_INTERCEPTION_H__ - -namespace sandbox { - -extern "C" { - -typedef BOOL (WINAPI *CreateProcessWFunction)( - LPCWSTR lpApplicationName, - LPWSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCWSTR lpCurrentDirectory, - LPSTARTUPINFOW lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation); - -typedef BOOL (WINAPI *CreateProcessAFunction)( - LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation); - -typedef HANDLE (WINAPI *CreateThreadFunction)( - LPSECURITY_ATTRIBUTES lpThreadAttributes, - SIZE_T dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, - PVOID lpParameter, - DWORD dwCreationFlags, - LPDWORD lpThreadId); - -typedef LCID (WINAPI *GetUserDefaultLCIDFunction)(); - -// Interception of NtOpenThread on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThread( - NtOpenThreadFunction orig_OpenThread, PHANDLE thread, - ACCESS_MASK desired_access, POBJECT_ATTRIBUTES object_attributes, - PCLIENT_ID client_id); - -// Interception of NtOpenProcess on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcess( - NtOpenProcessFunction orig_OpenProcess, PHANDLE process, - ACCESS_MASK desired_access, POBJECT_ATTRIBUTES object_attributes, - PCLIENT_ID client_id); - -// Interception of NtOpenProcessToken on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcessToken( - NtOpenProcessTokenFunction orig_OpenProcessToken, HANDLE process, - ACCESS_MASK desired_access, PHANDLE token); - -// Interception of NtOpenProcessTokenEx on the child process. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenProcessTokenEx( - NtOpenProcessTokenExFunction orig_OpenProcessTokenEx, HANDLE process, - ACCESS_MASK desired_access, ULONG handle_attributes, PHANDLE token); - -// Interception of CreateProcessW and A in kernel32.dll. -SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessW( - CreateProcessWFunction orig_CreateProcessW, LPCWSTR application_name, - LPWSTR command_line, LPSECURITY_ATTRIBUTES process_attributes, - LPSECURITY_ATTRIBUTES thread_attributes, BOOL inherit_handles, DWORD flags, - LPVOID environment, LPCWSTR current_directory, LPSTARTUPINFOW startup_info, - LPPROCESS_INFORMATION process_information); - -SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessA( - CreateProcessAFunction orig_CreateProcessA, LPCSTR application_name, - LPSTR command_line, LPSECURITY_ATTRIBUTES process_attributes, - LPSECURITY_ATTRIBUTES thread_attributes, BOOL inherit_handles, DWORD flags, - LPVOID environment, LPCSTR current_directory, LPSTARTUPINFOA startup_info, - LPPROCESS_INFORMATION process_information); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_PROCESS_THREAD_INTERCEPTION_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/process_thread_policy.cc b/security/sandbox/chromium/sandbox/win/src/process_thread_policy.cc deleted file mode 100644 index b4976c0bb..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_thread_policy.cc +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/process_thread_policy.h" - -#include <stdint.h> - -#include <string> - -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -// These are the only safe rights that can be given to a sandboxed -// process for the process created by the broker. All others are potential -// vectors of privilege elevation. -const DWORD kProcessRights = SYNCHRONIZE | - PROCESS_QUERY_INFORMATION | - PROCESS_QUERY_LIMITED_INFORMATION | - PROCESS_TERMINATE | - PROCESS_SUSPEND_RESUME; - -const DWORD kThreadRights = SYNCHRONIZE | - THREAD_TERMINATE | - THREAD_SUSPEND_RESUME | - THREAD_QUERY_INFORMATION | - THREAD_QUERY_LIMITED_INFORMATION | - THREAD_SET_LIMITED_INFORMATION; - -// Creates a child process and duplicates the handles to 'target_process'. The -// remaining parameters are the same as CreateProcess(). -BOOL CreateProcessExWHelper(HANDLE target_process, BOOL give_full_access, - LPCWSTR lpApplicationName, LPWSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, DWORD dwCreationFlags, - LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, - LPSTARTUPINFOW lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation) { - if (!::CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, - lpThreadAttributes, bInheritHandles, dwCreationFlags, - lpEnvironment, lpCurrentDirectory, lpStartupInfo, - lpProcessInformation)) { - return FALSE; - } - - DWORD process_access = kProcessRights; - DWORD thread_access = kThreadRights; - if (give_full_access) { - process_access = PROCESS_ALL_ACCESS; - thread_access = THREAD_ALL_ACCESS; - } - if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation->hProcess, - target_process, &lpProcessInformation->hProcess, - process_access, FALSE, DUPLICATE_CLOSE_SOURCE)) { - ::CloseHandle(lpProcessInformation->hThread); - return FALSE; - } - if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation->hThread, - target_process, &lpProcessInformation->hThread, - thread_access, FALSE, DUPLICATE_CLOSE_SOURCE)) { - return FALSE; - } - return TRUE; -} - -} - -namespace sandbox { - -bool ProcessPolicy::GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy) { - scoped_ptr<PolicyRule> process; - switch (semantics) { - case TargetPolicy::PROCESS_MIN_EXEC: { - process.reset(new PolicyRule(GIVE_READONLY)); - break; - }; - case TargetPolicy::PROCESS_ALL_EXEC: { - process.reset(new PolicyRule(GIVE_ALLACCESS)); - break; - }; - default: { - return false; - }; - } - - if (!process->AddStringMatch(IF, NameBased::NAME, name, CASE_INSENSITIVE)) { - return false; - } - if (!policy->AddRule(IPC_CREATEPROCESSW_TAG, process.get())) { - return false; - } - return true; -} - -NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info, - uint32_t desired_access, - uint32_t thread_id, - HANDLE* handle) { - *handle = NULL; - - NtOpenThreadFunction NtOpenThread = NULL; - ResolveNTFunctionPtr("NtOpenThread", &NtOpenThread); - - OBJECT_ATTRIBUTES attributes = {0}; - attributes.Length = sizeof(attributes); - CLIENT_ID client_id = {0}; - client_id.UniqueProcess = reinterpret_cast<PVOID>( - static_cast<ULONG_PTR>(client_info.process_id)); - client_id.UniqueThread = - reinterpret_cast<PVOID>(static_cast<ULONG_PTR>(thread_id)); - - HANDLE local_handle = NULL; - NTSTATUS status = NtOpenThread(&local_handle, desired_access, &attributes, - &client_id); - if (NT_SUCCESS(status)) { - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - client_info.process, handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - } - - return status; -} - -NTSTATUS ProcessPolicy::OpenProcessAction(const ClientInfo& client_info, - uint32_t desired_access, - uint32_t process_id, - HANDLE* handle) { - *handle = NULL; - - NtOpenProcessFunction NtOpenProcess = NULL; - ResolveNTFunctionPtr("NtOpenProcess", &NtOpenProcess); - - if (client_info.process_id != process_id) - return STATUS_ACCESS_DENIED; - - OBJECT_ATTRIBUTES attributes = {0}; - attributes.Length = sizeof(attributes); - CLIENT_ID client_id = {0}; - client_id.UniqueProcess = reinterpret_cast<PVOID>( - static_cast<ULONG_PTR>(client_info.process_id)); - HANDLE local_handle = NULL; - NTSTATUS status = NtOpenProcess(&local_handle, desired_access, &attributes, - &client_id); - if (NT_SUCCESS(status)) { - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - client_info.process, handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - } - - return status; -} - -NTSTATUS ProcessPolicy::OpenProcessTokenAction(const ClientInfo& client_info, - HANDLE process, - uint32_t desired_access, - HANDLE* handle) { - *handle = NULL; - NtOpenProcessTokenFunction NtOpenProcessToken = NULL; - ResolveNTFunctionPtr("NtOpenProcessToken", &NtOpenProcessToken); - - if (CURRENT_PROCESS != process) - return STATUS_ACCESS_DENIED; - - HANDLE local_handle = NULL; - NTSTATUS status = NtOpenProcessToken(client_info.process, desired_access, - &local_handle); - if (NT_SUCCESS(status)) { - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - client_info.process, handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - } - return status; -} - -NTSTATUS ProcessPolicy::OpenProcessTokenExAction(const ClientInfo& client_info, - HANDLE process, - uint32_t desired_access, - uint32_t attributes, - HANDLE* handle) { - *handle = NULL; - NtOpenProcessTokenExFunction NtOpenProcessTokenEx = NULL; - ResolveNTFunctionPtr("NtOpenProcessTokenEx", &NtOpenProcessTokenEx); - - if (CURRENT_PROCESS != process) - return STATUS_ACCESS_DENIED; - - HANDLE local_handle = NULL; - NTSTATUS status = NtOpenProcessTokenEx(client_info.process, desired_access, - attributes, &local_handle); - if (NT_SUCCESS(status)) { - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - client_info.process, handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - } - return status; -} - -DWORD ProcessPolicy::CreateProcessWAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16 &app_name, - const base::string16 &command_line, - PROCESS_INFORMATION* process_info) { - // The only action supported is ASK_BROKER which means create the process. - if (GIVE_ALLACCESS != eval_result && GIVE_READONLY != eval_result) { - return ERROR_ACCESS_DENIED; - } - - STARTUPINFO startup_info = {0}; - startup_info.cb = sizeof(startup_info); - scoped_ptr<wchar_t, base::FreeDeleter> - cmd_line(_wcsdup(command_line.c_str())); - - BOOL should_give_full_access = (GIVE_ALLACCESS == eval_result); - if (!CreateProcessExWHelper(client_info.process, should_give_full_access, - app_name.c_str(), cmd_line.get(), NULL, NULL, - FALSE, 0, NULL, NULL, &startup_info, - process_info)) { - return ERROR_ACCESS_DENIED; - } - return ERROR_SUCCESS; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/process_thread_policy.h b/security/sandbox/chromium/sandbox/win/src/process_thread_policy.h deleted file mode 100644 index a66b52eb2..000000000 --- a/security/sandbox/chromium/sandbox/win/src/process_thread_policy.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_PROCESS_THREAD_POLICY_H_ -#define SANDBOX_SRC_PROCESS_THREAD_POLICY_H_ - -#include <stdint.h> - -#include <string> - -#include "sandbox/win/src/policy_low_level.h" - -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox_policy.h" - -namespace sandbox { - -enum EvalResult; - -// This class centralizes most of the knowledge related to process execution. -class ProcessPolicy { - public: - // Creates the required low-level policy rules to evaluate a high-level. - // policy rule for process creation - // 'name' is the executable to be spawn. - // 'semantics' is the desired semantics. - // 'policy' is the policy generator to which the rules are going to be added. - static bool GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy); - - // Opens a thread from the child process and returns the handle. - // client_info contains the information about the child process, - // desired_access is the access requested by the child and thread_id - // is the thread_id to be opened. - // The function returns the return value of NtOpenThread. - static NTSTATUS OpenThreadAction(const ClientInfo& client_info, - uint32_t desired_access, - uint32_t thread_id, - HANDLE* handle); - - // Opens the process id passed in and returns the duplicated handle to - // the child. We only allow the child processes to open themselves. Any other - // pid open is denied. - static NTSTATUS OpenProcessAction(const ClientInfo& client_info, - uint32_t desired_access, - uint32_t process_id, - HANDLE* handle); - - // Opens the token associated with the process and returns the duplicated - // handle to the child. We only allow the child processes to open his own - // token (using ::GetCurrentProcess()). - static NTSTATUS OpenProcessTokenAction(const ClientInfo& client_info, - HANDLE process, - uint32_t desired_access, - HANDLE* handle); - - // Opens the token associated with the process and returns the duplicated - // handle to the child. We only allow the child processes to open his own - // token (using ::GetCurrentProcess()). - static NTSTATUS OpenProcessTokenExAction(const ClientInfo& client_info, - HANDLE process, - uint32_t desired_access, - uint32_t attributes, - HANDLE* handle); - - // Processes a 'CreateProcessW()' request from the target. - // 'client_info' : the target process that is making the request. - // 'eval_result' : The desired policy action to accomplish. - // 'app_name' : The full path of the process to be created. - // 'command_line' : The command line passed to the created process. - static DWORD CreateProcessWAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16 &app_name, - const base::string16 &command_line, - PROCESS_INFORMATION* process_info); -}; - -} // namespace sandbox - - -#endif // SANDBOX_SRC_PROCESS_THREAD_POLICY_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/registry_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/registry_dispatcher.cc deleted file mode 100644 index fef727dac..000000000 --- a/security/sandbox/chromium/sandbox/win/src/registry_dispatcher.cc +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/registry_dispatcher.h" - -#include <stdint.h> - -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_broker.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/registry_interception.h" -#include "sandbox/win/src/registry_policy.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_nt_util.h" - -namespace { - -// Builds a path using the root directory and the name. -bool GetCompletePath(HANDLE root, const base::string16& name, - base::string16* complete_name) { - if (root) { - if (!sandbox::GetPathFromHandle(root, complete_name)) - return false; - - *complete_name += L"\\"; - *complete_name += name; - } else { - *complete_name = name; - } - - return true; -} - -} - -namespace sandbox { - -RegistryDispatcher::RegistryDispatcher(PolicyBase* policy_base) - : policy_base_(policy_base) { - static const IPCCall create_params = { - {IPC_NTCREATEKEY_TAG, - {WCHAR_TYPE, - UINT32_TYPE, - VOIDPTR_TYPE, - UINT32_TYPE, - UINT32_TYPE, - UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>(&RegistryDispatcher::NtCreateKey)}; - - static const IPCCall open_params = { - {IPC_NTOPENKEY_TAG, {WCHAR_TYPE, UINT32_TYPE, VOIDPTR_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>(&RegistryDispatcher::NtOpenKey)}; - - ipc_calls_.push_back(create_params); - ipc_calls_.push_back(open_params); -} - -bool RegistryDispatcher::SetupService(InterceptionManager* manager, - int service) { - if (IPC_NTCREATEKEY_TAG == service) - return INTERCEPT_NT(manager, NtCreateKey, CREATE_KEY_ID, 32); - - if (IPC_NTOPENKEY_TAG == service) { - bool result = INTERCEPT_NT(manager, NtOpenKey, OPEN_KEY_ID, 16); - if (base::win::GetVersion() >= base::win::VERSION_WIN7 || - (base::win::GetVersion() == base::win::VERSION_VISTA && - base::win::OSInfo::GetInstance()->version_type() == - base::win::SUITE_SERVER)) - result &= INTERCEPT_NT(manager, NtOpenKeyEx, OPEN_KEY_EX_ID, 20); - return result; - } - - return false; -} - -bool RegistryDispatcher::NtCreateKey(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - HANDLE root, - uint32_t desired_access, - uint32_t title_index, - uint32_t create_options) { - base::win::ScopedHandle root_handle; - base::string16 real_path = *name; - - // If there is a root directory, we need to duplicate the handle to make - // it valid in this process. - if (root) { - if (!::DuplicateHandle(ipc->client_info->process, root, - ::GetCurrentProcess(), &root, 0, FALSE, - DUPLICATE_SAME_ACCESS)) - return false; - - root_handle.Set(root); - } - - if (!GetCompletePath(root, *name, &real_path)) - return false; - - const wchar_t* regname = real_path.c_str(); - CountedParameterSet<OpenKey> params; - params[OpenKey::NAME] = ParamPickerMake(regname); - params[OpenKey::ACCESS] = ParamPickerMake(desired_access); - - EvalResult result = policy_base_->EvalPolicy(IPC_NTCREATEKEY_TAG, - params.GetBase()); - - HANDLE handle; - NTSTATUS nt_status; - ULONG disposition = 0; - if (!RegistryPolicy::CreateKeyAction(result, *ipc->client_info, *name, - attributes, root, desired_access, - title_index, create_options, &handle, - &nt_status, &disposition)) { - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - // Return operation status on the IPC. - ipc->return_info.extended[0].unsigned_int = disposition; - ipc->return_info.nt_status = nt_status; - ipc->return_info.handle = handle; - return true; -} - -bool RegistryDispatcher::NtOpenKey(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - HANDLE root, - uint32_t desired_access) { - base::win::ScopedHandle root_handle; - base::string16 real_path = *name; - - // If there is a root directory, we need to duplicate the handle to make - // it valid in this process. - if (root) { - if (!::DuplicateHandle(ipc->client_info->process, root, - ::GetCurrentProcess(), &root, 0, FALSE, - DUPLICATE_SAME_ACCESS)) - return false; - root_handle.Set(root); - } - - if (!GetCompletePath(root, *name, &real_path)) - return false; - - const wchar_t* regname = real_path.c_str(); - CountedParameterSet<OpenKey> params; - params[OpenKey::NAME] = ParamPickerMake(regname); - params[OpenKey::ACCESS] = ParamPickerMake(desired_access); - - EvalResult result = policy_base_->EvalPolicy(IPC_NTOPENKEY_TAG, - params.GetBase()); - HANDLE handle; - NTSTATUS nt_status; - if (!RegistryPolicy::OpenKeyAction(result, *ipc->client_info, *name, - attributes, root, desired_access, &handle, - &nt_status)) { - ipc->return_info.nt_status = STATUS_ACCESS_DENIED; - return true; - } - - // Return operation status on the IPC. - ipc->return_info.nt_status = nt_status; - ipc->return_info.handle = handle; - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/registry_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/registry_dispatcher.h deleted file mode 100644 index cb5af0c3d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/registry_dispatcher.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_REGISTRY_DISPATCHER_H_ -#define SANDBOX_SRC_REGISTRY_DISPATCHER_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox_policy_base.h" - -namespace sandbox { - -// This class handles registry-related IPC calls. -class RegistryDispatcher : public Dispatcher { - public: - explicit RegistryDispatcher(PolicyBase* policy_base); - ~RegistryDispatcher() override {} - - // Dispatcher interface. - bool SetupService(InterceptionManager* manager, int service) override; - - private: - // Processes IPC requests coming from calls to NtCreateKey in the target. - bool NtCreateKey(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - HANDLE root, - uint32_t desired_access, - uint32_t title_index, - uint32_t create_options); - - // Processes IPC requests coming from calls to NtOpenKey in the target. - bool NtOpenKey(IPCInfo* ipc, - base::string16* name, - uint32_t attributes, - HANDLE root, - uint32_t desired_access); - - PolicyBase* policy_base_; - DISALLOW_COPY_AND_ASSIGN(RegistryDispatcher); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_REGISTRY_DISPATCHER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/registry_interception.cc b/security/sandbox/chromium/sandbox/win/src/registry_interception.cc deleted file mode 100644 index 2ff1b33f8..000000000 --- a/security/sandbox/chromium/sandbox/win/src/registry_interception.cc +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/registry_interception.h" - -#include <stdint.h> - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/policy_target.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/target_services.h" -#include "mozilla/sandboxing/sandboxLogging.h" - -namespace sandbox { - -NTSTATUS WINAPI TargetNtCreateKey(NtCreateKeyFunction orig_CreateKey, - PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, - ULONG title_index, PUNICODE_STRING class_name, - ULONG create_options, PULONG disposition) { - // Check if the process can create it first. - NTSTATUS status = orig_CreateKey(key, desired_access, object_attributes, - title_index, class_name, create_options, - disposition); - if (NT_SUCCESS(status)) - return status; - - if (STATUS_OBJECT_NAME_NOT_FOUND != status) { - mozilla::sandboxing::LogBlocked("NtCreateKey", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - do { - if (!ValidParameter(key, sizeof(HANDLE), WRITE)) - break; - - if (disposition && !ValidParameter(disposition, sizeof(ULONG), WRITE)) - break; - - // At this point we don't support class_name. - if (class_name && class_name->Buffer && class_name->Length) - break; - - // We don't support creating link keys, volatile keys and backup/restore. - if (create_options) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - wchar_t* name; - uint32_t attributes = 0; - HANDLE root_directory = 0; - NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, - &root_directory); - if (!NT_SUCCESS(ret) || NULL == name) - break; - - uint32_t desired_access_uint32 = desired_access; - CountedParameterSet<OpenKey> params; - params[OpenKey::ACCESS] = ParamPickerMake(desired_access_uint32); - - wchar_t* full_name = NULL; - - if (root_directory) { - ret = sandbox::AllocAndGetFullPath(root_directory, name, &full_name); - if (!NT_SUCCESS(ret) || NULL == full_name) - break; - params[OpenKey::NAME] = ParamPickerMake(full_name); - } else { - params[OpenKey::NAME] = ParamPickerMake(name); - } - - bool query_broker = QueryBroker(IPC_NTCREATEKEY_TAG, params.GetBase()); - - if (full_name != NULL) - operator delete(full_name, NT_ALLOC); - - if (!query_broker) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - - ResultCode code = CrossCall(ipc, IPC_NTCREATEKEY_TAG, name, attributes, - root_directory, desired_access, title_index, - create_options, &answer); - - operator delete(name, NT_ALLOC); - - if (SBOX_ALL_OK != code) - break; - - if (!NT_SUCCESS(answer.nt_status)) - // TODO(nsylvain): We should return answer.nt_status here instead - // of status. We can do this only after we checked the policy. - // otherwise we will returns ACCESS_DENIED for all paths - // that are not specified by a policy, even though your token allows - // access to that path, and the original call had a more meaningful - // error. Bug 4369 - break; - - __try { - *key = answer.handle; - - if (disposition) - *disposition = answer.extended[0].unsigned_int; - - status = answer.nt_status; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - mozilla::sandboxing::LogAllowed("NtCreateKey", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } while (false); - - return status; -} - -NTSTATUS WINAPI CommonNtOpenKey(NTSTATUS status, PHANDLE key, - ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes) { - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - do { - if (!ValidParameter(key, sizeof(HANDLE), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) - break; - - wchar_t* name; - uint32_t attributes; - HANDLE root_directory; - NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes, - &root_directory); - if (!NT_SUCCESS(ret) || NULL == name) - break; - - uint32_t desired_access_uint32 = desired_access; - CountedParameterSet<OpenKey> params; - params[OpenKey::ACCESS] = ParamPickerMake(desired_access_uint32); - - wchar_t* full_name = NULL; - - if (root_directory) { - ret = sandbox::AllocAndGetFullPath(root_directory, name, &full_name); - if (!NT_SUCCESS(ret) || NULL == full_name) - break; - params[OpenKey::NAME] = ParamPickerMake(full_name); - } else { - params[OpenKey::NAME] = ParamPickerMake(name); - } - - bool query_broker = QueryBroker(IPC_NTOPENKEY_TAG, params.GetBase()); - - if (full_name != NULL) - operator delete(full_name, NT_ALLOC); - - if (!query_broker) - break; - - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - ResultCode code = CrossCall(ipc, IPC_NTOPENKEY_TAG, name, attributes, - root_directory, desired_access, &answer); - - operator delete(name, NT_ALLOC); - - if (SBOX_ALL_OK != code) - break; - - if (!NT_SUCCESS(answer.nt_status)) - // TODO(nsylvain): We should return answer.nt_status here instead - // of status. We can do this only after we checked the policy. - // otherwise we will returns ACCESS_DENIED for all paths - // that are not specified by a policy, even though your token allows - // access to that path, and the original call had a more meaningful - // error. Bug 4369 - break; - - __try { - *key = answer.handle; - status = answer.nt_status; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - mozilla::sandboxing::LogAllowed("NtOpenKey[Ex]", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } while (false); - - return status; -} - -NTSTATUS WINAPI TargetNtOpenKey(NtOpenKeyFunction orig_OpenKey, PHANDLE key, - ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes) { - // Check if the process can open it first. - NTSTATUS status = orig_OpenKey(key, desired_access, object_attributes); - if (NT_SUCCESS(status)) - return status; - - if (STATUS_OBJECT_NAME_NOT_FOUND != status) { - mozilla::sandboxing::LogBlocked("NtOpenKey", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } - - return CommonNtOpenKey(status, key, desired_access, object_attributes); -} - -NTSTATUS WINAPI TargetNtOpenKeyEx(NtOpenKeyExFunction orig_OpenKeyEx, - PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, - ULONG open_options) { - // Check if the process can open it first. - NTSTATUS status = orig_OpenKeyEx(key, desired_access, object_attributes, - open_options); - - // We do not support open_options at this time. The 2 current known values - // are REG_OPTION_CREATE_LINK, to open a symbolic link, and - // REG_OPTION_BACKUP_RESTORE to open the key with special privileges. - if (NT_SUCCESS(status) || open_options != 0) - return status; - - if (STATUS_OBJECT_NAME_NOT_FOUND != status) { - mozilla::sandboxing::LogBlocked("NtOpenKeyEx", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } - - return CommonNtOpenKey(status, key, desired_access, object_attributes); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/registry_interception.h b/security/sandbox/chromium/sandbox/win/src/registry_interception.h deleted file mode 100644 index c3cbde02e..000000000 --- a/security/sandbox/chromium/sandbox/win/src/registry_interception.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_REGISTRY_INTERCEPTION_H__ -#define SANDBOX_SRC_REGISTRY_INTERCEPTION_H__ - -namespace sandbox { - -extern "C" { - -// Interception of NtCreateKey on the child process. -// It should never be called directly -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateKey( - NtCreateKeyFunction orig_CreateKey, PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, ULONG title_index, - PUNICODE_STRING class_name, ULONG create_options, PULONG disposition); - -// Interception of NtOpenKey on the child process. -// It should never be called directly -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKey( - NtOpenKeyFunction orig_OpenKey, PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes); - -// Interception of NtOpenKeyEx on the child process. -// It should never be called directly -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKeyEx( - NtOpenKeyExFunction orig_OpenKeyEx, PHANDLE key, ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, ULONG open_options); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_REGISTRY_INTERCEPTION_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/registry_policy.cc b/security/sandbox/chromium/sandbox/win/src/registry_policy.cc deleted file mode 100644 index d056c9c59..000000000 --- a/security/sandbox/chromium/sandbox/win/src/registry_policy.cc +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include <string> - -#include "sandbox/win/src/registry_policy.h" - -#include "base/logging.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sandbox_utils.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -static const uint32_t kAllowedRegFlags = - KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_READ | - GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL | KEY_WOW64_64KEY | - KEY_WOW64_32KEY; - -// Opens the key referenced by |obj_attributes| with |access| and -// checks what permission was given. Remove the WRITE flags and update -// |access| with the new value. -NTSTATUS TranslateMaximumAllowed(OBJECT_ATTRIBUTES* obj_attributes, - DWORD* access) { - NtOpenKeyFunction NtOpenKey = NULL; - ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey); - - NtCloseFunction NtClose = NULL; - ResolveNTFunctionPtr("NtClose", &NtClose); - - NtQueryObjectFunction NtQueryObject = NULL; - ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject); - - // Open the key. - HANDLE handle; - NTSTATUS status = NtOpenKey(&handle, *access, obj_attributes); - if (!NT_SUCCESS(status)) - return status; - - OBJECT_BASIC_INFORMATION info = {0}; - status = NtQueryObject(handle, ObjectBasicInformation, &info, sizeof(info), - NULL); - CHECK(NT_SUCCESS(NtClose(handle))); - if (!NT_SUCCESS(status)) - return status; - - *access = info.GrantedAccess & kAllowedRegFlags; - return STATUS_SUCCESS; -} - -NTSTATUS NtCreateKeyInTarget(HANDLE* target_key_handle, - ACCESS_MASK desired_access, - OBJECT_ATTRIBUTES* obj_attributes, - ULONG title_index, - UNICODE_STRING* class_name, - ULONG create_options, - ULONG* disposition, - HANDLE target_process) { - NtCreateKeyFunction NtCreateKey = NULL; - ResolveNTFunctionPtr("NtCreateKey", &NtCreateKey); - - if (MAXIMUM_ALLOWED & desired_access) { - NTSTATUS status = TranslateMaximumAllowed(obj_attributes, &desired_access); - if (!NT_SUCCESS(status)) - return STATUS_ACCESS_DENIED; - } - - HANDLE local_handle = INVALID_HANDLE_VALUE; - NTSTATUS status = NtCreateKey(&local_handle, desired_access, obj_attributes, - title_index, class_name, create_options, - disposition); - if (!NT_SUCCESS(status)) - return status; - - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - target_process, target_key_handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - return STATUS_SUCCESS; -} - -NTSTATUS NtOpenKeyInTarget(HANDLE* target_key_handle, - ACCESS_MASK desired_access, - OBJECT_ATTRIBUTES* obj_attributes, - HANDLE target_process) { - NtOpenKeyFunction NtOpenKey = NULL; - ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey); - - if (MAXIMUM_ALLOWED & desired_access) { - NTSTATUS status = TranslateMaximumAllowed(obj_attributes, &desired_access); - if (!NT_SUCCESS(status)) - return STATUS_ACCESS_DENIED; - } - - HANDLE local_handle = INVALID_HANDLE_VALUE; - NTSTATUS status = NtOpenKey(&local_handle, desired_access, obj_attributes); - - if (!NT_SUCCESS(status)) - return status; - - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - target_process, target_key_handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - return STATUS_SUCCESS; -} - -} - -namespace sandbox { - -bool RegistryPolicy::GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy) { - base::string16 resovled_name(name); - if (resovled_name.empty()) { - return false; - } - - if (!ResolveRegistryName(resovled_name, &resovled_name)) - return false; - - name = resovled_name.c_str(); - - EvalResult result = ASK_BROKER; - - PolicyRule open(result); - PolicyRule create(result); - - switch (semantics) { - case TargetPolicy::REG_ALLOW_READONLY: { - // We consider all flags that are not known to be readonly as potentially - // used for write. Here we also support MAXIMUM_ALLOWED, but we are going - // to expand it to read-only before the call. - uint32_t restricted_flags = ~(kAllowedRegFlags | MAXIMUM_ALLOWED); - open.AddNumberMatch(IF_NOT, OpenKey::ACCESS, restricted_flags, AND); - create.AddNumberMatch(IF_NOT, OpenKey::ACCESS, restricted_flags, AND); - break; - } - case TargetPolicy::REG_ALLOW_ANY: { - break; - } - default: { - NOTREACHED(); - return false; - } - } - - if (!create.AddStringMatch(IF, OpenKey::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTCREATEKEY_TAG, &create)) { - return false; - } - - if (!open.AddStringMatch(IF, OpenKey::NAME, name, CASE_INSENSITIVE) || - !policy->AddRule(IPC_NTOPENKEY_TAG, &open)) { - return false; - } - - return true; -} - -bool RegistryPolicy::CreateKeyAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& key, - uint32_t attributes, - HANDLE root_directory, - uint32_t desired_access, - uint32_t title_index, - uint32_t create_options, - HANDLE* handle, - NTSTATUS* nt_status, - ULONG* disposition) { - // The only action supported is ASK_BROKER which means create the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return false; - } - - // We don't support creating link keys, volatile keys or backup/restore. - if (create_options) { - *nt_status = STATUS_ACCESS_DENIED; - return false; - } - - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - InitObjectAttribs(key, attributes, root_directory, &obj_attributes, - &uni_name, NULL); - *nt_status = NtCreateKeyInTarget(handle, desired_access, &obj_attributes, - title_index, NULL, create_options, - disposition, client_info.process); - return true; -} - -bool RegistryPolicy::OpenKeyAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& key, - uint32_t attributes, - HANDLE root_directory, - uint32_t desired_access, - HANDLE* handle, - NTSTATUS* nt_status) { - // The only action supported is ASK_BROKER which means open the requested - // file as specified. - if (ASK_BROKER != eval_result) { - *nt_status = STATUS_ACCESS_DENIED; - return true; - } - - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - InitObjectAttribs(key, attributes, root_directory, &obj_attributes, - &uni_name, NULL); - *nt_status = NtOpenKeyInTarget(handle, desired_access, &obj_attributes, - client_info.process); - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/registry_policy.h b/security/sandbox/chromium/sandbox/win/src/registry_policy.h deleted file mode 100644 index ddea1bf5a..000000000 --- a/security/sandbox/chromium/sandbox/win/src/registry_policy.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_REGISTRY_POLICY_H__ -#define SANDBOX_SRC_REGISTRY_POLICY_H__ - -#include <stdint.h> - -#include <string> - -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/sandbox_policy.h" - -namespace sandbox { - -enum EvalResult; - -// This class centralizes most of the knowledge related to registry policy -class RegistryPolicy { - public: - // Creates the required low-level policy rules to evaluate a high-level - // policy rule for registry IO, in particular open or create actions. - static bool GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy); - - // Performs the desired policy action on a create request with an - // API that is compatible with the IPC-received parameters. - static bool CreateKeyAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& key, - uint32_t attributes, - HANDLE root_directory, - uint32_t desired_access, - uint32_t title_index, - uint32_t create_options, - HANDLE* handle, - NTSTATUS* nt_status, - ULONG* disposition); - - // Performs the desired policy action on an open request with an - // API that is compatible with the IPC-received parameters. - static bool OpenKeyAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& key, - uint32_t attributes, - HANDLE root_directory, - uint32_t desired_access, - HANDLE* handle, - NTSTATUS* nt_status); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_REGISTRY_POLICY_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/registry_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/registry_policy_test.cc deleted file mode 100644 index d8ee34b06..000000000 --- a/security/sandbox/chromium/sandbox/win/src/registry_policy_test.cc +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <shlobj.h> - -#include "testing/gtest/include/gtest/gtest.h" -#include "sandbox/win/src/registry_policy.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/win_utils.h" -#include "sandbox/win/tests/common/controller.h" - -namespace { - -static const DWORD kAllowedRegFlags = KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | - KEY_NOTIFY | KEY_READ | GENERIC_READ | - GENERIC_EXECUTE | READ_CONTROL; - -#define BINDNTDLL(name) \ - name ## Function name = reinterpret_cast<name ## Function>( \ - ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name)) - -bool IsKeyOpenForRead(HKEY handle) { - BINDNTDLL(NtQueryObject); - - OBJECT_BASIC_INFORMATION info = {0}; - NTSTATUS status = NtQueryObject(handle, ObjectBasicInformation, &info, - sizeof(info), NULL); - - if (!NT_SUCCESS(status)) - return false; - - if ((info.GrantedAccess & (~kAllowedRegFlags)) != 0) - return false; - return true; -} - -} - -namespace sandbox { - -SBOX_TESTS_COMMAND int Reg_OpenKey(int argc, wchar_t **argv) { - if (argc != 4) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - REGSAM desired_access = 0; - ULONG options = 0; - if (wcscmp(argv[1], L"read") == 0) { - desired_access = KEY_READ; - } else if (wcscmp(argv[1], L"write") == 0) { - desired_access = KEY_ALL_ACCESS; - } else if (wcscmp(argv[1], L"link") == 0) { - options = REG_OPTION_CREATE_LINK; - desired_access = KEY_ALL_ACCESS; - } else { - desired_access = MAXIMUM_ALLOWED; - } - - HKEY root = GetReservedKeyFromName(argv[2]); - HKEY key; - LRESULT result = 0; - - if (wcscmp(argv[0], L"create") == 0) - result = ::RegCreateKeyEx(root, argv[3], 0, NULL, options, desired_access, - NULL, &key, NULL); - else - result = ::RegOpenKeyEx(root, argv[3], 0, desired_access, &key); - - if (ERROR_SUCCESS == result) { - if (MAXIMUM_ALLOWED == desired_access) { - if (!IsKeyOpenForRead(key)) { - ::RegCloseKey(key); - return SBOX_TEST_FAILED; - } - } - ::RegCloseKey(key); - return SBOX_TEST_SUCCEEDED; - } else if (ERROR_ACCESS_DENIED == result) { - return SBOX_TEST_DENIED; - } - - return SBOX_TEST_FAILED; -} - -TEST(RegistryPolicyTest, TestKeyAnyAccess) { - TestRunner runner; - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_LOCAL_MACHINE")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_ANY, - L"HKEY_LOCAL_MACHINE\\Software\\Microsoft")); - - // Tests read access on key allowed for read-write. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( - L"Reg_OpenKey create read HKEY_LOCAL_MACHINE software\\microsoft")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( - L"Reg_OpenKey open read HKEY_LOCAL_MACHINE software\\microsoft")); - - if (::IsUserAnAdmin()) { - // Tests write access on key allowed for read-write. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( - L"Reg_OpenKey create write HKEY_LOCAL_MACHINE software\\microsoft")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( - L"Reg_OpenKey open write HKEY_LOCAL_MACHINE software\\microsoft")); - } - - // Tests subdirectory access on keys where we don't have subdirectory acess. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Reg_OpenKey create read " - L"HKEY_LOCAL_MACHINE software\\microsoft\\Windows")); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Reg_OpenKey open read " - L"HKEY_LOCAL_MACHINE software\\microsoft\\windows")); - - // Tests to see if we can create keys where we dont have subdirectory access. - // This is denied. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Reg_OpenKey create write " - L"HKEY_LOCAL_MACHINE software\\Microsoft\\google_unit_tests")); - - RegDeleteKey(HKEY_LOCAL_MACHINE, L"software\\Microsoft\\google_unit_tests"); - - // Tests if we need to handle differently the "\\" at the end. - // This is denied. We need to add both rules. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( - L"Reg_OpenKey create read HKEY_LOCAL_MACHINE software\\microsoft\\")); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( - L"Reg_OpenKey open read HKEY_LOCAL_MACHINE software\\microsoft\\")); -} - -TEST(RegistryPolicyTest, TestKeyNoAccess) { - TestRunner runner; - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_LOCAL_MACHINE")); - - // Tests read access where we don't have access at all. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( - L"Reg_OpenKey create read HKEY_LOCAL_MACHINE software")); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( - L"Reg_OpenKey open read HKEY_LOCAL_MACHINE software")); -} - -TEST(RegistryPolicyTest, TestKeyReadOnlyAccess) { - TestRunner runner; - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_LOCAL_MACHINE")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_LOCAL_MACHINE\\Software\\Policies")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_LOCAL_MACHINE\\Software\\Policies\\*")); - - // Tests subdirectory acess on keys where we have subdirectory acess. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Reg_OpenKey create read " - L"HKEY_LOCAL_MACHINE software\\Policies\\microsoft")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Reg_OpenKey open read " - L"HKEY_LOCAL_MACHINE software\\Policies\\microsoft")); - - // Tests to see if we can create keys where we have subdirectory access. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Reg_OpenKey create write " - L"HKEY_LOCAL_MACHINE software\\Policies\\google_unit_tests")); - - RegDeleteKey(HKEY_LOCAL_MACHINE, L"software\\Policies\\google_unit_tests"); -} - -TEST(RegistryPolicyTest, TestKeyAllAccessSubDir) { - TestRunner runner; - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_LOCAL_MACHINE")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_ANY, - L"HKEY_LOCAL_MACHINE\\Software\\Policies")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_ANY, - L"HKEY_LOCAL_MACHINE\\Software\\Policies\\*")); - - if (::IsUserAnAdmin()) { - // Tests to see if we can create keys where we have subdirectory access. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Reg_OpenKey create write " - L"HKEY_LOCAL_MACHINE software\\Policies\\google_unit_tests")); - - RegDeleteKey(HKEY_LOCAL_MACHINE, L"software\\Policies\\google_unit_tests"); - } -} - -TEST(RegistryPolicyTest, TestKeyCreateLink) { - TestRunner runner; - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_LOCAL_MACHINE")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_ANY, - L"HKEY_LOCAL_MACHINE\\Software\\Policies")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_ANY, - L"HKEY_LOCAL_MACHINE\\Software\\Policies\\*")); - - // Tests to see if we can create a registry link key. - // NOTE: In theory here we should make sure to check for SBOX_TEST_DENIED - // instead of !SBOX_TEST_SUCCEEDED, but unfortunately the result is not - // access denied. Internally RegCreateKeyEx (At least on Vista 64) tries to - // create the link, and we return successfully access denied, then, it - // decides to try to break the path in multiple chunks, and create the links - // one by one. In this scenario, it tries to create "HKLM\Software" as a - // link key, which obviously fail with STATUS_OBJECT_NAME_COLLISION, and - // this is what is returned to the user. - EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Reg_OpenKey create link " - L"HKEY_LOCAL_MACHINE software\\Policies\\google_unit_tests")); - - // In case our code fails, and the call works, we need to delete the new - // link. There is no api for this, so we need to use the NT call. - HKEY key = NULL; - LRESULT result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, - L"software\\Policies\\google_unit_tests", - REG_OPTION_OPEN_LINK, MAXIMUM_ALLOWED, - &key); - - if (!result) { - HMODULE ntdll = GetModuleHandle(L"ntdll.dll"); - NtDeleteKeyFunction NtDeleteKey = - reinterpret_cast<NtDeleteKeyFunction>(GetProcAddress(ntdll, - "NtDeleteKey")); - NtDeleteKey(key); - } -} - -TEST(RegistryPolicyTest, TestKeyReadOnlyHKCU) { - TestRunner runner; - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_CURRENT_USER")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_CURRENT_USER\\Software")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_USERS\\.default")); - - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_READONLY, - L"HKEY_USERS\\.default\\software")); - - // Tests read access where we only have read-only access. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( - L"Reg_OpenKey create read HKEY_CURRENT_USER software")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( - L"Reg_OpenKey open read HKEY_CURRENT_USER software")); - - // Tests write access where we only have read-only acess. - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( - L"Reg_OpenKey create write HKEY_CURRENT_USER software")); - - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest( - L"Reg_OpenKey open write HKEY_CURRENT_USER software")); - - // Tests maximum allowed access where we only have read-only access. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( - L"Reg_OpenKey create maximum_allowed HKEY_CURRENT_USER software")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest( - L"Reg_OpenKey open maximum_allowed HKEY_CURRENT_USER software")); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/resolver.cc b/security/sandbox/chromium/sandbox/win/src/resolver.cc deleted file mode 100644 index d1719da51..000000000 --- a/security/sandbox/chromium/sandbox/win/src/resolver.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/resolver.h" - -#include <stddef.h> - -#include "base/win/pe_image.h" -#include "sandbox/win/src/sandbox_nt_util.h" - -namespace sandbox { - -NTSTATUS ResolverThunk::Init(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes) { - if (NULL == thunk_storage || 0 == storage_bytes || - NULL == target_module || NULL == target_name) - return STATUS_INVALID_PARAMETER; - - if (storage_bytes < GetThunkSize()) - return STATUS_BUFFER_TOO_SMALL; - - NTSTATUS ret = STATUS_SUCCESS; - if (NULL == interceptor_entry_point) { - ret = ResolveInterceptor(interceptor_module, interceptor_name, - &interceptor_entry_point); - if (!NT_SUCCESS(ret)) - return ret; - } - - ret = ResolveTarget(target_module, target_name, &target_); - if (!NT_SUCCESS(ret)) - return ret; - - interceptor_ = interceptor_entry_point; - - return ret; -} - -NTSTATUS ResolverThunk::ResolveInterceptor(const void* interceptor_module, - const char* interceptor_name, - const void** address) { - DCHECK_NT(address); - if (!interceptor_module) - return STATUS_INVALID_PARAMETER; - - base::win::PEImage pe(interceptor_module); - if (!pe.VerifyMagic()) - return STATUS_INVALID_IMAGE_FORMAT; - - *address = pe.GetProcAddress(interceptor_name); - - if (!(*address)) - return STATUS_PROCEDURE_NOT_FOUND; - - return STATUS_SUCCESS; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/resolver.h b/security/sandbox/chromium/sandbox/win/src/resolver.h deleted file mode 100644 index 9424060a3..000000000 --- a/security/sandbox/chromium/sandbox/win/src/resolver.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Defines ResolverThunk, the interface for classes that perform interceptions. -// For more details see -// http://dev.chromium.org/developers/design-documents/sandbox . - -#include <stddef.h> - -#include "base/macros.h" -#include "sandbox/win/src/nt_internals.h" - -#ifndef SANDBOX_SRC_RESOLVER_H__ -#define SANDBOX_SRC_RESOLVER_H__ - -namespace sandbox { - -// A resolver is the object in charge of performing the actual interception of -// a function. There should be a concrete implementation of a resolver roughly -// per type of interception. -class ResolverThunk { - public: - ResolverThunk() {} - virtual ~ResolverThunk() {} - - // Performs the actual interception of a function. - // target_name is an exported function from the module loaded at - // target_module, and must be replaced by interceptor_name, exported from - // interceptor_module. interceptor_entry_point can be provided instead of - // interceptor_name / interceptor_module. - // thunk_storage must point to a buffer on the child's address space, to hold - // the patch thunk, and related data. If provided, storage_used will receive - // the number of bytes used from thunk_storage. - // - // Example: (without error checking) - // - // size_t size = resolver.GetThunkSize(); - // char* buffer = ::VirtualAllocEx(child_process, NULL, size, - // MEM_COMMIT, PAGE_READWRITE); - // resolver.Setup(ntdll_module, NULL, L"NtCreateFile", NULL, - // &MyReplacementFunction, buffer, size, NULL); - // - // In general, the idea is to allocate a single big buffer for all - // interceptions on the same dll, and call Setup n times. - // WARNING: This means that any data member that is specific to a single - // interception must be reset within this method. - virtual NTSTATUS Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) = 0; - - // Gets the address of function_name inside module (main exe). - virtual NTSTATUS ResolveInterceptor(const void* module, - const char* function_name, - const void** address); - - // Gets the address of an exported function_name inside module. - virtual NTSTATUS ResolveTarget(const void* module, - const char* function_name, - void** address); - - // Gets the required buffer size for this type of thunk. - virtual size_t GetThunkSize() const = 0; - - protected: - // Performs basic initialization on behalf of a concrete instance of a - // resolver. That is, parameter validation and resolution of the target - // and the interceptor into the member variables. - // - // target_name is an exported function from the module loaded at - // target_module, and must be replaced by interceptor_name, exported from - // interceptor_module. interceptor_entry_point can be provided instead of - // interceptor_name / interceptor_module. - // thunk_storage must point to a buffer on the child's address space, to hold - // the patch thunk, and related data. - virtual NTSTATUS Init(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes); - - // Gets the required buffer size for the internal part of the thunk. - size_t GetInternalThunkSize() const; - - // Initializes the internal part of the thunk. - // interceptor is the function to be called instead of original_function. - bool SetInternalThunk(void* storage, size_t storage_bytes, - const void* original_function, const void* interceptor); - - // Holds the resolved interception target. - void* target_; - // Holds the resolved interception interceptor. - const void* interceptor_; - - DISALLOW_COPY_AND_ASSIGN(ResolverThunk); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_RESOLVER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/resolver_32.cc b/security/sandbox/chromium/sandbox/win/src/resolver_32.cc deleted file mode 100644 index 25df11cc4..000000000 --- a/security/sandbox/chromium/sandbox/win/src/resolver_32.cc +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/resolver.h" - -#include <stddef.h> - -// For placement new. This file must not depend on the CRT at runtime, but -// placement operator new is inline. -#include <new> - -#include "sandbox/win/src/sandbox_nt_util.h" - -namespace { - -#pragma pack(push, 1) -struct InternalThunk { - // This struct contains roughly the following code: - // sub esp, 8 // Create working space - // push edx // Save register - // mov edx, [esp + 0xc] // Get return adddress - // mov [esp + 8], edx // Store return address - // mov dword ptr [esp + 0xc], 0x7c401200 // Store extra argument - // mov dword ptr [esp + 4], 0x40010203 // Store address to jump to - // pop edx // Restore register - // ret // Jump to interceptor - // - // This code only modifies esp and eip so it must work with to normal calling - // convention. It is assembled as: - // - // 00 83ec08 sub esp,8 - // 03 52 push edx - // 04 8b54240c mov edx,dword ptr [esp + 0Ch] - // 08 89542408 mov dword ptr [esp + 8], edx - // 0c c744240c0012407c mov dword ptr [esp + 0Ch], 7C401200h - // 14 c744240403020140 mov dword ptr [esp + 4], 40010203h - // 1c 5a pop edx - // 1d c3 ret - InternalThunk() { - opcodes_1 = 0x5208ec83; - opcodes_2 = 0x0c24548b; - opcodes_3 = 0x08245489; - opcodes_4 = 0x0c2444c7; - opcodes_5 = 0x042444c7; - opcodes_6 = 0xc35a; - extra_argument = 0; - interceptor_function = 0; - }; - ULONG opcodes_1; // = 0x5208ec83 - ULONG opcodes_2; // = 0x0c24548b - ULONG opcodes_3; // = 0x08245489 - ULONG opcodes_4; // = 0x0c2444c7 - ULONG extra_argument; - ULONG opcodes_5; // = 0x042444c7 - ULONG interceptor_function; - USHORT opcodes_6; // = 0xc35a -}; -#pragma pack(pop) - -}; // namespace - -namespace sandbox { - -bool ResolverThunk::SetInternalThunk(void* storage, size_t storage_bytes, - const void* original_function, - const void* interceptor) { - if (storage_bytes < sizeof(InternalThunk)) - return false; - - InternalThunk* thunk = new(storage) InternalThunk; - -#pragma warning(push) -#pragma warning(disable: 4311) - // These casts generate warnings because they are 32 bit specific. - thunk->interceptor_function = reinterpret_cast<ULONG>(interceptor); - thunk->extra_argument = reinterpret_cast<ULONG>(original_function); -#pragma warning(pop) - - return true; -} - -size_t ResolverThunk::GetInternalThunkSize() const { - return sizeof(InternalThunk); -} - -NTSTATUS ResolverThunk::ResolveTarget(const void* module, - const char* function_name, - void** address) { - const void** casted = const_cast<const void**>(address); - return ResolverThunk::ResolveInterceptor(module, function_name, casted); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/resolver_64.cc b/security/sandbox/chromium/sandbox/win/src/resolver_64.cc deleted file mode 100644 index 6a9973544..000000000 --- a/security/sandbox/chromium/sandbox/win/src/resolver_64.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/resolver.h" - -#include <stddef.h> - -// For placement new. This file must not depend on the CRT at runtime, but -// placement operator new is inline. -#include <new> - -#include "sandbox/win/src/sandbox_nt_util.h" - -namespace { - -const USHORT kMovRax = 0xB848; -const USHORT kJmpRax = 0xe0ff; - -#pragma pack(push, 1) -struct InternalThunk { - // This struct contains roughly the following code: - // 01 48b8f0debc9a78563412 mov rax,123456789ABCDEF0h - // ff e0 jmp rax - // - // The code modifies rax, but that's fine for x64 ABI. - - InternalThunk() { - mov_rax = kMovRax; - jmp_rax = kJmpRax; - interceptor_function = 0; - }; - USHORT mov_rax; // = 48 B8 - ULONG_PTR interceptor_function; - USHORT jmp_rax; // = ff e0 -}; -#pragma pack(pop) - -} // namespace. - -namespace sandbox { - -size_t ResolverThunk::GetInternalThunkSize() const { - return sizeof(InternalThunk); -} - -bool ResolverThunk::SetInternalThunk(void* storage, size_t storage_bytes, - const void* original_function, - const void* interceptor) { - if (storage_bytes < sizeof(InternalThunk)) - return false; - - InternalThunk* thunk = new(storage) InternalThunk; - thunk->interceptor_function = reinterpret_cast<ULONG_PTR>(interceptor); - - return true; -} - -NTSTATUS ResolverThunk::ResolveTarget(const void* module, - const char* function_name, - void** address) { - // We don't support sidestep & co. - return STATUS_NOT_IMPLEMENTED; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token.cc b/security/sandbox/chromium/sandbox/win/src/restricted_token.cc deleted file mode 100644 index 607795240..000000000 --- a/security/sandbox/chromium/sandbox/win/src/restricted_token.cc +++ /dev/null @@ -1,458 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/restricted_token.h" - -#include <stddef.h> - -#include <vector> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/acl.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -// Calls GetTokenInformation with the desired |info_class| and returns a buffer -// with the result. -scoped_ptr<BYTE[]> GetTokenInfo(const base::win::ScopedHandle& token, - TOKEN_INFORMATION_CLASS info_class, - DWORD* error) { - // Get the required buffer size. - DWORD size = 0; - ::GetTokenInformation(token.Get(), info_class, NULL, 0, &size); - if (!size) { - *error = ::GetLastError(); - return nullptr; - } - - scoped_ptr<BYTE[]> buffer(new BYTE[size]); - if (!::GetTokenInformation(token.Get(), info_class, buffer.get(), size, - &size)) { - *error = ::GetLastError(); - return nullptr; - } - - *error = ERROR_SUCCESS; - return buffer.Pass(); -} - -} // namespace - -namespace sandbox { - -RestrictedToken::RestrictedToken() - : integrity_level_(INTEGRITY_LEVEL_LAST), - init_(false) { -} - -RestrictedToken::~RestrictedToken() { -} - -DWORD RestrictedToken::Init(const HANDLE effective_token) { - if (init_) - return ERROR_ALREADY_INITIALIZED; - - HANDLE temp_token; - if (effective_token) { - // We duplicate the handle to be able to use it even if the original handle - // is closed. - if (!::DuplicateHandle(::GetCurrentProcess(), effective_token, - ::GetCurrentProcess(), &temp_token, - 0, FALSE, DUPLICATE_SAME_ACCESS)) { - return ::GetLastError(); - } - } else { - if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, - &temp_token)) { - return ::GetLastError(); - } - } - effective_token_.Set(temp_token); - - init_ = true; - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::GetRestrictedToken( - base::win::ScopedHandle* token) const { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - size_t deny_size = sids_for_deny_only_.size(); - size_t restrict_size = sids_to_restrict_.size(); - size_t privileges_size = privileges_to_disable_.size(); - - SID_AND_ATTRIBUTES *deny_only_array = NULL; - if (deny_size) { - deny_only_array = new SID_AND_ATTRIBUTES[deny_size]; - - for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) { - deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY; - deny_only_array[i].Sid = - const_cast<SID*>(sids_for_deny_only_[i].GetPSID()); - } - } - - SID_AND_ATTRIBUTES *sids_to_restrict_array = NULL; - if (restrict_size) { - sids_to_restrict_array = new SID_AND_ATTRIBUTES[restrict_size]; - - for (unsigned int i = 0; i < restrict_size; ++i) { - sids_to_restrict_array[i].Attributes = 0; - sids_to_restrict_array[i].Sid = - const_cast<SID*>(sids_to_restrict_[i].GetPSID()); - } - } - - LUID_AND_ATTRIBUTES *privileges_to_disable_array = NULL; - if (privileges_size) { - privileges_to_disable_array = new LUID_AND_ATTRIBUTES[privileges_size]; - - for (unsigned int i = 0; i < privileges_size; ++i) { - privileges_to_disable_array[i].Attributes = 0; - privileges_to_disable_array[i].Luid = privileges_to_disable_[i]; - } - } - - BOOL result = TRUE; - HANDLE new_token_handle = NULL; - // The SANDBOX_INERT flag did nothing in XP and it was just a way to tell - // if a token has ben restricted given the limiations of IsTokenRestricted() - // but it appears that in Windows 7 it hints the AppLocker subsystem to - // leave us alone. - if (deny_size || restrict_size || privileges_size) { - result = ::CreateRestrictedToken(effective_token_.Get(), - SANDBOX_INERT, - static_cast<DWORD>(deny_size), - deny_only_array, - static_cast<DWORD>(privileges_size), - privileges_to_disable_array, - static_cast<DWORD>(restrict_size), - sids_to_restrict_array, - &new_token_handle); - } else { - // Duplicate the token even if it's not modified at this point - // because any subsequent changes to this token would also affect the - // current process. - result = ::DuplicateTokenEx(effective_token_.Get(), TOKEN_ALL_ACCESS, NULL, - SecurityIdentification, TokenPrimary, - &new_token_handle); - } - auto last_error = ::GetLastError(); - - if (deny_only_array) - delete[] deny_only_array; - - if (sids_to_restrict_array) - delete[] sids_to_restrict_array; - - if (privileges_to_disable_array) - delete[] privileges_to_disable_array; - - if (!result) - return last_error; - - base::win::ScopedHandle new_token(new_token_handle); - - // Modify the default dacl on the token to contain Restricted and the user. - if (!AddSidToDefaultDacl(new_token.Get(), WinRestrictedCodeSid, GENERIC_ALL)) - return ::GetLastError(); - - if (!AddUserSidToDefaultDacl(new_token.Get(), GENERIC_ALL)) - return ::GetLastError(); - - DWORD error = SetTokenIntegrityLevel(new_token.Get(), integrity_level_); - if (ERROR_SUCCESS != error) - return error; - - HANDLE token_handle; - if (!::DuplicateHandle(::GetCurrentProcess(), new_token.Get(), - ::GetCurrentProcess(), &token_handle, - TOKEN_ALL_ACCESS, FALSE, // Don't inherit. - 0)) { - return ::GetLastError(); - } - - token->Set(token_handle); - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::GetRestrictedTokenForImpersonation( - base::win::ScopedHandle* token) const { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - base::win::ScopedHandle restricted_token; - DWORD err_code = GetRestrictedToken(&restricted_token); - if (ERROR_SUCCESS != err_code) - return err_code; - - HANDLE impersonation_token_handle; - if (!::DuplicateToken(restricted_token.Get(), - SecurityImpersonation, - &impersonation_token_handle)) { - return ::GetLastError(); - } - base::win::ScopedHandle impersonation_token(impersonation_token_handle); - - HANDLE token_handle; - if (!::DuplicateHandle(::GetCurrentProcess(), impersonation_token.Get(), - ::GetCurrentProcess(), &token_handle, - TOKEN_ALL_ACCESS, FALSE, // Don't inherit. - 0)) { - return ::GetLastError(); - } - - token->Set(token_handle); - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - DWORD error; - scoped_ptr<BYTE[]> buffer = - GetTokenInfo(effective_token_, TokenGroups, &error); - - if (!buffer) - return error; - - TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get()); - - // Build the list of the deny only group SIDs - for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) { - if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0 && - (token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == 0) { - bool should_ignore = false; - if (exceptions) { - for (unsigned int j = 0; j < exceptions->size(); ++j) { - if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()), - token_groups->Groups[i].Sid)) { - should_ignore = true; - break; - } - } - } - if (!should_ignore) { - sids_for_deny_only_.push_back( - reinterpret_cast<SID*>(token_groups->Groups[i].Sid)); - } - } - } - - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddDenyOnlySids(const std::vector<Sid>& deny_only_sids) { - DCHECK(init_); - if (!init_) { - return ERROR_NO_TOKEN; - } - - DWORD error; - scoped_ptr<BYTE[]> buffer = GetTokenInfo(effective_token_, TokenGroups, &error); - - if (!buffer) { - return error; - } - - TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get()); - - // Build the list of the deny only group SIDs - for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) { - if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0 && - (token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == 0) { - for (unsigned int j = 0; j < deny_only_sids.size(); ++j) { - if (::EqualSid(const_cast<SID*>(deny_only_sids[j].GetPSID()), - token_groups->Groups[i].Sid)) { - sids_for_deny_only_.push_back( - reinterpret_cast<SID*>(token_groups->Groups[i].Sid)); - break; - } - } - } - } - - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddSidForDenyOnly(const Sid &sid) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - sids_for_deny_only_.push_back(sid); - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddUserSidForDenyOnly() { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; - scoped_ptr<BYTE[]> buffer(new BYTE[size]); - TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(buffer.get()); - - BOOL result = ::GetTokenInformation(effective_token_.Get(), TokenUser, - token_user, size, &size); - - if (!result) - return ::GetLastError(); - - Sid user = reinterpret_cast<SID*>(token_user->User.Sid); - sids_for_deny_only_.push_back(user); - - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::DeleteAllPrivileges( - const std::vector<base::string16> *exceptions) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - DWORD error; - scoped_ptr<BYTE[]> buffer = - GetTokenInfo(effective_token_, TokenPrivileges, &error); - - if (!buffer) - return error; - - TOKEN_PRIVILEGES* token_privileges = - reinterpret_cast<TOKEN_PRIVILEGES*>(buffer.get()); - - // Build the list of privileges to disable - for (unsigned int i = 0; i < token_privileges->PrivilegeCount; ++i) { - bool should_ignore = false; - if (exceptions) { - for (unsigned int j = 0; j < exceptions->size(); ++j) { - LUID luid = {0}; - ::LookupPrivilegeValue(NULL, (*exceptions)[j].c_str(), &luid); - if (token_privileges->Privileges[i].Luid.HighPart == luid.HighPart && - token_privileges->Privileges[i].Luid.LowPart == luid.LowPart) { - should_ignore = true; - break; - } - } - } - if (!should_ignore) { - privileges_to_disable_.push_back(token_privileges->Privileges[i].Luid); - } - } - - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::DeletePrivilege(const wchar_t *privilege) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - LUID luid = {0}; - if (LookupPrivilegeValue(NULL, privilege, &luid)) - privileges_to_disable_.push_back(luid); - else - return ::GetLastError(); - - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddRestrictingSid(const Sid &sid) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - sids_to_restrict_.push_back(sid); // No attributes - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddRestrictingSidLogonSession() { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - DWORD error; - scoped_ptr<BYTE[]> buffer = - GetTokenInfo(effective_token_, TokenGroups, &error); - - if (!buffer) - return error; - - TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get()); - - SID *logon_sid = NULL; - for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) { - if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) != 0) { - logon_sid = static_cast<SID*>(token_groups->Groups[i].Sid); - break; - } - } - - if (logon_sid) - sids_to_restrict_.push_back(logon_sid); - - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddRestrictingSidCurrentUser() { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; - scoped_ptr<BYTE[]> buffer(new BYTE[size]); - TOKEN_USER* token_user = reinterpret_cast<TOKEN_USER*>(buffer.get()); - - BOOL result = ::GetTokenInformation(effective_token_.Get(), TokenUser, - token_user, size, &size); - - if (!result) - return ::GetLastError(); - - Sid user = reinterpret_cast<SID*>(token_user->User.Sid); - sids_to_restrict_.push_back(user); - - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddRestrictingSidAllSids() { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - // Add the current user to the list. - DWORD error = AddRestrictingSidCurrentUser(); - if (ERROR_SUCCESS != error) - return error; - - scoped_ptr<BYTE[]> buffer = - GetTokenInfo(effective_token_, TokenGroups, &error); - - if (!buffer) - return error; - - TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get()); - - // Build the list of restricting sids from all groups. - for (unsigned int i = 0; i < token_groups->GroupCount ; ++i) { - if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0) - AddRestrictingSid(reinterpret_cast<SID*>(token_groups->Groups[i].Sid)); - } - - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) { - integrity_level_ = integrity_level; - return ERROR_SUCCESS; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token.h b/security/sandbox/chromium/sandbox/win/src/restricted_token.h deleted file mode 100644 index 623c885fc..000000000 --- a/security/sandbox/chromium/sandbox/win/src/restricted_token.h +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_RESTRICTED_TOKEN_H_ -#define SANDBOX_SRC_RESTRICTED_TOKEN_H_ - -#include <windows.h> -#include <vector> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/restricted_token_utils.h" -#include "sandbox/win/src/security_level.h" -#include "sandbox/win/src/sid.h" - -// Flags present in the Group SID list. These 2 flags are new in Windows Vista -#ifndef SE_GROUP_INTEGRITY -#define SE_GROUP_INTEGRITY (0x00000020L) -#endif -#ifndef SE_GROUP_INTEGRITY_ENABLED -#define SE_GROUP_INTEGRITY_ENABLED (0x00000040L) -#endif - -namespace sandbox { - -// Handles the creation of a restricted token using the effective token or -// any token handle. -// Sample usage: -// RestrictedToken restricted_token; -// DWORD err_code = restricted_token.Init(NULL); // Use the current -// // effective token -// if (ERROR_SUCCESS != err_code) { -// // handle error. -// } -// -// restricted_token.AddRestrictingSid(ATL::Sids::Users().GetPSID()); -// base::win::ScopedHandle token_handle; -// err_code = restricted_token.GetRestrictedToken(&token_handle); -// if (ERROR_SUCCESS != err_code) { -// // handle error. -// } -// [...] -class RestrictedToken { - public: - // Init() has to be called before calling any other method in the class. - RestrictedToken(); - ~RestrictedToken(); - - // Initializes the RestrictedToken object with effective_token. - // If effective_token is NULL, it initializes the RestrictedToken object with - // the effective token of the current process. - DWORD Init(HANDLE effective_token); - - // Creates a restricted token. - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD GetRestrictedToken(base::win::ScopedHandle* token) const; - - // Creates a restricted token and uses this new token to create a new token - // for impersonation. Returns this impersonation token. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - // - // The sample usage is the same as the GetRestrictedToken function. - DWORD GetRestrictedTokenForImpersonation( - base::win::ScopedHandle* token) const; - - // Lists all sids in the token and mark them as Deny Only except for those - // present in the exceptions parameter. If there is no exception needed, - // the caller can pass an empty list or NULL for the exceptions - // parameter. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - // - // Sample usage: - // std::vector<Sid> sid_exceptions; - // sid_exceptions.push_back(ATL::Sids::Users().GetPSID()); - // sid_exceptions.push_back(ATL::Sids::World().GetPSID()); - // restricted_token.AddAllSidsForDenyOnly(&sid_exceptions); - // Note: A Sid marked for Deny Only in a token cannot be used to grant - // access to any resource. It can only be used to deny access. - DWORD AddAllSidsForDenyOnly(std::vector<Sid> *exceptions); - - // Lists all sids in the token and mark them as Deny Only if present in the - // deny_only_sids parameter. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - // - // Note: A Sid marked for Deny Only in a token cannot be used to grant - // access to any resource. It can only be used to deny access. - DWORD AddDenyOnlySids(const std::vector<Sid>& deny_only_sids); - - // Adds a user or group SID for Deny Only in the restricted token. - // Parameter: sid is the SID to add in the Deny Only list. - // The return value is always ERROR_SUCCESS. - // - // Sample Usage: - // restricted_token.AddSidForDenyOnly(ATL::Sids::Admins().GetPSID()); - DWORD AddSidForDenyOnly(const Sid &sid); - - // Adds the user sid of the token for Deny Only in the restricted token. - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AddUserSidForDenyOnly(); - - // Lists all privileges in the token and add them to the list of privileges - // to remove except for those present in the exceptions parameter. If - // there is no exception needed, the caller can pass an empty list or NULL - // for the exceptions parameter. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - // - // Sample usage: - // std::vector<base::string16> privilege_exceptions; - // privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - // restricted_token.DeleteAllPrivileges(&privilege_exceptions); - DWORD DeleteAllPrivileges(const std::vector<base::string16> *exceptions); - - // Adds a privilege to the list of privileges to remove in the restricted - // token. - // Parameter: privilege is the privilege name to remove. This is the string - // representing the privilege. (e.g. "SeChangeNotifyPrivilege"). - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - // - // Sample usage: - // restricted_token.DeletePrivilege(SE_LOAD_DRIVER_NAME); - DWORD DeletePrivilege(const wchar_t *privilege); - - // Adds a SID to the list of restricting sids in the restricted token. - // Parameter: sid is the sid to add to the list restricting sids. - // The return value is always ERROR_SUCCESS. - // - // Sample usage: - // restricted_token.AddRestrictingSid(ATL::Sids::Users().GetPSID()); - // Note: The list of restricting is used to force Windows to perform all - // access checks twice. The first time using your user SID and your groups, - // and the second time using your list of restricting sids. The access has - // to be granted in both places to get access to the resource requested. - DWORD AddRestrictingSid(const Sid &sid); - - // Adds the logon sid of the token in the list of restricting sids for the - // restricted token. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AddRestrictingSidLogonSession(); - - // Adds the owner sid of the token in the list of restricting sids for the - // restricted token. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AddRestrictingSidCurrentUser(); - - // Adds all group sids and the user sid to the restricting sids list. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AddRestrictingSidAllSids(); - - // Sets the token integrity level. This is only valid on Vista. The integrity - // level cannot be higher than your current integrity level. - DWORD SetIntegrityLevel(IntegrityLevel integrity_level); - - private: - // The list of restricting sids in the restricted token. - std::vector<Sid> sids_to_restrict_; - // The list of privileges to remove in the restricted token. - std::vector<LUID> privileges_to_disable_; - // The list of sids to mark as Deny Only in the restricted token. - std::vector<Sid> sids_for_deny_only_; - // The token to restrict. Can only be set in a constructor. - base::win::ScopedHandle effective_token_; - // The token integrity level. Only valid on Vista. - IntegrityLevel integrity_level_; - // Tells if the object is initialized or not (if Init() has been called) - bool init_; - - DISALLOW_COPY_AND_ASSIGN(RestrictedToken); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_RESTRICTED_TOKEN_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_unittest.cc b/security/sandbox/chromium/sandbox/win/src/restricted_token_unittest.cc deleted file mode 100644 index b11948e9f..000000000 --- a/security/sandbox/chromium/sandbox/win/src/restricted_token_unittest.cc +++ /dev/null @@ -1,620 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains unit tests for the RestrictedToken. - -#define _ATL_NO_EXCEPTIONS -#include <atlbase.h> -#include <atlsecurity.h> -#include <vector> - -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/restricted_token.h" -#include "sandbox/win/src/sid.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -// Tests the initializatioin with an invalid token handle. -TEST(RestrictedTokenTest, InvalidHandle) { - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_INVALID_HANDLE), - token.Init(reinterpret_cast<HANDLE>(0x5555))); -} - -// Tests the initialization with NULL as parameter. -TEST(RestrictedTokenTest, DefaultInit) { - // Get the current process token. - HANDLE token_handle = INVALID_HANDLE_VALUE; - ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, - &token_handle)); - - ASSERT_NE(INVALID_HANDLE_VALUE, token_handle); - - ATL::CAccessToken access_token; - access_token.Attach(token_handle); - - // Create the token using the current token. - RestrictedToken token_default; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token_default.Init(NULL)); - - // Get the handle to the restricted token. - - base::win::ScopedHandle restricted_token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token_default.GetRestrictedToken(&restricted_token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(restricted_token_handle.Take()); - - ATL::CSid sid_user_restricted; - ATL::CSid sid_user_default; - ATL::CSid sid_owner_restricted; - ATL::CSid sid_owner_default; - ASSERT_TRUE(restricted_token.GetUser(&sid_user_restricted)); - ASSERT_TRUE(access_token.GetUser(&sid_user_default)); - ASSERT_TRUE(restricted_token.GetOwner(&sid_owner_restricted)); - ASSERT_TRUE(access_token.GetOwner(&sid_owner_default)); - - // Check if both token have the same owner and user. - ASSERT_EQ(sid_user_restricted, sid_user_default); - ASSERT_EQ(sid_owner_restricted, sid_owner_default); -} - -// Tests the initialization with a custom token as parameter. -TEST(RestrictedTokenTest, CustomInit) { - // Get the current process token. - HANDLE token_handle = INVALID_HANDLE_VALUE; - ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, - &token_handle)); - - ASSERT_NE(INVALID_HANDLE_VALUE, token_handle); - - ATL::CAccessToken access_token; - access_token.Attach(token_handle); - - // Change the primary group. - access_token.SetPrimaryGroup(ATL::Sids::World()); - - // Create the token using the current token. - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.Init(access_token.GetHandle())); - - // Get the handle to the restricted token. - - base::win::ScopedHandle restricted_token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&restricted_token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(restricted_token_handle.Take()); - - ATL::CSid sid_restricted; - ATL::CSid sid_default; - ASSERT_TRUE(restricted_token.GetPrimaryGroup(&sid_restricted)); - ASSERT_TRUE(access_token.GetPrimaryGroup(&sid_default)); - - // Check if both token have the same owner. - ASSERT_EQ(sid_restricted, sid_default); -} - -// Verifies that the token created by the object are valid. -TEST(RestrictedTokenTest, ResultToken) { - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSid(ATL::Sids::World().GetPSID())); - - base::win::ScopedHandle restricted_token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&restricted_token)); - - ASSERT_TRUE(::IsTokenRestricted(restricted_token.Get())); - - DWORD length = 0; - TOKEN_TYPE type; - ASSERT_TRUE(::GetTokenInformation(restricted_token.Get(), - ::TokenType, - &type, - sizeof(type), - &length)); - - ASSERT_EQ(type, TokenPrimary); - - base::win::ScopedHandle impersonation_token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedTokenForImpersonation(&impersonation_token)); - - ASSERT_TRUE(::IsTokenRestricted(impersonation_token.Get())); - - ASSERT_TRUE(::GetTokenInformation(impersonation_token.Get(), - ::TokenType, - &type, - sizeof(type), - &length)); - - ASSERT_EQ(type, TokenImpersonation); -} - -// Verifies that the token created has "Restricted" in its default dacl. -TEST(RestrictedTokenTest, DefaultDacl) { - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSid(ATL::Sids::World().GetPSID())); - - base::win::ScopedHandle handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(handle.Take()); - - ATL::CDacl dacl; - ASSERT_TRUE(restricted_token.GetDefaultDacl(&dacl)); - - bool restricted_found = false; - - unsigned int ace_count = dacl.GetAceCount(); - for (unsigned int i = 0; i < ace_count ; ++i) { - ATL::CSid sid; - ACCESS_MASK mask = 0; - dacl.GetAclEntry(i, &sid, &mask); - if (sid == ATL::Sids::RestrictedCode() && mask == GENERIC_ALL) { - restricted_found = true; - break; - } - } - - ASSERT_TRUE(restricted_found); -} - -// Tests the method "AddSidForDenyOnly". -TEST(RestrictedTokenTest, DenySid) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddSidForDenyOnly(Sid(WinWorldSid))); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenGroups groups; - ASSERT_TRUE(restricted_token.GetGroups(&groups)); - - ATL::CSid::CSidArray sids; - ATL::CAtlArray<DWORD> attributes; - groups.GetSidsAndAttributes(&sids, &attributes); - - for (unsigned int i = 0; i < sids.GetCount(); i++) { - if (ATL::Sids::World() == sids[i]) { - ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY), - attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY); - } - } -} - -// Tests the method "AddAllSidsForDenyOnly". -TEST(RestrictedTokenTest, DenySids) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddAllSidsForDenyOnly(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenGroups groups; - ASSERT_TRUE(restricted_token.GetGroups(&groups)); - - ATL::CSid::CSidArray sids; - ATL::CAtlArray<DWORD> attributes; - groups.GetSidsAndAttributes(&sids, &attributes); - - // Verify that all sids are really gone. - for (unsigned int i = 0; i < sids.GetCount(); i++) { - if ((attributes[i] & SE_GROUP_LOGON_ID) == 0 && - (attributes[i] & SE_GROUP_INTEGRITY) == 0) { - ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY), - attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY); - } - } -} - -// Tests the method "AddAllSidsForDenyOnly" using an exception list. -TEST(RestrictedTokenTest, DenySidsException) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - std::vector<Sid> sids_exception; - sids_exception.push_back(Sid(WinWorldSid)); - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddAllSidsForDenyOnly(&sids_exception)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenGroups groups; - ASSERT_TRUE(restricted_token.GetGroups(&groups)); - - ATL::CSid::CSidArray sids; - ATL::CAtlArray<DWORD> attributes; - groups.GetSidsAndAttributes(&sids, &attributes); - - // Verify that all sids are really gone. - for (unsigned int i = 0; i < sids.GetCount(); i++) { - if ((attributes[i] & SE_GROUP_LOGON_ID) == 0 && - (attributes[i] & SE_GROUP_INTEGRITY) == 0) { - if (ATL::Sids::World() == sids[i]) { - ASSERT_EQ(0u, attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY); - } else { - ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY), - attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY); - } - } - } -} - -// Tests test method AddOwnerSidForDenyOnly. -TEST(RestrictedTokenTest, DenyOwnerSid) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenGroups groups; - ASSERT_TRUE(restricted_token.GetGroups(&groups)); - - ATL::CSid::CSidArray sids; - ATL::CAtlArray<DWORD> attributes; - groups.GetSidsAndAttributes(&sids, &attributes); - - ATL::CSid user_sid; - ASSERT_TRUE(restricted_token.GetUser(&user_sid)); - - for (unsigned int i = 0; i < sids.GetCount(); ++i) { - if (user_sid == sids[i]) { - ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY), - attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY); - } - } -} - -// Tests test method AddOwnerSidForDenyOnly with a custom effective token. -TEST(RestrictedTokenTest, DenyOwnerSidCustom) { - // Get the current process token. - HANDLE access_handle = INVALID_HANDLE_VALUE; - ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, - &access_handle)); - - ASSERT_NE(INVALID_HANDLE_VALUE, access_handle); - - ATL::CAccessToken access_token; - access_token.Attach(access_handle); - - RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.Init(access_token.GetHandle())); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenGroups groups; - ASSERT_TRUE(restricted_token.GetGroups(&groups)); - - ATL::CSid::CSidArray sids; - ATL::CAtlArray<DWORD> attributes; - groups.GetSidsAndAttributes(&sids, &attributes); - - ATL::CSid user_sid; - ASSERT_TRUE(restricted_token.GetUser(&user_sid)); - - for (unsigned int i = 0; i < sids.GetCount(); ++i) { - if (user_sid == sids[i]) { - ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY), - attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY); - } - } -} - -// Tests the method DeleteAllPrivileges. -TEST(RestrictedTokenTest, DeleteAllPrivileges) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.DeleteAllPrivileges(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenPrivileges privileges; - ASSERT_TRUE(restricted_token.GetPrivileges(&privileges)); - - ASSERT_EQ(0u, privileges.GetCount()); -} - -// Tests the method DeleteAllPrivileges with an exception list. -TEST(RestrictedTokenTest, DeleteAllPrivilegesException) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - std::vector<base::string16> exceptions; - exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.DeleteAllPrivileges(&exceptions)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenPrivileges privileges; - ASSERT_TRUE(restricted_token.GetPrivileges(&privileges)); - - ATL::CTokenPrivileges::CNames privilege_names; - ATL::CTokenPrivileges::CAttributes privilege_name_attributes; - privileges.GetNamesAndAttributes(&privilege_names, - &privilege_name_attributes); - - ASSERT_EQ(1u, privileges.GetCount()); - - for (unsigned int i = 0; i < privileges.GetCount(); ++i) { - ASSERT_EQ(privilege_names[i], SE_CHANGE_NOTIFY_NAME); - } -} - -// Tests the method DeletePrivilege. -TEST(RestrictedTokenTest, DeletePrivilege) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.DeletePrivilege(SE_CHANGE_NOTIFY_NAME)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenPrivileges privileges; - ASSERT_TRUE(restricted_token.GetPrivileges(&privileges)); - - ATL::CTokenPrivileges::CNames privilege_names; - ATL::CTokenPrivileges::CAttributes privilege_name_attributes; - privileges.GetNamesAndAttributes(&privilege_names, - &privilege_name_attributes); - - for (unsigned int i = 0; i < privileges.GetCount(); ++i) { - ASSERT_NE(privilege_names[i], SE_CHANGE_NOTIFY_NAME); - } -} - -// Checks if a sid is in the restricting list of the restricted token. -// Asserts if it's not the case. If count is a positive number, the number of -// elements in the restricting sids list has to be equal. -void CheckRestrictingSid(const ATL::CAccessToken &restricted_token, - ATL::CSid sid, int count) { - DWORD length = 8192; - BYTE *memory = new BYTE[length]; - TOKEN_GROUPS *groups = reinterpret_cast<TOKEN_GROUPS*>(memory); - ASSERT_TRUE(::GetTokenInformation(restricted_token.GetHandle(), - TokenRestrictedSids, - groups, - length, - &length)); - - ATL::CTokenGroups atl_groups(*groups); - delete[] memory; - - if (count >= 0) - ASSERT_EQ(static_cast<unsigned>(count), atl_groups.GetCount()); - - ATL::CSid::CSidArray sids; - ATL::CAtlArray<DWORD> attributes; - atl_groups.GetSidsAndAttributes(&sids, &attributes); - - bool present = false; - for (unsigned int i = 0; i < sids.GetCount(); ++i) { - if (sids[i] == sid) { - present = true; - break; - } - } - - ASSERT_TRUE(present); -} - -// Tests the method AddRestrictingSid. -TEST(RestrictedTokenTest, AddRestrictingSid) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSid(ATL::Sids::World().GetPSID())); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - CheckRestrictingSid(restricted_token, ATL::Sids::World(), 1); -} - -// Tests the method AddRestrictingSidCurrentUser. -TEST(RestrictedTokenTest, AddRestrictingSidCurrentUser) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidCurrentUser()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - ATL::CSid user; - restricted_token.GetUser(&user); - - CheckRestrictingSid(restricted_token, user, 1); -} - -// Tests the method AddRestrictingSidCurrentUser with a custom effective token. -TEST(RestrictedTokenTest, AddRestrictingSidCurrentUserCustom) { - // Get the current process token. - HANDLE access_handle = INVALID_HANDLE_VALUE; - ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, - &access_handle)); - - ASSERT_NE(INVALID_HANDLE_VALUE, access_handle); - - ATL::CAccessToken access_token; - access_token.Attach(access_handle); - - RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.Init(access_token.GetHandle())); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidCurrentUser()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - ATL::CSid user; - restricted_token.GetUser(&user); - - CheckRestrictingSid(restricted_token, user, 1); -} - -// Tests the method AddRestrictingSidLogonSession. -TEST(RestrictedTokenTest, AddRestrictingSidLogonSession) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidLogonSession()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - ATL::CSid session; - restricted_token.GetLogonSid(&session); - - CheckRestrictingSid(restricted_token, session, 1); -} - -// Tests adding a lot of restricting sids. -TEST(RestrictedTokenTest, AddMultipleRestrictingSids) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidCurrentUser()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidLogonSession()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSid(ATL::Sids::World().GetPSID())); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - ATL::CSid session; - restricted_token.GetLogonSid(&session); - - DWORD length = 8192; - BYTE *memory = new BYTE[length]; - TOKEN_GROUPS *groups = reinterpret_cast<TOKEN_GROUPS*>(memory); - ASSERT_TRUE(::GetTokenInformation(restricted_token.GetHandle(), - TokenRestrictedSids, - groups, - length, - &length)); - - ATL::CTokenGroups atl_groups(*groups); - delete[] memory; - - ASSERT_EQ(3u, atl_groups.GetCount()); -} - -// Tests the method "AddRestrictingSidAllSids". -TEST(RestrictedTokenTest, AddAllSidToRestrictingSids) { - RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidAllSids()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(token_handle.Take()); - - ATL::CTokenGroups groups; - ASSERT_TRUE(restricted_token.GetGroups(&groups)); - - ATL::CSid::CSidArray sids; - ATL::CAtlArray<DWORD> attributes; - groups.GetSidsAndAttributes(&sids, &attributes); - - // Verify that all group sids are in the restricting sid list. - for (unsigned int i = 0; i < sids.GetCount(); i++) { - if ((attributes[i] & SE_GROUP_INTEGRITY) == 0) { - CheckRestrictingSid(restricted_token, sids[i], -1); - } - } - - // Verify that the user is in the restricting sid list. - ATL::CSid user; - restricted_token.GetUser(&user); - CheckRestrictingSid(restricted_token, user, -1); -} - -// Checks the error code when the object is initialized twice. -TEST(RestrictedTokenTest, DoubleInit) { - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(NULL)); - - ASSERT_EQ(static_cast<DWORD>(ERROR_ALREADY_INITIALIZED), token.Init(NULL)); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc deleted file mode 100644 index d5b0e13c3..000000000 --- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <aclapi.h> -#include <sddl.h> -#include <vector> - -#include "sandbox/win/src/restricted_token_utils.h" - -#include "base/logging.h" -#include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/job.h" -#include "sandbox/win/src/restricted_token.h" -#include "sandbox/win/src/security_level.h" -#include "sandbox/win/src/sid.h" - -namespace sandbox { - -DWORD CreateRestrictedToken(TokenLevel security_level, - IntegrityLevel integrity_level, - TokenType token_type, - base::win::ScopedHandle* token) { - RestrictedToken restricted_token; - restricted_token.Init(NULL); // Initialized with the current process token - - std::vector<base::string16> privilege_exceptions; - std::vector<Sid> sid_exceptions; - std::vector<Sid> deny_only_sids; - - bool deny_sids = true; - bool remove_privileges = true; - - switch (security_level) { - case USER_UNPROTECTED: { - deny_sids = false; - remove_privileges = false; - break; - } - case USER_RESTRICTED_SAME_ACCESS: { - deny_sids = false; - remove_privileges = false; - - unsigned err_code = restricted_token.AddRestrictingSidAllSids(); - if (ERROR_SUCCESS != err_code) - return err_code; - - break; - } - case USER_NON_ADMIN: { - deny_sids = false; - deny_only_sids.push_back(WinBuiltinAdministratorsSid); - deny_only_sids.push_back(WinAccountAdministratorSid); - deny_only_sids.push_back(WinAccountDomainAdminsSid); - deny_only_sids.push_back(WinAccountCertAdminsSid); - deny_only_sids.push_back(WinAccountSchemaAdminsSid); - deny_only_sids.push_back(WinAccountEnterpriseAdminsSid); - deny_only_sids.push_back(WinAccountPolicyAdminsSid); - deny_only_sids.push_back(WinBuiltinHyperVAdminsSid); - deny_only_sids.push_back(WinLocalAccountAndAdministratorSid); - privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - break; - } - case USER_INTERACTIVE: { - sid_exceptions.push_back(WinBuiltinUsersSid); - sid_exceptions.push_back(WinWorldSid); - sid_exceptions.push_back(WinInteractiveSid); - sid_exceptions.push_back(WinAuthenticatedUserSid); - privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - restricted_token.AddRestrictingSid(WinBuiltinUsersSid); - restricted_token.AddRestrictingSid(WinWorldSid); - restricted_token.AddRestrictingSid(WinRestrictedCodeSid); - restricted_token.AddRestrictingSidCurrentUser(); - restricted_token.AddRestrictingSidLogonSession(); - break; - } - case USER_LIMITED: { - sid_exceptions.push_back(WinBuiltinUsersSid); - sid_exceptions.push_back(WinWorldSid); - sid_exceptions.push_back(WinInteractiveSid); - privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - restricted_token.AddRestrictingSid(WinBuiltinUsersSid); - restricted_token.AddRestrictingSid(WinWorldSid); - restricted_token.AddRestrictingSid(WinRestrictedCodeSid); - - // This token has to be able to create objects in BNO. - // Unfortunately, on vista, it needs the current logon sid - // in the token to achieve this. You should also set the process to be - // low integrity level so it can't access object created by other - // processes. - if (base::win::GetVersion() >= base::win::VERSION_VISTA) - restricted_token.AddRestrictingSidLogonSession(); - break; - } - case USER_RESTRICTED: { - privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - restricted_token.AddUserSidForDenyOnly(); - restricted_token.AddRestrictingSid(WinRestrictedCodeSid); - break; - } - case USER_LOCKDOWN: { - restricted_token.AddUserSidForDenyOnly(); - restricted_token.AddRestrictingSid(WinNullSid); - break; - } - default: { - return ERROR_BAD_ARGUMENTS; - } - } - - DWORD err_code = ERROR_SUCCESS; - if (deny_sids) { - err_code = restricted_token.AddAllSidsForDenyOnly(&sid_exceptions); - if (ERROR_SUCCESS != err_code) - return err_code; - } else if (!deny_only_sids.empty()) { - err_code = restricted_token.AddDenyOnlySids(deny_only_sids); - if (ERROR_SUCCESS != err_code) { - return err_code; - } - } - - if (remove_privileges) { - err_code = restricted_token.DeleteAllPrivileges(&privilege_exceptions); - if (ERROR_SUCCESS != err_code) - return err_code; - } - - restricted_token.SetIntegrityLevel(integrity_level); - - switch (token_type) { - case PRIMARY: { - err_code = restricted_token.GetRestrictedToken(token); - break; - } - case IMPERSONATION: { - err_code = restricted_token.GetRestrictedTokenForImpersonation(token); - break; - } - default: { - err_code = ERROR_BAD_ARGUMENTS; - break; - } - } - - return err_code; -} - -DWORD SetObjectIntegrityLabel(HANDLE handle, SE_OBJECT_TYPE type, - const wchar_t* ace_access, - const wchar_t* integrity_level_sid) { - // Build the SDDL string for the label. - base::string16 sddl = L"S:("; // SDDL for a SACL. - sddl += SDDL_MANDATORY_LABEL; // Ace Type is "Mandatory Label". - sddl += L";;"; // No Ace Flags. - sddl += ace_access; // Add the ACE access. - sddl += L";;;"; // No ObjectType and Inherited Object Type. - sddl += integrity_level_sid; // Trustee Sid. - sddl += L")"; - - DWORD error = ERROR_SUCCESS; - PSECURITY_DESCRIPTOR sec_desc = NULL; - - PACL sacl = NULL; - BOOL sacl_present = FALSE; - BOOL sacl_defaulted = FALSE; - - if (::ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl.c_str(), - SDDL_REVISION, - &sec_desc, NULL)) { - if (::GetSecurityDescriptorSacl(sec_desc, &sacl_present, &sacl, - &sacl_defaulted)) { - error = ::SetSecurityInfo(handle, type, - LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, - sacl); - } else { - error = ::GetLastError(); - } - - ::LocalFree(sec_desc); - } else { - return::GetLastError(); - } - - return error; -} - -const wchar_t* GetIntegrityLevelString(IntegrityLevel integrity_level) { - switch (integrity_level) { - case INTEGRITY_LEVEL_SYSTEM: - return L"S-1-16-16384"; - case INTEGRITY_LEVEL_HIGH: - return L"S-1-16-12288"; - case INTEGRITY_LEVEL_MEDIUM: - return L"S-1-16-8192"; - case INTEGRITY_LEVEL_MEDIUM_LOW: - return L"S-1-16-6144"; - case INTEGRITY_LEVEL_LOW: - return L"S-1-16-4096"; - case INTEGRITY_LEVEL_BELOW_LOW: - return L"S-1-16-2048"; - case INTEGRITY_LEVEL_UNTRUSTED: - return L"S-1-16-0"; - case INTEGRITY_LEVEL_LAST: - return NULL; - } - - NOTREACHED(); - return NULL; -} -DWORD SetTokenIntegrityLevel(HANDLE token, IntegrityLevel integrity_level) { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return ERROR_SUCCESS; - - const wchar_t* integrity_level_str = GetIntegrityLevelString(integrity_level); - if (!integrity_level_str) { - // No mandatory level specified, we don't change it. - return ERROR_SUCCESS; - } - - PSID integrity_sid = NULL; - if (!::ConvertStringSidToSid(integrity_level_str, &integrity_sid)) - return ::GetLastError(); - - TOKEN_MANDATORY_LABEL label = {}; - label.Label.Attributes = SE_GROUP_INTEGRITY; - label.Label.Sid = integrity_sid; - - DWORD size = sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(integrity_sid); - BOOL result = ::SetTokenInformation(token, TokenIntegrityLevel, &label, - size); - auto last_error = ::GetLastError(); - ::LocalFree(integrity_sid); - - return result ? ERROR_SUCCESS : last_error; -} - -DWORD SetProcessIntegrityLevel(IntegrityLevel integrity_level) { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return ERROR_SUCCESS; - - // We don't check for an invalid level here because we'll just let it - // fail on the SetTokenIntegrityLevel call later on. - if (integrity_level == INTEGRITY_LEVEL_LAST) { - // No mandatory level specified, we don't change it. - return ERROR_SUCCESS; - } - - HANDLE token_handle; - if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT, - &token_handle)) - return ::GetLastError(); - - base::win::ScopedHandle token(token_handle); - - return SetTokenIntegrityLevel(token.Get(), integrity_level); -} - -DWORD HardenTokenIntegrityLevelPolicy(HANDLE token) { - if (base::win::GetVersion() < base::win::VERSION_WIN7) - return ERROR_SUCCESS; - - DWORD last_error = 0; - DWORD length_needed = 0; - - ::GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, - NULL, 0, &length_needed); - - last_error = ::GetLastError(); - if (last_error != ERROR_INSUFFICIENT_BUFFER) - return last_error; - - std::vector<char> security_desc_buffer(length_needed); - PSECURITY_DESCRIPTOR security_desc = - reinterpret_cast<PSECURITY_DESCRIPTOR>(&security_desc_buffer[0]); - - if (!::GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, - security_desc, length_needed, - &length_needed)) - return ::GetLastError(); - - PACL sacl = NULL; - BOOL sacl_present = FALSE; - BOOL sacl_defaulted = FALSE; - - if (!::GetSecurityDescriptorSacl(security_desc, &sacl_present, - &sacl, &sacl_defaulted)) - return ::GetLastError(); - - for (DWORD ace_index = 0; ace_index < sacl->AceCount; ++ace_index) { - PSYSTEM_MANDATORY_LABEL_ACE ace; - - if (::GetAce(sacl, ace_index, reinterpret_cast<LPVOID*>(&ace)) - && ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE) { - ace->Mask |= SYSTEM_MANDATORY_LABEL_NO_READ_UP - | SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP; - break; - } - } - - if (!::SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, - security_desc)) - return ::GetLastError(); - - return ERROR_SUCCESS; -} - -DWORD HardenProcessIntegrityLevelPolicy() { - if (base::win::GetVersion() < base::win::VERSION_WIN7) - return ERROR_SUCCESS; - - HANDLE token_handle; - if (!::OpenProcessToken(GetCurrentProcess(), READ_CONTROL | WRITE_OWNER, - &token_handle)) - return ::GetLastError(); - - base::win::ScopedHandle token(token_handle); - - return HardenTokenIntegrityLevelPolicy(token.Get()); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h deleted file mode 100644 index b4e4fded9..000000000 --- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_RESTRICTED_TOKEN_UTILS_H__ -#define SANDBOX_SRC_RESTRICTED_TOKEN_UTILS_H__ - -#include <accctrl.h> -#include <windows.h> - -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/restricted_token.h" -#include "sandbox/win/src/security_level.h" - -// Contains the utility functions to be able to create restricted tokens based -// on a security profiles. - -namespace sandbox { - -// The type of the token returned by the CreateNakedToken. -enum TokenType { - IMPERSONATION = 0, - PRIMARY -}; - -// Creates a restricted token based on the effective token of the current -// process. The parameter security_level determines how much the token is -// restricted. The token_type determines if the token will be used as a primary -// token or impersonation token. The integrity level of the token is set to -// |integrity level| on Vista only. -// |token| is the output value containing the handle of the newly created -// restricted token. -// If the function succeeds, the return value is ERROR_SUCCESS. If the -// function fails, the return value is the win32 error code corresponding to -// the error. -DWORD CreateRestrictedToken(TokenLevel security_level, - IntegrityLevel integrity_level, - TokenType token_type, - base::win::ScopedHandle* token); - -// Sets the integrity label on a object handle. -DWORD SetObjectIntegrityLabel(HANDLE handle, SE_OBJECT_TYPE type, - const wchar_t* ace_access, - const wchar_t* integrity_level_sid); - -// Sets the integrity level on a token. This is only valid on Vista. It returns -// without failing on XP. If the integrity level that you specify is greater -// than the current integrity level, the function will fail. -DWORD SetTokenIntegrityLevel(HANDLE token, IntegrityLevel integrity_level); - -// Returns the integrity level SDDL string associated with a given -// IntegrityLevel value. -const wchar_t* GetIntegrityLevelString(IntegrityLevel integrity_level); - -// Sets the integrity level on the current process on Vista. It returns without -// failing on XP. If the integrity level that you specify is greater than the -// current integrity level, the function will fail. -DWORD SetProcessIntegrityLevel(IntegrityLevel integrity_level); - -// Hardens the integrity level policy on a token. This is only valid on Win 7 -// and above. Specifically it sets the policy to block read and execute so -// that a lower privileged process cannot open the token for impersonate or -// duplicate permissions. This should limit potential security holes. -DWORD HardenTokenIntegrityLevelPolicy(HANDLE token); - -// Hardens the integrity level policy on the current process. This is only -// valid on Win 7 and above. Specifically it sets the policy to block read -// and execute so that a lower privileged process cannot open the token for -// impersonate or duplicate permissions. This should limit potential security -// holes. -DWORD HardenProcessIntegrityLevelPolicy(); - -} // namespace sandbox - -#endif // SANDBOX_SRC_RESTRICTED_TOKEN_UTILS_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.cc b/security/sandbox/chromium/sandbox/win/src/sandbox.cc deleted file mode 100644 index 984dfecec..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdio.h> -#include <windows.h> -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/broker_services.h" -#include "sandbox/win/src/target_services.h" - -namespace sandbox { -// The section for IPC and policy. -SANDBOX_INTERCEPT HANDLE g_shared_section; -static bool s_is_broker = false; - -// GetBrokerServices: the current implementation relies on a shared section -// that is created by the broker and opened by the target. -BrokerServices* SandboxFactory::GetBrokerServices() { - // Can't be the broker if the shared section is open. - if (NULL != g_shared_section) { - return NULL; - } - // If the shared section does not exist we are the broker, then create - // the broker object. - s_is_broker = true; - return BrokerServicesBase::GetInstance(); -} - -// GetTargetServices implementation must follow the same technique as the -// GetBrokerServices, but in this case the logic is the opposite. -TargetServices* SandboxFactory::GetTargetServices() { - // Can't be the target if the section handle is not valid. - if (NULL == g_shared_section) { - return NULL; - } - // We are the target - s_is_broker = false; - // Creates and returns the target services implementation. - return TargetServicesBase::GetInstance(); -} - -} // namespace sandbox - -// Allows querying for whether the current process has been sandboxed. -extern "C" bool __declspec(dllexport) IsSandboxedProcess() { - return sandbox::g_shared_section != NULL; -} diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h deleted file mode 100644 index 193605d1e..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox.h +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Sandbox is a sandbox library for windows processes. Use when you want a -// 'privileged' process and a 'locked down process' to interact with. -// The privileged process is called the broker and it is started by external -// means (such as the user starting it). The 'sandboxed' process is called the -// target and it is started by the broker. There can be many target processes -// started by a single broker process. This library provides facilities -// for both the broker and the target. -// -// The design rationale and relevant documents can be found at http://go/sbox. -// -// Note: this header does not include the SandboxFactory definitions because -// there are cases where the Sandbox library is linked against the main .exe -// while its API needs to be used in a DLL. - -#ifndef SANDBOX_WIN_SRC_SANDBOX_H_ -#define SANDBOX_WIN_SRC_SANDBOX_H_ - -#include <windows.h> - -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/sandbox_types.h" - -// sandbox: Google User-Land Application Sandbox -namespace sandbox { - -class BrokerServices; -class ProcessState; -class TargetPolicy; -class TargetServices; - -// BrokerServices exposes all the broker API. -// The basic use is to start the target(s) and wait for them to end. -// -// This API is intended to be called in the following order -// (error checking omitted): -// BrokerServices* broker = SandboxFactory::GetBrokerServices(); -// broker->Init(); -// PROCESS_INFORMATION target; -// broker->SpawnTarget(target_exe_path, target_args, &target); -// ::ResumeThread(target->hThread); -// // -- later you can call: -// broker->WaitForAllTargets(option); -// -class BrokerServices { - public: - // Initializes the broker. Must be called before any other on this class. - // returns ALL_OK if successful. All other return values imply failure. - // If the return is ERROR_GENERIC, you can call ::GetLastError() to get - // more information. - virtual ResultCode Init() = 0; - - // Returns the interface pointer to a new, empty policy object. Use this - // interface to specify the sandbox policy for new processes created by - // SpawnTarget() - virtual TargetPolicy* CreatePolicy() = 0; - - // Creates a new target (child process) in a suspended state. - // Parameters: - // exe_path: This is the full path to the target binary. This parameter - // can be null and in this case the exe path must be the first argument - // of the command_line. - // command_line: The arguments to be passed as command line to the new - // process. This can be null if the exe_path parameter is not null. - // policy: This is the pointer to the policy object for the sandbox to - // be created. - // target: returns the resulting target process information such as process - // handle and PID just as if CreateProcess() had been called. The caller is - // responsible for closing the handles returned in this structure. - // Returns: - // ALL_OK if successful. All other return values imply failure. - virtual ResultCode SpawnTarget(const wchar_t* exe_path, - const wchar_t* command_line, - TargetPolicy* policy, - PROCESS_INFORMATION* target) = 0; - - // This call blocks (waits) for all the targets to terminate. - // Returns: - // ALL_OK if successful. All other return values imply failure. - // If the return is ERROR_GENERIC, you can call ::GetLastError() to get - // more information. - virtual ResultCode WaitForAllTargets() = 0; - - // Adds an unsandboxed process as a peer for policy decisions (e.g. - // HANDLES_DUP_ANY policy). - // Returns: - // ALL_OK if successful. All other return values imply failure. - // If the return is ERROR_GENERIC, you can call ::GetLastError() to get - // more information. - virtual ResultCode AddTargetPeer(HANDLE peer_process) = 0; - - // Install the AppContainer with the specified sid an name. Returns ALL_OK if - // successful or an error code if the AppContainer cannot be installed. - virtual ResultCode InstallAppContainer(const wchar_t* sid, - const wchar_t* name) = 0; - - // Removes from the system the AppContainer with the specified sid. - // Returns ALL_OK if successful or an error code otherwise. - virtual ResultCode UninstallAppContainer(const wchar_t* sid) = 0; -}; - -// TargetServices models the current process from the perspective -// of a target process. To obtain a pointer to it use -// Sandbox::GetTargetServices(). Note that this call returns a non-null -// pointer only if this process is in fact a target. A process is a target -// only if the process was spawned by a call to BrokerServices::SpawnTarget(). -// -// This API allows the target to gain access to resources with a high -// privilege token and then when it is ready to perform dangerous activities -// (such as download content from the web) it can lower its token and -// enter into locked-down (sandbox) mode. -// The typical usage is as follows: -// -// TargetServices* target_services = Sandbox::GetTargetServices(); -// if (NULL != target_services) { -// // We are the target. -// target_services->Init(); -// // Do work that requires high privileges here. -// // .... -// // When ready to enter lock-down mode call LowerToken: -// target_services->LowerToken(); -// } -// -// For more information see the BrokerServices API documentation. -class TargetServices { - public: - // Initializes the target. Must call this function before any other. - // returns ALL_OK if successful. All other return values imply failure. - // If the return is ERROR_GENERIC, you can call ::GetLastError() to get - // more information. - virtual ResultCode Init() = 0; - - // Discards the impersonation token and uses the lower token, call before - // processing any untrusted data or running third-party code. If this call - // fails the current process could be terminated immediately. - virtual void LowerToken() = 0; - - // Returns the ProcessState object. Through that object it's possible to have - // information about the current state of the process, such as whether - // LowerToken has been called or not. - virtual ProcessState* GetState() = 0; - - // Requests the broker to duplicate the supplied handle into the target - // process. The target process must be an active sandbox child process - // and the source process must have a corresponding policy allowing - // handle duplication for this object type. - // Returns: - // ALL_OK if successful. All other return values imply failure. - // If the return is ERROR_GENERIC, you can call ::GetLastError() to get - // more information. - virtual ResultCode DuplicateHandle(HANDLE source_handle, - DWORD target_process_id, - HANDLE* target_handle, - DWORD desired_access, - DWORD options) = 0; -}; - -} // namespace sandbox - - -#endif // SANDBOX_WIN_SRC_SANDBOX_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.vcproj b/security/sandbox/chromium/sandbox/win/src/sandbox.vcproj deleted file mode 100644 index f206e01a1..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox.vcproj +++ /dev/null @@ -1,658 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="sandbox" - ProjectGUID="{881F6A97-D539-4C48-B401-DF04385B2343}" - RootNamespace="sandbox" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - ConfigurationType="4" - InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - UsePrecompiledHeader="2" - ForcedIncludeFiles="stdafx.h" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - Description="Copy wow_helper to output directory" - CommandLine="copy $(ProjectDir)\..\wow_helper\wow_helper.exe $(OutDir) && copy $(ProjectDir)\..\wow_helper\wow_helper.pdb $(OutDir)" - /> - </Configuration> - <Configuration - Name="Release|Win32" - ConfigurationType="4" - InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - UsePrecompiledHeader="0" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - Description="Copy wow_helper to output directory" - CommandLine="copy $(ProjectDir)\..\wow_helper\wow_helper.exe $(OutDir) && copy $(ProjectDir)\..\wow_helper\wow_helper.pdb $(OutDir)" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="security" - > - <File - RelativePath=".\acl.cc" - > - </File> - <File - RelativePath=".\acl.h" - > - </File> - <File - RelativePath=".\dep.cc" - > - </File> - <File - RelativePath=".\dep.h" - > - </File> - <File - RelativePath=".\job.cc" - > - </File> - <File - RelativePath=".\job.h" - > - </File> - <File - RelativePath=".\restricted_token.cc" - > - </File> - <File - RelativePath=".\restricted_token.h" - > - </File> - <File - RelativePath=".\restricted_token_utils.cc" - > - </File> - <File - RelativePath=".\restricted_token_utils.h" - > - </File> - <File - RelativePath=".\security_level.h" - > - </File> - <File - RelativePath=".\sid.cc" - > - </File> - <File - RelativePath=".\sid.h" - > - </File> - <File - RelativePath=".\window.cc" - > - </File> - <File - RelativePath=".\window.h" - > - </File> - </Filter> - <Filter - Name="Interception" - > - <File - RelativePath=".\eat_resolver.cc" - > - </File> - <File - RelativePath=".\eat_resolver.h" - > - </File> - <File - RelativePath=".\interception.cc" - > - </File> - <File - RelativePath=".\interception.h" - > - </File> - <File - RelativePath=".\interception_agent.cc" - > - </File> - <File - RelativePath=".\interception_agent.h" - > - </File> - <File - RelativePath=".\interception_internal.h" - > - </File> - <File - RelativePath=".\pe_image.cc" - > - </File> - <File - RelativePath=".\pe_image.h" - > - </File> - <File - RelativePath=".\resolver.cc" - > - </File> - <File - RelativePath=".\resolver.h" - > - </File> - <File - RelativePath=".\service_resolver.cc" - > - </File> - <File - RelativePath=".\service_resolver.h" - > - </File> - <File - RelativePath=".\sidestep_resolver.cc" - > - </File> - <File - RelativePath=".\sidestep_resolver.h" - > - </File> - <File - RelativePath=".\target_interceptions.cc" - > - </File> - <File - RelativePath=".\target_interceptions.h" - > - </File> - <File - RelativePath=".\Wow64.cc" - > - </File> - <File - RelativePath=".\Wow64.h" - > - </File> - <Filter - Name="sidestep" - > - <File - RelativePath=".\sidestep\ia32_modrm_map.cpp" - > - </File> - <File - RelativePath=".\sidestep\ia32_opcode_map.cpp" - > - </File> - <File - RelativePath=".\sidestep\mini_disassembler.cpp" - > - </File> - <File - RelativePath=".\sidestep\mini_disassembler.h" - > - </File> - <File - RelativePath=".\sidestep\mini_disassembler_types.h" - > - </File> - <File - RelativePath=".\sidestep\preamble_patcher.h" - > - </File> - <File - RelativePath=".\sidestep\preamble_patcher_with_stub.cpp" - > - </File> - </Filter> - </Filter> - <Filter - Name="nt_level" - > - <File - RelativePath=".\nt_internals.h" - > - </File> - <File - RelativePath=".\policy_target.cc" - > - </File> - <File - RelativePath=".\policy_target.h" - > - </File> - <File - RelativePath=".\sandbox_nt_types.h" - > - </File> - <File - RelativePath=".\sandbox_nt_util.cc" - > - </File> - <File - RelativePath=".\sandbox_nt_util.h" - > - </File> - </Filter> - <Filter - Name="Policy_handlers" - > - <File - RelativePath=".\filesystem_dispatcher.cc" - > - </File> - <File - RelativePath=".\filesystem_dispatcher.h" - > - </File> - <File - RelativePath=".\filesystem_interception.cc" - > - </File> - <File - RelativePath=".\filesystem_interception.h" - > - </File> - <File - RelativePath=".\filesystem_policy.cc" - > - </File> - <File - RelativePath=".\filesystem_policy.h" - > - </File> - <File - RelativePath=".\named_pipe_dispatcher.cc" - > - </File> - <File - RelativePath=".\named_pipe_dispatcher.h" - > - </File> - <File - RelativePath=".\named_pipe_interception.cc" - > - </File> - <File - RelativePath=".\named_pipe_interception.h" - > - </File> - <File - RelativePath=".\named_pipe_policy.cc" - > - </File> - <File - RelativePath=".\named_pipe_policy.h" - > - </File> - <File - RelativePath=".\policy_params.h" - > - </File> - <File - RelativePath=".\process_thread_dispatcher.cc" - > - </File> - <File - RelativePath=".\process_thread_dispatcher.h" - > - </File> - <File - RelativePath=".\process_thread_interception.cc" - > - </File> - <File - RelativePath=".\process_thread_interception.h" - > - </File> - <File - RelativePath=".\process_thread_policy.cc" - > - </File> - <File - RelativePath=".\process_thread_policy.h" - > - </File> - <File - RelativePath=".\registry_dispatcher.cc" - > - </File> - <File - RelativePath=".\registry_dispatcher.h" - > - </File> - <File - RelativePath=".\registry_interception.cc" - > - </File> - <File - RelativePath=".\registry_interception.h" - > - </File> - <File - RelativePath=".\registry_policy.cc" - > - </File> - <File - RelativePath=".\registry_policy.h" - > - </File> - <File - RelativePath=".\sync_dispatcher.cc" - > - </File> - <File - RelativePath=".\sync_dispatcher.h" - > - </File> - <File - RelativePath=".\sync_interception.cc" - > - </File> - <File - RelativePath=".\sync_interception.h" - > - </File> - <File - RelativePath=".\sync_policy.cc" - > - </File> - <File - RelativePath=".\sync_policy.h" - > - </File> - </Filter> - <Filter - Name="IPC" - > - <File - RelativePath=".\crosscall_client.h" - > - </File> - <File - RelativePath=".\crosscall_params.h" - > - </File> - <File - RelativePath=".\crosscall_server.cc" - > - </File> - <File - RelativePath=".\crosscall_server.h" - > - </File> - <File - RelativePath=".\ipc_tags.h" - > - </File> - <File - RelativePath=".\sharedmem_ipc_client.cc" - > - </File> - <File - RelativePath=".\sharedmem_ipc_client.h" - > - </File> - <File - RelativePath=".\sharedmem_ipc_server.cc" - > - </File> - <File - RelativePath=".\sharedmem_ipc_server.h" - > - </File> - </Filter> - <Filter - Name="Policy_base" - > - <File - RelativePath=".\policy_engine_opcodes.cc" - > - </File> - <File - RelativePath=".\policy_engine_opcodes.h" - > - </File> - <File - RelativePath=".\policy_engine_params.h" - > - </File> - <File - RelativePath=".\policy_engine_processor.cc" - > - </File> - <File - RelativePath=".\policy_engine_processor.h" - > - </File> - <File - RelativePath=".\policy_low_level.cc" - > - </File> - <File - RelativePath=".\policy_low_level.h" - > - </File> - <File - RelativePath=".\sandbox_policy_base.cc" - > - </File> - <File - RelativePath=".\sandbox_policy_base.h" - > - </File> - </Filter> - <File - RelativePath=".\broker_services.cc" - > - </File> - <File - RelativePath=".\broker_services.h" - > - </File> - <File - RelativePath=".\internal_types.h" - > - </File> - <File - RelativePath=".\policy_broker.cc" - > - </File> - <File - RelativePath=".\policy_broker.h" - > - </File> - <File - RelativePath=".\sandbox.cc" - > - </File> - <File - RelativePath=".\sandbox.h" - > - </File> - <File - RelativePath=".\sandbox_factory.h" - > - </File> - <File - RelativePath=".\sandbox_policy.h" - > - </File> - <File - RelativePath=".\sandbox_types.h" - > - </File> - <File - RelativePath=".\sandbox_utils.cc" - > - </File> - <File - RelativePath=".\sandbox_utils.h" - > - </File> - <File - RelativePath=".\shared_handles.cc" - > - </File> - <File - RelativePath=".\shared_handles.h" - > - </File> - <File - RelativePath=".\stdafx.cc" - > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - UsePrecompiledHeader="1" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - UsePrecompiledHeader="0" - /> - </FileConfiguration> - </File> - <File - RelativePath=".\stdafx.h" - > - </File> - <File - RelativePath=".\target_process.cc" - > - </File> - <File - RelativePath=".\target_process.h" - > - </File> - <File - RelativePath=".\target_services.cc" - > - </File> - <File - RelativePath=".\target_services.h" - > - </File> - <File - RelativePath=".\win2k_threadpool.cc" - > - </File> - <File - RelativePath=".\win2k_threadpool.h" - > - </File> - <File - RelativePath=".\win_utils.cc" - > - </File> - <File - RelativePath=".\win_utils.h" - > - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_factory.h b/security/sandbox/chromium/sandbox/win/src/sandbox_factory.h deleted file mode 100644 index f5888ffcd..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_factory.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SANDBOX_FACTORY_H__ -#define SANDBOX_SRC_SANDBOX_FACTORY_H__ - -#include "base/macros.h" -#include "sandbox/win/src/sandbox.h" - -// SandboxFactory is a set of static methods to get access to the broker -// or target services object. Only one of the two methods (GetBrokerServices, -// GetTargetServices) will return a non-null pointer and that should be used -// as the indication that the process is the broker or the target: -// -// BrokerServices* broker_services = SandboxFactory::GetBrokerServices(); -// if (NULL != broker_services) { -// //we are the broker, call broker api here -// broker_services->Init(); -// } else { -// TargetServices* target_services = SandboxFactory::GetTargetServices(); -// if (NULL != target_services) { -// //we are the target, call target api here -// target_services->Init(); -// } -// -// The methods in this class are expected to be called from a single thread -// -// The Sandbox library needs to be linked against the main executable, but -// sometimes the API calls are issued from a DLL that loads into the exe -// process. These factory methods then need to be called from the main -// exe and the interface pointers then can be safely passed to the DLL where -// the Sandbox API calls are made. -namespace sandbox { - -class SandboxFactory { - public: - // Returns the Broker API interface, returns NULL if this process is the - // target. - static BrokerServices* GetBrokerServices(); - - // Returns the Target API interface, returns NULL if this process is the - // broker. - static TargetServices* GetTargetServices(); - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxFactory); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_SANDBOX_FACTORY_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_globals.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_globals.cc deleted file mode 100644 index b4ab52392..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_globals.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <windows.h> - -#include "sandbox/win/src/sandbox_nt_types.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace sandbox { - -// The section for IPC and policy. -SANDBOX_INTERCEPT HANDLE g_shared_section = NULL; - -// This is the list of all imported symbols from ntdll.dll. -SANDBOX_INTERCEPT NtExports g_nt = {}; - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_types.h b/security/sandbox/chromium/sandbox/win/src/sandbox_nt_types.h deleted file mode 100644 index a4a88bba7..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_types.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SANDBOX_NT_TYPES_H__ -#define SANDBOX_SRC_SANDBOX_NT_TYPES_H__ - -#include "sandbox/win/src/nt_internals.h" - -namespace sandbox { - -struct NtExports { - NtAllocateVirtualMemoryFunction AllocateVirtualMemory; - NtCloseFunction Close; - NtDuplicateObjectFunction DuplicateObject; - NtFreeVirtualMemoryFunction FreeVirtualMemory; - NtMapViewOfSectionFunction MapViewOfSection; - NtProtectVirtualMemoryFunction ProtectVirtualMemory; - NtQueryInformationProcessFunction QueryInformationProcess; - NtQueryObjectFunction QueryObject; - NtQuerySectionFunction QuerySection; - NtQueryVirtualMemoryFunction QueryVirtualMemory; - NtUnmapViewOfSectionFunction UnmapViewOfSection; - RtlAllocateHeapFunction RtlAllocateHeap; - RtlAnsiStringToUnicodeStringFunction RtlAnsiStringToUnicodeString; - RtlCompareUnicodeStringFunction RtlCompareUnicodeString; - RtlCreateHeapFunction RtlCreateHeap; - RtlCreateUserThreadFunction RtlCreateUserThread; - RtlDestroyHeapFunction RtlDestroyHeap; - RtlFreeHeapFunction RtlFreeHeap; - _strnicmpFunction _strnicmp; - strlenFunction strlen; - wcslenFunction wcslen; - memcpyFunction memcpy; -}; - -// This is the value used for the ntdll level allocator. -enum AllocationType { - NT_ALLOC, - NT_PAGE -}; - -} // namespace sandbox - - -#endif // SANDBOX_SRC_SANDBOX_NT_TYPES_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.cc deleted file mode 100644 index 62f2422ca..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.cc +++ /dev/null @@ -1,676 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sandbox_nt_util.h" - -#include <stddef.h> -#include <stdint.h> - -#include <string> - -#include "base/win/pe_image.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/target_services.h" - -namespace sandbox { - -// This is the list of all imported symbols from ntdll.dll. -SANDBOX_INTERCEPT NtExports g_nt; - -} // namespace sandbox - -namespace { - -#if defined(_WIN64) -void* AllocateNearTo(void* source, size_t size) { - using sandbox::g_nt; - - // Start with 1 GB above the source. - const size_t kOneGB = 0x40000000; - void* base = reinterpret_cast<char*>(source) + kOneGB; - SIZE_T actual_size = size; - ULONG_PTR zero_bits = 0; // Not the correct type if used. - ULONG type = MEM_RESERVE; - - NTSTATUS ret; - int attempts = 0; - for (; attempts < 41; attempts++) { - ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, zero_bits, - &actual_size, type, PAGE_READWRITE); - if (NT_SUCCESS(ret)) { - if (base < source || - base >= reinterpret_cast<char*>(source) + 4 * kOneGB) { - // We won't be able to patch this dll. - VERIFY_SUCCESS(g_nt.FreeVirtualMemory(NtCurrentProcess, &base, &size, - MEM_RELEASE)); - return NULL; - } - break; - } - - if (attempts == 30) { - // Try the first GB. - base = reinterpret_cast<char*>(source); - } else if (attempts == 40) { - // Try the highest available address. - base = NULL; - type |= MEM_TOP_DOWN; - } - - // Try 100 MB higher. - base = reinterpret_cast<char*>(base) + 100 * 0x100000; - } - - if (attempts == 41) - return NULL; - - ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, zero_bits, - &actual_size, MEM_COMMIT, PAGE_READWRITE); - - if (!NT_SUCCESS(ret)) { - VERIFY_SUCCESS(g_nt.FreeVirtualMemory(NtCurrentProcess, &base, &size, - MEM_RELEASE)); - base = NULL; - } - - return base; -} -#else // defined(_WIN64). -void* AllocateNearTo(void* source, size_t size) { - using sandbox::g_nt; - - // In 32-bit processes allocations below 512k are predictable, so mark - // anything in that range as reserved and retry until we get a good address. - const void* const kMinAddress = reinterpret_cast<void*>(512 * 1024); - NTSTATUS ret; - SIZE_T actual_size; - void* base; - do { - base = NULL; - actual_size = 64 * 1024; - ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, 0, &actual_size, - MEM_RESERVE, PAGE_NOACCESS); - if (!NT_SUCCESS(ret)) - return NULL; - } while (base < kMinAddress); - - actual_size = size; - ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, 0, &actual_size, - MEM_COMMIT, PAGE_READWRITE); - if (!NT_SUCCESS(ret)) - return NULL; - return base; -} -#endif // defined(_WIN64). - -} // namespace. - -namespace sandbox { - -// Handle for our private heap. -void* g_heap = NULL; - -SANDBOX_INTERCEPT HANDLE g_shared_section; -SANDBOX_INTERCEPT size_t g_shared_IPC_size = 0; -SANDBOX_INTERCEPT size_t g_shared_policy_size = 0; - -void* volatile g_shared_policy_memory = NULL; -void* volatile g_shared_IPC_memory = NULL; - -// Both the IPC and the policy share a single region of memory in which the IPC -// memory is first and the policy memory is last. -bool MapGlobalMemory() { - if (NULL == g_shared_IPC_memory) { - void* memory = NULL; - SIZE_T size = 0; - // Map the entire shared section from the start. - NTSTATUS ret = g_nt.MapViewOfSection(g_shared_section, NtCurrentProcess, - &memory, 0, 0, NULL, &size, ViewUnmap, - 0, PAGE_READWRITE); - - if (!NT_SUCCESS(ret) || NULL == memory) { - NOTREACHED_NT(); - return false; - } - - if (NULL != _InterlockedCompareExchangePointer(&g_shared_IPC_memory, - memory, NULL)) { - // Somebody beat us to the memory setup. - VERIFY_SUCCESS(g_nt.UnmapViewOfSection(NtCurrentProcess, memory)); - } - DCHECK_NT(g_shared_IPC_size > 0); - g_shared_policy_memory = reinterpret_cast<char*>(g_shared_IPC_memory) - + g_shared_IPC_size; - } - DCHECK_NT(g_shared_policy_memory); - DCHECK_NT(g_shared_policy_size > 0); - return true; -} - -void* GetGlobalIPCMemory() { - if (!MapGlobalMemory()) - return NULL; - return g_shared_IPC_memory; -} - -void* GetGlobalPolicyMemory() { - if (!MapGlobalMemory()) - return NULL; - return g_shared_policy_memory; -} - -bool InitHeap() { - if (!g_heap) { - // Create a new heap using default values for everything. - void* heap = g_nt.RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL); - if (!heap) - return false; - - if (NULL != _InterlockedCompareExchangePointer(&g_heap, heap, NULL)) { - // Somebody beat us to the memory setup. - g_nt.RtlDestroyHeap(heap); - } - } - return (g_heap != NULL); -} - -// Physically reads or writes from memory to verify that (at this time), it is -// valid. Returns a dummy value. -int TouchMemory(void* buffer, size_t size_bytes, RequiredAccess intent) { - const int kPageSize = 4096; - int dummy = 0; - char* start = reinterpret_cast<char*>(buffer); - char* end = start + size_bytes - 1; - - if (WRITE == intent) { - for (; start < end; start += kPageSize) { - *start = 0; - } - *end = 0; - } else { - for (; start < end; start += kPageSize) { - dummy += *start; - } - dummy += *end; - } - - return dummy; -} - -bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) { - DCHECK_NT(size); - __try { - TouchMemory(buffer, size, intent); - } __except(EXCEPTION_EXECUTE_HANDLER) { - return false; - } - return true; -} - -NTSTATUS CopyData(void* destination, const void* source, size_t bytes) { - NTSTATUS ret = STATUS_SUCCESS; - __try { - g_nt.memcpy(destination, source, bytes); - } __except(EXCEPTION_EXECUTE_HANDLER) { - ret = GetExceptionCode(); - } - return ret; -} - -NTSTATUS AllocAndGetFullPath(HANDLE root, - wchar_t* path, - wchar_t** full_path) { - if (!InitHeap()) - return STATUS_NO_MEMORY; - - DCHECK_NT(full_path); - DCHECK_NT(path); - *full_path = NULL; - OBJECT_NAME_INFORMATION* handle_name = NULL; - NTSTATUS ret = STATUS_UNSUCCESSFUL; - __try { - do { - static NtQueryObjectFunction NtQueryObject = NULL; - if (!NtQueryObject) - ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject); - - ULONG size = 0; - // Query the name information a first time to get the size of the name. - ret = NtQueryObject(root, ObjectNameInformation, NULL, 0, &size); - - if (size) { - handle_name = reinterpret_cast<OBJECT_NAME_INFORMATION*>( - new(NT_ALLOC) BYTE[size]); - - // Query the name information a second time to get the name of the - // object referenced by the handle. - ret = NtQueryObject(root, ObjectNameInformation, handle_name, size, - &size); - } - - if (STATUS_SUCCESS != ret) - break; - - // Space for path + '\' + name + '\0'. - size_t name_length = handle_name->ObjectName.Length + - (wcslen(path) + 2) * sizeof(wchar_t); - *full_path = new(NT_ALLOC) wchar_t[name_length/sizeof(wchar_t)]; - if (NULL == *full_path) - break; - wchar_t* off = *full_path; - ret = CopyData(off, handle_name->ObjectName.Buffer, - handle_name->ObjectName.Length); - if (!NT_SUCCESS(ret)) - break; - off += handle_name->ObjectName.Length / sizeof(wchar_t); - *off = L'\\'; - off += 1; - ret = CopyData(off, path, wcslen(path) * sizeof(wchar_t)); - if (!NT_SUCCESS(ret)) - break; - off += wcslen(path); - *off = L'\0'; - } while (false); - } __except(EXCEPTION_EXECUTE_HANDLER) { - ret = GetExceptionCode(); - } - - if (!NT_SUCCESS(ret)) { - if (*full_path) { - operator delete(*full_path, NT_ALLOC); - *full_path = NULL; - } - if (handle_name) { - operator delete(handle_name, NT_ALLOC); - handle_name = NULL; - } - } - - return ret; -} - -// Hacky code... replace with AllocAndCopyObjectAttributes. -NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object, - wchar_t** out_name, - uint32_t* attributes, - HANDLE* root) { - if (!InitHeap()) - return STATUS_NO_MEMORY; - - DCHECK_NT(out_name); - *out_name = NULL; - NTSTATUS ret = STATUS_UNSUCCESSFUL; - __try { - do { - if (in_object->RootDirectory != static_cast<HANDLE>(0) && !root) - break; - if (NULL == in_object->ObjectName) - break; - if (NULL == in_object->ObjectName->Buffer) - break; - - size_t size = in_object->ObjectName->Length + sizeof(wchar_t); - *out_name = new(NT_ALLOC) wchar_t[size/sizeof(wchar_t)]; - if (NULL == *out_name) - break; - - ret = CopyData(*out_name, in_object->ObjectName->Buffer, - size - sizeof(wchar_t)); - if (!NT_SUCCESS(ret)) - break; - - (*out_name)[size / sizeof(wchar_t) - 1] = L'\0'; - - if (attributes) - *attributes = in_object->Attributes; - - if (root) - *root = in_object->RootDirectory; - ret = STATUS_SUCCESS; - } while (false); - } __except(EXCEPTION_EXECUTE_HANDLER) { - ret = GetExceptionCode(); - } - - if (!NT_SUCCESS(ret) && *out_name) { - operator delete(*out_name, NT_ALLOC); - *out_name = NULL; - } - - return ret; -} - -NTSTATUS GetProcessId(HANDLE process, DWORD *process_id) { - PROCESS_BASIC_INFORMATION proc_info; - ULONG bytes_returned; - - NTSTATUS ret = g_nt.QueryInformationProcess(process, ProcessBasicInformation, - &proc_info, sizeof(proc_info), - &bytes_returned); - if (!NT_SUCCESS(ret) || sizeof(proc_info) != bytes_returned) - return ret; - - *process_id = proc_info.UniqueProcessId; - return STATUS_SUCCESS; -} - -bool IsSameProcess(HANDLE process) { - if (NtCurrentProcess == process) - return true; - - static DWORD s_process_id = 0; - - if (!s_process_id) { - NTSTATUS ret = GetProcessId(NtCurrentProcess, &s_process_id); - if (!NT_SUCCESS(ret)) - return false; - } - - DWORD process_id; - NTSTATUS ret = GetProcessId(process, &process_id); - if (!NT_SUCCESS(ret)) - return false; - - return (process_id == s_process_id); -} - -bool IsValidImageSection(HANDLE section, PVOID *base, PLARGE_INTEGER offset, - PSIZE_T view_size) { - if (!section || !base || !view_size || offset) - return false; - - HANDLE query_section; - - NTSTATUS ret = g_nt.DuplicateObject(NtCurrentProcess, section, - NtCurrentProcess, &query_section, - SECTION_QUERY, 0, 0); - if (!NT_SUCCESS(ret)) - return false; - - SECTION_BASIC_INFORMATION basic_info; - SIZE_T bytes_returned; - ret = g_nt.QuerySection(query_section, SectionBasicInformation, &basic_info, - sizeof(basic_info), &bytes_returned); - - VERIFY_SUCCESS(g_nt.Close(query_section)); - - if (!NT_SUCCESS(ret) || sizeof(basic_info) != bytes_returned) - return false; - - if (!(basic_info.Attributes & SEC_IMAGE)) - return false; - - return true; -} - -UNICODE_STRING* AnsiToUnicode(const char* string) { - ANSI_STRING ansi_string; - ansi_string.Length = static_cast<USHORT>(g_nt.strlen(string)); - ansi_string.MaximumLength = ansi_string.Length + 1; - ansi_string.Buffer = const_cast<char*>(string); - - if (ansi_string.Length > ansi_string.MaximumLength) - return NULL; - - size_t name_bytes = ansi_string.MaximumLength * sizeof(wchar_t) + - sizeof(UNICODE_STRING); - - UNICODE_STRING* out_string = reinterpret_cast<UNICODE_STRING*>( - new(NT_ALLOC) char[name_bytes]); - if (!out_string) - return NULL; - - out_string->MaximumLength = ansi_string.MaximumLength * sizeof(wchar_t); - out_string->Buffer = reinterpret_cast<wchar_t*>(&out_string[1]); - - BOOLEAN alloc_destination = FALSE; - NTSTATUS ret = g_nt.RtlAnsiStringToUnicodeString(out_string, &ansi_string, - alloc_destination); - DCHECK_NT(STATUS_BUFFER_OVERFLOW != ret); - if (!NT_SUCCESS(ret)) { - operator delete(out_string, NT_ALLOC); - return NULL; - } - - return out_string; -} - -UNICODE_STRING* GetImageInfoFromModule(HMODULE module, uint32_t* flags) { - // PEImage's dtor won't be run during SEH unwinding, but that's OK. -#pragma warning(push) -#pragma warning(disable: 4509) - UNICODE_STRING* out_name = NULL; - __try { - do { - *flags = 0; - base::win::PEImage pe(module); - - if (!pe.VerifyMagic()) - break; - *flags |= MODULE_IS_PE_IMAGE; - - PIMAGE_EXPORT_DIRECTORY exports = pe.GetExportDirectory(); - if (exports) { - char* name = reinterpret_cast<char*>(pe.RVAToAddr(exports->Name)); - out_name = AnsiToUnicode(name); - } - - PIMAGE_NT_HEADERS headers = pe.GetNTHeaders(); - if (headers) { - if (headers->OptionalHeader.AddressOfEntryPoint) - *flags |= MODULE_HAS_ENTRY_POINT; - if (headers->OptionalHeader.SizeOfCode) - *flags |= MODULE_HAS_CODE; - } - } while (false); - } __except(EXCEPTION_EXECUTE_HANDLER) { - } - - return out_name; -#pragma warning(pop) -} - -UNICODE_STRING* GetBackingFilePath(PVOID address) { - // We'll start with something close to max_path charactes for the name. - SIZE_T buffer_bytes = MAX_PATH * 2; - - for (;;) { - MEMORY_SECTION_NAME* section_name = reinterpret_cast<MEMORY_SECTION_NAME*>( - new(NT_ALLOC) char[buffer_bytes]); - - if (!section_name) - return NULL; - - SIZE_T returned_bytes; - NTSTATUS ret = g_nt.QueryVirtualMemory(NtCurrentProcess, address, - MemorySectionName, section_name, - buffer_bytes, &returned_bytes); - - if (STATUS_BUFFER_OVERFLOW == ret) { - // Retry the call with the given buffer size. - operator delete(section_name, NT_ALLOC); - section_name = NULL; - buffer_bytes = returned_bytes; - continue; - } - if (!NT_SUCCESS(ret)) { - operator delete(section_name, NT_ALLOC); - return NULL; - } - - return reinterpret_cast<UNICODE_STRING*>(section_name); - } -} - -UNICODE_STRING* ExtractModuleName(const UNICODE_STRING* module_path) { - if ((!module_path) || (!module_path->Buffer)) - return NULL; - - wchar_t* sep = NULL; - int start_pos = module_path->Length / sizeof(wchar_t) - 1; - int ix = start_pos; - - for (; ix >= 0; --ix) { - if (module_path->Buffer[ix] == L'\\') { - sep = &module_path->Buffer[ix]; - break; - } - } - - // Ends with path separator. Not a valid module name. - if ((ix == start_pos) && sep) - return NULL; - - // No path separator found. Use the entire name. - if (!sep) { - sep = &module_path->Buffer[-1]; - } - - // Add one to the size so we can null terminate the string. - size_t size_bytes = (start_pos - ix + 1) * sizeof(wchar_t); - - // Based on the code above, size_bytes should always be small enough - // to make the static_cast below safe. - DCHECK_NT(UINT16_MAX > size_bytes); - char* str_buffer = new(NT_ALLOC) char[size_bytes + sizeof(UNICODE_STRING)]; - if (!str_buffer) - return NULL; - - UNICODE_STRING* out_string = reinterpret_cast<UNICODE_STRING*>(str_buffer); - out_string->Buffer = reinterpret_cast<wchar_t*>(&out_string[1]); - out_string->Length = static_cast<USHORT>(size_bytes - sizeof(wchar_t)); - out_string->MaximumLength = static_cast<USHORT>(size_bytes); - - NTSTATUS ret = CopyData(out_string->Buffer, &sep[1], out_string->Length); - if (!NT_SUCCESS(ret)) { - operator delete(out_string, NT_ALLOC); - return NULL; - } - - out_string->Buffer[out_string->Length / sizeof(wchar_t)] = L'\0'; - return out_string; -} - -NTSTATUS AutoProtectMemory::ChangeProtection(void* address, size_t bytes, - ULONG protect) { - DCHECK_NT(!changed_); - SIZE_T new_bytes = bytes; - NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address, - &new_bytes, protect, &old_protect_); - if (NT_SUCCESS(ret)) { - changed_ = true; - address_ = address; - bytes_ = new_bytes; - } - - return ret; -} - -NTSTATUS AutoProtectMemory::RevertProtection() { - if (!changed_) - return STATUS_SUCCESS; - - DCHECK_NT(address_); - DCHECK_NT(bytes_); - - SIZE_T new_bytes = bytes_; - NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address_, - &new_bytes, old_protect_, - &old_protect_); - DCHECK_NT(NT_SUCCESS(ret)); - - changed_ = false; - address_ = NULL; - bytes_ = 0; - old_protect_ = 0; - - return ret; -} - -bool IsSupportedRenameCall(FILE_RENAME_INFORMATION* file_info, - DWORD length, - uint32_t file_info_class) { - if (FileRenameInformation != file_info_class) - return false; - - if (length < sizeof(FILE_RENAME_INFORMATION)) - return false; - - // Make sure file name length doesn't exceed the message length - if (length - offsetof(FILE_RENAME_INFORMATION, FileName) < - file_info->FileNameLength) - return false; - - // We don't support a root directory. - if (file_info->RootDirectory) - return false; - - static const wchar_t kPathPrefix[] = { L'\\', L'?', L'?', L'\\'}; - - // Check if it starts with \\??\\. We don't support relative paths. - if (file_info->FileNameLength < sizeof(kPathPrefix) || - file_info->FileNameLength > UINT16_MAX) - return false; - - if (file_info->FileName[0] != kPathPrefix[0] || - file_info->FileName[1] != kPathPrefix[1] || - file_info->FileName[2] != kPathPrefix[2] || - file_info->FileName[3] != kPathPrefix[3]) - return false; - - return true; -} - -} // namespace sandbox - -void* operator new(size_t size, sandbox::AllocationType type, - void* near_to) { - void* result = NULL; - if (type == sandbox::NT_ALLOC) { - if (sandbox::InitHeap()) { - // Use default flags for the allocation. - result = sandbox::g_nt.RtlAllocateHeap(sandbox::g_heap, 0, size); - } - } else if (type == sandbox::NT_PAGE) { - result = AllocateNearTo(near_to, size); - } else { - NOTREACHED_NT(); - } - - // TODO: Returning NULL from operator new has undefined behavior, but - // the Allocate() functions called above can return NULL. Consider checking - // for NULL here and crashing or throwing. - - return result; -} - -void operator delete(void* memory, sandbox::AllocationType type) { - if (type == sandbox::NT_ALLOC) { - // Use default flags. - VERIFY(sandbox::g_nt.RtlFreeHeap(sandbox::g_heap, 0, memory)); - } else if (type == sandbox::NT_PAGE) { - void* base = memory; - SIZE_T size = 0; - VERIFY_SUCCESS(sandbox::g_nt.FreeVirtualMemory(NtCurrentProcess, &base, - &size, MEM_RELEASE)); - } else { - NOTREACHED_NT(); - } -} - -void operator delete(void* memory, - sandbox::AllocationType type, - void* near_to) { - operator delete(memory, type); -} - -void* __cdecl operator new(size_t size, - void* buffer, - sandbox::AllocationType type) { - return buffer; -} - -void __cdecl operator delete(void* memory, - void* buffer, - sandbox::AllocationType type) {} diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.h b/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.h deleted file mode 100644 index 3e0238206..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SANDBOX_NT_UTIL_H_ -#define SANDBOX_SRC_SANDBOX_NT_UTIL_H_ - -#include <intrin.h> -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_nt_types.h" - -// Placement new and delete to be used from ntdll interception code. -void* __cdecl operator new(size_t size, sandbox::AllocationType type, - void* near_to = NULL); -void __cdecl operator delete(void* memory, sandbox::AllocationType type); -// Add operator delete that matches the placement form of the operator new -// above. This is required by compiler to generate code to call operator delete -// in case the object's constructor throws an exception. -// See http://msdn.microsoft.com/en-us/library/cxdxz3x6.aspx -void __cdecl operator delete(void* memory, sandbox::AllocationType type, - void* near_to); - -// Regular placement new and delete -void* __cdecl operator new(size_t size, void* buffer, - sandbox::AllocationType type); -void __cdecl operator delete(void* memory, void* buffer, - sandbox::AllocationType type); - -// DCHECK_NT is defined to be pretty much an assert at this time because we -// don't have logging from the ntdll layer on the child. -// -// VERIFY_NT and VERIFY_SUCCESS are the standard asserts on debug, but -// execute the actual argument on release builds. VERIFY_NT expects an action -// returning a bool, while VERIFY_SUCCESS expects an action returning -// NTSTATUS. -#ifndef NDEBUG -#define DCHECK_NT(condition) { (condition) ? (void)0 : __debugbreak(); } -#define VERIFY(action) DCHECK_NT(action) -#define VERIFY_SUCCESS(action) DCHECK_NT(NT_SUCCESS(action)) -#else -#define DCHECK_NT(condition) -#define VERIFY(action) (action) -#define VERIFY_SUCCESS(action) (action) -#endif - -#define CHECK_NT(condition) { (condition) ? (void)0 : __debugbreak(); } - -#define NOTREACHED_NT() DCHECK_NT(false) - -namespace sandbox { - -#if defined(_M_X64) -#pragma intrinsic(_InterlockedCompareExchange) -#pragma intrinsic(_InterlockedCompareExchangePointer) - -#elif defined(_M_IX86) -extern "C" long _InterlockedCompareExchange(long volatile* destination, - long exchange, long comperand); - -#pragma intrinsic(_InterlockedCompareExchange) - -// We want to make sure that we use an intrinsic version of the function, not -// the one provided by kernel32. -__forceinline void* _InterlockedCompareExchangePointer( - void* volatile* destination, void* exchange, void* comperand) { - size_t ret = _InterlockedCompareExchange( - reinterpret_cast<long volatile*>(destination), - static_cast<long>(reinterpret_cast<size_t>(exchange)), - static_cast<long>(reinterpret_cast<size_t>(comperand))); - - return reinterpret_cast<void*>(static_cast<size_t>(ret)); -} - -#else -#error Architecture not supported. - -#endif - -// Returns a pointer to the IPC shared memory. -void* GetGlobalIPCMemory(); - -// Returns a pointer to the Policy shared memory. -void* GetGlobalPolicyMemory(); - -enum RequiredAccess { - READ, - WRITE -}; - -// Performs basic user mode buffer validation. In any case, buffers access must -// be protected by SEH. intent specifies if the buffer should be tested for read -// or write. -// Note that write intent implies destruction of the buffer content (we actually -// write) -bool ValidParameter(void* buffer, size_t size, RequiredAccess intent); - -// Copies data from a user buffer to our buffer. Returns the operation status. -NTSTATUS CopyData(void* destination, const void* source, size_t bytes); - -// Copies the name from an object attributes. -NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object, - wchar_t** out_name, - uint32_t* attributes, - HANDLE* root); - -// Determine full path name from object root and path. -NTSTATUS AllocAndGetFullPath(HANDLE root, - wchar_t* path, - wchar_t** full_path); - -// Initializes our ntdll level heap -bool InitHeap(); - -// Returns true if the provided handle refers to the current process. -bool IsSameProcess(HANDLE process); - -enum MappedModuleFlags { - MODULE_IS_PE_IMAGE = 1, // Module is an executable. - MODULE_HAS_ENTRY_POINT = 2, // Execution entry point found. - MODULE_HAS_CODE = 4 // Non zero size of executable sections. -}; - -// Returns the name and characteristics for a given PE module. The return -// value is the name as defined by the export table and the flags is any -// combination of the MappedModuleFlags enumeration. -// -// The returned buffer must be freed with a placement delete from the ntdll -// level allocator: -// -// UNICODE_STRING* name = GetPEImageInfoFromModule(HMODULE module, &flags); -// if (!name) { -// // probably not a valid dll -// return; -// } -// InsertYourLogicHere(name); -// operator delete(name, NT_ALLOC); -UNICODE_STRING* GetImageInfoFromModule(HMODULE module, uint32_t* flags); - -// Returns the full path and filename for a given dll. -// May return NULL if the provided address is not backed by a named section, or -// if the current OS version doesn't support the call. The returned buffer must -// be freed with a placement delete (see GetImageNameFromModule example). -UNICODE_STRING* GetBackingFilePath(PVOID address); - -// Returns the last component of a path that contains the module name. -// It will return NULL if the path ends with the path separator. The returned -// buffer must be freed with a placement delete (see GetImageNameFromModule -// example). -UNICODE_STRING* ExtractModuleName(const UNICODE_STRING* module_path); - -// Returns true if the parameters correspond to a dll mapped as code. -bool IsValidImageSection(HANDLE section, PVOID *base, PLARGE_INTEGER offset, - PSIZE_T view_size); - -// Converts an ansi string to an UNICODE_STRING. -UNICODE_STRING* AnsiToUnicode(const char* string); - -// Provides a simple way to temporarily change the protection of a memory page. -class AutoProtectMemory { - public: - AutoProtectMemory() - : changed_(false), address_(NULL), bytes_(0), old_protect_(0) {} - - ~AutoProtectMemory() { - RevertProtection(); - } - - // Sets the desired protection of a given memory range. - NTSTATUS ChangeProtection(void* address, size_t bytes, ULONG protect); - - // Restores the original page protection. - NTSTATUS RevertProtection(); - - private: - bool changed_; - void* address_; - size_t bytes_; - ULONG old_protect_; - - DISALLOW_COPY_AND_ASSIGN(AutoProtectMemory); -}; - -// Returns true if the file_rename_information structure is supported by our -// rename handler. -bool IsSupportedRenameCall(FILE_RENAME_INFORMATION* file_info, - DWORD length, - uint32_t file_info_class); - -} // namespace sandbox - - -#endif // SANDBOX_SRC_SANDBOX_NT_UTIL_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h deleted file mode 100644 index cc39c6283..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_SANDBOX_POLICY_H_ -#define SANDBOX_WIN_SRC_SANDBOX_POLICY_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <string> - -#include "base/strings/string16.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/security_level.h" - -namespace sandbox { - -class TargetPolicy { - public: - // Windows subsystems that can have specific rules. - // Note: The process subsystem(SUBSY_PROCESS) does not evaluate the request - // exactly like the CreateProcess API does. See the comment at the top of - // process_thread_dispatcher.cc for more details. - enum SubSystem { - SUBSYS_FILES, // Creation and opening of files and pipes. - SUBSYS_NAMED_PIPES, // Creation of named pipes. - SUBSYS_PROCESS, // Creation of child processes. - SUBSYS_REGISTRY, // Creation and opening of registry keys. - SUBSYS_SYNC, // Creation of named sync objects. - SUBSYS_HANDLES, // Duplication of handles to other processes. - SUBSYS_WIN32K_LOCKDOWN // Win32K Lockdown related policy. - }; - - // Allowable semantics when a rule is matched. - enum Semantics { - FILES_ALLOW_ANY, // Allows open or create for any kind of access that - // the file system supports. - FILES_ALLOW_READONLY, // Allows open or create with read access only. - FILES_ALLOW_QUERY, // Allows access to query the attributes of a file. - FILES_ALLOW_DIR_ANY, // Allows open or create with directory semantics - // only. - HANDLES_DUP_ANY, // Allows duplicating handles opened with any - // access permissions. - HANDLES_DUP_BROKER, // Allows duplicating handles to the broker process. - NAMEDPIPES_ALLOW_ANY, // Allows creation of a named pipe. - PROCESS_MIN_EXEC, // Allows to create a process with minimal rights - // over the resulting process and thread handles. - // No other parameters besides the command line are - // passed to the child process. - PROCESS_ALL_EXEC, // Allows the creation of a process and return fill - // access on the returned handles. - // This flag can be used only when the main token of - // the sandboxed application is at least INTERACTIVE. - EVENTS_ALLOW_ANY, // Allows the creation of an event with full access. - EVENTS_ALLOW_READONLY, // Allows opening an even with synchronize access. - REG_ALLOW_READONLY, // Allows readonly access to a registry key. - REG_ALLOW_ANY, // Allows read and write access to a registry key. - FAKE_USER_GDI_INIT // Fakes user32 and gdi32 initialization. This can - // be used to allow the DLLs to load and initialize - // even if the process cannot access that subsystem. - }; - - // Increments the reference count of this object. The reference count must - // be incremented if this interface is given to another component. - virtual void AddRef() = 0; - - // Decrements the reference count of this object. When the reference count - // is zero the object is automatically destroyed. - // Indicates that the caller is done with this interface. After calling - // release no other method should be called. - virtual void Release() = 0; - - // Sets the security level for the target process' two tokens. - // This setting is permanent and cannot be changed once the target process is - // spawned. - // initial: the security level for the initial token. This is the token that - // is used by the process from the creation of the process until the moment - // the process calls TargetServices::LowerToken() or the process calls - // win32's RevertToSelf(). Once this happens the initial token is no longer - // available and the lockdown token is in effect. Using an initial token is - // not compatible with AppContainer, see SetAppContainer. - // lockdown: the security level for the token that comes into force after the - // process calls TargetServices::LowerToken() or the process calls - // RevertToSelf(). See the explanation of each level in the TokenLevel - // definition. - // Return value: SBOX_ALL_OK if the setting succeeds and false otherwise. - // Returns false if the lockdown value is more permissive than the initial - // value. - // - // Important: most of the sandbox-provided security relies on this single - // setting. The caller should strive to set the lockdown level as restricted - // as possible. - virtual ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) = 0; - - // Returns the initial token level. - virtual TokenLevel GetInitialTokenLevel() const = 0; - - // Returns the lockdown token level. - virtual TokenLevel GetLockdownTokenLevel() const = 0; - - // Sets the security level of the Job Object to which the target process will - // belong. This setting is permanent and cannot be changed once the target - // process is spawned. The job controls the global security settings which - // can not be specified in the token security profile. - // job_level: the security level for the job. See the explanation of each - // level in the JobLevel definition. - // ui_exceptions: specify what specific rights that are disabled in the - // chosen job_level that need to be granted. Use this parameter to avoid - // selecting the next permissive job level unless you need all the rights - // that are granted in such level. - // The exceptions can be specified as a combination of the following - // constants: - // JOB_OBJECT_UILIMIT_HANDLES : grant access to all user-mode handles. These - // include windows, icons, menus and various GDI objects. In addition the - // target process can set hooks, and broadcast messages to other processes - // that belong to the same desktop. - // JOB_OBJECT_UILIMIT_READCLIPBOARD : grant read-only access to the clipboard. - // JOB_OBJECT_UILIMIT_WRITECLIPBOARD : grant write access to the clipboard. - // JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS : allow changes to the system-wide - // parameters as defined by the Win32 call SystemParametersInfo(). - // JOB_OBJECT_UILIMIT_DISPLAYSETTINGS : allow programmatic changes to the - // display settings. - // JOB_OBJECT_UILIMIT_GLOBALATOMS : allow access to the global atoms table. - // JOB_OBJECT_UILIMIT_DESKTOP : allow the creation of new desktops. - // JOB_OBJECT_UILIMIT_EXITWINDOWS : allow the call to ExitWindows(). - // - // Return value: SBOX_ALL_OK if the setting succeeds and false otherwise. - // - // Note: JOB_OBJECT_XXXX constants are defined in winnt.h and documented at - // length in: - // http://msdn2.microsoft.com/en-us/library/ms684152.aspx - // - // Note: the recommended level is JOB_RESTRICTED or JOB_LOCKDOWN. - virtual ResultCode SetJobLevel(JobLevel job_level, - uint32_t ui_exceptions) = 0; - - // Sets a hard limit on the size of the commit set for the sandboxed process. - // If the limit is reached, the process will be terminated with - // SBOX_FATAL_MEMORY_EXCEEDED (7012). - virtual ResultCode SetJobMemoryLimit(size_t memory_limit) = 0; - - // Specifies the desktop on which the application is going to run. If the - // desktop does not exist, it will be created. If alternate_winstation is - // set to true, the desktop will be created on an alternate window station. - virtual ResultCode SetAlternateDesktop(bool alternate_winstation) = 0; - - // Returns the name of the alternate desktop used. If an alternate window - // station is specified, the name is prepended by the window station name, - // followed by a backslash. - virtual base::string16 GetAlternateDesktop() const = 0; - - // Precreates the desktop and window station, if any. - virtual ResultCode CreateAlternateDesktop(bool alternate_winstation) = 0; - - // Destroys the desktop and windows station. - virtual void DestroyAlternateDesktop() = 0; - - // Sets the integrity level of the process in the sandbox. Both the initial - // token and the main token will be affected by this. If the integrity level - // is set to a level higher than the current level, the sandbox will fail - // to start. - virtual ResultCode SetIntegrityLevel(IntegrityLevel level) = 0; - - // Returns the initial integrity level used. - virtual IntegrityLevel GetIntegrityLevel() const = 0; - - // Sets the integrity level of the process in the sandbox. The integrity level - // will not take effect before you call LowerToken. User Interface Privilege - // Isolation is not affected by this setting and will remain off for the - // process in the sandbox. If the integrity level is set to a level higher - // than the current level, the sandbox will fail to start. - virtual ResultCode SetDelayedIntegrityLevel(IntegrityLevel level) = 0; - - // Sets the AppContainer to be used for the sandboxed process. Any capability - // to be enabled for the process should be added before this method is invoked - // (by calling SetCapability() as many times as needed). - // The desired AppContainer must be already installed on the system, otherwise - // launching the sandboxed process will fail. See BrokerServices for details - // about installing an AppContainer. - // Note that currently Windows restricts the use of impersonation within - // AppContainers, so this function is incompatible with the use of an initial - // token. - virtual ResultCode SetAppContainer(const wchar_t* sid) = 0; - - // Sets a capability to be enabled for the sandboxed process' AppContainer. - virtual ResultCode SetCapability(const wchar_t* sid) = 0; - - // Sets the LowBox token for sandboxed process. This is mutually exclusive - // with SetAppContainer method. - virtual ResultCode SetLowBox(const wchar_t* sid) = 0; - - // Sets the mitigations enabled when the process is created. Most of these - // are implemented as attributes passed via STARTUPINFOEX. So they take - // effect before any thread in the target executes. The declaration of - // MitigationFlags is followed by a detailed description of each flag. - virtual ResultCode SetProcessMitigations(MitigationFlags flags) = 0; - - // Returns the currently set mitigation flags. - virtual MitigationFlags GetProcessMitigations() = 0; - - // Sets process mitigation flags that don't take effect before the call to - // LowerToken(). - virtual ResultCode SetDelayedProcessMitigations(MitigationFlags flags) = 0; - - // Returns the currently set delayed mitigation flags. - virtual MitigationFlags GetDelayedProcessMitigations() const = 0; - - // Sets the interceptions to operate in strict mode. By default, interceptions - // are performed in "relaxed" mode, where if something inside NTDLL.DLL is - // already patched we attempt to intercept it anyway. Setting interceptions - // to strict mode means that when we detect that the function is patched we'll - // refuse to perform the interception. - virtual void SetStrictInterceptions() = 0; - - // Set the handles the target process should inherit for stdout and - // stderr. The handles the caller passes must remain valid for the - // lifetime of the policy object. This only has an effect on - // Windows Vista and later versions. These methods accept pipe and - // file handles, but not console handles. - virtual ResultCode SetStdoutHandle(HANDLE handle) = 0; - virtual ResultCode SetStderrHandle(HANDLE handle) = 0; - - // Adds a policy rule effective for processes spawned using this policy. - // subsystem: One of the above enumerated windows subsystems. - // semantics: One of the above enumerated FileSemantics. - // pattern: A specific full path or a full path with wildcard patterns. - // The valid wildcards are: - // '*' : Matches zero or more character. Only one in series allowed. - // '?' : Matches a single character. One or more in series are allowed. - // Examples: - // "c:\\documents and settings\\vince\\*.dmp" - // "c:\\documents and settings\\*\\crashdumps\\*.dmp" - // "c:\\temp\\app_log_?????_chrome.txt" - virtual ResultCode AddRule(SubSystem subsystem, Semantics semantics, - const wchar_t* pattern) = 0; - - // Adds a dll that will be unloaded in the target process before it gets - // a chance to initialize itself. Typically, dlls that cause the target - // to crash go here. - virtual ResultCode AddDllToUnload(const wchar_t* dll_name) = 0; - - // Adds a handle that will be closed in the target process after lockdown. - // A NULL value for handle_name indicates all handles of the specified type. - // An empty string for handle_name indicates the handle is unnamed. - virtual ResultCode AddKernelObjectToClose(const wchar_t* handle_type, - const wchar_t* handle_name) = 0; - - // Adds a handle that will be shared with the target process. - // Returns the handle which was actually shared with the target. This is - // achieved by duplicating the handle to ensure that it is inheritable by - // the target. The caller should treat this as an opaque value. - virtual void* AddHandleToShare(HANDLE handle) = 0; -}; - -} // namespace sandbox - - -#endif // SANDBOX_WIN_SRC_SANDBOX_POLICY_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc deleted file mode 100644 index 28662b42d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc +++ /dev/null @@ -1,770 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sandbox_policy_base.h" - -#include <sddl.h> -#include <stddef.h> -#include <stdint.h> - -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/stl_util.h" -#include "base/strings/stringprintf.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/app_container.h" -#include "sandbox/win/src/filesystem_policy.h" -#include "sandbox/win/src/handle_policy.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/job.h" -#include "sandbox/win/src/named_pipe_policy.h" -#include "sandbox/win/src/policy_broker.h" -#include "sandbox/win/src/policy_engine_processor.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/process_mitigations.h" -#include "sandbox/win/src/process_mitigations_win32k_policy.h" -#include "sandbox/win/src/process_thread_policy.h" -#include "sandbox/win/src/registry_policy.h" -#include "sandbox/win/src/restricted_token_utils.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/sandbox_utils.h" -#include "sandbox/win/src/sync_policy.h" -#include "sandbox/win/src/target_process.h" -#include "sandbox/win/src/top_level_dispatcher.h" -#include "sandbox/win/src/window.h" - -namespace { - -// The standard windows size for one memory page. -const size_t kOneMemPage = 4096; -// The IPC and Policy shared memory sizes. -const size_t kIPCMemSize = kOneMemPage * 2; -const size_t kPolMemSize = kOneMemPage * 14; - -// Helper function to allocate space (on the heap) for policy. -sandbox::PolicyGlobal* MakeBrokerPolicyMemory() { - const size_t kTotalPolicySz = kPolMemSize; - sandbox::PolicyGlobal* policy = static_cast<sandbox::PolicyGlobal*> - (::operator new(kTotalPolicySz)); - DCHECK(policy); - memset(policy, 0, kTotalPolicySz); - policy->data_size = kTotalPolicySz - sizeof(sandbox::PolicyGlobal); - return policy; -} - -bool IsInheritableHandle(HANDLE handle) { - if (!handle) - return false; - if (handle == INVALID_HANDLE_VALUE) - return false; - // File handles (FILE_TYPE_DISK) and pipe handles are known to be - // inheritable. Console handles (FILE_TYPE_CHAR) are not - // inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST. - DWORD handle_type = GetFileType(handle); - return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE; -} - -HANDLE CreateLowBoxObjectDirectory(PSID lowbox_sid) { - DWORD session_id = 0; - if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &session_id)) - return NULL; - - LPWSTR sid_string = NULL; - if (!::ConvertSidToStringSid(lowbox_sid, &sid_string)) - return NULL; - - base::string16 directory_path = base::StringPrintf( - L"\\Sessions\\%d\\AppContainerNamedObjects\\%ls", - session_id, sid_string).c_str(); - ::LocalFree(sid_string); - - NtCreateDirectoryObjectFunction CreateObjectDirectory = NULL; - ResolveNTFunctionPtr("NtCreateDirectoryObject", &CreateObjectDirectory); - - OBJECT_ATTRIBUTES obj_attr; - UNICODE_STRING obj_name; - sandbox::InitObjectAttribs(directory_path, - OBJ_CASE_INSENSITIVE | OBJ_OPENIF, - NULL, - &obj_attr, - &obj_name, - NULL); - - HANDLE handle = NULL; - NTSTATUS status = CreateObjectDirectory(&handle, - DIRECTORY_ALL_ACCESS, - &obj_attr); - - if (!NT_SUCCESS(status)) - return NULL; - - return handle; -} - -} // namespace - -namespace sandbox { - -SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level; -SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations; - -// Initializes static members. -HWINSTA PolicyBase::alternate_winstation_handle_ = NULL; -HDESK PolicyBase::alternate_desktop_handle_ = NULL; -IntegrityLevel PolicyBase::alternate_desktop_integrity_level_label_ = - INTEGRITY_LEVEL_SYSTEM; - -PolicyBase::PolicyBase() - : ref_count(1), - lockdown_level_(USER_LOCKDOWN), - initial_level_(USER_LOCKDOWN), - job_level_(JOB_LOCKDOWN), - ui_exceptions_(0), - memory_limit_(0), - use_alternate_desktop_(false), - use_alternate_winstation_(false), - file_system_init_(false), - relaxed_interceptions_(true), - stdout_handle_(INVALID_HANDLE_VALUE), - stderr_handle_(INVALID_HANDLE_VALUE), - integrity_level_(INTEGRITY_LEVEL_LAST), - delayed_integrity_level_(INTEGRITY_LEVEL_LAST), - mitigations_(0), - delayed_mitigations_(0), - policy_maker_(NULL), - policy_(NULL), - lowbox_sid_(NULL) { - ::InitializeCriticalSection(&lock_); - dispatcher_.reset(new TopLevelDispatcher(this)); -} - -PolicyBase::~PolicyBase() { - ClearSharedHandles(); - - TargetSet::iterator it; - for (it = targets_.begin(); it != targets_.end(); ++it) { - TargetProcess* target = (*it); - delete target; - } - delete policy_maker_; - delete policy_; - - if (lowbox_sid_) - ::LocalFree(lowbox_sid_); - - ::DeleteCriticalSection(&lock_); -} - -void PolicyBase::AddRef() { - ::InterlockedIncrement(&ref_count); -} - -void PolicyBase::Release() { - if (0 == ::InterlockedDecrement(&ref_count)) - delete this; -} - -ResultCode PolicyBase::SetTokenLevel(TokenLevel initial, TokenLevel lockdown) { - if (initial < lockdown) { - return SBOX_ERROR_BAD_PARAMS; - } - initial_level_ = initial; - lockdown_level_ = lockdown; - return SBOX_ALL_OK; -} - -TokenLevel PolicyBase::GetInitialTokenLevel() const { - return initial_level_; -} - -TokenLevel PolicyBase::GetLockdownTokenLevel() const{ - return lockdown_level_; -} - -ResultCode PolicyBase::SetJobLevel(JobLevel job_level, uint32_t ui_exceptions) { - if (memory_limit_ && job_level == JOB_NONE) { - return SBOX_ERROR_BAD_PARAMS; - } - job_level_ = job_level; - ui_exceptions_ = ui_exceptions; - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::SetJobMemoryLimit(size_t memory_limit) { - if (memory_limit && job_level_ == JOB_NONE) { - return SBOX_ERROR_BAD_PARAMS; - } - memory_limit_ = memory_limit; - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::SetAlternateDesktop(bool alternate_winstation) { - use_alternate_desktop_ = true; - use_alternate_winstation_ = alternate_winstation; - return CreateAlternateDesktop(alternate_winstation); -} - -base::string16 PolicyBase::GetAlternateDesktop() const { - // No alternate desktop or winstation. Return an empty string. - if (!use_alternate_desktop_ && !use_alternate_winstation_) { - return base::string16(); - } - - // The desktop and winstation should have been created by now. - // If we hit this scenario, it means that the user ignored the failure - // during SetAlternateDesktop, so we ignore it here too. - if (use_alternate_desktop_ && !alternate_desktop_handle_) { - return base::string16(); - } - if (use_alternate_winstation_ && (!alternate_desktop_handle_ || - !alternate_winstation_handle_)) { - return base::string16(); - } - - return GetFullDesktopName(alternate_winstation_handle_, - alternate_desktop_handle_); -} - -ResultCode PolicyBase::CreateAlternateDesktop(bool alternate_winstation) { - if (alternate_winstation) { - // Previously called with alternate_winstation = false? - if (!alternate_winstation_handle_ && alternate_desktop_handle_) - return SBOX_ERROR_UNSUPPORTED; - - // Check if it's already created. - if (alternate_winstation_handle_ && alternate_desktop_handle_) - return SBOX_ALL_OK; - - DCHECK(!alternate_winstation_handle_); - // Create the window station. - ResultCode result = CreateAltWindowStation(&alternate_winstation_handle_); - if (SBOX_ALL_OK != result) - return result; - - // Verify that everything is fine. - if (!alternate_winstation_handle_ || - GetWindowObjectName(alternate_winstation_handle_).empty()) - return SBOX_ERROR_CANNOT_CREATE_DESKTOP; - - // Create the destkop. - result = CreateAltDesktop(alternate_winstation_handle_, - &alternate_desktop_handle_); - if (SBOX_ALL_OK != result) - return result; - - // Verify that everything is fine. - if (!alternate_desktop_handle_ || - GetWindowObjectName(alternate_desktop_handle_).empty()) - return SBOX_ERROR_CANNOT_CREATE_DESKTOP; - } else { - // Previously called with alternate_winstation = true? - if (alternate_winstation_handle_) - return SBOX_ERROR_UNSUPPORTED; - - // Check if it already exists. - if (alternate_desktop_handle_) - return SBOX_ALL_OK; - - // Create the destkop. - ResultCode result = CreateAltDesktop(NULL, &alternate_desktop_handle_); - if (SBOX_ALL_OK != result) - return result; - - // Verify that everything is fine. - if (!alternate_desktop_handle_ || - GetWindowObjectName(alternate_desktop_handle_).empty()) - return SBOX_ERROR_CANNOT_CREATE_DESKTOP; - } - - return SBOX_ALL_OK; -} - -void PolicyBase::DestroyAlternateDesktop() { - if (alternate_desktop_handle_) { - ::CloseDesktop(alternate_desktop_handle_); - alternate_desktop_handle_ = NULL; - } - - if (alternate_winstation_handle_) { - ::CloseWindowStation(alternate_winstation_handle_); - alternate_winstation_handle_ = NULL; - } -} - -ResultCode PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level) { - integrity_level_ = integrity_level; - return SBOX_ALL_OK; -} - -IntegrityLevel PolicyBase::GetIntegrityLevel() const { - return integrity_level_; -} - -ResultCode PolicyBase::SetDelayedIntegrityLevel( - IntegrityLevel integrity_level) { - delayed_integrity_level_ = integrity_level; - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::SetAppContainer(const wchar_t* sid) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return SBOX_ALL_OK; - - // SetLowBox and SetAppContainer are mutually exclusive. - if (lowbox_sid_) - return SBOX_ERROR_UNSUPPORTED; - - // Windows refuses to work with an impersonation token for a process inside - // an AppContainer. If the caller wants to use a more privileged initial - // token, or if the lockdown level will prevent the process from starting, - // we have to fail the operation. - if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) - return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; - - DCHECK(!appcontainer_list_.get()); - appcontainer_list_.reset(new AppContainerAttributes); - ResultCode rv = appcontainer_list_->SetAppContainer(sid, capabilities_); - if (rv != SBOX_ALL_OK) - return rv; - - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::SetCapability(const wchar_t* sid) { - capabilities_.push_back(sid); - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::SetLowBox(const wchar_t* sid) { - if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8) - return SBOX_ERROR_UNSUPPORTED; - - // SetLowBox and SetAppContainer are mutually exclusive. - if (appcontainer_list_.get()) - return SBOX_ERROR_UNSUPPORTED; - - DCHECK(sid); - - if (lowbox_sid_) - return SBOX_ERROR_BAD_PARAMS; - - if (!ConvertStringSidToSid(sid, &lowbox_sid_)) - return SBOX_ERROR_GENERIC; - - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::SetProcessMitigations( - MitigationFlags flags) { - if (!CanSetProcessMitigationsPreStartup(flags)) - return SBOX_ERROR_BAD_PARAMS; - mitigations_ = flags; - return SBOX_ALL_OK; -} - -MitigationFlags PolicyBase::GetProcessMitigations() { - return mitigations_; -} - -ResultCode PolicyBase::SetDelayedProcessMitigations( - MitigationFlags flags) { - if (!CanSetProcessMitigationsPostStartup(flags)) - return SBOX_ERROR_BAD_PARAMS; - delayed_mitigations_ = flags; - return SBOX_ALL_OK; -} - -MitigationFlags PolicyBase::GetDelayedProcessMitigations() const { - return delayed_mitigations_; -} - -void PolicyBase::SetStrictInterceptions() { - relaxed_interceptions_ = false; -} - -ResultCode PolicyBase::SetStdoutHandle(HANDLE handle) { - if (!IsInheritableHandle(handle)) - return SBOX_ERROR_BAD_PARAMS; - stdout_handle_ = handle; - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::SetStderrHandle(HANDLE handle) { - if (!IsInheritableHandle(handle)) - return SBOX_ERROR_BAD_PARAMS; - stderr_handle_ = handle; - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::AddRule(SubSystem subsystem, - Semantics semantics, - const wchar_t* pattern) { - ResultCode result = AddRuleInternal(subsystem, semantics, pattern); - LOG_IF(ERROR, result != SBOX_ALL_OK) << "Failed to add sandbox rule." - << " error = " << result - << ", subsystem = " << subsystem - << ", semantics = " << semantics - << ", pattern = '" << pattern << "'"; - return result; -} - -ResultCode PolicyBase::AddDllToUnload(const wchar_t* dll_name) { - blacklisted_dlls_.push_back(dll_name); - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::AddKernelObjectToClose(const base::char16* handle_type, - const base::char16* handle_name) { - return handle_closer_.AddHandle(handle_type, handle_name); -} - -void* PolicyBase::AddHandleToShare(HANDLE handle) { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return nullptr; - - if (!handle) - return nullptr; - - HANDLE duped_handle = nullptr; - if (!::DuplicateHandle(::GetCurrentProcess(), handle, ::GetCurrentProcess(), - &duped_handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - return nullptr; - } - handles_to_share_.push_back(new base::win::ScopedHandle(duped_handle)); - return duped_handle; -} - -const HandleList& PolicyBase::GetHandlesBeingShared() { - return handles_to_share_; -} - -void PolicyBase::ClearSharedHandles() { - STLDeleteElements(&handles_to_share_); -} - -ResultCode PolicyBase::MakeJobObject(base::win::ScopedHandle* job) { - if (job_level_ != JOB_NONE) { - // Create the windows job object. - Job job_obj; - DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_, - memory_limit_); - if (ERROR_SUCCESS != result) - return SBOX_ERROR_GENERIC; - - *job = job_obj.Take(); - } else { - *job = base::win::ScopedHandle(); - } - return SBOX_ALL_OK; -} - -ResultCode PolicyBase::MakeTokens(base::win::ScopedHandle* initial, - base::win::ScopedHandle* lockdown, - base::win::ScopedHandle* lowbox) { - if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer() && - lowbox_sid_) { - return SBOX_ERROR_BAD_PARAMS; - } - - // Create the 'naked' token. This will be the permanent token associated - // with the process and therefore with any thread that is not impersonating. - DWORD result = CreateRestrictedToken(lockdown_level_, integrity_level_, - PRIMARY, lockdown); - if (ERROR_SUCCESS != result) - return SBOX_ERROR_GENERIC; - - // If we're launching on the alternate desktop we need to make sure the - // integrity label on the object is no higher than the sandboxed process's - // integrity level. So, we lower the label on the desktop process if it's - // not already low enough for our process. - if (alternate_desktop_handle_ && use_alternate_desktop_ && - integrity_level_ != INTEGRITY_LEVEL_LAST && - alternate_desktop_integrity_level_label_ < integrity_level_ && - base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { - // Integrity label enum is reversed (higher level is a lower value). - static_assert(INTEGRITY_LEVEL_SYSTEM < INTEGRITY_LEVEL_UNTRUSTED, - "Integrity level ordering reversed."); - result = SetObjectIntegrityLabel(alternate_desktop_handle_, - SE_WINDOW_OBJECT, - L"", - GetIntegrityLevelString(integrity_level_)); - if (ERROR_SUCCESS != result) - return SBOX_ERROR_GENERIC; - - alternate_desktop_integrity_level_label_ = integrity_level_; - } - - // We are maintaining two mutually exclusive approaches. One is to start an - // AppContainer process through StartupInfoEx and other is replacing - // existing token with LowBox token after process creation. - if (appcontainer_list_.get() && appcontainer_list_->HasAppContainer()) { - // Windows refuses to work with an impersonation token. See SetAppContainer - // implementation for more details. - if (lockdown_level_ < USER_LIMITED || lockdown_level_ != initial_level_) - return SBOX_ERROR_CANNOT_INIT_APPCONTAINER; - - *initial = base::win::ScopedHandle(); - return SBOX_ALL_OK; - } - - if (lowbox_sid_) { - NtCreateLowBoxToken CreateLowBoxToken = NULL; - ResolveNTFunctionPtr("NtCreateLowBoxToken", &CreateLowBoxToken); - OBJECT_ATTRIBUTES obj_attr; - InitializeObjectAttributes(&obj_attr, NULL, 0, NULL, NULL); - HANDLE token_lowbox = NULL; - - if (!lowbox_directory_.IsValid()) - lowbox_directory_.Set(CreateLowBoxObjectDirectory(lowbox_sid_)); - DCHECK(lowbox_directory_.IsValid()); - - // The order of handles isn't important in the CreateLowBoxToken call. - // The kernel will maintain a reference to the object directory handle. - HANDLE saved_handles[1] = {lowbox_directory_.Get()}; - DWORD saved_handles_count = lowbox_directory_.IsValid() ? 1 : 0; - - NTSTATUS status = CreateLowBoxToken(&token_lowbox, lockdown->Get(), - TOKEN_ALL_ACCESS, &obj_attr, - lowbox_sid_, 0, NULL, - saved_handles_count, saved_handles); - if (!NT_SUCCESS(status)) - return SBOX_ERROR_GENERIC; - - DCHECK(token_lowbox); - lowbox->Set(token_lowbox); - } - - // Create the 'better' token. We use this token as the one that the main - // thread uses when booting up the process. It should contain most of - // what we need (before reaching main( )) - result = CreateRestrictedToken(initial_level_, integrity_level_, - IMPERSONATION, initial); - if (ERROR_SUCCESS != result) - return SBOX_ERROR_GENERIC; - - return SBOX_ALL_OK; -} - -const AppContainerAttributes* PolicyBase::GetAppContainer() const { - if (!appcontainer_list_.get() || !appcontainer_list_->HasAppContainer()) - return NULL; - - return appcontainer_list_.get(); -} - -PSID PolicyBase::GetLowBoxSid() const { - return lowbox_sid_; -} - -bool PolicyBase::AddTarget(TargetProcess* target) { - if (NULL != policy_) - policy_maker_->Done(); - - if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(), - mitigations_)) { - return false; - } - - if (!SetupAllInterceptions(target)) - return false; - - if (!SetupHandleCloser(target)) - return false; - - // Initialize the sandbox infrastructure for the target. - if (ERROR_SUCCESS != - target->Init(dispatcher_.get(), policy_, kIPCMemSize, kPolMemSize)) - return false; - - g_shared_delayed_integrity_level = delayed_integrity_level_; - ResultCode ret = target->TransferVariable( - "g_shared_delayed_integrity_level", - &g_shared_delayed_integrity_level, - sizeof(g_shared_delayed_integrity_level)); - g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST; - if (SBOX_ALL_OK != ret) - return false; - - // Add in delayed mitigations and pseudo-mitigations enforced at startup. - g_shared_delayed_mitigations = delayed_mitigations_ | - FilterPostStartupProcessMitigations(mitigations_); - if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations)) - return false; - - ret = target->TransferVariable("g_shared_delayed_mitigations", - &g_shared_delayed_mitigations, - sizeof(g_shared_delayed_mitigations)); - g_shared_delayed_mitigations = 0; - if (SBOX_ALL_OK != ret) - return false; - - AutoLock lock(&lock_); - targets_.push_back(target); - return true; -} - -bool PolicyBase::OnJobEmpty(HANDLE job) { - AutoLock lock(&lock_); - TargetSet::iterator it; - for (it = targets_.begin(); it != targets_.end(); ++it) { - if ((*it)->Job() == job) - break; - } - if (it == targets_.end()) { - return false; - } - TargetProcess* target = *it; - targets_.erase(it); - delete target; - return true; -} - -EvalResult PolicyBase::EvalPolicy(int service, - CountedParameterSetBase* params) { - if (NULL != policy_) { - if (NULL == policy_->entry[service]) { - // There is no policy for this particular service. This is not a big - // deal. - return DENY_ACCESS; - } - for (int i = 0; i < params->count; i++) { - if (!params->parameters[i].IsValid()) { - NOTREACHED(); - return SIGNAL_ALARM; - } - } - PolicyProcessor pol_evaluator(policy_->entry[service]); - PolicyResult result = pol_evaluator.Evaluate(kShortEval, - params->parameters, - params->count); - if (POLICY_MATCH == result) { - return pol_evaluator.GetAction(); - } - DCHECK(POLICY_ERROR != result); - } - - return DENY_ACCESS; -} - -HANDLE PolicyBase::GetStdoutHandle() { - return stdout_handle_; -} - -HANDLE PolicyBase::GetStderrHandle() { - return stderr_handle_; -} - -bool PolicyBase::SetupAllInterceptions(TargetProcess* target) { - InterceptionManager manager(target, relaxed_interceptions_); - - if (policy_) { - for (int i = 0; i < IPC_LAST_TAG; i++) { - if (policy_->entry[i] && !dispatcher_->SetupService(&manager, i)) - return false; - } - } - - if (!blacklisted_dlls_.empty()) { - std::vector<base::string16>::iterator it = blacklisted_dlls_.begin(); - for (; it != blacklisted_dlls_.end(); ++it) { - manager.AddToUnloadModules(it->c_str()); - } - } - - if (!SetupBasicInterceptions(&manager)) - return false; - - if (!manager.InitializeInterceptions()) - return false; - - // Finally, setup imports on the target so the interceptions can work. - return SetupNtdllImports(target); -} - -bool PolicyBase::SetupHandleCloser(TargetProcess* target) { - return handle_closer_.InitializeTargetHandles(target); -} - -ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem, - Semantics semantics, - const wchar_t* pattern) { - if (NULL == policy_) { - policy_ = MakeBrokerPolicyMemory(); - DCHECK(policy_); - policy_maker_ = new LowLevelPolicy(policy_); - DCHECK(policy_maker_); - } - - switch (subsystem) { - case SUBSYS_FILES: { - if (!file_system_init_) { - if (!FileSystemPolicy::SetInitialRules(policy_maker_)) - return SBOX_ERROR_BAD_PARAMS; - file_system_init_ = true; - } - if (!FileSystemPolicy::GenerateRules(pattern, semantics, policy_maker_)) { - NOTREACHED(); - return SBOX_ERROR_BAD_PARAMS; - } - break; - } - case SUBSYS_SYNC: { - if (!SyncPolicy::GenerateRules(pattern, semantics, policy_maker_)) { - NOTREACHED(); - return SBOX_ERROR_BAD_PARAMS; - } - break; - } - case SUBSYS_PROCESS: { - if (lockdown_level_ < USER_INTERACTIVE && - TargetPolicy::PROCESS_ALL_EXEC == semantics) { - // This is unsupported. This is a huge security risk to give full access - // to a process handle. - return SBOX_ERROR_UNSUPPORTED; - } - if (!ProcessPolicy::GenerateRules(pattern, semantics, policy_maker_)) { - NOTREACHED(); - return SBOX_ERROR_BAD_PARAMS; - } - break; - } - case SUBSYS_NAMED_PIPES: { - if (!NamedPipePolicy::GenerateRules(pattern, semantics, policy_maker_)) { - NOTREACHED(); - return SBOX_ERROR_BAD_PARAMS; - } - break; - } - case SUBSYS_REGISTRY: { - if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) { - NOTREACHED(); - return SBOX_ERROR_BAD_PARAMS; - } - break; - } - case SUBSYS_HANDLES: { - if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) { - NOTREACHED(); - return SBOX_ERROR_BAD_PARAMS; - } - break; - } - - case SUBSYS_WIN32K_LOCKDOWN: { - if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules( - pattern, semantics, policy_maker_)) { - NOTREACHED(); - return SBOX_ERROR_BAD_PARAMS; - } - break; - } - - default: { return SBOX_ERROR_UNSUPPORTED; } - } - - return SBOX_ALL_OK; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h deleted file mode 100644 index b2d1b7c85..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_SANDBOX_POLICY_BASE_H_ -#define SANDBOX_WIN_SRC_SANDBOX_POLICY_BASE_H_ - -#include <windows.h> -#include <stddef.h> -#include <stdint.h> - -#include <list> -#include <vector> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/handle_closer.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_engine_params.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/win_utils.h" - -namespace sandbox { - -class AppContainerAttributes; -class LowLevelPolicy; -class TargetProcess; -struct PolicyGlobal; - -typedef std::vector<base::win::ScopedHandle*> HandleList; - -class PolicyBase final : public TargetPolicy { - public: - PolicyBase(); - - // TargetPolicy: - void AddRef() override; - void Release() override; - ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) override; - TokenLevel GetInitialTokenLevel() const override; - TokenLevel GetLockdownTokenLevel() const override; - ResultCode SetJobLevel(JobLevel job_level, uint32_t ui_exceptions) override; - ResultCode SetJobMemoryLimit(size_t memory_limit) override; - ResultCode SetAlternateDesktop(bool alternate_winstation) override; - base::string16 GetAlternateDesktop() const override; - ResultCode CreateAlternateDesktop(bool alternate_winstation) override; - void DestroyAlternateDesktop() override; - ResultCode SetIntegrityLevel(IntegrityLevel integrity_level) override; - IntegrityLevel GetIntegrityLevel() const override; - ResultCode SetDelayedIntegrityLevel(IntegrityLevel integrity_level) override; - ResultCode SetAppContainer(const wchar_t* sid) override; - ResultCode SetCapability(const wchar_t* sid) override; - ResultCode SetLowBox(const wchar_t* sid) override; - ResultCode SetProcessMitigations(MitigationFlags flags) override; - MitigationFlags GetProcessMitigations() override; - ResultCode SetDelayedProcessMitigations(MitigationFlags flags) override; - MitigationFlags GetDelayedProcessMitigations() const override; - void SetStrictInterceptions() override; - ResultCode SetStdoutHandle(HANDLE handle) override; - ResultCode SetStderrHandle(HANDLE handle) override; - ResultCode AddRule(SubSystem subsystem, - Semantics semantics, - const wchar_t* pattern) override; - ResultCode AddDllToUnload(const wchar_t* dll_name) override; - ResultCode AddKernelObjectToClose(const base::char16* handle_type, - const base::char16* handle_name) override; - void* AddHandleToShare(HANDLE handle) override; - - // Creates a Job object with the level specified in a previous call to - // SetJobLevel(). - ResultCode MakeJobObject(base::win::ScopedHandle* job); - - // Creates the two tokens with the levels specified in a previous call to - // SetTokenLevel(). Also creates a lowbox token if specified based on the - // lowbox SID. - ResultCode MakeTokens(base::win::ScopedHandle* initial, - base::win::ScopedHandle* lockdown, - base::win::ScopedHandle* lowbox); - - const AppContainerAttributes* GetAppContainer() const; - - PSID GetLowBoxSid() const; - - // Adds a target process to the internal list of targets. Internally a - // call to TargetProcess::Init() is issued. - bool AddTarget(TargetProcess* target); - - // Called when there are no more active processes in a Job. - // Removes a Job object associated with this policy and the target associated - // with the job. - bool OnJobEmpty(HANDLE job); - - EvalResult EvalPolicy(int service, CountedParameterSetBase* params); - - HANDLE GetStdoutHandle(); - HANDLE GetStderrHandle(); - - // Returns the list of handles being shared with the target process. - const HandleList& GetHandlesBeingShared(); - - // Closes the handles being shared with the target and clears out the list. - void ClearSharedHandles(); - - private: - ~PolicyBase(); - - // Sets up interceptions for a new target. - bool SetupAllInterceptions(TargetProcess* target); - - // Sets up the handle closer for a new target. - bool SetupHandleCloser(TargetProcess* target); - - ResultCode AddRuleInternal(SubSystem subsystem, - Semantics semantics, - const wchar_t* pattern); - - // This lock synchronizes operations on the targets_ collection. - CRITICAL_SECTION lock_; - // Maintains the list of target process associated with this policy. - // The policy takes ownership of them. - typedef std::list<TargetProcess*> TargetSet; - TargetSet targets_; - // Standard object-lifetime reference counter. - volatile LONG ref_count; - // The user-defined global policy settings. - TokenLevel lockdown_level_; - TokenLevel initial_level_; - JobLevel job_level_; - uint32_t ui_exceptions_; - size_t memory_limit_; - bool use_alternate_desktop_; - bool use_alternate_winstation_; - // Helps the file system policy initialization. - bool file_system_init_; - bool relaxed_interceptions_; - HANDLE stdout_handle_; - HANDLE stderr_handle_; - IntegrityLevel integrity_level_; - IntegrityLevel delayed_integrity_level_; - MitigationFlags mitigations_; - MitigationFlags delayed_mitigations_; - // Object in charge of generating the low level policy. - LowLevelPolicy* policy_maker_; - // Memory structure that stores the low level policy. - PolicyGlobal* policy_; - // The list of dlls to unload in the target process. - std::vector<base::string16> blacklisted_dlls_; - // This is a map of handle-types to names that we need to close in the - // target process. A null set means we need to close all handles of the - // given type. - HandleCloser handle_closer_; - std::vector<base::string16> capabilities_; - scoped_ptr<AppContainerAttributes> appcontainer_list_; - PSID lowbox_sid_; - base::win::ScopedHandle lowbox_directory_; - scoped_ptr<Dispatcher> dispatcher_; - - static HDESK alternate_desktop_handle_; - static HWINSTA alternate_winstation_handle_; - static IntegrityLevel alternate_desktop_integrity_level_label_; - - // Contains the list of handles being shared with the target process. - // This list contains handles other than the stderr/stdout handles which are - // shared with the target at times. - HandleList handles_to_share_; - - DISALLOW_COPY_AND_ASSIGN(PolicyBase); -}; - -} // namespace sandbox - -#endif // SANDBOX_WIN_SRC_SANDBOX_POLICY_BASE_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_rand.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_rand.cc deleted file mode 100644 index b3f977374..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_rand.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sandbox_rand.h" - -#include <windows.h> - -// #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the -// "Community Additions" comment on MSDN here: -// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx -#define SystemFunction036 NTAPI SystemFunction036 -#include <NTSecAPI.h> -#undef SystemFunction036 - -namespace sandbox { - -bool GetRandom(unsigned int* random_value) { - return RtlGenRandom(random_value, sizeof(unsigned int)) != FALSE; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_rand.h b/security/sandbox/chromium/sandbox/win/src/sandbox_rand.h deleted file mode 100644 index 7c4febcd5..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_rand.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SANDBOX_RAND_H_ -#define SANDBOX_SRC_SANDBOX_RAND_H_ - - -namespace sandbox { - -// Generate a random value in |random_value|. Returns true on success. -bool GetRandom(unsigned int* random_value); - -} // namespace sandbox - -#endif // SANDBOX_SRC_SANDBOX_RAND_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_types.h b/security/sandbox/chromium/sandbox/win/src/sandbox_types.h deleted file mode 100644 index b749b9ca5..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_types.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_SANDBOX_TYPES_H_ -#define SANDBOX_WIN_SRC_SANDBOX_TYPES_H_ - -namespace sandbox { - -// Operation result codes returned by the sandbox API. -enum ResultCode { - SBOX_ALL_OK = 0, - // Error is originating on the win32 layer. Call GetlastError() for more - // information. - SBOX_ERROR_GENERIC = 1, - // An invalid combination of parameters was given to the API. - SBOX_ERROR_BAD_PARAMS = 2, - // The desired operation is not supported at this time. - SBOX_ERROR_UNSUPPORTED = 3, - // The request requires more memory that allocated or available. - SBOX_ERROR_NO_SPACE = 4, - // The ipc service requested does not exist. - SBOX_ERROR_INVALID_IPC = 5, - // The ipc service did not complete. - SBOX_ERROR_FAILED_IPC = 6, - // The requested handle was not found. - SBOX_ERROR_NO_HANDLE = 7, - // This function was not expected to be called at this time. - SBOX_ERROR_UNEXPECTED_CALL = 8, - // WaitForAllTargets is already called. - SBOX_ERROR_WAIT_ALREADY_CALLED = 9, - // A channel error prevented DoCall from executing. - SBOX_ERROR_CHANNEL_ERROR = 10, - // Failed to create the alternate desktop. - SBOX_ERROR_CANNOT_CREATE_DESKTOP = 11, - // Failed to create the alternate window station. - SBOX_ERROR_CANNOT_CREATE_WINSTATION = 12, - // Failed to switch back to the interactive window station. - SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION = 13, - // The supplied AppContainer is not valid. - SBOX_ERROR_INVALID_APP_CONTAINER = 14, - // The supplied capability is not valid. - SBOX_ERROR_INVALID_CAPABILITY = 15, - // There is a failure initializing the AppContainer. - SBOX_ERROR_CANNOT_INIT_APPCONTAINER = 16, - // Initializing or updating ProcThreadAttributes failed. - SBOX_ERROR_PROC_THREAD_ATTRIBUTES = 17, - // Error in creating process. - SBOX_ERROR_CREATE_PROCESS = 18, - // Placeholder for last item of the enum. - SBOX_ERROR_LAST -}; - -// If the sandbox cannot create a secure environment for the target, the -// target will be forcibly terminated. These are the process exit codes. -enum TerminationCodes { - SBOX_FATAL_INTEGRITY = 7006, // Could not set the integrity level. - SBOX_FATAL_DROPTOKEN = 7007, // Could not lower the token. - SBOX_FATAL_FLUSHANDLES = 7008, // Failed to flush registry handles. - SBOX_FATAL_CACHEDISABLE = 7009, // Failed to forbid HCKU caching. - SBOX_FATAL_CLOSEHANDLES = 7010, // Failed to close pending handles. - SBOX_FATAL_MITIGATION = 7011, // Could not set the mitigation policy. - SBOX_FATAL_MEMORY_EXCEEDED = 7012, // Exceeded the job memory limit. - SBOX_FATAL_WARMUP = 7013, // Failed to warmup. - SBOX_FATAL_LAST -}; - -class BrokerServices; -class TargetServices; - -// Contains the pointer to a target or broker service. -struct SandboxInterfaceInfo { - BrokerServices* broker_services; - TargetServices* target_services; -}; - -#if SANDBOX_EXPORTS -#define SANDBOX_INTERCEPT extern "C" __declspec(dllexport) -#else -#define SANDBOX_INTERCEPT extern "C" -#endif - -enum InterceptionType { - INTERCEPTION_INVALID = 0, - INTERCEPTION_SERVICE_CALL, // Trampoline of an NT native call - INTERCEPTION_EAT, - INTERCEPTION_SIDESTEP, // Preamble patch - INTERCEPTION_SMART_SIDESTEP, // Preamble patch but bypass internal calls - INTERCEPTION_UNLOAD_MODULE, // Unload the module (don't patch) - INTERCEPTION_LAST // Placeholder for last item in the enumeration -}; - -} // namespace sandbox - -#endif // SANDBOX_WIN_SRC_SANDBOX_TYPES_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_utils.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_utils.cc deleted file mode 100644 index 6057caffc..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_utils.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sandbox_utils.h" - -#include <windows.h> - -#include "base/logging.h" -#include "sandbox/win/src/internal_types.h" - -namespace sandbox { - -void InitObjectAttribs(const base::string16& name, - ULONG attributes, - HANDLE root, - OBJECT_ATTRIBUTES* obj_attr, - UNICODE_STRING* uni_name, - SECURITY_QUALITY_OF_SERVICE* security_qos) { - static RtlInitUnicodeStringFunction RtlInitUnicodeString; - if (!RtlInitUnicodeString) { - HMODULE ntdll = ::GetModuleHandle(kNtdllName); - RtlInitUnicodeString = reinterpret_cast<RtlInitUnicodeStringFunction>( - GetProcAddress(ntdll, "RtlInitUnicodeString")); - DCHECK(RtlInitUnicodeString); - } - RtlInitUnicodeString(uni_name, name.c_str()); - InitializeObjectAttributes(obj_attr, uni_name, attributes, root, NULL); - obj_attr->SecurityQualityOfService = security_qos; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_utils.h b/security/sandbox/chromium/sandbox/win/src/sandbox_utils.h deleted file mode 100644 index b1c1f3134..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_utils.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SANDBOX_UTILS_H_ -#define SANDBOX_SRC_SANDBOX_UTILS_H_ - -#include <windows.h> -#include <string> - -#include "base/strings/string16.h" -#include "sandbox/win/src/nt_internals.h" - -namespace sandbox { - -void InitObjectAttribs(const base::string16& name, - ULONG attributes, - HANDLE root, - OBJECT_ATTRIBUTES* obj_attr, - UNICODE_STRING* uni_name, - SECURITY_QUALITY_OF_SERVICE* security_qos); - -} // namespace sandbox - -#endif // SANDBOX_SRC_SANDBOX_UTILS_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/security_level.h b/security/sandbox/chromium/sandbox/win/src/security_level.h deleted file mode 100644 index 26ec306a6..000000000 --- a/security/sandbox/chromium/sandbox/win/src/security_level.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SECURITY_LEVEL_H_ -#define SANDBOX_SRC_SECURITY_LEVEL_H_ - -#include <stdint.h> - -namespace sandbox { - -// List of all the integrity levels supported in the sandbox. This is used -// only on Windows Vista. You can't set the integrity level of the process -// in the sandbox to a level higher than yours. -enum IntegrityLevel { - INTEGRITY_LEVEL_SYSTEM, - INTEGRITY_LEVEL_HIGH, - INTEGRITY_LEVEL_MEDIUM, - INTEGRITY_LEVEL_MEDIUM_LOW, - INTEGRITY_LEVEL_LOW, - INTEGRITY_LEVEL_BELOW_LOW, - INTEGRITY_LEVEL_UNTRUSTED, - INTEGRITY_LEVEL_LAST -}; - -// The Token level specifies a set of security profiles designed to -// provide the bulk of the security of sandbox. -// -// TokenLevel |Restricting |Deny Only |Privileges| -// |Sids |Sids | | -// ----------------------------|--------------|----------------|----------| -// USER_LOCKDOWN | Null Sid | All | None | -// ----------------------------|--------------|----------------|----------| -// USER_RESTRICTED | RESTRICTED | All | Traverse | -// ----------------------------|--------------|----------------|----------| -// USER_LIMITED | Users | All except: | Traverse | -// | Everyone | Users | | -// | RESTRICTED | Everyone | | -// | | Interactive | | -// ----------------------------|--------------|----------------|----------| -// USER_INTERACTIVE | Users | All except: | Traverse | -// | Everyone | Users | | -// | RESTRICTED | Everyone | | -// | Owner | Interactive | | -// | | Local | | -// | | Authent-users | | -// | | User | | -// ----------------------------|--------------|----------------|----------| -// USER_NON_ADMIN | None | All except: | Traverse | -// | | Users | | -// | | Everyone | | -// | | Interactive | | -// | | Local | | -// | | Authent-users | | -// | | User | | -// ----------------------------|--------------|----------------|----------| -// USER_RESTRICTED_SAME_ACCESS | All | None | All | -// ----------------------------|--------------|----------------|----------| -// USER_UNPROTECTED | None | None | All | -// ----------------------------|--------------|----------------|----------| -// -// The above restrictions are actually a transformation that is applied to -// the existing broker process token. The resulting token that will be -// applied to the target process depends both on the token level selected -// and on the broker token itself. -// -// The LOCKDOWN and RESTRICTED are designed to allow access to almost -// nothing that has security associated with and they are the recommended -// levels to run sandboxed code specially if there is a chance that the -// broker is process might be started by a user that belongs to the Admins -// or power users groups. -enum TokenLevel { - USER_LOCKDOWN = 0, - USER_RESTRICTED, - USER_LIMITED, - USER_INTERACTIVE, - USER_NON_ADMIN, - USER_RESTRICTED_SAME_ACCESS, - USER_UNPROTECTED, - USER_LAST -}; - -// The Job level specifies a set of decreasing security profiles for the -// Job object that the target process will be placed into. -// This table summarizes the security associated with each level: -// -// JobLevel |General |Quota | -// |restrictions |restrictions | -// -----------------|---------------------------------- |--------------------| -// JOB_NONE | No job is assigned to the | None | -// | sandboxed process. | | -// -----------------|---------------------------------- |--------------------| -// JOB_UNPROTECTED | None | *Kill on Job close.| -// -----------------|---------------------------------- |--------------------| -// JOB_INTERACTIVE | *Forbid system-wide changes using | | -// | SystemParametersInfo(). | *Kill on Job close.| -// | *Forbid the creation/switch of | | -// | Desktops. | | -// | *Forbids calls to ExitWindows(). | | -// -----------------|---------------------------------- |--------------------| -// JOB_LIMITED_USER | Same as INTERACTIVE_USER plus: | *One active process| -// | *Forbid changes to the display | limit. | -// | settings. | *Kill on Job close.| -// -----------------|---------------------------------- |--------------------| -// JOB_RESTRICTED | Same as LIMITED_USER plus: | *One active process| -// | * No read/write to the clipboard. | limit. | -// | * No access to User Handles that | *Kill on Job close.| -// | belong to other processes. | | -// | * Forbid message broadcasts. | | -// | * Forbid setting global hooks. | | -// | * No access to the global atoms | | -// | table. | | -// -----------------|-----------------------------------|--------------------| -// JOB_LOCKDOWN | Same as RESTRICTED | *One active process| -// | | limit. | -// | | *Kill on Job close.| -// | | *Kill on unhandled | -// | | exception. | -// | | | -// In the context of the above table, 'user handles' refers to the handles of -// windows, bitmaps, menus, etc. Files, treads and registry handles are kernel -// handles and are not affected by the job level settings. -enum JobLevel { - JOB_LOCKDOWN = 0, - JOB_RESTRICTED, - JOB_LIMITED_USER, - JOB_INTERACTIVE, - JOB_UNPROTECTED, - JOB_NONE -}; - -// These flags correspond to various process-level mitigations (eg. ASLR and -// DEP). Most are implemented via UpdateProcThreadAttribute() plus flags for -// the PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY attribute argument; documented -// here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686880 -// Some mitigations are implemented directly by the sandbox or emulated to -// the greatest extent possible when not directly supported by the OS. -// Flags that are unsupported for the target OS will be silently ignored. -// Flags that are invalid for their application (pre or post startup) will -// return SBOX_ERROR_BAD_PARAMS. -typedef uint64_t MitigationFlags; - -// Permanently enables DEP for the target process. Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE. -const MitigationFlags MITIGATION_DEP = 0x00000001; - -// Permanently Disables ATL thunk emulation when DEP is enabled. Valid -// only when MITIGATION_DEP is passed. Corresponds to not passing -// PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE. -const MitigationFlags MITIGATION_DEP_NO_ATL_THUNK = 0x00000002; - -// Enables Structured exception handling override prevention. Must be -// enabled prior to process start. Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE. -const MitigationFlags MITIGATION_SEHOP = 0x00000004; - -// Forces ASLR on all images in the child process. Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON . -const MitigationFlags MITIGATION_RELOCATE_IMAGE = 0x00000008; - -// Refuses to load DLLs that cannot support ASLR. Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON_REQ_RELOCS. -const MitigationFlags MITIGATION_RELOCATE_IMAGE_REQUIRED = 0x00000010; - -// Terminates the process on Windows heap corruption. Coresponds to -// PROCESS_CREATION_MITIGATION_POLICY_HEAP_TERMINATE_ALWAYS_ON. -const MitigationFlags MITIGATION_HEAP_TERMINATE = 0x00000020; - -// Sets a random lower bound as the minimum user address. Must be -// enabled prior to process start. On 32-bit processes this is -// emulated to a much smaller degree. Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_ON. -const MitigationFlags MITIGATION_BOTTOM_UP_ASLR = 0x00000040; - -// Increases the randomness range of bottom-up ASLR to up to 1TB. Must be -// enabled prior to process start and with MITIGATION_BOTTOM_UP_ASLR. -// Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_HIGH_ENTROPY_ASLR_ALWAYS_ON -const MitigationFlags MITIGATION_HIGH_ENTROPY_ASLR = 0x00000080; - -// Immediately raises an exception on a bad handle reference. Must be -// enabled after startup. Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON. -const MitigationFlags MITIGATION_STRICT_HANDLE_CHECKS = 0x00000100; - -// Prevents the process from making Win32k calls. Must be enabled after -// startup. Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON. -const MitigationFlags MITIGATION_WIN32K_DISABLE = 0x00000200; - -// Disables common DLL injection methods (e.g. window hooks and -// App_InitDLLs). Corresponds to -// PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON. -const MitigationFlags MITIGATION_EXTENSION_DLL_DISABLE = 0x00000400; - -// Sets the DLL search order to LOAD_LIBRARY_SEARCH_DEFAULT_DIRS. Additional -// directories can be added via the Windows AddDllDirectory() function. -// http://msdn.microsoft.com/en-us/library/windows/desktop/hh310515 -// Must be enabled after startup. -const MitigationFlags MITIGATION_DLL_SEARCH_ORDER = 0x00000001ULL << 32; - -// Changes the mandatory integrity level policy on the current process' token -// to enable no-read and no-execute up. This prevents a lower IL process from -// opening the process token for impersonate/duplicate/assignment. -const MitigationFlags MITIGATION_HARDEN_TOKEN_IL_POLICY = 0x00000001ULL << 33; - -} // namespace sandbox - -#endif // SANDBOX_SRC_SECURITY_LEVEL_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/service_resolver.cc b/security/sandbox/chromium/sandbox/win/src/service_resolver.cc deleted file mode 100644 index 92f21a7c2..000000000 --- a/security/sandbox/chromium/sandbox/win/src/service_resolver.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/service_resolver.h" - -#include "base/win/pe_image.h" -#include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/sandbox_nt_util.h" - -namespace sandbox { - -NTSTATUS ServiceResolverThunk::ResolveInterceptor( - const void* interceptor_module, - const char* interceptor_name, - const void** address) { - // After all, we are using a locally mapped version of the exe, so the - // action is the same as for a target function. - return ResolveTarget(interceptor_module, interceptor_name, - const_cast<void**>(address)); -} - -// In this case all the work is done from the parent, so resolve is -// just a simple GetProcAddress. -NTSTATUS ServiceResolverThunk::ResolveTarget(const void* module, - const char* function_name, - void** address) { - if (NULL == module) - return STATUS_UNSUCCESSFUL; - - base::win::PEImage module_image(module); - *address = module_image.GetProcAddress(function_name); - - if (NULL == *address) { - NOTREACHED_NT(); - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -void ServiceResolverThunk::AllowLocalPatches() { - ntdll_base_ = ::GetModuleHandle(kNtdllName); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/service_resolver.h b/security/sandbox/chromium/sandbox/win/src/service_resolver.h deleted file mode 100644 index 7ac5a2490..000000000 --- a/security/sandbox/chromium/sandbox/win/src/service_resolver.h +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SERVICE_RESOLVER_H__ -#define SANDBOX_SRC_SERVICE_RESOLVER_H__ - -#include <stddef.h> - -#include "base/macros.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/resolver.h" - -namespace sandbox { - -// This is the concrete resolver used to perform service-call type functions -// inside ntdll.dll. -class ServiceResolverThunk : public ResolverThunk { - public: - // The service resolver needs a child process to write to. - ServiceResolverThunk(HANDLE process, bool relaxed) - : ntdll_base_(NULL), - process_(process), - relaxed_(relaxed), - relative_jump_(0) {} - ~ServiceResolverThunk() override {} - - // Implementation of Resolver::Setup. - NTSTATUS Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) override; - - // Implementation of Resolver::ResolveInterceptor. - NTSTATUS ResolveInterceptor(const void* module, - const char* function_name, - const void** address) override; - - // Implementation of Resolver::ResolveTarget. - NTSTATUS ResolveTarget(const void* module, - const char* function_name, - void** address) override; - - // Implementation of Resolver::GetThunkSize. - size_t GetThunkSize() const override; - - // Call this to set up ntdll_base_ which will allow for local patches. - virtual void AllowLocalPatches(); - - // Verifies that the function specified by |target_name| in |target_module| is - // a service and copies the data from that function into |thunk_storage|. If - // |storage_bytes| is too small, then the method fails. - virtual NTSTATUS CopyThunk(const void* target_module, - const char* target_name, - BYTE* thunk_storage, - size_t storage_bytes, - size_t* storage_used); - - protected: - // The unit test will use this member to allow local patch on a buffer. - HMODULE ntdll_base_; - - // Handle of the child process. - HANDLE process_; - - private: - // Returns true if the code pointer by target_ corresponds to the expected - // type of function. Saves that code on the first part of the thunk pointed - // by local_thunk (should be directly accessible from the parent). - virtual bool IsFunctionAService(void* local_thunk) const; - - // Performs the actual patch of target_. - // local_thunk must be already fully initialized, and the first part must - // contain the original code. The real type of this buffer is ServiceFullThunk - // (yes, private). remote_thunk (real type ServiceFullThunk), must be - // allocated on the child, and will contain the thunk data, after this call. - // Returns the apropriate status code. - virtual NTSTATUS PerformPatch(void* local_thunk, void* remote_thunk); - - // Provides basically the same functionality as IsFunctionAService but it - // continues even if it does not recognize the function code. remote_thunk - // is the address of our memory on the child. - bool SaveOriginalFunction(void* local_thunk, void* remote_thunk); - - // true if we are allowed to patch already-patched functions. - bool relaxed_; - ULONG relative_jump_; - - DISALLOW_COPY_AND_ASSIGN(ServiceResolverThunk); -}; - -// This is the concrete resolver used to perform service-call type functions -// inside ntdll.dll on WOW64 (32 bit ntdll on 64 bit Vista). -class Wow64ResolverThunk : public ServiceResolverThunk { - public: - // The service resolver needs a child process to write to. - Wow64ResolverThunk(HANDLE process, bool relaxed) - : ServiceResolverThunk(process, relaxed) {} - ~Wow64ResolverThunk() override {} - - private: - bool IsFunctionAService(void* local_thunk) const override; - - DISALLOW_COPY_AND_ASSIGN(Wow64ResolverThunk); -}; - -// This is the concrete resolver used to perform service-call type functions -// inside ntdll.dll on WOW64 for Windows 8. -class Wow64W8ResolverThunk : public ServiceResolverThunk { - public: - // The service resolver needs a child process to write to. - Wow64W8ResolverThunk(HANDLE process, bool relaxed) - : ServiceResolverThunk(process, relaxed) {} - ~Wow64W8ResolverThunk() override {} - - private: - bool IsFunctionAService(void* local_thunk) const override; - - DISALLOW_COPY_AND_ASSIGN(Wow64W8ResolverThunk); -}; - -// This is the concrete resolver used to perform service-call type functions -// inside ntdll.dll on Windows 8. -class Win8ResolverThunk : public ServiceResolverThunk { - public: - // The service resolver needs a child process to write to. - Win8ResolverThunk(HANDLE process, bool relaxed) - : ServiceResolverThunk(process, relaxed) {} - ~Win8ResolverThunk() override {} - - private: - bool IsFunctionAService(void* local_thunk) const override; - - DISALLOW_COPY_AND_ASSIGN(Win8ResolverThunk); -}; - -// This is the concrete resolver used to perform service-call type functions -// inside ntdll.dll on WOW64 for Windows 10. -class Wow64W10ResolverThunk : public ServiceResolverThunk { - public: - // The service resolver needs a child process to write to. - Wow64W10ResolverThunk(HANDLE process, bool relaxed) - : ServiceResolverThunk(process, relaxed) {} - ~Wow64W10ResolverThunk() override {} - - private: - bool IsFunctionAService(void* local_thunk) const override; - - DISALLOW_COPY_AND_ASSIGN(Wow64W10ResolverThunk); -}; - -} // namespace sandbox - - -#endif // SANDBOX_SRC_SERVICE_RESOLVER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/service_resolver_32.cc b/security/sandbox/chromium/sandbox/win/src/service_resolver_32.cc deleted file mode 100644 index f809227e9..000000000 --- a/security/sandbox/chromium/sandbox/win/src/service_resolver_32.cc +++ /dev/null @@ -1,478 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/service_resolver.h" - -#include <stddef.h> - -#include "base/bit_cast.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/win_utils.h" - -namespace { -#pragma pack(push, 1) - -const BYTE kMovEax = 0xB8; -const BYTE kMovEdx = 0xBA; -const USHORT kMovEdxEsp = 0xD48B; -const USHORT kCallPtrEdx = 0x12FF; -const USHORT kCallEdx = 0xD2FF; -const BYTE kCallEip = 0xE8; -const BYTE kRet = 0xC2; -const BYTE kRet2 = 0xC3; -const USHORT kJmpEdx = 0xE2FF; -const USHORT kXorEcx = 0xC933; -const ULONG kLeaEdx = 0x0424548D; -const ULONG kCallFs1 = 0xC015FF64; -const USHORT kCallFs2 = 0; -const BYTE kCallFs3 = 0; -const BYTE kAddEsp1 = 0x83; -const USHORT kAddEsp2 = 0x4C4; -const BYTE kJmp32 = 0xE9; -const USHORT kSysenter = 0x340F; - -// Service code for 32 bit systems. -// NOTE: on win2003 "call dword ptr [edx]" is "call edx". -struct ServiceEntry { - // This struct contains roughly the following code: - // 00 mov eax,25h - // 05 mov edx,offset SharedUserData!SystemCallStub (7ffe0300) - // 0a call dword ptr [edx] - // 0c ret 2Ch - // 0f nop - BYTE mov_eax; // = B8 - ULONG service_id; - BYTE mov_edx; // = BA - ULONG stub; - USHORT call_ptr_edx; // = FF 12 - BYTE ret; // = C2 - USHORT num_params; - BYTE nop; -}; - -// Service code for 32 bit Windows 8. -struct ServiceEntryW8 { - // This struct contains the following code: - // 00 b825000000 mov eax,25h - // 05 e803000000 call eip+3 - // 0a c22c00 ret 2Ch - // 0d 8bd4 mov edx,esp - // 0f 0f34 sysenter - // 11 c3 ret - // 12 8bff mov edi,edi - BYTE mov_eax; // = B8 - ULONG service_id; - BYTE call_eip; // = E8 - ULONG call_offset; - BYTE ret_p; // = C2 - USHORT num_params; - USHORT mov_edx_esp; // = BD D4 - USHORT sysenter; // = 0F 34 - BYTE ret; // = C3 - USHORT nop; -}; - -// Service code for a 32 bit process running on a 64 bit os. -struct Wow64Entry { - // This struct may contain one of two versions of code: - // 1. For XP, Vista and 2K3: - // 00 b825000000 mov eax, 25h - // 05 33c9 xor ecx, ecx - // 07 8d542404 lea edx, [esp + 4] - // 0b 64ff15c0000000 call dword ptr fs:[0C0h] - // 12 c22c00 ret 2Ch - // - // 2. For Windows 7: - // 00 b825000000 mov eax, 25h - // 05 33c9 xor ecx, ecx - // 07 8d542404 lea edx, [esp + 4] - // 0b 64ff15c0000000 call dword ptr fs:[0C0h] - // 12 83c404 add esp, 4 - // 15 c22c00 ret 2Ch - // - // So we base the structure on the bigger one: - BYTE mov_eax; // = B8 - ULONG service_id; - USHORT xor_ecx; // = 33 C9 - ULONG lea_edx; // = 8D 54 24 04 - ULONG call_fs1; // = 64 FF 15 C0 - USHORT call_fs2; // = 00 00 - BYTE call_fs3; // = 00 - BYTE add_esp1; // = 83 or ret - USHORT add_esp2; // = C4 04 or num_params - BYTE ret; // = C2 - USHORT num_params; -}; - -// Service code for a 32 bit process running on 64 bit Windows 8. -struct Wow64EntryW8 { - // 00 b825000000 mov eax, 25h - // 05 64ff15c0000000 call dword ptr fs:[0C0h] - // 0b c22c00 ret 2Ch - // 0f 90 nop - BYTE mov_eax; // = B8 - ULONG service_id; - ULONG call_fs1; // = 64 FF 15 C0 - USHORT call_fs2; // = 00 00 - BYTE call_fs3; // = 00 - BYTE ret; // = C2 - USHORT num_params; - BYTE nop; -}; - -// Service code for a 32 bit process running on 64 bit Windows 10. -struct Wow64EntryW10 { - // 00 b828000000 mov eax, 28h - // 05 bab0d54877 mov edx, 7748D5B0h - // 09 ffd2 call edx - // 0b c22800 ret 28h - BYTE mov_eax; // = B8 - ULONG service_id; - BYTE mov_edx; // = BA - ULONG mov_edx_param; - USHORT call_edx; // = FF D2 - BYTE ret; // = C2 - USHORT num_params; -}; - -// Make sure that relaxed patching works as expected. -const size_t kMinServiceSize = offsetof(ServiceEntry, ret); -static_assert(sizeof(ServiceEntryW8) >= kMinServiceSize, - "wrong service length"); -static_assert(sizeof(Wow64Entry) >= kMinServiceSize, "wrong service length"); -static_assert(sizeof(Wow64EntryW8) >= kMinServiceSize, "wrong service length"); - -struct ServiceFullThunk { - union { - ServiceEntry original; - ServiceEntryW8 original_w8; - Wow64Entry wow_64; - Wow64EntryW8 wow_64_w8; - }; - int internal_thunk; // Dummy member to the beginning of the internal thunk. -}; - -#pragma pack(pop) - -}; // namespace - -namespace sandbox { - -NTSTATUS ServiceResolverThunk::Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) { - NTSTATUS ret = Init(target_module, interceptor_module, target_name, - interceptor_name, interceptor_entry_point, - thunk_storage, storage_bytes); - if (!NT_SUCCESS(ret)) - return ret; - - relative_jump_ = 0; - size_t thunk_bytes = GetThunkSize(); - scoped_ptr<char[]> thunk_buffer(new char[thunk_bytes]); - ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>( - thunk_buffer.get()); - - if (!IsFunctionAService(&thunk->original) && - (!relaxed_ || !SaveOriginalFunction(&thunk->original, thunk_storage))) { - return STATUS_UNSUCCESSFUL; - } - - ret = PerformPatch(thunk, thunk_storage); - - if (NULL != storage_used) - *storage_used = thunk_bytes; - - return ret; -} - -size_t ServiceResolverThunk::GetThunkSize() const { - return offsetof(ServiceFullThunk, internal_thunk) + GetInternalThunkSize(); -} - -NTSTATUS ServiceResolverThunk::CopyThunk(const void* target_module, - const char* target_name, - BYTE* thunk_storage, - size_t storage_bytes, - size_t* storage_used) { - NTSTATUS ret = ResolveTarget(target_module, target_name, &target_); - if (!NT_SUCCESS(ret)) - return ret; - - size_t thunk_bytes = GetThunkSize(); - if (storage_bytes < thunk_bytes) - return STATUS_UNSUCCESSFUL; - - ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>(thunk_storage); - - if (!IsFunctionAService(&thunk->original) && - (!relaxed_ || !SaveOriginalFunction(&thunk->original, thunk_storage))) { - return STATUS_UNSUCCESSFUL; - } - - if (NULL != storage_used) - *storage_used = thunk_bytes; - - return ret; -} - -bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { - ServiceEntry function_code; - SIZE_T read; - if (!::ReadProcessMemory(process_, target_, &function_code, - sizeof(function_code), &read)) { - return false; - } - - if (sizeof(function_code) != read) - return false; - - if (kMovEax != function_code.mov_eax || - kMovEdx != function_code.mov_edx || - (kCallPtrEdx != function_code.call_ptr_edx && - kCallEdx != function_code.call_ptr_edx) || - kRet != function_code.ret) { - return false; - } - - // Find the system call pointer if we don't already have it. - if (kCallEdx != function_code.call_ptr_edx) { - DWORD ki_system_call; - if (!::ReadProcessMemory(process_, - bit_cast<const void*>(function_code.stub), - &ki_system_call, sizeof(ki_system_call), &read)) { - return false; - } - - if (sizeof(ki_system_call) != read) - return false; - - HMODULE module_1, module_2; - // last check, call_stub should point to a KiXXSystemCall function on ntdll - if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - bit_cast<const wchar_t*>(ki_system_call), - &module_1)) { - return false; - } - - if (NULL != ntdll_base_) { - // This path is only taken when running the unit tests. We want to be - // able to patch a buffer in memory, so target_ is not inside ntdll. - module_2 = ntdll_base_; - } else { - if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - reinterpret_cast<const wchar_t*>(target_), - &module_2)) - return false; - } - - if (module_1 != module_2) - return false; - } - - // Save the verified code - memcpy(local_thunk, &function_code, sizeof(function_code)); - - return true; -} - -NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk, - void* remote_thunk) { - ServiceEntry intercepted_code; - size_t bytes_to_write = sizeof(intercepted_code); - ServiceFullThunk *full_local_thunk = reinterpret_cast<ServiceFullThunk*>( - local_thunk); - ServiceFullThunk *full_remote_thunk = reinterpret_cast<ServiceFullThunk*>( - remote_thunk); - - // patch the original code - memcpy(&intercepted_code, &full_local_thunk->original, - sizeof(intercepted_code)); - intercepted_code.mov_eax = kMovEax; - intercepted_code.service_id = full_local_thunk->original.service_id; - intercepted_code.mov_edx = kMovEdx; - intercepted_code.stub = bit_cast<ULONG>(&full_remote_thunk->internal_thunk); - intercepted_code.call_ptr_edx = kJmpEdx; - bytes_to_write = kMinServiceSize; - - if (relative_jump_) { - intercepted_code.mov_eax = kJmp32; - intercepted_code.service_id = relative_jump_; - bytes_to_write = offsetof(ServiceEntry, mov_edx); - } - - // setup the thunk - SetInternalThunk(&full_local_thunk->internal_thunk, GetInternalThunkSize(), - remote_thunk, interceptor_); - - size_t thunk_size = GetThunkSize(); - - // copy the local thunk buffer to the child - SIZE_T written; - if (!::WriteProcessMemory(process_, remote_thunk, local_thunk, - thunk_size, &written)) { - return STATUS_UNSUCCESSFUL; - } - - if (thunk_size != written) - return STATUS_UNSUCCESSFUL; - - // and now change the function to intercept, on the child - if (NULL != ntdll_base_) { - // running a unit test - if (!::WriteProcessMemory(process_, target_, &intercepted_code, - bytes_to_write, &written)) - return STATUS_UNSUCCESSFUL; - } else { - if (!WriteProtectedChildMemory(process_, target_, &intercepted_code, - bytes_to_write)) - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -bool ServiceResolverThunk::SaveOriginalFunction(void* local_thunk, - void* remote_thunk) { - ServiceEntry function_code; - SIZE_T read; - if (!::ReadProcessMemory(process_, target_, &function_code, - sizeof(function_code), &read)) { - return false; - } - - if (sizeof(function_code) != read) - return false; - - if (kJmp32 == function_code.mov_eax) { - // Plain old entry point patch. The relative jump address follows it. - ULONG relative = function_code.service_id; - - // First, fix our copy of their patch. - relative += bit_cast<ULONG>(target_) - bit_cast<ULONG>(remote_thunk); - - function_code.service_id = relative; - - // And now, remember how to re-patch it. - ServiceFullThunk *full_thunk = - reinterpret_cast<ServiceFullThunk*>(remote_thunk); - - const ULONG kJmp32Size = 5; - - relative_jump_ = bit_cast<ULONG>(&full_thunk->internal_thunk) - - bit_cast<ULONG>(target_) - kJmp32Size; - } - - // Save the verified code - memcpy(local_thunk, &function_code, sizeof(function_code)); - - return true; -} - -bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const { - Wow64Entry function_code; - SIZE_T read; - if (!::ReadProcessMemory(process_, target_, &function_code, - sizeof(function_code), &read)) { - return false; - } - - if (sizeof(function_code) != read) - return false; - - if (kMovEax != function_code.mov_eax || kXorEcx != function_code.xor_ecx || - kLeaEdx != function_code.lea_edx || kCallFs1 != function_code.call_fs1 || - kCallFs2 != function_code.call_fs2 || - kCallFs3 != function_code.call_fs3) { - return false; - } - - if ((kAddEsp1 == function_code.add_esp1 && - kAddEsp2 == function_code.add_esp2 && - kRet == function_code.ret) || kRet == function_code.add_esp1) { - // Save the verified code - memcpy(local_thunk, &function_code, sizeof(function_code)); - return true; - } - - return false; -} - -bool Wow64W8ResolverThunk::IsFunctionAService(void* local_thunk) const { - Wow64EntryW8 function_code; - SIZE_T read; - if (!::ReadProcessMemory(process_, target_, &function_code, - sizeof(function_code), &read)) { - return false; - } - - if (sizeof(function_code) != read) - return false; - - if (kMovEax != function_code.mov_eax || kCallFs1 != function_code.call_fs1 || - kCallFs2 != function_code.call_fs2 || - kCallFs3 != function_code.call_fs3 || kRet != function_code.ret) { - return false; - } - - // Save the verified code - memcpy(local_thunk, &function_code, sizeof(function_code)); - return true; -} - -bool Win8ResolverThunk::IsFunctionAService(void* local_thunk) const { - ServiceEntryW8 function_code; - SIZE_T read; - if (!::ReadProcessMemory(process_, target_, &function_code, - sizeof(function_code), &read)) { - return false; - } - - if (sizeof(function_code) != read) - return false; - - if (kMovEax != function_code.mov_eax || kCallEip != function_code.call_eip || - function_code.call_offset != 3 || kRet != function_code.ret_p || - kMovEdxEsp != function_code.mov_edx_esp || - kSysenter != function_code.sysenter || kRet2 != function_code.ret) { - return false; - } - - // Save the verified code - memcpy(local_thunk, &function_code, sizeof(function_code)); - - return true; -} - -bool Wow64W10ResolverThunk::IsFunctionAService(void* local_thunk) const { - Wow64EntryW10 function_code; - SIZE_T read; - if (!::ReadProcessMemory(process_, target_, &function_code, - sizeof(function_code), &read)) { - return false; - } - - if (sizeof(function_code) != read) - return false; - - if (kMovEax != function_code.mov_eax || - kMovEdx != function_code.mov_edx || - kCallEdx != function_code.call_edx || - kRet != function_code.ret) { - return false; - } - - // Save the verified code - memcpy(local_thunk, &function_code, sizeof(function_code)); - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/service_resolver_64.cc b/security/sandbox/chromium/sandbox/win/src/service_resolver_64.cc deleted file mode 100644 index 25ee9db26..000000000 --- a/security/sandbox/chromium/sandbox/win/src/service_resolver_64.cc +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/service_resolver.h" - -#include <stddef.h> - -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/win_utils.h" - -namespace { -#pragma pack(push, 1) - -const ULONG kMmovR10EcxMovEax = 0xB8D18B4C; -const USHORT kSyscall = 0x050F; -const BYTE kRetNp = 0xC3; -const ULONG64 kMov1 = 0x54894808244C8948; -const ULONG64 kMov2 = 0x4C182444894C1024; -const ULONG kMov3 = 0x20244C89; -const USHORT kTestByte = 0x04F6; -const BYTE kPtr = 0x25; -const BYTE kRet = 0xC3; -const USHORT kJne = 0x0375; - -// Service code for 64 bit systems. -struct ServiceEntry { - // This struct contains roughly the following code: - // 00 mov r10,rcx - // 03 mov eax,52h - // 08 syscall - // 0a ret - // 0b xchg ax,ax - // 0e xchg ax,ax - - ULONG mov_r10_rcx_mov_eax; // = 4C 8B D1 B8 - ULONG service_id; - USHORT syscall; // = 0F 05 - BYTE ret; // = C3 - BYTE pad; // = 66 - USHORT xchg_ax_ax1; // = 66 90 - USHORT xchg_ax_ax2; // = 66 90 -}; - -// Service code for 64 bit Windows 8. -struct ServiceEntryW8 { - // This struct contains the following code: - // 00 48894c2408 mov [rsp+8], rcx - // 05 4889542410 mov [rsp+10], rdx - // 0a 4c89442418 mov [rsp+18], r8 - // 0f 4c894c2420 mov [rsp+20], r9 - // 14 4c8bd1 mov r10,rcx - // 17 b825000000 mov eax,25h - // 1c 0f05 syscall - // 1e c3 ret - // 1f 90 nop - - ULONG64 mov_1; // = 48 89 4C 24 08 48 89 54 - ULONG64 mov_2; // = 24 10 4C 89 44 24 18 4C - ULONG mov_3; // = 89 4C 24 20 - ULONG mov_r10_rcx_mov_eax; // = 4C 8B D1 B8 - ULONG service_id; - USHORT syscall; // = 0F 05 - BYTE ret; // = C3 - BYTE nop; // = 90 -}; - -// Service code for 64 bit systems with int 2e fallback. -struct ServiceEntryWithInt2E { - // This struct contains roughly the following code: - // 00 4c8bd1 mov r10,rcx - // 03 b855000000 mov eax,52h - // 08 f604250803fe7f01 test byte ptr SharedUserData!308, 1 - // 10 7503 jne [over syscall] - // 12 0f05 syscall - // 14 c3 ret - // 15 cd2e int 2e - // 17 c3 ret - - ULONG mov_r10_rcx_mov_eax; // = 4C 8B D1 B8 - ULONG service_id; - USHORT test_byte; // = F6 04 - BYTE ptr; // = 25 - ULONG user_shared_data_ptr; - BYTE one; // = 01 - USHORT jne_over_syscall; // = 75 03 - USHORT syscall; // = 0F 05 - BYTE ret; // = C3 - USHORT int2e; // = CD 2E - BYTE ret2; // = C3 -}; - -// We don't have an internal thunk for x64. -struct ServiceFullThunk { - union { - ServiceEntry original; - ServiceEntryW8 original_w8; - ServiceEntryWithInt2E original_int2e_fallback; - }; -}; - -#pragma pack(pop) - -bool IsService(const void* source) { - const ServiceEntry* service = - reinterpret_cast<const ServiceEntry*>(source); - - return (kMmovR10EcxMovEax == service->mov_r10_rcx_mov_eax && - kSyscall == service->syscall && kRetNp == service->ret); -} - -bool IsServiceW8(const void* source) { - const ServiceEntryW8* service = - reinterpret_cast<const ServiceEntryW8*>(source); - - return (kMmovR10EcxMovEax == service->mov_r10_rcx_mov_eax && - kMov1 == service->mov_1 && kMov2 == service->mov_2 && - kMov3 == service->mov_3); -} - -bool IsServiceWithInt2E(const void* source) { - const ServiceEntryWithInt2E* service = - reinterpret_cast<const ServiceEntryWithInt2E*>(source); - - return (kMmovR10EcxMovEax == service->mov_r10_rcx_mov_eax && - kTestByte == service->test_byte && kPtr == service->ptr && - kJne == service->jne_over_syscall && kSyscall == service->syscall && - kRet == service->ret && kRet == service->ret2); -} - -}; // namespace - -namespace sandbox { - -NTSTATUS ServiceResolverThunk::Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) { - NTSTATUS ret = - Init(target_module, interceptor_module, target_name, interceptor_name, - interceptor_entry_point, thunk_storage, storage_bytes); - if (!NT_SUCCESS(ret)) - return ret; - - size_t thunk_bytes = GetThunkSize(); - scoped_ptr<char[]> thunk_buffer(new char[thunk_bytes]); - ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>( - thunk_buffer.get()); - - if (!IsFunctionAService(&thunk->original)) - return STATUS_UNSUCCESSFUL; - - ret = PerformPatch(thunk, thunk_storage); - - if (NULL != storage_used) - *storage_used = thunk_bytes; - - return ret; -} - -size_t ServiceResolverThunk::GetThunkSize() const { - return sizeof(ServiceFullThunk); -} - -NTSTATUS ServiceResolverThunk::CopyThunk(const void* target_module, - const char* target_name, - BYTE* thunk_storage, - size_t storage_bytes, - size_t* storage_used) { - NTSTATUS ret = ResolveTarget(target_module, target_name, &target_); - if (!NT_SUCCESS(ret)) - return ret; - - size_t thunk_bytes = GetThunkSize(); - if (storage_bytes < thunk_bytes) - return STATUS_UNSUCCESSFUL; - - ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>(thunk_storage); - - if (!IsFunctionAService(&thunk->original)) - return STATUS_UNSUCCESSFUL; - - if (NULL != storage_used) - *storage_used = thunk_bytes; - - return ret; -} - -bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { - ServiceFullThunk function_code; - SIZE_T read; - if (!::ReadProcessMemory(process_, target_, &function_code, - sizeof(function_code), &read)) - return false; - - if (sizeof(function_code) != read) - return false; - - if (!IsService(&function_code) && !IsServiceW8(&function_code) && - !IsServiceWithInt2E(&function_code)) - return false; - - // Save the verified code. - memcpy(local_thunk, &function_code, sizeof(function_code)); - - return true; -} - -NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk, - void* remote_thunk) { - // Patch the original code. - ServiceEntry local_service; - DCHECK_NT(GetInternalThunkSize() <= sizeof(local_service)); - if (!SetInternalThunk(&local_service, sizeof(local_service), NULL, - interceptor_)) - return STATUS_UNSUCCESSFUL; - - // Copy the local thunk buffer to the child. - SIZE_T actual; - if (!::WriteProcessMemory(process_, remote_thunk, local_thunk, - sizeof(ServiceFullThunk), &actual)) - return STATUS_UNSUCCESSFUL; - - if (sizeof(ServiceFullThunk) != actual) - return STATUS_UNSUCCESSFUL; - - // And now change the function to intercept, on the child. - if (NULL != ntdll_base_) { - // Running a unit test. - if (!::WriteProcessMemory(process_, target_, &local_service, - sizeof(local_service), &actual)) - return STATUS_UNSUCCESSFUL; - } else { - if (!WriteProtectedChildMemory(process_, target_, &local_service, - sizeof(local_service))) - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const { - NOTREACHED_NT(); - return false; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/service_resolver_unittest.cc b/security/sandbox/chromium/sandbox/win/src/service_resolver_unittest.cc deleted file mode 100644 index 25d087573..000000000 --- a/security/sandbox/chromium/sandbox/win/src/service_resolver_unittest.cc +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains unit tests for ServiceResolverThunk. - -#include <stddef.h> - -#include "base/bit_cast.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/resolver.h" -#include "sandbox/win/src/sandbox_utils.h" -#include "sandbox/win/src/service_resolver.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -// This is the concrete resolver used to perform service-call type functions -// inside ntdll.dll. -template<typename T> -class ResolverThunkTest : public T { - public: - // The service resolver needs a child process to write to. - explicit ResolverThunkTest(bool relaxed) - : T(::GetCurrentProcess(), relaxed) {} - - // Sets the interception target to the desired address. - void set_target(void* target) { - fake_target_ = target; - } - - protected: - // Overrides Resolver::Init - virtual NTSTATUS Init(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes) { - NTSTATUS ret = STATUS_SUCCESS; - ret = T::Init(target_module, interceptor_module, target_name, - interceptor_name, interceptor_entry_point, thunk_storage, - storage_bytes); - EXPECT_EQ(STATUS_SUCCESS, ret); - - this->target_ = fake_target_; - - return ret; - }; - - private: - // Holds the address of the fake target. - void* fake_target_; - - DISALLOW_COPY_AND_ASSIGN(ResolverThunkTest); -}; - -typedef ResolverThunkTest<sandbox::ServiceResolverThunk> WinXpResolverTest; - -#if !defined(_WIN64) -typedef ResolverThunkTest<sandbox::Win8ResolverThunk> Win8ResolverTest; -typedef ResolverThunkTest<sandbox::Wow64ResolverThunk> Wow64ResolverTest; -typedef ResolverThunkTest<sandbox::Wow64W8ResolverThunk> Wow64W8ResolverTest; -typedef ResolverThunkTest<sandbox::Wow64W10ResolverThunk> Wow64W10ResolverTest; -#endif - -const BYTE kJump32 = 0xE9; - -void CheckJump(void* source, void* target) { -#pragma pack(push) -#pragma pack(1) - struct Code { - BYTE jump; - ULONG delta; - }; -#pragma pack(pop) - -#if defined(_WIN64) - FAIL() << "Running 32-bit codepath"; -#else - Code* patched = reinterpret_cast<Code*>(source); - EXPECT_EQ(kJump32, patched->jump); - - ULONG source_addr = bit_cast<ULONG>(source); - ULONG target_addr = bit_cast<ULONG>(target); - EXPECT_EQ(target_addr + 19 - source_addr, patched->delta); -#endif -} - -NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed, - sandbox::ServiceResolverThunk* resolver) { - HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll"); - EXPECT_TRUE(NULL != ntdll_base); - - void* target = ::GetProcAddress(ntdll_base, function); - EXPECT_TRUE(NULL != target); - if (NULL == target) - return STATUS_UNSUCCESSFUL; - - BYTE service[50]; - memcpy(service, target, sizeof(service)); - - static_cast<WinXpResolverTest*>(resolver)->set_target(service); - - // Any pointer will do as an interception_entry_point - void* function_entry = resolver; - size_t thunk_size = resolver->GetThunkSize(); - scoped_ptr<char[]> thunk(new char[thunk_size]); - size_t used; - - resolver->AllowLocalPatches(); - - NTSTATUS ret = resolver->Setup(ntdll_base, NULL, function, NULL, - function_entry, thunk.get(), thunk_size, - &used); - if (NT_SUCCESS(ret)) { - EXPECT_EQ(thunk_size, used); - EXPECT_NE(0, memcmp(service, target, sizeof(service))); - EXPECT_NE(kJump32, service[0]); - - if (relaxed) { - // It's already patched, let's patch again, and simulate a direct patch. - service[0] = kJump32; - ret = resolver->Setup(ntdll_base, NULL, function, NULL, function_entry, - thunk.get(), thunk_size, &used); - CheckJump(service, thunk.get()); - } - } - - return ret; -} - -sandbox::ServiceResolverThunk* GetTestResolver(bool relaxed) { -#if defined(_WIN64) - return new WinXpResolverTest(relaxed); -#else - base::win::OSInfo* os_info = base::win::OSInfo::GetInstance(); - if (os_info->wow64_status() == base::win::OSInfo::WOW64_ENABLED) { - if (os_info->version() >= base::win::VERSION_WIN10) - return new Wow64W10ResolverTest(relaxed); - if (os_info->version() >= base::win::VERSION_WIN8) - return new Wow64W8ResolverTest(relaxed); - return new Wow64ResolverTest(relaxed); - } - - if (os_info->version() >= base::win::VERSION_WIN8) - return new Win8ResolverTest(relaxed); - - return new WinXpResolverTest(relaxed); -#endif -} - -NTSTATUS PatchNtdll(const char* function, bool relaxed) { - sandbox::ServiceResolverThunk* resolver = GetTestResolver(relaxed); - - NTSTATUS ret = PatchNtdllWithResolver(function, relaxed, resolver); - delete resolver; - return ret; -} - -TEST(ServiceResolverTest, PatchesServices) { - NTSTATUS ret = PatchNtdll("NtClose", false); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError(); - - ret = PatchNtdll("NtCreateFile", false); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " << - ::GetLastError(); - - ret = PatchNtdll("NtCreateMutant", false); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " << - ::GetLastError(); - - ret = PatchNtdll("NtMapViewOfSection", false); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " << - ::GetLastError(); -} - -TEST(ServiceResolverTest, FailsIfNotService) { -#if !defined(_WIN64) - EXPECT_NE(STATUS_SUCCESS, PatchNtdll("RtlUlongByteSwap", false)); -#endif - - EXPECT_NE(STATUS_SUCCESS, PatchNtdll("LdrLoadDll", false)); -} - -TEST(ServiceResolverTest, PatchesPatchedServices) { -// We don't support "relaxed mode" for Win64 apps. -#if !defined(_WIN64) - NTSTATUS ret = PatchNtdll("NtClose", true); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError(); - - ret = PatchNtdll("NtCreateFile", true); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " << - ::GetLastError(); - - ret = PatchNtdll("NtCreateMutant", true); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " << - ::GetLastError(); - - ret = PatchNtdll("NtMapViewOfSection", true); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " << - ::GetLastError(); -#endif -} - -TEST(ServiceResolverTest, MultiplePatchedServices) { -// We don't support "relaxed mode" for Win64 apps. -#if !defined(_WIN64) - sandbox::ServiceResolverThunk* resolver = GetTestResolver(true); - NTSTATUS ret = PatchNtdllWithResolver("NtClose", true, resolver); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtClose, last error: " << ::GetLastError(); - - ret = PatchNtdllWithResolver("NtCreateFile", true, resolver); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateFile, last error: " << - ::GetLastError(); - - ret = PatchNtdllWithResolver("NtCreateMutant", true, resolver); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtCreateMutant, last error: " << - ::GetLastError(); - - ret = PatchNtdllWithResolver("NtMapViewOfSection", true, resolver); - EXPECT_EQ(STATUS_SUCCESS, ret) << "NtMapViewOfSection, last error: " << - ::GetLastError(); - delete resolver; -#endif -} - -TEST(ServiceResolverTest, LocalPatchesAllowed) { - sandbox::ServiceResolverThunk* resolver = GetTestResolver(true); - - HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll"); - ASSERT_TRUE(NULL != ntdll_base); - - const char kFunctionName[] = "NtClose"; - - void* target = ::GetProcAddress(ntdll_base, kFunctionName); - ASSERT_TRUE(NULL != target); - - BYTE service[50]; - memcpy(service, target, sizeof(service)); - static_cast<WinXpResolverTest*>(resolver)->set_target(service); - - // Any pointer will do as an interception_entry_point - void* function_entry = resolver; - size_t thunk_size = resolver->GetThunkSize(); - scoped_ptr<char[]> thunk(new char[thunk_size]); - size_t used; - - NTSTATUS ret = STATUS_UNSUCCESSFUL; - - // First try patching without having allowed local patches. - ret = resolver->Setup(ntdll_base, NULL, kFunctionName, NULL, - function_entry, thunk.get(), thunk_size, - &used); - EXPECT_FALSE(NT_SUCCESS(ret)); - - // Now allow local patches and check that things work. - resolver->AllowLocalPatches(); - ret = resolver->Setup(ntdll_base, NULL, kFunctionName, NULL, - function_entry, thunk.get(), thunk_size, - &used); - EXPECT_EQ(STATUS_SUCCESS, ret); -} - -} // namespace diff --git a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.cc b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.cc deleted file mode 100644 index eac13937c..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.cc +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <string.h> - -#include "base/logging.h" -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/crosscall_params.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" - -namespace sandbox { - -// Get the base of the data buffer of the channel; this is where the input -// parameters get serialized. Since they get serialized directly into the -// channel we avoid one copy. -void* SharedMemIPCClient::GetBuffer() { - bool failure = false; - size_t ix = LockFreeChannel(&failure); - if (failure) { - return NULL; - } - return reinterpret_cast<char*>(control_) + - control_->channels[ix].channel_base; -} - -// If we need to cancel an IPC before issuing DoCall -// our client should call FreeBuffer with the same pointer -// returned by GetBuffer. -void SharedMemIPCClient::FreeBuffer(void* buffer) { - size_t num = ChannelIndexFromBuffer(buffer); - ChannelControl* channel = control_->channels; - LONG result = ::InterlockedExchange(&channel[num].state, kFreeChannel); - DCHECK_NE(kFreeChannel, static_cast<ChannelState>(result)); -} - -// The constructor simply casts the shared memory to the internal -// structures. This is a cheap step that is why this IPC object can -// and should be constructed per call. -SharedMemIPCClient::SharedMemIPCClient(void* shared_mem) - : control_(reinterpret_cast<IPCControl*>(shared_mem)) { - first_base_ = reinterpret_cast<char*>(shared_mem) + - control_->channels[0].channel_base; - // There must be at least one channel. - DCHECK(0 != control_->channels_count); -} - -// Do the IPC. At this point the channel should have already been -// filled with the serialized input parameters. -// We follow the pattern explained in the header file. -ResultCode SharedMemIPCClient::DoCall(CrossCallParams* params, - CrossCallReturn* answer) { - if (!control_->server_alive) - return SBOX_ERROR_CHANNEL_ERROR; - - size_t num = ChannelIndexFromBuffer(params->GetBuffer()); - ChannelControl* channel = control_->channels; - // Note that the IPC tag goes outside the buffer as well inside - // the buffer. This should enable the server to prioritize based on - // IPC tags without having to de-serialize the entire message. - channel[num].ipc_tag = params->GetTag(); - - // Wait for the server to service this IPC call. After kIPCWaitTimeOut1 - // we check if the server_alive mutex was abandoned which will indicate - // that the server has died. - - // While the atomic signaling and waiting is not a requirement, it - // is nice because we save a trip to kernel. - DWORD wait = ::SignalObjectAndWait(channel[num].ping_event, - channel[num].pong_event, - kIPCWaitTimeOut1, FALSE); - if (WAIT_TIMEOUT == wait) { - // The server is taking too long. Enter a loop were we check if the - // server_alive mutex has been abandoned which would signal a server crash - // or else we keep waiting for a response. - while (true) { - wait = ::WaitForSingleObject(control_->server_alive, 0); - if (WAIT_TIMEOUT == wait) { - // Server seems still alive. We already signaled so here we just wait. - wait = ::WaitForSingleObject(channel[num].pong_event, kIPCWaitTimeOut1); - if (WAIT_OBJECT_0 == wait) { - // The server took a long time but responded. - break; - } else if (WAIT_TIMEOUT == wait) { - continue; - } else { - return SBOX_ERROR_CHANNEL_ERROR; - } - } else { - // The server has crashed and windows has signaled the mutex as - // abandoned. - ::InterlockedExchange(&channel[num].state, kAbandonedChannel); - control_->server_alive = 0; - return SBOX_ERROR_CHANNEL_ERROR; - } - } - } else if (WAIT_OBJECT_0 != wait) { - // Probably the server crashed before the kIPCWaitTimeOut1 occurred. - return SBOX_ERROR_CHANNEL_ERROR; - } - - // The server has returned an answer, copy it and free the channel. - memcpy(answer, params->GetCallReturn(), sizeof(CrossCallReturn)); - - // Return the IPC state It can indicate that while the IPC has - // completed some error in the Broker has caused to not return valid - // results. - return answer->call_outcome; -} - -// Locking a channel is a simple as looping over all the channels -// looking for one that is has state = kFreeChannel and atomically -// swapping it to kBusyChannel. -// If there is no free channel, then we must back off so some other -// thread makes progress and frees a channel. To back off we sleep. -size_t SharedMemIPCClient::LockFreeChannel(bool* severe_failure) { - if (0 == control_->channels_count) { - *severe_failure = true; - return 0; - } - ChannelControl* channel = control_->channels; - do { - for (size_t ix = 0; ix != control_->channels_count; ++ix) { - if (kFreeChannel == ::InterlockedCompareExchange(&channel[ix].state, - kBusyChannel, - kFreeChannel)) { - *severe_failure = false; - return ix; - } - } - // We did not find any available channel, maybe the server is dead. - DWORD wait = ::WaitForSingleObject(control_->server_alive, - kIPCWaitTimeOut2); - if (WAIT_TIMEOUT != wait) { - // The server is dead and we outlive it enough to get in trouble. - *severe_failure = true; - return 0; - } - } - while (true); -} - -// Find out which channel we are from the pointer returned by GetBuffer. -size_t SharedMemIPCClient::ChannelIndexFromBuffer(const void* buffer) { - ptrdiff_t d = reinterpret_cast<const char*>(buffer) - first_base_; - size_t num = d/kIPCChannelSize; - DCHECK_LT(num, control_->channels_count); - return (num); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h deleted file mode 100644 index 67fd06359..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__ -#define SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__ - -#include <stddef.h> -#include <stdint.h> - -#include "sandbox/win/src/crosscall_params.h" -#include "sandbox/win/src/sandbox.h" - -// IPC transport implementation that uses shared memory. -// This is the client side -// -// The shared memory is divided on blocks called channels, and potentially -// it can perform as many concurrent IPC calls as channels. The IPC over -// each channel is strictly synchronous for the client. -// -// Each channel as a channel control section associated with. Each control -// section has two kernel events (known as ping and pong) and a integer -// variable that maintains a state -// -// this is the state diagram of a channel: -// -// locked in service -// kFreeChannel---------->BusyChannel-------------->kAckChannel -// ^ | -// |_________________________________________________| -// answer ready -// -// The protocol is as follows: -// 1) client finds a free channel: state = kFreeChannel -// 2) does an atomic compare-and-swap, now state = BusyChannel -// 3) client writes the data into the channel buffer -// 4) client signals the ping event and waits (blocks) on the pong event -// 5) eventually the server signals the pong event -// 6) the client awakes and reads the answer from the same channel -// 7) the client updates its InOut parameters with the new data from the -// shared memory section. -// 8) the client atomically sets the state = kFreeChannel -// -// In the shared memory the layout is as follows: -// -// [ channel count ] -// [ channel control 0] -// [ channel control 1] -// [ channel control N] -// [ channel buffer 0 ] 1024 bytes -// [ channel buffer 1 ] 1024 bytes -// [ channel buffer N ] 1024 bytes -// -// By default each channel buffer is 1024 bytes -namespace sandbox { - -// the possible channel states as described above -enum ChannelState { - // channel is free - kFreeChannel = 1, - // IPC in progress client side - kBusyChannel, - // IPC in progress server side - kAckChannel, - // not used right now - kReadyChannel, - // IPC abandoned by client side - kAbandonedChannel -}; - -// The next two constants control the time outs for the IPC. -const DWORD kIPCWaitTimeOut1 = 1000; // Milliseconds. -const DWORD kIPCWaitTimeOut2 = 50; // Milliseconds. - -// the channel control structure -struct ChannelControl { - // points to be beginning of the channel buffer, where data goes - size_t channel_base; - // maintains the state from the ChannelState enumeration - volatile LONG state; - // the ping event is signaled by the client when the IPC data is ready on - // the buffer - HANDLE ping_event; - // the client waits on the pong event for the IPC answer back - HANDLE pong_event; - // the IPC unique identifier - uint32_t ipc_tag; -}; - -struct IPCControl { - // total number of channels available, some might be busy at a given time - size_t channels_count; - // handle to a shared mutex to detect when the server is dead - HANDLE server_alive; - // array of channel control structures - ChannelControl channels[1]; -}; - -// the actual shared memory IPC implementation class. This object is designed -// to be lightweight so it can be constructed on-site (at the calling place) -// wherever an IPC call is needed. -class SharedMemIPCClient { - public: - // Creates the IPC client. - // as parameter it takes the base address of the shared memory - explicit SharedMemIPCClient(void* shared_mem); - - // locks a free channel and returns the channel buffer memory base. This call - // blocks until there is a free channel - void* GetBuffer(); - - // releases the lock on the channel, for other to use. call this if you have - // called GetBuffer and you want to abort but have not called yet DoCall() - void FreeBuffer(void* buffer); - - // Performs the actual IPC call. - // params: The blob of packed input parameters. - // answer: upon IPC completion, it contains the server answer to the IPC. - // If the return value is not SBOX_ERROR_CHANNEL_ERROR, the caller has to free - // the channel. - // returns ALL_OK if the IPC mechanism successfully delivered. You still need - // to check on the answer structure to see the actual IPC result. - ResultCode DoCall(CrossCallParams* params, CrossCallReturn* answer); - - private: - // Returns the index of the first free channel. It sets 'severe_failure' - // to true if there is an unrecoverable error that does not allow to - // find a channel. - size_t LockFreeChannel(bool* severe_failure); - // Return the channel index given the address of the buffer. - size_t ChannelIndexFromBuffer(const void* buffer); - IPCControl* control_; - // point to the first channel base - char* first_base_; -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.cc b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.cc deleted file mode 100644 index cf2d800e5..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.cc +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "base/callback.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" -#include "sandbox/win/src/crosscall_params.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/sharedmem_ipc_server.h" - -namespace { -// This handle must not be closed. -volatile HANDLE g_alive_mutex = NULL; -} - -namespace sandbox { - -SharedMemIPCServer::ServerControl::ServerControl() { -} - -SharedMemIPCServer::ServerControl::~ServerControl() { -} - -SharedMemIPCServer::SharedMemIPCServer(HANDLE target_process, - DWORD target_process_id, - ThreadProvider* thread_provider, - Dispatcher* dispatcher) - : client_control_(NULL), - thread_provider_(thread_provider), - target_process_(target_process), - target_process_id_(target_process_id), - call_dispatcher_(dispatcher) { - // We create a initially owned mutex. If the server dies unexpectedly, - // the thread that owns it will fail to release the lock and windows will - // report to the target (when it tries to acquire it) that the wait was - // abandoned. Note: We purposely leak the local handle because we want it to - // be closed by Windows itself so it is properly marked as abandoned if the - // server dies. - if (!g_alive_mutex) { - HANDLE mutex = ::CreateMutexW(NULL, TRUE, NULL); - if (::InterlockedCompareExchangePointer(&g_alive_mutex, mutex, NULL)) { - // We lost the race to create the mutex. - ::CloseHandle(mutex); - } - } -} - -SharedMemIPCServer::~SharedMemIPCServer() { - // Free the wait handles associated with the thread pool. - if (!thread_provider_->UnRegisterWaits(this)) { - // Better to leak than to crash. - return; - } - STLDeleteElements(&server_contexts_); - - if (client_control_) - ::UnmapViewOfFile(client_control_); -} - -bool SharedMemIPCServer::Init(void* shared_mem, - uint32_t shared_size, - uint32_t channel_size) { - // The shared memory needs to be at least as big as a channel. - if (shared_size < channel_size) { - return false; - } - // The channel size should be aligned. - if (0 != (channel_size % 32)) { - return false; - } - - // Calculate how many channels we can fit in the shared memory. - shared_size -= offsetof(IPCControl, channels); - size_t channel_count = shared_size / (sizeof(ChannelControl) + channel_size); - - // If we cannot fit even one channel we bail out. - if (0 == channel_count) { - return false; - } - // Calculate the start of the first channel. - size_t base_start = (sizeof(ChannelControl)* channel_count) + - offsetof(IPCControl, channels); - - client_control_ = reinterpret_cast<IPCControl*>(shared_mem); - client_control_->channels_count = 0; - - // This is the initialization that we do per-channel. Basically: - // 1) make two events (ping & pong) - // 2) create handles to the events for the client and the server. - // 3) initialize the channel (client_context) with the state. - // 4) initialize the server side of the channel (service_context). - // 5) call the thread provider RegisterWait to register the ping events. - for (size_t ix = 0; ix != channel_count; ++ix) { - ChannelControl* client_context = &client_control_->channels[ix]; - ServerControl* service_context = new ServerControl; - server_contexts_.push_back(service_context); - - if (!MakeEvents(&service_context->ping_event, - &service_context->pong_event, - &client_context->ping_event, - &client_context->pong_event)) { - return false; - } - - client_context->channel_base = base_start; - client_context->state = kFreeChannel; - - // Note that some of these values are available as members of this object - // but we put them again into the service_context because we will be called - // on a static method (ThreadPingEventReady). In particular, target_process_ - // is a raw handle that is not owned by this object (it's owned by the - // owner of this object), and we are storing it in multiple places. - service_context->shared_base = reinterpret_cast<char*>(shared_mem); - service_context->channel_size = channel_size; - service_context->channel = client_context; - service_context->channel_buffer = service_context->shared_base + - client_context->channel_base; - service_context->dispatcher = call_dispatcher_; - service_context->target_info.process = target_process_; - service_context->target_info.process_id = target_process_id_; - // Advance to the next channel. - base_start += channel_size; - // Register the ping event with the threadpool. - thread_provider_->RegisterWait(this, service_context->ping_event.Get(), - ThreadPingEventReady, service_context); - } - if (!::DuplicateHandle(::GetCurrentProcess(), g_alive_mutex, - target_process_, &client_control_->server_alive, - SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, 0)) { - return false; - } - // This last setting indicates to the client all is setup. - client_control_->channels_count = channel_count; - return true; -} - -// Releases memory allocated for IPC arguments, if needed. -void ReleaseArgs(const IPCParams* ipc_params, void* args[kMaxIpcParams]) { - for (size_t i = 0; i < kMaxIpcParams; i++) { - switch (ipc_params->args[i]) { - case WCHAR_TYPE: { - delete reinterpret_cast<base::string16*>(args[i]); - args[i] = NULL; - break; - } - case INOUTPTR_TYPE: { - delete reinterpret_cast<CountedBuffer*>(args[i]); - args[i] = NULL; - break; - } - default: break; - } - } -} - -// Fills up the list of arguments (args and ipc_params) for an IPC call. -bool GetArgs(CrossCallParamsEx* params, IPCParams* ipc_params, - void* args[kMaxIpcParams]) { - if (kMaxIpcParams < params->GetParamsCount()) - return false; - - for (uint32_t i = 0; i < params->GetParamsCount(); i++) { - uint32_t size; - ArgType type; - args[i] = params->GetRawParameter(i, &size, &type); - if (args[i]) { - ipc_params->args[i] = type; - switch (type) { - case WCHAR_TYPE: { - scoped_ptr<base::string16> data(new base::string16); - if (!params->GetParameterStr(i, data.get())) { - args[i] = 0; - ReleaseArgs(ipc_params, args); - return false; - } - args[i] = data.release(); - break; - } - case UINT32_TYPE: { - uint32_t data; - if (!params->GetParameter32(i, &data)) { - ReleaseArgs(ipc_params, args); - return false; - } - IPCInt ipc_int(data); - args[i] = ipc_int.AsVoidPtr(); - break; - } - case VOIDPTR_TYPE : { - void* data; - if (!params->GetParameterVoidPtr(i, &data)) { - ReleaseArgs(ipc_params, args); - return false; - } - args[i] = data; - break; - } - case INOUTPTR_TYPE: { - if (!args[i]) { - ReleaseArgs(ipc_params, args); - return false; - } - CountedBuffer* buffer = new CountedBuffer(args[i] , size); - args[i] = buffer; - break; - } - default: break; - } - } - } - return true; -} - -bool SharedMemIPCServer::InvokeCallback(const ServerControl* service_context, - void* ipc_buffer, - CrossCallReturn* call_result) { - // Set the default error code; - SetCallError(SBOX_ERROR_INVALID_IPC, call_result); - uint32_t output_size = 0; - // Parse, verify and copy the message. The handler operates on a copy - // of the message so the client cannot play dirty tricks by changing the - // data in the channel while the IPC is being processed. - scoped_ptr<CrossCallParamsEx> params( - CrossCallParamsEx::CreateFromBuffer(ipc_buffer, - service_context->channel_size, - &output_size)); - if (!params.get()) - return false; - - uint32_t tag = params->GetTag(); - static_assert(0 == INVALID_TYPE, "incorrect type enum"); - IPCParams ipc_params = {0}; - ipc_params.ipc_tag = tag; - - void* args[kMaxIpcParams]; - if (!GetArgs(params.get(), &ipc_params, args)) - return false; - - IPCInfo ipc_info = {0}; - ipc_info.ipc_tag = tag; - ipc_info.client_info = &service_context->target_info; - Dispatcher* dispatcher = service_context->dispatcher; - DCHECK(dispatcher); - bool error = true; - Dispatcher* handler = NULL; - - Dispatcher::CallbackGeneric callback_generic; - handler = dispatcher->OnMessageReady(&ipc_params, &callback_generic); - if (handler) { - switch (params->GetParamsCount()) { - case 0: { - // Ask the IPC dispatcher if she can service this IPC. - Dispatcher::Callback0 callback = - reinterpret_cast<Dispatcher::Callback0>(callback_generic); - if (!(handler->*callback)(&ipc_info)) - break; - error = false; - break; - } - case 1: { - Dispatcher::Callback1 callback = - reinterpret_cast<Dispatcher::Callback1>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0])) - break; - error = false; - break; - } - case 2: { - Dispatcher::Callback2 callback = - reinterpret_cast<Dispatcher::Callback2>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0], args[1])) - break; - error = false; - break; - } - case 3: { - Dispatcher::Callback3 callback = - reinterpret_cast<Dispatcher::Callback3>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2])) - break; - error = false; - break; - } - case 4: { - Dispatcher::Callback4 callback = - reinterpret_cast<Dispatcher::Callback4>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], - args[3])) - break; - error = false; - break; - } - case 5: { - Dispatcher::Callback5 callback = - reinterpret_cast<Dispatcher::Callback5>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], - args[4])) - break; - error = false; - break; - } - case 6: { - Dispatcher::Callback6 callback = - reinterpret_cast<Dispatcher::Callback6>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], - args[4], args[5])) - break; - error = false; - break; - } - case 7: { - Dispatcher::Callback7 callback = - reinterpret_cast<Dispatcher::Callback7>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], - args[4], args[5], args[6])) - break; - error = false; - break; - } - case 8: { - Dispatcher::Callback8 callback = - reinterpret_cast<Dispatcher::Callback8>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], - args[4], args[5], args[6], args[7])) - break; - error = false; - break; - } - case 9: { - Dispatcher::Callback9 callback = - reinterpret_cast<Dispatcher::Callback9>(callback_generic); - if (!(handler->*callback)(&ipc_info, args[0], args[1], args[2], args[3], - args[4], args[5], args[6], args[7], args[8])) - break; - error = false; - break; - } - default: { - NOTREACHED(); - break; - } - } - } - - if (error) { - if (handler) - SetCallError(SBOX_ERROR_FAILED_IPC, call_result); - } else { - memcpy(call_result, &ipc_info.return_info, sizeof(*call_result)); - SetCallSuccess(call_result); - if (params->IsInOut()) { - // Maybe the params got changed by the broker. We need to upadte the - // memory section. - memcpy(ipc_buffer, params.get(), output_size); - } - } - - ReleaseArgs(&ipc_params, args); - - return !error; -} - -// This function gets called by a thread from the thread pool when a -// ping event fires. The context is the same as passed in the RegisterWait() -// call above. -void __stdcall SharedMemIPCServer::ThreadPingEventReady(void* context, - unsigned char) { - if (NULL == context) { - DCHECK(false); - return; - } - ServerControl* service_context = reinterpret_cast<ServerControl*>(context); - // Since the event fired, the channel *must* be busy. Change to kAckChannel - // while we service it. - LONG last_state = - ::InterlockedCompareExchange(&service_context->channel->state, - kAckChannel, kBusyChannel); - if (kBusyChannel != last_state) { - DCHECK(false); - return; - } - - // Prepare the result structure. At this point we will return some result - // even if the IPC is invalid, malformed or has no handler. - CrossCallReturn call_result = {0}; - void* buffer = service_context->channel_buffer; - - InvokeCallback(service_context, buffer, &call_result); - - // Copy the answer back into the channel and signal the pong event. This - // should wake up the client so he can finish the the ipc cycle. - CrossCallParams* call_params = reinterpret_cast<CrossCallParams*>(buffer); - memcpy(call_params->GetCallReturn(), &call_result, sizeof(call_result)); - ::InterlockedExchange(&service_context->channel->state, kAckChannel); - ::SetEvent(service_context->pong_event.Get()); -} - -bool SharedMemIPCServer::MakeEvents(base::win::ScopedHandle* server_ping, - base::win::ScopedHandle* server_pong, - HANDLE* client_ping, HANDLE* client_pong) { - // Note that the IPC client has no right to delete the events. That would - // cause problems. The server *owns* the events. - const DWORD kDesiredAccess = SYNCHRONIZE | EVENT_MODIFY_STATE; - - // The events are auto reset, and start not signaled. - server_ping->Set(::CreateEventW(NULL, FALSE, FALSE, NULL)); - if (!::DuplicateHandle(::GetCurrentProcess(), server_ping->Get(), - target_process_, client_ping, kDesiredAccess, FALSE, - 0)) { - return false; - } - - server_pong->Set(::CreateEventW(NULL, FALSE, FALSE, NULL)); - if (!::DuplicateHandle(::GetCurrentProcess(), server_pong->Get(), - target_process_, client_pong, kDesiredAccess, FALSE, - 0)) { - return false; - } - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.h b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.h deleted file mode 100644 index 5afca1d6c..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_ -#define SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_ - -#include <stdint.h> - -#include <list> - -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/crosscall_params.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" - -// IPC transport implementation that uses shared memory. -// This is the server side -// -// The server side has knowledge about the layout of the shared memory -// and the state transitions. Both are explained in sharedmem_ipc_client.h -// -// As opposed to SharedMemIPClient, the Server object should be one for the -// entire lifetime of the target process. The server is in charge of creating -// the events (ping, pong) both for the client and for the target that are used -// to signal the IPC and also in charge of setting the initial state of the -// channels. -// -// When an IPC is ready, the server relies on being called by on the -// ThreadPingEventReady callback. The IPC server then retrieves the buffer, -// marshals it into a CrossCallParam object and calls the Dispatcher, who is in -// charge of fulfilling the IPC request. -namespace sandbox { - -// the shared memory implementation of the IPC server. There should be one -// of these objects per target (IPC client) process -class SharedMemIPCServer { - public: - // Creates the IPC server. - // target_process: handle to the target process. It must be suspended. It is - // unfortunate to receive a raw handle (and store it inside this object) as - // that dilutes ownership of the process, but in practice a SharedMemIPCServer - // is owned by TargetProcess, which calls this method, and owns the handle, so - // everything is safe. If that changes, we should break this dependency and - // duplicate the handle instead. - // target_process_id: process id of the target process. - // thread_provider: a thread provider object. - // dispatcher: an object that can service IPC calls. - SharedMemIPCServer(HANDLE target_process, DWORD target_process_id, - ThreadProvider* thread_provider, Dispatcher* dispatcher); - - ~SharedMemIPCServer(); - - // Initializes the server structures, shared memory structures and - // creates the kernels events used to signal the IPC. - bool Init(void* shared_mem, uint32_t shared_size, uint32_t channel_size); - - private: - // Allow tests to be marked DISABLED_. Note that FLAKY_ and FAILS_ prefixes - // do not work with sandbox tests. - FRIEND_TEST_ALL_PREFIXES(IPCTest, SharedMemServerTests); - // When an event fires (IPC request). A thread from the ThreadProvider - // will call this function. The context parameter should be the same as - // provided when ThreadProvider::RegisterWait was called. - static void __stdcall ThreadPingEventReady(void* context, - unsigned char); - - // Makes the client and server events. This function is called once - // per channel. - bool MakeEvents(base::win::ScopedHandle* server_ping, - base::win::ScopedHandle* server_pong, - HANDLE* client_ping, HANDLE* client_pong); - - // A copy this structure is maintained per channel. - // Note that a lot of the fields are just the same of what we have in the IPC - // object itself. It is better to have the copies since we can dispatch in the - // static method without worrying about converting back to a member function - // call or about threading issues. - struct ServerControl { - ServerControl(); - ~ServerControl(); - - // This channel server ping event. - base::win::ScopedHandle ping_event; - // This channel server pong event. - base::win::ScopedHandle pong_event; - // The size of this channel. - uint32_t channel_size; - // The pointer to the actual channel data. - char* channel_buffer; - // The pointer to the base of the shared memory. - char* shared_base; - // A pointer to this channel's client-side control structure this structure - // lives in the shared memory. - ChannelControl* channel; - // the IPC dispatcher associated with this channel. - Dispatcher* dispatcher; - // The target process information associated with this channel. - ClientInfo target_info; - }; - - // Looks for the appropriate handler for this IPC and invokes it. - static bool InvokeCallback(const ServerControl* service_context, - void* ipc_buffer, CrossCallReturn* call_result); - - // Points to the shared memory channel control which lives at - // the start of the shared section. - IPCControl* client_control_; - - // Keeps track of the server side objects that are used to answer an IPC. - typedef std::list<ServerControl*> ServerContexts; - ServerContexts server_contexts_; - - // The thread provider provides the threads that call back into this object - // when the IPC events fire. - ThreadProvider* thread_provider_; - - // The IPC object is associated with a target process. - HANDLE target_process_; - - // The target process id associated with the IPC object. - DWORD target_process_id_; - - // The dispatcher handles 'ready' IPC calls. - Dispatcher* call_dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(SharedMemIPCServer); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/sid.cc b/security/sandbox/chromium/sandbox/win/src/sid.cc deleted file mode 100644 index 19c645bf6..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sid.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sid.h" - -#include "base/logging.h" - -namespace sandbox { - -Sid::Sid(const SID *sid) { - ::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid)); -}; - -Sid::Sid(WELL_KNOWN_SID_TYPE type) { - DWORD size_sid = SECURITY_MAX_SID_SIZE; - BOOL result = ::CreateWellKnownSid(type, NULL, sid_, &size_sid); - DCHECK(result); - (void)result; -} - -const SID *Sid::GetPSID() const { - return reinterpret_cast<SID*>(const_cast<BYTE*>(sid_)); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sid.h b/security/sandbox/chromium/sandbox/win/src/sid.h deleted file mode 100644 index 4656859be..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sid.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SID_H_ -#define SANDBOX_SRC_SID_H_ - -#include <windows.h> - -namespace sandbox { - -// This class is used to hold and generate SIDS. -class Sid { - public: - // Constructors initializing the object with the SID passed. - // This is a converting constructor. It is not explicit. - Sid(const SID *sid); - Sid(WELL_KNOWN_SID_TYPE type); - - // Returns sid_. - const SID *GetPSID() const; - - private: - BYTE sid_[SECURITY_MAX_SID_SIZE]; -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_SID_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/sid_unittest.cc b/security/sandbox/chromium/sandbox/win/src/sid_unittest.cc deleted file mode 100644 index 76d61e82f..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sid_unittest.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains unit tests for the sid class. - -#define _ATL_NO_EXCEPTIONS -#include <atlbase.h> -#include <atlsecurity.h> - -#include "sandbox/win/src/sid.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -// Calls ::EqualSid. This function exists only to simplify the calls to -// ::EqualSid by removing the need to cast the input params. -BOOL EqualSid(const SID *sid1, const SID *sid2) { - return ::EqualSid(const_cast<SID*>(sid1), const_cast<SID*>(sid2)); -} - -// Tests the creation if a Sid -TEST(SidTest, Constructors) { - ATL::CSid sid_world = ATL::Sids::World(); - SID *sid_world_pointer = const_cast<SID*>(sid_world.GetPSID()); - - // Check the SID* constructor - Sid sid_sid_star(sid_world_pointer); - ASSERT_TRUE(EqualSid(sid_world_pointer, sid_sid_star.GetPSID())); - - // Check the copy constructor - Sid sid_copy(sid_sid_star); - ASSERT_TRUE(EqualSid(sid_world_pointer, sid_copy.GetPSID())); - - // Note that the WELL_KNOWN_SID_TYPE constructor is tested in the GetPSID - // test. -} - -// Tests the method GetPSID -TEST(SidTest, GetPSID) { - // Check for non-null result; - ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinLocalSid).GetPSID()); - ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinCreatorOwnerSid).GetPSID()); - ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinBatchSid).GetPSID()); - - ASSERT_TRUE(EqualSid(Sid(::WinNullSid).GetPSID(), - ATL::Sids::Null().GetPSID())); - - ASSERT_TRUE(EqualSid(Sid(::WinWorldSid).GetPSID(), - ATL::Sids::World().GetPSID())); - - ASSERT_TRUE(EqualSid(Sid(::WinDialupSid).GetPSID(), - ATL::Sids::Dialup().GetPSID())); - - ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid).GetPSID(), - ATL::Sids::Network().GetPSID())); - - ASSERT_TRUE(EqualSid(Sid(::WinBuiltinAdministratorsSid).GetPSID(), - ATL::Sids::Admins().GetPSID())); - - ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid).GetPSID(), - ATL::Sids::Users().GetPSID())); - - ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid).GetPSID(), - ATL::Sids::Guests().GetPSID())); - - ASSERT_TRUE(EqualSid(Sid(::WinProxySid).GetPSID(), - ATL::Sids::Proxy().GetPSID())); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep/ia32_modrm_map.cpp b/security/sandbox/chromium/sandbox/win/src/sidestep/ia32_modrm_map.cpp deleted file mode 100644 index 89bc1895e..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep/ia32_modrm_map.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Table of relevant information about how to decode the ModR/M byte. -// Based on information in the IA-32 Intel Architecture -// Software Developer's Manual Volume 2: Instruction Set Reference. - -#include "sandbox/win/src/sidestep/mini_disassembler.h" -#include "sandbox/win/src/sidestep/mini_disassembler_types.h" - -namespace sidestep { - -const ModrmEntry MiniDisassembler::s_ia16_modrm_map_[] = { -// mod == 00 - /* r/m == 000 */ { false, false, OS_ZERO }, - /* r/m == 001 */ { false, false, OS_ZERO }, - /* r/m == 010 */ { false, false, OS_ZERO }, - /* r/m == 011 */ { false, false, OS_ZERO }, - /* r/m == 100 */ { false, false, OS_ZERO }, - /* r/m == 101 */ { false, false, OS_ZERO }, - /* r/m == 110 */ { true, false, OS_WORD }, - /* r/m == 111 */ { false, false, OS_ZERO }, -// mod == 01 - /* r/m == 000 */ { true, false, OS_BYTE }, - /* r/m == 001 */ { true, false, OS_BYTE }, - /* r/m == 010 */ { true, false, OS_BYTE }, - /* r/m == 011 */ { true, false, OS_BYTE }, - /* r/m == 100 */ { true, false, OS_BYTE }, - /* r/m == 101 */ { true, false, OS_BYTE }, - /* r/m == 110 */ { true, false, OS_BYTE }, - /* r/m == 111 */ { true, false, OS_BYTE }, -// mod == 10 - /* r/m == 000 */ { true, false, OS_WORD }, - /* r/m == 001 */ { true, false, OS_WORD }, - /* r/m == 010 */ { true, false, OS_WORD }, - /* r/m == 011 */ { true, false, OS_WORD }, - /* r/m == 100 */ { true, false, OS_WORD }, - /* r/m == 101 */ { true, false, OS_WORD }, - /* r/m == 110 */ { true, false, OS_WORD }, - /* r/m == 111 */ { true, false, OS_WORD }, -// mod == 11 - /* r/m == 000 */ { false, false, OS_ZERO }, - /* r/m == 001 */ { false, false, OS_ZERO }, - /* r/m == 010 */ { false, false, OS_ZERO }, - /* r/m == 011 */ { false, false, OS_ZERO }, - /* r/m == 100 */ { false, false, OS_ZERO }, - /* r/m == 101 */ { false, false, OS_ZERO }, - /* r/m == 110 */ { false, false, OS_ZERO }, - /* r/m == 111 */ { false, false, OS_ZERO } -}; - -const ModrmEntry MiniDisassembler::s_ia32_modrm_map_[] = { -// mod == 00 - /* r/m == 000 */ { false, false, OS_ZERO }, - /* r/m == 001 */ { false, false, OS_ZERO }, - /* r/m == 010 */ { false, false, OS_ZERO }, - /* r/m == 011 */ { false, false, OS_ZERO }, - /* r/m == 100 */ { false, true, OS_ZERO }, - /* r/m == 101 */ { true, false, OS_DOUBLE_WORD }, - /* r/m == 110 */ { false, false, OS_ZERO }, - /* r/m == 111 */ { false, false, OS_ZERO }, -// mod == 01 - /* r/m == 000 */ { true, false, OS_BYTE }, - /* r/m == 001 */ { true, false, OS_BYTE }, - /* r/m == 010 */ { true, false, OS_BYTE }, - /* r/m == 011 */ { true, false, OS_BYTE }, - /* r/m == 100 */ { true, true, OS_BYTE }, - /* r/m == 101 */ { true, false, OS_BYTE }, - /* r/m == 110 */ { true, false, OS_BYTE }, - /* r/m == 111 */ { true, false, OS_BYTE }, -// mod == 10 - /* r/m == 000 */ { true, false, OS_DOUBLE_WORD }, - /* r/m == 001 */ { true, false, OS_DOUBLE_WORD }, - /* r/m == 010 */ { true, false, OS_DOUBLE_WORD }, - /* r/m == 011 */ { true, false, OS_DOUBLE_WORD }, - /* r/m == 100 */ { true, true, OS_DOUBLE_WORD }, - /* r/m == 101 */ { true, false, OS_DOUBLE_WORD }, - /* r/m == 110 */ { true, false, OS_DOUBLE_WORD }, - /* r/m == 111 */ { true, false, OS_DOUBLE_WORD }, -// mod == 11 - /* r/m == 000 */ { false, false, OS_ZERO }, - /* r/m == 001 */ { false, false, OS_ZERO }, - /* r/m == 010 */ { false, false, OS_ZERO }, - /* r/m == 011 */ { false, false, OS_ZERO }, - /* r/m == 100 */ { false, false, OS_ZERO }, - /* r/m == 101 */ { false, false, OS_ZERO }, - /* r/m == 110 */ { false, false, OS_ZERO }, - /* r/m == 111 */ { false, false, OS_ZERO }, -}; - -}; // namespace sidestep diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep/ia32_opcode_map.cpp b/security/sandbox/chromium/sandbox/win/src/sidestep/ia32_opcode_map.cpp deleted file mode 100644 index b7d8a60bc..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep/ia32_opcode_map.cpp +++ /dev/null @@ -1,1159 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Opcode decoding maps. Based on the IA-32 Intel Architecture -// Software Developer's Manual Volume 2: Instruction Set Reference. Idea -// for how to lay out the tables in memory taken from the implementation -// in the Bastard disassembly environment. - -#include "sandbox/win/src/sidestep/mini_disassembler.h" - -namespace sidestep { - -/* -* This is the first table to be searched; the first field of each -* Opcode in the table is either 0 to indicate you're in the -* right table, or an index to the correct table, in the global -* map g_pentiumOpcodeMap -*/ -const Opcode s_first_opcode_byte[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF */ { 1, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x10 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x11 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x12 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x13 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x14 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x15 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x16 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x17 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x18 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x19 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1E */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1F */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x20 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x21 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x22 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x23 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x24 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x25 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x26 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x27 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "daa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x28 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x29 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "das", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x30 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x31 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x32 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x33 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x34 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x35 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x36 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x37 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aaa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x38 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x39 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aas", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x40 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x41 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x42 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x43 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x44 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x45 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x46 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x47 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x48 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x49 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x50 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x51 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x52 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x53 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x54 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x55 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x56 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x57 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x58 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x59 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x60 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x61 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x62 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_A, AM_NOT_USED, "bound", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x63 */ { 0, IT_GENERIC, AM_E | OT_W, AM_G | OT_W, AM_NOT_USED, "arpl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x64 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x65 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x66 */ { 0, IT_PREFIX_OPERAND, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x67 */ { 0, IT_PREFIX_ADDRESS, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x68 */ { 0, IT_GENERIC, AM_I | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x69 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_V, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6A */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_B, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6C */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "insb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6D */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "insd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6E */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X | OT_B, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X | OT_V, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x70 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x71 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x72 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x73 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x74 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x75 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x76 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x77 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x78 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x79 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7A */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7B */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7C */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7D */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7E */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7F */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x80 */ { 2, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x81 */ { 3, IT_REFERENCE, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x82 */ { 4, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x83 */ { 5, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x84 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x85 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x86 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x87 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x88 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x89 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8C */ { 0, IT_GENERIC, AM_E | OT_W, AM_S | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8D */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, "lea", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8E */ { 0, IT_GENERIC, AM_S | OT_W, AM_E | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8F */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x90 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "nop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x91 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x92 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x93 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x94 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x95 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x96 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x97 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x98 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cwde", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x99 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cdq", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9A */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "callf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9B */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wait", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9E */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_O | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_O | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA2 */ { 0, IT_GENERIC, AM_O | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA3 */ { 0, IT_GENERIC, AM_O | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA4 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "movsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA5 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "movsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA6 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "cmpsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA7 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "cmpsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAA */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "stosb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAB */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "stosd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X| OT_B, AM_NOT_USED, "lodsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X| OT_V, AM_NOT_USED, "lodsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAE */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_Y | OT_B, AM_NOT_USED, "scasb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_Y | OT_V, AM_NOT_USED, "scasd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB1 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB2 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB3 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB8 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBA */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBB */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBC */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBE */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC0 */ { 6, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC1 */ { 7, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC2 */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC3 */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC4 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "les", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "lds", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC8 */ { 0, IT_GENERIC, AM_I | OT_W, AM_I | OT_B, AM_NOT_USED, "enter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "leave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCA */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCB */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "int3", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCD */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "int", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCE */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "into", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCF */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "iret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD0 */ { 8, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD1 */ { 9, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD2 */ { 10, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD3 */ { 11, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD4 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aam", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD5 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "xlat", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - - // The following 8 lines would be references to the FPU tables, but we currently - // do not support the FPU instructions in this disassembler. - - /* 0xD8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xDA */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xDB */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xDC */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xDD */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xDE */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xDF */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - - - /* 0xE0 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE1 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE2 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE3 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jcxz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE6 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE7 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE8 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE9 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xEA */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xEB */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xEC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xED */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xEE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xEF */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_V, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF0 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lock:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF2 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "repne:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF3 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rep:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF4 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "hlt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF6 */ { 12, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF7 */ { 13, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xFA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cli", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xFB */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xFC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xFD */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "std", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xFE */ { 14, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xFF */ { 15, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_0f[] = { - /* 0x0 */ { 16, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 17, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lsl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "invd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wbinvd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud2", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xE */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x10 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movups", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "movsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "movss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movupd" } }, - /* 0x11 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movups", true, - /* F2h */ { 0, IT_GENERIC, AM_W | OT_SD, AM_V | OT_SD, AM_NOT_USED, "movsd" }, - /* F3h */ { 0, IT_GENERIC, AM_W | OT_SS, AM_V | OT_SS, AM_NOT_USED, "movss" }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movupd" } }, - /* 0x12 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // only one of ... - /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // ...these two is correct, Intel doesn't specify which - /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_S, AM_NOT_USED, "movlpd" } }, - /* 0x13 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlpd" } }, - /* 0x14 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpcklps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpcklpd" } }, - /* 0x15 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpckhps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpckhpd" } }, - /* 0x16 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // only one of... - /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // ...these two is correct, Intel doesn't specify which - /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhpd" } }, - /* 0x17 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhpd" } }, - /* 0x18 */ { 18, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x19 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1C */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x20 */ { 0, IT_GENERIC, AM_R | OT_D, AM_C | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x21 */ { 0, IT_GENERIC, AM_R | OT_D, AM_D | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x22 */ { 0, IT_GENERIC, AM_C | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x23 */ { 0, IT_GENERIC, AM_D | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x24 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x25 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x26 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x27 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x28 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movaps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movapd" } }, - /* 0x29 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movaps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movapd" } }, - /* 0x2A */ { 0, IT_GENERIC, AM_V | OT_PS, AM_Q | OT_Q, AM_NOT_USED, "cvtpi2ps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_E | OT_D, AM_NOT_USED, "cvtsi2sd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_E | OT_D, AM_NOT_USED, "cvtsi2ss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_Q | OT_DQ, AM_NOT_USED, "cvtpi2pd" } }, - /* 0x2B */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movntps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movntpd" } }, - /* 0x2C */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvttps2pi", true, - /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvttsd2si" }, - /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvttss2si" }, - /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2pi" } }, - /* 0x2D */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvtps2pi", true, - /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvtsd2si" }, - /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvtss2si" }, - /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2pi" } }, - /* 0x2E */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "ucomiss", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "ucomisd" } }, - /* 0x2F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_SS, AM_NOT_USED, "comiss", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "comisd" } }, - /* 0x30 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wrmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x31 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdtsc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x32 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x33 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdpmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x34 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysenter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x35 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysexit", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x36 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x37 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x38 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x39 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x40 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x41 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x42 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x43 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x44 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x45 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x46 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x47 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmova", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x48 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x49 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4A */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4D */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4E */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4F */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x50 */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PS, AM_NOT_USED, "movmskps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PD, AM_NOT_USED, "movmskpd" } }, - /* 0x51 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "sqrtps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "sqrtsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "sqrtss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "sqrtpd" } }, - /* 0x52 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rsqrtps", true, - /* F2h */ { 0 }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rsqrtss" }, - /* 66h */ { 0 } }, - /* 0x53 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rcpps", true, - /* F2h */ { 0 }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rcpss" }, - /* 66h */ { 0 } }, - /* 0x54 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andpd" } }, - /* 0x55 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andnps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andnpd" } }, - /* 0x56 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "orps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "orpd" } }, - /* 0x57 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "xorps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "xorpd" } }, - /* 0x58 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "addps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "addsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "addss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "addpd" } }, - /* 0x59 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "mulps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "mulsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "mulss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "mulpd" } }, - /* 0x5A */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PS, AM_NOT_USED, "cvtps2pd", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "cvtsd2ss" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "cvtss2sd" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PD, AM_NOT_USED, "cvtpd2ps" } }, - /* 0x5B */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2ps", true, - /* F2h */ { 0 }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvttps2dq" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvtps2dq" } }, - /* 0x5C */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "subps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "subsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "subss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "subpd" } }, - /* 0x5D */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "minps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "minsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "minss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "minpd" } }, - /* 0x5E */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "divps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "divsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "divss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "divpd" } }, - /* 0x5F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "maxps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "maxsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "maxss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "maxpd" } }, - /* 0x60 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklbw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklbw" } }, - /* 0x61 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklwd", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklwd" } }, - /* 0x62 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckldq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpckldq" } }, - /* 0x63 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packsswb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packsswb" } }, - /* 0x64 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtb" } }, - /* 0x65 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtw" } }, - /* 0x66 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtd", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtd" } }, - /* 0x67 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packuswb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packuswb" } }, - /* 0x68 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhbw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhbw" } }, - /* 0x69 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhwd", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhwd" } }, - /* 0x6A */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhdq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhdq" } }, - /* 0x6B */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packssdw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "packssdw" } }, - /* 0x6C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } }, - /* 0x6D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } }, - /* 0x6E */ { 0, IT_GENERIC, AM_P | OT_D, AM_E | OT_D, AM_NOT_USED, "movd", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_NOT_USED, "movd" } }, - /* 0x6F */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "movq", true, - /* F2h */ { 0 }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqu" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqa" } }, - /* 0x70 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_I | OT_B, "pshuf", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshuflw" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufhw" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufd" } }, - /* 0x71 */ { 19, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x72 */ { 20, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x73 */ { 21, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x74 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqb" } }, - /* 0x75 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqw" } }, - /* 0x76 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqd", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqd" } }, - /* 0x77 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "emms", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - - // The following six opcodes are escapes into the MMX stuff, which this disassembler does not support. - /* 0x78 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x79 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7A */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7B */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7C */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7D */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - - /* 0x7E */ { 0, IT_GENERIC, AM_E | OT_D, AM_P | OT_D, AM_NOT_USED, "movd", true, - /* F2h */ { 0 }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movq" }, - /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_DQ, AM_NOT_USED, "movd" } }, - /* 0x7F */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_P | OT_Q, AM_NOT_USED, "movq", true, - /* F2h */ { 0 }, - /* F3h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqu" }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqa" } }, - /* 0x80 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x81 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x82 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x83 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x84 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x85 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x86 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x87 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x88 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x89 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8A */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8B */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8C */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8D */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8E */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x8F */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x90 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seto", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x91 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x92 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x93 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x94 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x95 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x96 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x97 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seta", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x98 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "sets", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x99 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9A */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9B */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9C */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9D */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9E */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x9F */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cpuid", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA6 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA7 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rsm", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAC */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAD */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAE */ { 22, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xAF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB2 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lss", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB4 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lfs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB5 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lgs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB6 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB7 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xB9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud1", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBA */ { 23, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBC */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBD */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBE */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xBF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC2 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "cmpps", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_I | OT_B, "cmpsd" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_I | OT_B, "cmpss" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "cmppd" } }, - /* 0xC3 */ { 0, IT_GENERIC, AM_E | OT_D, AM_G | OT_D, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_E | OT_D, AM_I | OT_B, "pinsrw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_I | OT_B, "pinsrw" } }, - /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_I | OT_B, "pextrw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_I | OT_B, "pextrw" } }, - /* 0xC6 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "shufps", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "shufpd" } }, - /* 0xC7 */ { 24, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC8 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xC9 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCA */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCB */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCC */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCD */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCE */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xCF */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xD1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlw" } }, - /* 0xD2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrld", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrld" } }, - /* 0xD3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlq" } }, - /* 0xD4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddq" } }, - /* 0xD5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmullw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmullw" } }, - /* 0xD6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "unused without prefix", true, - /* F2h */ { 0, IT_GENERIC, AM_P | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movdq2q" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_Q | OT_Q, AM_NOT_USED, "movq2dq" }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movq" } }, - /* 0xD7 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_NOT_USED, "pmovmskb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_NOT_USED, "pmovmskb" } }, - /* 0xD8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusb" } }, - /* 0xD9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusw" } }, - /* 0xDA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminub", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminub" } }, - /* 0xDB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pand", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pand" } }, - /* 0xDC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusb" } }, - /* 0xDD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusw" } }, - /* 0xDE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxub", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxub" } }, - /* 0xDF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pandn", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pandn" } }, - /* 0xE0 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgb" } }, - /* 0xE1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psraw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrqw" } }, - /* 0xE2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrad", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrad" } }, - /* 0xE3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgw" } }, - /* 0xE4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhuw" } }, - /* 0xE5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhw" } }, - /* 0xE6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true, - /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2dq" }, - /* F3h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2pd" }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2dq" } }, - /* 0xE7 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movntq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movntdq" } }, - /* 0xE8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsb" } }, - /* 0xE9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsw" } }, - /* 0xEA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminsw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminsw" } }, - /* 0xEB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "por", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "por" } }, - /* 0xEC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsb" } }, - /* 0xED */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsw" } }, - /* 0xEE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxsw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxsw" } }, - /* 0xEF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pxor", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pxor" } }, - /* 0xF0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0xF1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllw" } }, - /* 0xF2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pslld", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pslld" } }, - /* 0xF3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllq" } }, - /* 0xF4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmuludq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmuludq" } }, - /* 0xF5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaddwd", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaddwd" } }, - /* 0xF6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psadbw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psadbw" } }, - /* 0xF7 */ { 0, IT_GENERIC, AM_P | OT_PI, AM_Q | OT_PI, AM_NOT_USED, "maskmovq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "maskmovdqu" } }, - /* 0xF8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubb" } }, - /* 0xF9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubw" } }, - /* 0xFA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubd", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubd" } }, - /* 0xFB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubq" } }, - /* 0xFC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddb", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddb" } }, - /* 0xFD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddw" } }, - /* 0xFE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddd", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddd" } }, - /* 0xFF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_0f00[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "sldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "str", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "ltr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_0f01[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "smsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lmsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_M | OT_B, AM_NOT_USED, AM_NOT_USED, "invlpg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_0f18[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_0f71[] = { - /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlw" } }, - /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psraw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psraw" } }, - /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllw", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllw" } }, - /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_0f72[] = { - /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrld", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrld" } }, - /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrad", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrad" } }, - /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "pslld", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslld" } }, - /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_0f73[] = { - /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlq" } }, - /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllq" } }, - /* 0x7 */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq", true, - /* F2h */ { 0 }, - /* F3h */ { 0 }, - /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq" } }, -}; - -const Opcode s_opcode_byte_after_0fae[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxsave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxrstor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ldmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "mfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clflush/sfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, -}; - -const Opcode s_opcode_byte_after_0fba[] = { - /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_0fc7[] = { - /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_Q, AM_NOT_USED, AM_NOT_USED, "cmpxch8b", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_80[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_81[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_82[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_83[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_c0[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_c1[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_d0[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_d1[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_d2[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_d3[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_f6[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_f7[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_fe[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -const Opcode s_opcode_byte_after_ff[] = { - /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x2 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x3 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x4 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x5 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }, - /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } } -}; - -/* -* A table of all the other tables, containing some extra information, e.g. -* how to mask out the byte we're looking at. -*/ -const OpcodeTable MiniDisassembler::s_ia32_opcode_map_[]={ - // One-byte opcodes and jumps to larger - /* 0 */ {s_first_opcode_byte, 0, 0xff, 0, 0xff}, - // Two-byte opcodes (second byte) - /* 1 */ {s_opcode_byte_after_0f, 0, 0xff, 0, 0xff}, - // Start of tables for opcodes using ModR/M bits as extension - /* 2 */ {s_opcode_byte_after_80, 3, 0x07, 0, 0x07}, - /* 3 */ {s_opcode_byte_after_81, 3, 0x07, 0, 0x07}, - /* 4 */ {s_opcode_byte_after_82, 3, 0x07, 0, 0x07}, - /* 5 */ {s_opcode_byte_after_83, 3, 0x07, 0, 0x07}, - /* 6 */ {s_opcode_byte_after_c0, 3, 0x07, 0, 0x07}, - /* 7 */ {s_opcode_byte_after_c1, 3, 0x07, 0, 0x07}, - /* 8 */ {s_opcode_byte_after_d0, 3, 0x07, 0, 0x07}, - /* 9 */ {s_opcode_byte_after_d1, 3, 0x07, 0, 0x07}, - /* 10 */ {s_opcode_byte_after_d2, 3, 0x07, 0, 0x07}, - /* 11 */ {s_opcode_byte_after_d3, 3, 0x07, 0, 0x07}, - /* 12 */ {s_opcode_byte_after_f6, 3, 0x07, 0, 0x07}, - /* 13 */ {s_opcode_byte_after_f7, 3, 0x07, 0, 0x07}, - /* 14 */ {s_opcode_byte_after_fe, 3, 0x07, 0, 0x01}, - /* 15 */ {s_opcode_byte_after_ff, 3, 0x07, 0, 0x07}, - /* 16 */ {s_opcode_byte_after_0f00, 3, 0x07, 0, 0x07}, - /* 17 */ {s_opcode_byte_after_0f01, 3, 0x07, 0, 0x07}, - /* 18 */ {s_opcode_byte_after_0f18, 3, 0x07, 0, 0x07}, - /* 19 */ {s_opcode_byte_after_0f71, 3, 0x07, 0, 0x07}, - /* 20 */ {s_opcode_byte_after_0f72, 3, 0x07, 0, 0x07}, - /* 21 */ {s_opcode_byte_after_0f73, 3, 0x07, 0, 0x07}, - /* 22 */ {s_opcode_byte_after_0fae, 3, 0x07, 0, 0x07}, - /* 23 */ {s_opcode_byte_after_0fba, 3, 0x07, 0, 0x07}, - /* 24 */ {s_opcode_byte_after_0fc7, 3, 0x07, 0, 0x01} -}; - -}; // namespace sidestep diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp b/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp deleted file mode 100644 index 1e8e0bd97..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Implementation of MiniDisassembler. - -#ifdef _WIN64 -#error The code in this file should not be used on 64-bit Windows. -#endif - -#include "sandbox/win/src/sidestep/mini_disassembler.h" - -namespace sidestep { - -MiniDisassembler::MiniDisassembler(bool operand_default_is_32_bits, - bool address_default_is_32_bits) - : operand_default_is_32_bits_(operand_default_is_32_bits), - address_default_is_32_bits_(address_default_is_32_bits) { - Initialize(); -} - -MiniDisassembler::MiniDisassembler() - : operand_default_is_32_bits_(true), - address_default_is_32_bits_(true) { - Initialize(); -} - -InstructionType MiniDisassembler::Disassemble( - unsigned char* start_byte, - unsigned int* instruction_bytes) { - // Clean up any state from previous invocations. - Initialize(); - - // Start by processing any prefixes. - unsigned char* current_byte = start_byte; - unsigned int size = 0; - InstructionType instruction_type = ProcessPrefixes(current_byte, &size); - - if (IT_UNKNOWN == instruction_type) - return instruction_type; - - current_byte += size; - size = 0; - - // Invariant: We have stripped all prefixes, and the operand_is_32_bits_ - // and address_is_32_bits_ flags are correctly set. - - instruction_type = ProcessOpcode(current_byte, 0, &size); - - // Check for error processing instruction - if ((IT_UNKNOWN == instruction_type_) || (IT_UNUSED == instruction_type_)) { - return IT_UNKNOWN; - } - - current_byte += size; - - // Invariant: operand_bytes_ indicates the total size of operands - // specified by the opcode and/or ModR/M byte and/or SIB byte. - // pCurrentByte points to the first byte after the ModR/M byte, or after - // the SIB byte if it is present (i.e. the first byte of any operands - // encoded in the instruction). - - // We get the total length of any prefixes, the opcode, and the ModR/M and - // SIB bytes if present, by taking the difference of the original starting - // address and the current byte (which points to the first byte of the - // operands if present, or to the first byte of the next instruction if - // they are not). Adding the count of bytes in the operands encoded in - // the instruction gives us the full length of the instruction in bytes. - *instruction_bytes += operand_bytes_ + (current_byte - start_byte); - - // Return the instruction type, which was set by ProcessOpcode(). - return instruction_type_; -} - -void MiniDisassembler::Initialize() { - operand_is_32_bits_ = operand_default_is_32_bits_; - address_is_32_bits_ = address_default_is_32_bits_; - operand_bytes_ = 0; - have_modrm_ = false; - should_decode_modrm_ = false; - instruction_type_ = IT_UNKNOWN; - got_f2_prefix_ = false; - got_f3_prefix_ = false; - got_66_prefix_ = false; -} - -InstructionType MiniDisassembler::ProcessPrefixes(unsigned char* start_byte, - unsigned int* size) { - InstructionType instruction_type = IT_GENERIC; - const Opcode& opcode = s_ia32_opcode_map_[0].table_[*start_byte]; - - switch (opcode.type_) { - case IT_PREFIX_ADDRESS: - address_is_32_bits_ = !address_default_is_32_bits_; - goto nochangeoperand; - case IT_PREFIX_OPERAND: - operand_is_32_bits_ = !operand_default_is_32_bits_; - nochangeoperand: - case IT_PREFIX: - - if (0xF2 == (*start_byte)) - got_f2_prefix_ = true; - else if (0xF3 == (*start_byte)) - got_f3_prefix_ = true; - else if (0x66 == (*start_byte)) - got_66_prefix_ = true; - - instruction_type = opcode.type_; - (*size)++; - // we got a prefix, so add one and check next byte - ProcessPrefixes(start_byte + 1, size); - default: - break; // not a prefix byte - } - - return instruction_type; -} - -InstructionType MiniDisassembler::ProcessOpcode(unsigned char* start_byte, - unsigned int table_index, - unsigned int* size) { - const OpcodeTable& table = s_ia32_opcode_map_[table_index]; // Get our table - unsigned char current_byte = (*start_byte) >> table.shift_; - current_byte = current_byte & table.mask_; // Mask out the bits we will use - - // Check whether the byte we have is inside the table we have. - if (current_byte < table.min_lim_ || current_byte > table.max_lim_) { - instruction_type_ = IT_UNKNOWN; - return instruction_type_; - } - - const Opcode& opcode = table.table_[current_byte]; - if (IT_UNUSED == opcode.type_) { - // This instruction is not used by the IA-32 ISA, so we indicate - // this to the user. Probably means that we were pointed to - // a byte in memory that was not the start of an instruction. - instruction_type_ = IT_UNUSED; - return instruction_type_; - } else if (IT_REFERENCE == opcode.type_) { - // We are looking at an opcode that has more bytes (or is continued - // in the ModR/M byte). Recursively find the opcode definition in - // the table for the opcode's next byte. - (*size)++; - ProcessOpcode(start_byte + 1, opcode.table_index_, size); - return instruction_type_; - } - - const SpecificOpcode* specific_opcode = reinterpret_cast< - const SpecificOpcode*>(&opcode); - if (opcode.is_prefix_dependent_) { - if (got_f2_prefix_ && opcode.opcode_if_f2_prefix_.mnemonic_ != 0) { - specific_opcode = &opcode.opcode_if_f2_prefix_; - } else if (got_f3_prefix_ && opcode.opcode_if_f3_prefix_.mnemonic_ != 0) { - specific_opcode = &opcode.opcode_if_f3_prefix_; - } else if (got_66_prefix_ && opcode.opcode_if_66_prefix_.mnemonic_ != 0) { - specific_opcode = &opcode.opcode_if_66_prefix_; - } - } - - // Inv: The opcode type is known. - instruction_type_ = specific_opcode->type_; - - // Let's process the operand types to see if we have any immediate - // operands, and/or a ModR/M byte. - - ProcessOperand(specific_opcode->flag_dest_); - ProcessOperand(specific_opcode->flag_source_); - ProcessOperand(specific_opcode->flag_aux_); - - // Inv: We have processed the opcode and incremented operand_bytes_ - // by the number of bytes of any operands specified by the opcode - // that are stored in the instruction (not registers etc.). Now - // we need to return the total number of bytes for the opcode and - // for the ModR/M or SIB bytes if they are present. - - if (table.mask_ != 0xff) { - if (have_modrm_) { - // we're looking at a ModR/M byte so we're not going to - // count that into the opcode size - ProcessModrm(start_byte, size); - return IT_GENERIC; - } else { - // need to count the ModR/M byte even if it's just being - // used for opcode extension - (*size)++; - return IT_GENERIC; - } - } else { - if (have_modrm_) { - // The ModR/M byte is the next byte. - (*size)++; - ProcessModrm(start_byte + 1, size); - return IT_GENERIC; - } else { - (*size)++; - return IT_GENERIC; - } - } -} - -bool MiniDisassembler::ProcessOperand(int flag_operand) { - bool succeeded = true; - if (AM_NOT_USED == flag_operand) - return succeeded; - - // Decide what to do based on the addressing mode. - switch (flag_operand & AM_MASK) { - // No ModR/M byte indicated by these addressing modes, and no - // additional (e.g. immediate) parameters. - case AM_A: // Direct address - case AM_F: // EFLAGS register - case AM_X: // Memory addressed by the DS:SI register pair - case AM_Y: // Memory addressed by the ES:DI register pair - case AM_IMPLICIT: // Parameter is implicit, occupies no space in - // instruction - break; - - // There is a ModR/M byte but it does not necessarily need - // to be decoded. - case AM_C: // reg field of ModR/M selects a control register - case AM_D: // reg field of ModR/M selects a debug register - case AM_G: // reg field of ModR/M selects a general register - case AM_P: // reg field of ModR/M selects an MMX register - case AM_R: // mod field of ModR/M may refer only to a general register - case AM_S: // reg field of ModR/M selects a segment register - case AM_T: // reg field of ModR/M selects a test register - case AM_V: // reg field of ModR/M selects a 128-bit XMM register - have_modrm_ = true; - break; - - // In these addressing modes, there is a ModR/M byte and it needs to be - // decoded. No other (e.g. immediate) params than indicated in ModR/M. - case AM_E: // Operand is either a general-purpose register or memory, - // specified by ModR/M byte - case AM_M: // ModR/M byte will refer only to memory - case AM_Q: // Operand is either an MMX register or memory (complex - // evaluation), specified by ModR/M byte - case AM_W: // Operand is either a 128-bit XMM register or memory (complex - // eval), specified by ModR/M byte - have_modrm_ = true; - should_decode_modrm_ = true; - break; - - // These addressing modes specify an immediate or an offset value - // directly, so we need to look at the operand type to see how many - // bytes. - case AM_I: // Immediate data. - case AM_J: // Jump to offset. - case AM_O: // Operand is at offset. - switch (flag_operand & OT_MASK) { - case OT_B: // Byte regardless of operand-size attribute. - operand_bytes_ += OS_BYTE; - break; - case OT_C: // Byte or word, depending on operand-size attribute. - if (operand_is_32_bits_) - operand_bytes_ += OS_WORD; - else - operand_bytes_ += OS_BYTE; - break; - case OT_D: // Doubleword, regardless of operand-size attribute. - operand_bytes_ += OS_DOUBLE_WORD; - break; - case OT_DQ: // Double-quadword, regardless of operand-size attribute. - operand_bytes_ += OS_DOUBLE_QUAD_WORD; - break; - case OT_P: // 32-bit or 48-bit pointer, depending on operand-size - // attribute. - if (operand_is_32_bits_) - operand_bytes_ += OS_48_BIT_POINTER; - else - operand_bytes_ += OS_32_BIT_POINTER; - break; - case OT_PS: // 128-bit packed single-precision floating-point data. - operand_bytes_ += OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING; - break; - case OT_Q: // Quadword, regardless of operand-size attribute. - operand_bytes_ += OS_QUAD_WORD; - break; - case OT_S: // 6-byte pseudo-descriptor. - operand_bytes_ += OS_PSEUDO_DESCRIPTOR; - break; - case OT_SD: // Scalar Double-Precision Floating-Point Value - case OT_PD: // Unaligned packed double-precision floating point value - operand_bytes_ += OS_DOUBLE_PRECISION_FLOATING; - break; - case OT_SS: - // Scalar element of a 128-bit packed single-precision - // floating data. - // We simply return enItUnknown since we don't have to support - // floating point - succeeded = false; - break; - case OT_V: // Word or doubleword, depending on operand-size attribute. - if (operand_is_32_bits_) - operand_bytes_ += OS_DOUBLE_WORD; - else - operand_bytes_ += OS_WORD; - break; - case OT_W: // Word, regardless of operand-size attribute. - operand_bytes_ += OS_WORD; - break; - - // Can safely ignore these. - case OT_A: // Two one-word operands in memory or two double-word - // operands in memory - case OT_PI: // Quadword MMX technology register (e.g. mm0) - case OT_SI: // Doubleword integer register (e.g., eax) - break; - - default: - break; - } - break; - - default: - break; - } - - return succeeded; -} - -bool MiniDisassembler::ProcessModrm(unsigned char* start_byte, - unsigned int* size) { - // If we don't need to decode, we just return the size of the ModR/M - // byte (there is never a SIB byte in this case). - if (!should_decode_modrm_) { - (*size)++; - return true; - } - - // We never care about the reg field, only the combination of the mod - // and r/m fields, so let's start by packing those fields together into - // 5 bits. - unsigned char modrm = (*start_byte); - unsigned char mod = modrm & 0xC0; // mask out top two bits to get mod field - modrm = modrm & 0x07; // mask out bottom 3 bits to get r/m field - mod = mod >> 3; // shift the mod field to the right place - modrm = mod | modrm; // combine the r/m and mod fields as discussed - mod = mod >> 3; // shift the mod field to bits 2..0 - - // Invariant: modrm contains the mod field in bits 4..3 and the r/m field - // in bits 2..0, and mod contains the mod field in bits 2..0 - - const ModrmEntry* modrm_entry = 0; - if (address_is_32_bits_) - modrm_entry = &s_ia32_modrm_map_[modrm]; - else - modrm_entry = &s_ia16_modrm_map_[modrm]; - - // Invariant: modrm_entry points to information that we need to decode - // the ModR/M byte. - - // Add to the count of operand bytes, if the ModR/M byte indicates - // that some operands are encoded in the instruction. - if (modrm_entry->is_encoded_in_instruction_) - operand_bytes_ += modrm_entry->operand_size_; - - // Process the SIB byte if necessary, and return the count - // of ModR/M and SIB bytes. - if (modrm_entry->use_sib_byte_) { - (*size)++; - return ProcessSib(start_byte + 1, mod, size); - } else { - (*size)++; - return true; - } -} - -bool MiniDisassembler::ProcessSib(unsigned char* start_byte, - unsigned char mod, - unsigned int* size) { - // get the mod field from the 2..0 bits of the SIB byte - unsigned char sib_base = (*start_byte) & 0x07; - if (0x05 == sib_base) { - switch (mod) { - case 0x00: // mod == 00 - case 0x02: // mod == 10 - operand_bytes_ += OS_DOUBLE_WORD; - break; - case 0x01: // mod == 01 - operand_bytes_ += OS_BYTE; - break; - case 0x03: // mod == 11 - // According to the IA-32 docs, there does not seem to be a disp - // value for this value of mod - default: - break; - } - } - - (*size)++; - return true; -} - -}; // namespace sidestep diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler.h b/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler.h deleted file mode 100644 index 202c4ecc2..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler.h +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Definition of MiniDisassembler. - -#ifndef SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_H__ -#define SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_H__ - -#include "sandbox/win/src/sidestep/mini_disassembler_types.h" - -namespace sidestep { - -// This small disassembler is very limited -// in its functionality, and in fact does only the bare minimum required by the -// preamble patching utility. It may be useful for other purposes, however. -// -// The limitations include at least the following: -// -# No support for coprocessor opcodes, MMX, etc. -// -# No machine-readable identification of opcodes or decoding of -// assembly parameters. The name of the opcode (as a string) is given, -// however, to aid debugging. -// -// You may ask what this little disassembler actually does, then? The answer is -// that it does the following, which is exactly what the patching utility needs: -// -# Indicates if opcode is a jump (any kind) or a return (any kind) -// because this is important for the patching utility to determine if -// a function is too short or there are jumps too early in it for it -// to be preamble patched. -// -# The opcode length is always calculated, so that the patching utility -// can figure out where the next instruction starts, and whether it -// already has enough instructions to replace with the absolute jump -// to the patching code. -// -// The usage is quite simple; just create a MiniDisassembler and use its -// Disassemble() method. -// -// If you would like to extend this disassembler, please refer to the -// IA-32 Intel Architecture Software Developer's Manual Volume 2: -// Instruction Set Reference for information about operand decoding -// etc. -class MiniDisassembler { - public: - - // Creates a new instance and sets defaults. - // - // operand_default_32_bits: If true, the default operand size is - // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits. - // address_default_32_bits: If true, the default address size is - // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits. - MiniDisassembler(bool operand_default_32_bits, - bool address_default_32_bits); - - // Equivalent to MiniDisassembler(true, true); - MiniDisassembler(); - - // Attempts to disassemble a single instruction starting from the - // address in memory it is pointed to. - // - // start: Address where disassembly should start. - // instruction_bytes: Variable that will be incremented by - // the length in bytes of the instruction. - // Returns enItJump, enItReturn or enItGeneric on success. enItUnknown - // if unable to disassemble, enItUnused if this seems to be an unused - // opcode. In the last two (error) cases, cbInstruction will be set - // to 0xffffffff. - // - // Postcondition: This instance of the disassembler is ready to be used again, - // with unchanged defaults from creation time. - InstructionType Disassemble(unsigned char* start, - unsigned int* instruction_bytes); - - private: - - // Makes the disassembler ready for reuse. - void Initialize(); - - // Sets the flags for address and operand sizes. - // Returns Number of prefix bytes. - InstructionType ProcessPrefixes(unsigned char* start, unsigned int* size); - - // Sets the flag for whether we have ModR/M, and increments - // operand_bytes_ if any are specifies by the opcode directly. - // Returns Number of opcode bytes. - InstructionType ProcessOpcode(unsigned char* start, - unsigned int table, - unsigned int* size); - - // Checks the type of the supplied operand. Increments - // operand_bytes_ if it directly indicates an immediate etc. - // operand. Asserts have_modrm_ if the operand specifies - // a ModR/M byte. - bool ProcessOperand(int flag_operand); - - // Increments operand_bytes_ by size specified by ModR/M and - // by SIB if present. - // Returns 0 in case of error, 1 if there is just a ModR/M byte, - // 2 if there is a ModR/M byte and a SIB byte. - bool ProcessModrm(unsigned char* start, unsigned int* size); - - // Processes the SIB byte that it is pointed to. - // start: Pointer to the SIB byte. - // mod: The mod field from the ModR/M byte. - // Returns 1 to indicate success (indicates 1 SIB byte) - bool ProcessSib(unsigned char* start, unsigned char mod, unsigned int* size); - - // The instruction type we have decoded from the opcode. - InstructionType instruction_type_; - - // Counts the number of bytes that is occupied by operands in - // the current instruction (note: we don't care about how large - // operands stored in registers etc. are). - unsigned int operand_bytes_; - - // True iff there is a ModR/M byte in this instruction. - bool have_modrm_; - - // True iff we need to decode the ModR/M byte (sometimes it just - // points to a register, we can tell by the addressing mode). - bool should_decode_modrm_; - - // Current operand size is 32 bits if true, 16 bits if false. - bool operand_is_32_bits_; - - // Default operand size is 32 bits if true, 16 bits if false. - bool operand_default_is_32_bits_; - - // Current address size is 32 bits if true, 16 bits if false. - bool address_is_32_bits_; - - // Default address size is 32 bits if true, 16 bits if false. - bool address_default_is_32_bits_; - - // Huge big opcode table based on the IA-32 manual, defined - // in Ia32OpcodeMap.cpp - static const OpcodeTable s_ia32_opcode_map_[]; - - // Somewhat smaller table to help with decoding ModR/M bytes - // when 16-bit addressing mode is being used. Defined in - // Ia32ModrmMap.cpp - static const ModrmEntry s_ia16_modrm_map_[]; - - // Somewhat smaller table to help with decoding ModR/M bytes - // when 32-bit addressing mode is being used. Defined in - // Ia32ModrmMap.cpp - static const ModrmEntry s_ia32_modrm_map_[]; - - // Indicators of whether we got certain prefixes that certain - // silly Intel instructions depend on in nonstandard ways for - // their behaviors. - bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_; -}; - -}; // namespace sidestep - -#endif // SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler_types.h b/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler_types.h deleted file mode 100644 index 1c1062631..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep/mini_disassembler_types.h +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Several simple types used by the disassembler and some of the patching -// mechanisms. - -#ifndef SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H__ -#define SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H__ - -namespace sidestep { - -// Categories of instructions that we care about -enum InstructionType { - // This opcode is not used - IT_UNUSED, - // This disassembler does not recognize this opcode (error) - IT_UNKNOWN, - // This is not an instruction but a reference to another table - IT_REFERENCE, - // This byte is a prefix byte that we can ignore - IT_PREFIX, - // This is a prefix byte that switches to the nondefault address size - IT_PREFIX_ADDRESS, - // This is a prefix byte that switches to the nondefault operand size - IT_PREFIX_OPERAND, - // A jump or call instruction - IT_JUMP, - // A return instruction - IT_RETURN, - // Any other type of instruction (in this case we don't care what it is) - IT_GENERIC, -}; - -// Lists IA-32 operand sizes in multiples of 8 bits -enum OperandSize { - OS_ZERO = 0, - OS_BYTE = 1, - OS_WORD = 2, - OS_DOUBLE_WORD = 4, - OS_QUAD_WORD = 8, - OS_DOUBLE_QUAD_WORD = 16, - OS_32_BIT_POINTER = 32/8, - OS_48_BIT_POINTER = 48/8, - OS_SINGLE_PRECISION_FLOATING = 32/8, - OS_DOUBLE_PRECISION_FLOATING = 64/8, - OS_DOUBLE_EXTENDED_PRECISION_FLOATING = 80/8, - OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING = 128/8, - OS_PSEUDO_DESCRIPTOR = 6 -}; - -// Operand addressing methods from the IA-32 manual. The enAmMask value -// is a mask for the rest. The other enumeration values are named for the -// names given to the addressing methods in the manual, e.g. enAm_D is for -// the D addressing method. -// -// The reason we use a full 4 bytes and a mask, is that we need to combine -// these flags with the enOperandType to store the details -// on the operand in a single integer. -enum AddressingMethod { - AM_NOT_USED = 0, // This operand is not used for this instruction - AM_MASK = 0x00FF0000, // Mask for the rest of the values in this enumeration - AM_A = 0x00010000, // A addressing type - AM_C = 0x00020000, // C addressing type - AM_D = 0x00030000, // D addressing type - AM_E = 0x00040000, // E addressing type - AM_F = 0x00050000, // F addressing type - AM_G = 0x00060000, // G addressing type - AM_I = 0x00070000, // I addressing type - AM_J = 0x00080000, // J addressing type - AM_M = 0x00090000, // M addressing type - AM_O = 0x000A0000, // O addressing type - AM_P = 0x000B0000, // P addressing type - AM_Q = 0x000C0000, // Q addressing type - AM_R = 0x000D0000, // R addressing type - AM_S = 0x000E0000, // S addressing type - AM_T = 0x000F0000, // T addressing type - AM_V = 0x00100000, // V addressing type - AM_W = 0x00110000, // W addressing type - AM_X = 0x00120000, // X addressing type - AM_Y = 0x00130000, // Y addressing type - AM_REGISTER = 0x00140000, // Specific register is always used as this op - AM_IMPLICIT = 0x00150000, // An implicit, fixed value is used -}; - -// Operand types from the IA-32 manual. The enOtMask value is -// a mask for the rest. The rest of the values are named for the -// names given to these operand types in the manual, e.g. enOt_ps -// is for the ps operand type in the manual. -// -// The reason we use a full 4 bytes and a mask, is that we need -// to combine these flags with the enAddressingMethod to store the details -// on the operand in a single integer. -enum OperandType { - OT_MASK = 0xFF000000, - OT_A = 0x01000000, - OT_B = 0x02000000, - OT_C = 0x03000000, - OT_D = 0x04000000, - OT_DQ = 0x05000000, - OT_P = 0x06000000, - OT_PI = 0x07000000, - OT_PS = 0x08000000, // actually unsupported for (we don't know its size) - OT_Q = 0x09000000, - OT_S = 0x0A000000, - OT_SS = 0x0B000000, - OT_SI = 0x0C000000, - OT_V = 0x0D000000, - OT_W = 0x0E000000, - OT_SD = 0x0F000000, // scalar double-precision floating-point value - OT_PD = 0x10000000, // double-precision floating point - // dummy "operand type" for address mode M - which doesn't specify - // operand type - OT_ADDRESS_MODE_M = 0x80000000 -}; - -// Everything that's in an Opcode (see below) except the three -// alternative opcode structs for different prefixes. -struct SpecificOpcode { - // Index to continuation table, or 0 if this is the last - // byte in the opcode. - int table_index_; - - // The opcode type - InstructionType type_; - - // Description of the type of the dest, src and aux operands, - // put together from an enOperandType flag and an enAddressingMethod - // flag. - int flag_dest_; - int flag_source_; - int flag_aux_; - - // We indicate the mnemonic for debugging purposes - const char* mnemonic_; -}; - -// The information we keep in our tables about each of the different -// valid instructions recognized by the IA-32 architecture. -struct Opcode { - // Index to continuation table, or 0 if this is the last - // byte in the opcode. - int table_index_; - - // The opcode type - InstructionType type_; - - // Description of the type of the dest, src and aux operands, - // put together from an enOperandType flag and an enAddressingMethod - // flag. - int flag_dest_; - int flag_source_; - int flag_aux_; - - // We indicate the mnemonic for debugging purposes - const char* mnemonic_; - - // Alternative opcode info if certain prefixes are specified. - // In most cases, all of these are zeroed-out. Only used if - // bPrefixDependent is true. - bool is_prefix_dependent_; - SpecificOpcode opcode_if_f2_prefix_; - SpecificOpcode opcode_if_f3_prefix_; - SpecificOpcode opcode_if_66_prefix_; -}; - -// Information about each table entry. -struct OpcodeTable { - // Table of instruction entries - const Opcode* table_; - // How many bytes left to shift ModR/M byte <b>before</b> applying mask - unsigned char shift_; - // Mask to apply to byte being looked at before comparing to table - unsigned char mask_; - // Minimum/maximum indexes in table. - unsigned char min_lim_; - unsigned char max_lim_; -}; - -// Information about each entry in table used to decode ModR/M byte. -struct ModrmEntry { - // Is the operand encoded as bytes in the instruction (rather than - // if it's e.g. a register in which case it's just encoded in the - // ModR/M byte) - bool is_encoded_in_instruction_; - - // Is there a SIB byte? In this case we always need to decode it. - bool use_sib_byte_; - - // What is the size of the operand (only important if it's encoded - // in the instruction)? - OperandSize operand_size_; -}; - -}; // namespace sidestep - -#endif // SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep/preamble_patcher.h b/security/sandbox/chromium/sandbox/win/src/sidestep/preamble_patcher.h deleted file mode 100644 index 3a0985ce9..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep/preamble_patcher.h +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Definition of PreamblePatcher - -#ifndef SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__ -#define SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__ - -#include <stddef.h> - -namespace sidestep { - -// Maximum size of the preamble stub. We overwrite at least the first 5 -// bytes of the function. Considering the worst case scenario, we need 4 -// bytes + the max instruction size + 5 more bytes for our jump back to -// the original code. With that in mind, 32 is a good number :) -const size_t kMaxPreambleStubSize = 32; - -// Possible results of patching/unpatching -enum SideStepError { - SIDESTEP_SUCCESS = 0, - SIDESTEP_INVALID_PARAMETER, - SIDESTEP_INSUFFICIENT_BUFFER, - SIDESTEP_JUMP_INSTRUCTION, - SIDESTEP_FUNCTION_TOO_SMALL, - SIDESTEP_UNSUPPORTED_INSTRUCTION, - SIDESTEP_NO_SUCH_MODULE, - SIDESTEP_NO_SUCH_FUNCTION, - SIDESTEP_ACCESS_DENIED, - SIDESTEP_UNEXPECTED, -}; - -// Implements a patching mechanism that overwrites the first few bytes of -// a function preamble with a jump to our hook function, which is then -// able to call the original function via a specially-made preamble-stub -// that imitates the action of the original preamble. -// -// Note that there are a number of ways that this method of patching can -// fail. The most common are: -// - If there is a jump (jxx) instruction in the first 5 bytes of -// the function being patched, we cannot patch it because in the -// current implementation we do not know how to rewrite relative -// jumps after relocating them to the preamble-stub. Note that -// if you really really need to patch a function like this, it -// would be possible to add this functionality (but at some cost). -// - If there is a return (ret) instruction in the first 5 bytes -// we cannot patch the function because it may not be long enough -// for the jmp instruction we use to inject our patch. -// - If there is another thread currently executing within the bytes -// that are copied to the preamble stub, it will crash in an undefined -// way. -// -// If you get any other error than the above, you're either pointing the -// patcher at an invalid instruction (e.g. into the middle of a multi- -// byte instruction, or not at memory containing executable instructions) -// or, there may be a bug in the disassembler we use to find -// instruction boundaries. -class PreamblePatcher { - public: - // Patches target_function to point to replacement_function using a provided - // preamble_stub of stub_size bytes. - // Returns An error code indicating the result of patching. - template <class T> - static SideStepError Patch(T target_function, T replacement_function, - void* preamble_stub, size_t stub_size) { - return RawPatchWithStub(target_function, replacement_function, - reinterpret_cast<unsigned char*>(preamble_stub), - stub_size, NULL); - } - - private: - - // Patches a function by overwriting its first few bytes with - // a jump to a different function. This is similar to the RawPatch - // function except that it uses the stub allocated by the caller - // instead of allocating it. - // - // To use this function, you first have to call VirtualProtect to make the - // target function writable at least for the duration of the call. - // - // target_function: A pointer to the function that should be - // patched. - // - // replacement_function: A pointer to the function that should - // replace the target function. The replacement function must have - // exactly the same calling convention and parameters as the original - // function. - // - // preamble_stub: A pointer to a buffer where the preamble stub - // should be copied. The size of the buffer should be sufficient to - // hold the preamble bytes. - // - // stub_size: Size in bytes of the buffer allocated for the - // preamble_stub - // - // bytes_needed: Pointer to a variable that receives the minimum - // number of bytes required for the stub. Can be set to NULL if you're - // not interested. - // - // Returns An error code indicating the result of patching. - static SideStepError RawPatchWithStub(void* target_function, - void *replacement_function, - unsigned char* preamble_stub, - size_t stub_size, - size_t* bytes_needed); -}; - -}; // namespace sidestep - -#endif // SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp b/security/sandbox/chromium/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp deleted file mode 100644 index b5016009d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Implementation of PreamblePatcher - -#include "sandbox/win/src/sidestep/preamble_patcher.h" - -#include <stddef.h> - -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sidestep/mini_disassembler.h" - -// Definitions of assembly statements we need -#define ASM_JMP32REL 0xE9 -#define ASM_INT3 0xCC - -namespace { - -// Very basic memcpy. We are copying 4 to 12 bytes most of the time, so there -// is no attempt to optimize this code or have a general purpose function. -// We don't want to call the crt from this code. -inline void* RawMemcpy(void* destination, const void* source, size_t bytes) { - const char* from = reinterpret_cast<const char*>(source); - char* to = reinterpret_cast<char*>(destination); - - for (size_t i = 0; i < bytes ; i++) - to[i] = from[i]; - - return destination; -} - -// Very basic memset. We are filling 1 to 7 bytes most of the time, so there -// is no attempt to optimize this code or have a general purpose function. -// We don't want to call the crt from this code. -inline void* RawMemset(void* destination, int value, size_t bytes) { - char* to = reinterpret_cast<char*>(destination); - - for (size_t i = 0; i < bytes ; i++) - to[i] = static_cast<char>(value); - - return destination; -} - -} // namespace - -#define ASSERT(a, b) DCHECK_NT(a) - -namespace sidestep { - -SideStepError PreamblePatcher::RawPatchWithStub( - void* target_function, - void* replacement_function, - unsigned char* preamble_stub, - size_t stub_size, - size_t* bytes_needed) { - if ((NULL == target_function) || - (NULL == replacement_function) || - (NULL == preamble_stub)) { - ASSERT(false, (L"Invalid parameters - either pTargetFunction or " - L"pReplacementFunction or pPreambleStub were NULL.")); - return SIDESTEP_INVALID_PARAMETER; - } - - // TODO(V7:joi) Siggi and I just had a discussion and decided that both - // patching and unpatching are actually unsafe. We also discussed a - // method of making it safe, which is to freeze all other threads in the - // process, check their thread context to see if their eip is currently - // inside the block of instructions we need to copy to the stub, and if so - // wait a bit and try again, then unfreeze all threads once we've patched. - // Not implementing this for now since we're only using SideStep for unit - // testing, but if we ever use it for production code this is what we - // should do. - // - // NOTE: Stoyan suggests we can write 8 or even 10 bytes atomically using - // FPU instructions, and on newer processors we could use cmpxchg8b or - // cmpxchg16b. So it might be possible to do the patching/unpatching - // atomically and avoid having to freeze other threads. Note though, that - // doing it atomically does not help if one of the other threads happens - // to have its eip in the middle of the bytes you change while you change - // them. - unsigned char* target = reinterpret_cast<unsigned char*>(target_function); - - // Let's disassemble the preamble of the target function to see if we can - // patch, and to see how much of the preamble we need to take. We need 5 - // bytes for our jmp instruction, so let's find the minimum number of - // instructions to get 5 bytes. - MiniDisassembler disassembler; - unsigned int preamble_bytes = 0; - while (preamble_bytes < 5) { - InstructionType instruction_type = - disassembler.Disassemble(target + preamble_bytes, &preamble_bytes); - if (IT_JUMP == instruction_type) { - ASSERT(false, (L"Unable to patch because there is a jump instruction " - L"in the first 5 bytes.")); - return SIDESTEP_JUMP_INSTRUCTION; - } else if (IT_RETURN == instruction_type) { - ASSERT(false, (L"Unable to patch because function is too short")); - return SIDESTEP_FUNCTION_TOO_SMALL; - } else if (IT_GENERIC != instruction_type) { - ASSERT(false, (L"Disassembler encountered unsupported instruction " - L"(either unused or unknown")); - return SIDESTEP_UNSUPPORTED_INSTRUCTION; - } - } - - if (NULL != bytes_needed) - *bytes_needed = preamble_bytes + 5; - - // Inv: preamble_bytes is the number of bytes (at least 5) that we need to - // take from the preamble to have whole instructions that are 5 bytes or more - // in size total. The size of the stub required is cbPreamble + size of - // jmp (5) - if (preamble_bytes + 5 > stub_size) { - NOTREACHED_NT(); - return SIDESTEP_INSUFFICIENT_BUFFER; - } - - // First, copy the preamble that we will overwrite. - RawMemcpy(reinterpret_cast<void*>(preamble_stub), - reinterpret_cast<void*>(target), preamble_bytes); - - // Now, make a jmp instruction to the rest of the target function (minus the - // preamble bytes we moved into the stub) and copy it into our preamble-stub. - // find address to jump to, relative to next address after jmp instruction -#pragma warning(push) -#pragma warning(disable:4244) - // This assignment generates a warning because it is 32 bit specific. - int relative_offset_to_target_rest - = ((reinterpret_cast<unsigned char*>(target) + preamble_bytes) - - (preamble_stub + preamble_bytes + 5)); -#pragma warning(pop) - // jmp (Jump near, relative, displacement relative to next instruction) - preamble_stub[preamble_bytes] = ASM_JMP32REL; - // copy the address - RawMemcpy(reinterpret_cast<void*>(preamble_stub + preamble_bytes + 1), - reinterpret_cast<void*>(&relative_offset_to_target_rest), 4); - - // Inv: preamble_stub points to assembly code that will execute the - // original function by first executing the first cbPreamble bytes of the - // preamble, then jumping to the rest of the function. - - // Overwrite the first 5 bytes of the target function with a jump to our - // replacement function. - // (Jump near, relative, displacement relative to next instruction) - target[0] = ASM_JMP32REL; - - // Find offset from instruction after jmp, to the replacement function. -#pragma warning(push) -#pragma warning(disable:4244) - int offset_to_replacement_function = - reinterpret_cast<unsigned char*>(replacement_function) - - reinterpret_cast<unsigned char*>(target) - 5; -#pragma warning(pop) - // complete the jmp instruction - RawMemcpy(reinterpret_cast<void*>(target + 1), - reinterpret_cast<void*>(&offset_to_replacement_function), 4); - // Set any remaining bytes that were moved to the preamble-stub to INT3 so - // as not to cause confusion (otherwise you might see some strange - // instructions if you look at the disassembly, or even invalid - // instructions). Also, by doing this, we will break into the debugger if - // some code calls into this portion of the code. If this happens, it - // means that this function cannot be patched using this patcher without - // further thought. - if (preamble_bytes > 5) { - RawMemset(reinterpret_cast<void*>(target + 5), ASM_INT3, - preamble_bytes - 5); - } - - // Inv: The memory pointed to by target_function now points to a relative - // jump instruction that jumps over to the preamble_stub. The preamble - // stub contains the first stub_size bytes of the original target - // function's preamble code, followed by a relative jump back to the next - // instruction after the first cbPreamble bytes. - - return SIDESTEP_SUCCESS; -} - -}; // namespace sidestep - -#undef ASSERT diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep_resolver.cc b/security/sandbox/chromium/sandbox/win/src/sidestep_resolver.cc deleted file mode 100644 index d5da2fbe9..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep_resolver.cc +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sidestep_resolver.h" - -#include <stddef.h> - -#include "base/win/pe_image.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sidestep/preamble_patcher.h" - -namespace { - -const size_t kSizeOfSidestepStub = sidestep::kMaxPreambleStubSize; - -struct SidestepThunk { - char sidestep[kSizeOfSidestepStub]; // Storage for the sidestep stub. - int internal_thunk; // Dummy member to the beginning of the internal thunk. -}; - -struct SmartThunk { - const void* module_base; // Target module's base. - const void* interceptor; // Real interceptor. - SidestepThunk sidestep; // Standard sidestep thunk. -}; - -} // namespace - -namespace sandbox { - -NTSTATUS SidestepResolverThunk::Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) { - NTSTATUS ret = Init(target_module, interceptor_module, target_name, - interceptor_name, interceptor_entry_point, - thunk_storage, storage_bytes); - if (!NT_SUCCESS(ret)) - return ret; - - SidestepThunk* thunk = reinterpret_cast<SidestepThunk*>(thunk_storage); - - size_t internal_bytes = storage_bytes - kSizeOfSidestepStub; - if (!SetInternalThunk(&thunk->internal_thunk, internal_bytes, thunk_storage, - interceptor_)) - return STATUS_BUFFER_TOO_SMALL; - - AutoProtectMemory memory; - ret = memory.ChangeProtection(target_, kSizeOfSidestepStub, PAGE_READWRITE); - if (!NT_SUCCESS(ret)) - return ret; - - sidestep::SideStepError rv = sidestep::PreamblePatcher::Patch( - target_, reinterpret_cast<void*>(&thunk->internal_thunk), thunk_storage, - kSizeOfSidestepStub); - - if (sidestep::SIDESTEP_INSUFFICIENT_BUFFER == rv) - return STATUS_BUFFER_TOO_SMALL; - - if (sidestep::SIDESTEP_SUCCESS != rv) - return STATUS_UNSUCCESSFUL; - - if (storage_used) - *storage_used = GetThunkSize(); - - return ret; -} - -size_t SidestepResolverThunk::GetThunkSize() const { - return GetInternalThunkSize() + kSizeOfSidestepStub; -} - -// This is basically a wrapper around the normal sidestep patch that extends -// the thunk to use a chained interceptor. It uses the fact that -// SetInternalThunk generates the code to pass as the first parameter whatever -// it receives as original_function; we let SidestepResolverThunk set this value -// to its saved code, and then we change it to our thunk data. -NTSTATUS SmartSidestepResolverThunk::Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) { - if (storage_bytes < GetThunkSize()) - return STATUS_BUFFER_TOO_SMALL; - - SmartThunk* thunk = reinterpret_cast<SmartThunk*>(thunk_storage); - thunk->module_base = target_module; - - NTSTATUS ret; - if (interceptor_entry_point) { - thunk->interceptor = interceptor_entry_point; - } else { - ret = ResolveInterceptor(interceptor_module, interceptor_name, - &thunk->interceptor); - if (!NT_SUCCESS(ret)) - return ret; - } - - // Perform a standard sidestep patch on the last part of the thunk, but point - // to our internal smart interceptor. - size_t standard_bytes = storage_bytes - offsetof(SmartThunk, sidestep); - ret = SidestepResolverThunk::Setup(target_module, interceptor_module, - target_name, NULL, &SmartStub, - &thunk->sidestep, standard_bytes, NULL); - if (!NT_SUCCESS(ret)) - return ret; - - // Fix the internal thunk to pass the whole buffer to the interceptor. - SetInternalThunk(&thunk->sidestep.internal_thunk, GetInternalThunkSize(), - thunk_storage, &SmartStub); - - if (storage_used) - *storage_used = GetThunkSize(); - - return ret; -} - -size_t SmartSidestepResolverThunk::GetThunkSize() const { - return GetInternalThunkSize() + kSizeOfSidestepStub + - offsetof(SmartThunk, sidestep); -} - -// This code must basically either call the intended interceptor or skip the -// call and invoke instead the original function. In any case, we are saving -// the registers that may be trashed by our c++ code. -// -// This function is called with a first parameter inserted by us, that points -// to our SmartThunk. When we call the interceptor we have to replace this -// parameter with the one expected by that function (stored inside our -// structure); on the other hand, when we skip the interceptor we have to remove -// that extra argument before calling the original function. -// -// When we skip the interceptor, the transformation of the stack looks like: -// On Entry: On Use: On Exit: -// [param 2] = first real argument [param 2] (esp+1c) [param 2] -// [param 1] = our SmartThunk [param 1] (esp+18) [ret address] -// [ret address] = real caller [ret address] (esp+14) [xxx] -// [xxx] [addr to jump to] (esp+10) [xxx] -// [xxx] [saved eax] [xxx] -// [xxx] [saved ebx] [xxx] -// [xxx] [saved ecx] [xxx] -// [xxx] [saved edx] [xxx] -__declspec(naked) -void SmartSidestepResolverThunk::SmartStub() { - __asm { - push eax // Space for the jump. - push eax // Save registers. - push ebx - push ecx - push edx - mov ebx, [esp + 0x18] // First parameter = SmartThunk. - mov edx, [esp + 0x14] // Get the return address. - mov eax, [ebx]SmartThunk.module_base - push edx - push eax - call SmartSidestepResolverThunk::IsInternalCall - add esp, 8 - - test eax, eax - lea edx, [ebx]SmartThunk.sidestep // The original function. - jz call_interceptor - - // Skip this call - mov ecx, [esp + 0x14] // Return address. - mov [esp + 0x18], ecx // Remove first parameter. - mov [esp + 0x10], edx - pop edx // Restore registers. - pop ecx - pop ebx - pop eax - ret 4 // Jump to original function. - - call_interceptor: - mov ecx, [ebx]SmartThunk.interceptor - mov [esp + 0x18], edx // Replace first parameter. - mov [esp + 0x10], ecx - pop edx // Restore registers. - pop ecx - pop ebx - pop eax - ret // Jump to original function. - } -} - -bool SmartSidestepResolverThunk::IsInternalCall(const void* base, - void* return_address) { - DCHECK_NT(base); - DCHECK_NT(return_address); - - base::win::PEImage pe(base); - if (pe.GetImageSectionFromAddr(return_address)) - return true; - return false; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sidestep_resolver.h b/security/sandbox/chromium/sandbox/win/src/sidestep_resolver.h deleted file mode 100644 index 8088272ee..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sidestep_resolver.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SIDESTEP_RESOLVER_H__ -#define SANDBOX_SRC_SIDESTEP_RESOLVER_H__ - -#include <stddef.h> - -#include "base/macros.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/resolver.h" - -namespace sandbox { - -// This is the concrete resolver used to perform sidestep interceptions. -class SidestepResolverThunk : public ResolverThunk { - public: - SidestepResolverThunk() {} - ~SidestepResolverThunk() override {} - - // Implementation of Resolver::Setup. - NTSTATUS Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) override; - - // Implementation of Resolver::GetThunkSize. - size_t GetThunkSize() const override; - - private: - DISALLOW_COPY_AND_ASSIGN(SidestepResolverThunk); -}; - -// This is the concrete resolver used to perform smart sidestep interceptions. -// This means basically a sidestep interception that skips the interceptor when -// the caller resides on the same dll being intercepted. It is intended as -// a helper only, because that determination is not infallible. -class SmartSidestepResolverThunk : public SidestepResolverThunk { - public: - SmartSidestepResolverThunk() {} - ~SmartSidestepResolverThunk() override {} - - // Implementation of Resolver::Setup. - NTSTATUS Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) override; - - // Implementation of Resolver::GetThunkSize. - size_t GetThunkSize() const override; - - private: - // Performs the actual call to the interceptor if the conditions are correct - // (as determined by IsInternalCall). - static void SmartStub(); - - // Returns true if return_address is inside the module loaded at base. - static bool IsInternalCall(const void* base, void* return_address); - - DISALLOW_COPY_AND_ASSIGN(SmartSidestepResolverThunk); -}; - -} // namespace sandbox - - -#endif // SANDBOX_SRC_SIDESTEP_RESOLVER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sync_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/sync_dispatcher.cc deleted file mode 100644 index 2e5d1c50f..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sync_dispatcher.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sync_dispatcher.h" - -#include <stdint.h> - -#include "base/win/windows_version.h" -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/interceptors.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_broker.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sync_interception.h" -#include "sandbox/win/src/sync_policy.h" - -namespace sandbox { - -SyncDispatcher::SyncDispatcher(PolicyBase* policy_base) - : policy_base_(policy_base) { - static const IPCCall create_params = { - {IPC_CREATEEVENT_TAG, {WCHAR_TYPE, UINT32_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>(&SyncDispatcher::CreateEvent)}; - - static const IPCCall open_params = { - {IPC_OPENEVENT_TAG, {WCHAR_TYPE, UINT32_TYPE}}, - reinterpret_cast<CallbackGeneric>(&SyncDispatcher::OpenEvent)}; - - ipc_calls_.push_back(create_params); - ipc_calls_.push_back(open_params); -} - -bool SyncDispatcher::SetupService(InterceptionManager* manager, - int service) { - if (service == IPC_CREATEEVENT_TAG) { - return INTERCEPT_NT(manager, NtCreateEvent, CREATE_EVENT_ID, 24); - } - return (service == IPC_OPENEVENT_TAG) && - INTERCEPT_NT(manager, NtOpenEvent, OPEN_EVENT_ID, 16); -} - -bool SyncDispatcher::CreateEvent(IPCInfo* ipc, - base::string16* name, - uint32_t event_type, - uint32_t initial_state) { - const wchar_t* event_name = name->c_str(); - CountedParameterSet<NameBased> params; - params[NameBased::NAME] = ParamPickerMake(event_name); - - EvalResult result = policy_base_->EvalPolicy(IPC_CREATEEVENT_TAG, - params.GetBase()); - HANDLE handle = NULL; - // Return operation status on the IPC. - ipc->return_info.nt_status = SyncPolicy::CreateEventAction( - result, *ipc->client_info, *name, event_type, initial_state, &handle); - ipc->return_info.handle = handle; - return true; -} - -bool SyncDispatcher::OpenEvent(IPCInfo* ipc, - base::string16* name, - uint32_t desired_access) { - const wchar_t* event_name = name->c_str(); - - CountedParameterSet<OpenEventParams> params; - params[OpenEventParams::NAME] = ParamPickerMake(event_name); - params[OpenEventParams::ACCESS] = ParamPickerMake(desired_access); - - EvalResult result = policy_base_->EvalPolicy(IPC_OPENEVENT_TAG, - params.GetBase()); - HANDLE handle = NULL; - // Return operation status on the IPC. - ipc->return_info.nt_status = SyncPolicy::OpenEventAction( - result, *ipc->client_info, *name, desired_access, &handle); - ipc->return_info.handle = handle; - return true; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sync_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/sync_dispatcher.h deleted file mode 100644 index 8a2a0e582..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sync_dispatcher.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SYNC_DISPATCHER_H_ -#define SANDBOX_SRC_SYNC_DISPATCHER_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox_policy_base.h" - -namespace sandbox { - -// This class handles sync-related IPC calls. -class SyncDispatcher : public Dispatcher { - public: - explicit SyncDispatcher(PolicyBase* policy_base); - ~SyncDispatcher() override {} - - // Dispatcher interface. - bool SetupService(InterceptionManager* manager, int service) override; - -private: - // Processes IPC requests coming from calls to CreateEvent in the target. - bool CreateEvent(IPCInfo* ipc, - base::string16* name, - uint32_t event_type, - uint32_t initial_state); - - // Processes IPC requests coming from calls to OpenEvent in the target. - bool OpenEvent(IPCInfo* ipc, base::string16* name, uint32_t desired_access); - - PolicyBase* policy_base_; - DISALLOW_COPY_AND_ASSIGN(SyncDispatcher); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_SYNC_DISPATCHER_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/sync_interception.cc b/security/sandbox/chromium/sandbox/win/src/sync_interception.cc deleted file mode 100644 index 35d092492..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sync_interception.cc +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sync_interception.h" - -#include <stdint.h> - -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/policy_target.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" -#include "sandbox/win/src/target_services.h" -#include "mozilla/sandboxing/sandboxLogging.h" - -namespace sandbox { - -ResultCode ProxyCreateEvent(LPCWSTR name, - uint32_t initial_state, - EVENT_TYPE event_type, - void* ipc_memory, - CrossCallReturn* answer) { - CountedParameterSet<NameBased> params; - params[NameBased::NAME] = ParamPickerMake(name); - - if (!QueryBroker(IPC_CREATEEVENT_TAG, params.GetBase())) - return SBOX_ERROR_GENERIC; - - SharedMemIPCClient ipc(ipc_memory); - ResultCode code = CrossCall(ipc, IPC_CREATEEVENT_TAG, name, event_type, - initial_state, answer); - return code; -} - -ResultCode ProxyOpenEvent(LPCWSTR name, - uint32_t desired_access, - void* ipc_memory, - CrossCallReturn* answer) { - CountedParameterSet<OpenEventParams> params; - params[OpenEventParams::NAME] = ParamPickerMake(name); - params[OpenEventParams::ACCESS] = ParamPickerMake(desired_access); - - if (!QueryBroker(IPC_OPENEVENT_TAG, params.GetBase())) - return SBOX_ERROR_GENERIC; - - SharedMemIPCClient ipc(ipc_memory); - ResultCode code = CrossCall(ipc, IPC_OPENEVENT_TAG, name, desired_access, - answer); - - return code; -} - -NTSTATUS WINAPI TargetNtCreateEvent(NtCreateEventFunction orig_CreateEvent, - PHANDLE event_handle, - ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, - EVENT_TYPE event_type, - BOOLEAN initial_state) { - NTSTATUS status = orig_CreateEvent(event_handle, desired_access, - object_attributes, event_type, - initial_state); - if (status != STATUS_ACCESS_DENIED || !object_attributes) - return status; - - mozilla::sandboxing::LogBlocked("NtCreatEvent", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - do { - if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (memory == NULL) - break; - - OBJECT_ATTRIBUTES object_attribs_copy = *object_attributes; - // The RootDirectory points to BaseNamedObjects. We can ignore it. - object_attribs_copy.RootDirectory = NULL; - - wchar_t* name = NULL; - uint32_t attributes = 0; - NTSTATUS ret = AllocAndCopyName(&object_attribs_copy, &name, &attributes, - NULL); - if (!NT_SUCCESS(ret) || name == NULL) - break; - - CrossCallReturn answer = {0}; - answer.nt_status = status; - ResultCode code = ProxyCreateEvent(name, initial_state, event_type, memory, - &answer); - operator delete(name, NT_ALLOC); - - if (code != SBOX_ALL_OK) { - status = answer.nt_status; - break; - } - __try { - *event_handle = answer.handle; - status = STATUS_SUCCESS; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - mozilla::sandboxing::LogAllowed("NtCreateEvent", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } while (false); - - return status; -} - -NTSTATUS WINAPI TargetNtOpenEvent(NtOpenEventFunction orig_OpenEvent, - PHANDLE event_handle, - ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes) { - NTSTATUS status = orig_OpenEvent(event_handle, desired_access, - object_attributes); - if (status != STATUS_ACCESS_DENIED || !object_attributes) - return status; - - mozilla::sandboxing::LogBlocked("NtOpenEvent", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - // - // We don't trust that the IPC can work this early. - if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) - return status; - - do { - if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE)) - break; - - void* memory = GetGlobalIPCMemory(); - if (memory == NULL) - break; - - OBJECT_ATTRIBUTES object_attribs_copy = *object_attributes; - // The RootDirectory points to BaseNamedObjects. We can ignore it. - object_attribs_copy.RootDirectory = NULL; - - wchar_t* name = NULL; - uint32_t attributes = 0; - NTSTATUS ret = AllocAndCopyName(&object_attribs_copy, &name, &attributes, - NULL); - if (!NT_SUCCESS(ret) || name == NULL) - break; - - CrossCallReturn answer = {0}; - answer.nt_status = status; - ResultCode code = ProxyOpenEvent(name, desired_access, memory, &answer); - operator delete(name, NT_ALLOC); - - if (code != SBOX_ALL_OK) { - status = answer.nt_status; - break; - } - __try { - *event_handle = answer.handle; - status = STATUS_SUCCESS; - } __except(EXCEPTION_EXECUTE_HANDLER) { - break; - } - mozilla::sandboxing::LogAllowed("NtOpenEvent", - object_attributes->ObjectName->Buffer, - object_attributes->ObjectName->Length); - } while (false); - - return status; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sync_interception.h b/security/sandbox/chromium/sandbox/win/src/sync_interception.h deleted file mode 100644 index 0f985a8ed..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sync_interception.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_SYNC_INTERCEPTION_H__ -#define SANDBOX_SRC_SYNC_INTERCEPTION_H__ - -namespace sandbox { - -extern "C" { - -typedef NTSTATUS (WINAPI* NtCreateEventFunction) ( - PHANDLE EventHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - EVENT_TYPE EventType, - BOOLEAN InitialState); - -typedef NTSTATUS (WINAPI *NtOpenEventFunction) ( - PHANDLE EventHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes); - -// Interceptors for NtCreateEvent/NtOpenEvent -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateEvent( - NtCreateEventFunction orig_CreateEvent, - PHANDLE event_handle, - ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes, - EVENT_TYPE event_type, - BOOLEAN initial_state); - -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenEvent( - NtOpenEventFunction orig_OpenEvent, - PHANDLE event_handle, - ACCESS_MASK desired_access, - POBJECT_ATTRIBUTES object_attributes); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_SYNC_INTERCEPTION_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sync_policy.cc b/security/sandbox/chromium/sandbox/win/src/sync_policy.cc deleted file mode 100644 index 7ef094ff7..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sync_policy.cc +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include <string> - -#include "sandbox/win/src/sync_policy.h" - -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/policy_engine_opcodes.h" -#include "sandbox/win/src/policy_params.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sandbox_utils.h" -#include "sandbox/win/src/sync_interception.h" -#include "sandbox/win/src/win_utils.h" - -namespace sandbox { - -// Provides functionality to resolve a symbolic link within the object -// directory passed in. -NTSTATUS ResolveSymbolicLink(const base::string16& directory_name, - const base::string16& name, - base::string16* target) { - NtOpenDirectoryObjectFunction NtOpenDirectoryObject = NULL; - ResolveNTFunctionPtr("NtOpenDirectoryObject", &NtOpenDirectoryObject); - - NtQuerySymbolicLinkObjectFunction NtQuerySymbolicLinkObject = NULL; - ResolveNTFunctionPtr("NtQuerySymbolicLinkObject", - &NtQuerySymbolicLinkObject); - - NtOpenSymbolicLinkObjectFunction NtOpenSymbolicLinkObject = NULL; - ResolveNTFunctionPtr("NtOpenSymbolicLinkObject", &NtOpenSymbolicLinkObject); - - NtCloseFunction NtClose = NULL; - ResolveNTFunctionPtr("NtClose", &NtClose); - - OBJECT_ATTRIBUTES symbolic_link_directory_attributes = {}; - UNICODE_STRING symbolic_link_directory_string = {}; - InitObjectAttribs(directory_name, OBJ_CASE_INSENSITIVE, NULL, - &symbolic_link_directory_attributes, - &symbolic_link_directory_string, NULL); - - HANDLE symbolic_link_directory = NULL; - NTSTATUS status = NtOpenDirectoryObject(&symbolic_link_directory, - DIRECTORY_QUERY, - &symbolic_link_directory_attributes); - if (!NT_SUCCESS(status)) - return status; - - OBJECT_ATTRIBUTES symbolic_link_attributes = {}; - UNICODE_STRING name_string = {}; - InitObjectAttribs(name, OBJ_CASE_INSENSITIVE, symbolic_link_directory, - &symbolic_link_attributes, &name_string, NULL); - - HANDLE symbolic_link = NULL; - status = NtOpenSymbolicLinkObject(&symbolic_link, GENERIC_READ, - &symbolic_link_attributes); - CHECK(NT_SUCCESS(NtClose(symbolic_link_directory))); - if (!NT_SUCCESS(status)) - return status; - - UNICODE_STRING target_path = {}; - unsigned long target_length = 0; - status = NtQuerySymbolicLinkObject(symbolic_link, &target_path, - &target_length); - if (status != STATUS_BUFFER_TOO_SMALL) { - CHECK(NT_SUCCESS(NtClose(symbolic_link))); - return status; - } - - target_path.Length = 0; - target_path.MaximumLength = static_cast<USHORT>(target_length); - target_path.Buffer = new wchar_t[target_path.MaximumLength + 1]; - status = NtQuerySymbolicLinkObject(symbolic_link, &target_path, - &target_length); - if (NT_SUCCESS(status)) - target->assign(target_path.Buffer, target_length); - - CHECK(NT_SUCCESS(NtClose(symbolic_link))); - delete[] target_path.Buffer; - return status; -} - -NTSTATUS GetBaseNamedObjectsDirectory(HANDLE* directory) { - static HANDLE base_named_objects_handle = NULL; - if (base_named_objects_handle) { - *directory = base_named_objects_handle; - return STATUS_SUCCESS; - } - - NtOpenDirectoryObjectFunction NtOpenDirectoryObject = NULL; - ResolveNTFunctionPtr("NtOpenDirectoryObject", &NtOpenDirectoryObject); - - DWORD session_id = 0; - ProcessIdToSessionId(::GetCurrentProcessId(), &session_id); - - base::string16 base_named_objects_path; - - NTSTATUS status = ResolveSymbolicLink(L"\\Sessions\\BNOLINKS", - base::StringPrintf(L"%d", session_id), - &base_named_objects_path); - if (!NT_SUCCESS(status)) { - DLOG(ERROR) << "Failed to resolve BaseNamedObjects path. Error: " - << status; - return status; - } - - UNICODE_STRING directory_name = {}; - OBJECT_ATTRIBUTES object_attributes = {}; - InitObjectAttribs(base_named_objects_path, OBJ_CASE_INSENSITIVE, NULL, - &object_attributes, &directory_name, NULL); - status = NtOpenDirectoryObject(&base_named_objects_handle, - DIRECTORY_ALL_ACCESS, - &object_attributes); - if (NT_SUCCESS(status)) - *directory = base_named_objects_handle; - return status; -} - -bool SyncPolicy::GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy) { - base::string16 mod_name(name); - if (mod_name.empty()) { - return false; - } - - if (TargetPolicy::EVENTS_ALLOW_ANY != semantics && - TargetPolicy::EVENTS_ALLOW_READONLY != semantics) { - // Other flags are not valid for sync policy yet. - NOTREACHED(); - return false; - } - - // Add the open rule. - EvalResult result = ASK_BROKER; - PolicyRule open(result); - - if (!open.AddStringMatch(IF, OpenEventParams::NAME, name, CASE_INSENSITIVE)) - return false; - - if (TargetPolicy::EVENTS_ALLOW_READONLY == semantics) { - // We consider all flags that are not known to be readonly as potentially - // used for write. - uint32_t allowed_flags = SYNCHRONIZE | GENERIC_READ | READ_CONTROL; - uint32_t restricted_flags = ~allowed_flags; - open.AddNumberMatch(IF_NOT, OpenEventParams::ACCESS, restricted_flags, AND); - } - - if (!policy->AddRule(IPC_OPENEVENT_TAG, &open)) - return false; - - // If it's not a read only, add the create rule. - if (TargetPolicy::EVENTS_ALLOW_READONLY != semantics) { - PolicyRule create(result); - if (!create.AddStringMatch(IF, NameBased::NAME, name, CASE_INSENSITIVE)) - return false; - - if (!policy->AddRule(IPC_CREATEEVENT_TAG, &create)) - return false; - } - - return true; -} - -NTSTATUS SyncPolicy::CreateEventAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& event_name, - uint32_t event_type, - uint32_t initial_state, - HANDLE* handle) { - NtCreateEventFunction NtCreateEvent = NULL; - ResolveNTFunctionPtr("NtCreateEvent", &NtCreateEvent); - - // The only action supported is ASK_BROKER which means create the requested - // file as specified. - if (ASK_BROKER != eval_result) - return false; - - HANDLE object_directory = NULL; - NTSTATUS status = GetBaseNamedObjectsDirectory(&object_directory); - if (status != STATUS_SUCCESS) - return status; - - UNICODE_STRING unicode_event_name = {}; - OBJECT_ATTRIBUTES object_attributes = {}; - InitObjectAttribs(event_name, OBJ_CASE_INSENSITIVE, object_directory, - &object_attributes, &unicode_event_name, NULL); - - HANDLE local_handle = NULL; - status = NtCreateEvent(&local_handle, EVENT_ALL_ACCESS, &object_attributes, - static_cast<EVENT_TYPE>(event_type), - static_cast<BOOLEAN>(initial_state)); - if (NULL == local_handle) - return status; - - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - client_info.process, handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - return status; -} - -NTSTATUS SyncPolicy::OpenEventAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& event_name, - uint32_t desired_access, - HANDLE* handle) { - NtOpenEventFunction NtOpenEvent = NULL; - ResolveNTFunctionPtr("NtOpenEvent", &NtOpenEvent); - - // The only action supported is ASK_BROKER which means create the requested - // event as specified. - if (ASK_BROKER != eval_result) - return false; - - HANDLE object_directory = NULL; - NTSTATUS status = GetBaseNamedObjectsDirectory(&object_directory); - if (status != STATUS_SUCCESS) - return status; - - UNICODE_STRING unicode_event_name = {}; - OBJECT_ATTRIBUTES object_attributes = {}; - InitObjectAttribs(event_name, OBJ_CASE_INSENSITIVE, object_directory, - &object_attributes, &unicode_event_name, NULL); - - HANDLE local_handle = NULL; - status = NtOpenEvent(&local_handle, desired_access, &object_attributes); - if (NULL == local_handle) - return status; - - if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, - client_info.process, handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return STATUS_ACCESS_DENIED; - } - return status; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sync_policy.h b/security/sandbox/chromium/sandbox/win/src/sync_policy.h deleted file mode 100644 index 24e5c7d87..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sync_policy.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_SYNC_POLICY_H__ -#define SANDBOX_SRC_SYNC_POLICY_H__ - -#include <stdint.h> - -#include <string> - -#include "base/strings/string16.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/sandbox_policy.h" - -namespace sandbox { - -enum EvalResult; - -// This class centralizes most of the knowledge related to sync policy -class SyncPolicy { - public: - // Creates the required low-level policy rules to evaluate a high-level - // policy rule for sync calls, in particular open or create actions. - // name is the sync object name, semantics is the desired semantics for the - // open or create and policy is the policy generator to which the rules are - // going to be added. - static bool GenerateRules(const wchar_t* name, - TargetPolicy::Semantics semantics, - LowLevelPolicy* policy); - - // Performs the desired policy action on a request. - // client_info is the target process that is making the request and - // eval_result is the desired policy action to accomplish. - static NTSTATUS CreateEventAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& event_name, - uint32_t event_type, - uint32_t initial_state, - HANDLE* handle); - static NTSTATUS OpenEventAction(EvalResult eval_result, - const ClientInfo& client_info, - const base::string16& event_name, - uint32_t desired_access, - HANDLE* handle); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_SYNC_POLICY_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/sync_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/sync_policy_test.cc deleted file mode 100644 index 875bc4b2c..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sync_policy_test.cc +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sync_policy_test.h" - -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/nt_internals.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -SBOX_TESTS_COMMAND int Event_Open(int argc, wchar_t **argv) { - if (argc != 2) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - DWORD desired_access = SYNCHRONIZE; - if (L'f' == argv[0][0]) - desired_access = EVENT_ALL_ACCESS; - - base::win::ScopedHandle event_open(::OpenEvent( - desired_access, FALSE, argv[1])); - DWORD error_open = ::GetLastError(); - - if (event_open.IsValid()) - return SBOX_TEST_SUCCEEDED; - - if (ERROR_ACCESS_DENIED == error_open || - ERROR_BAD_PATHNAME == error_open || - ERROR_FILE_NOT_FOUND == error_open) - return SBOX_TEST_DENIED; - - return SBOX_TEST_FAILED; -} - -SBOX_TESTS_COMMAND int Event_CreateOpen(int argc, wchar_t **argv) { - if (argc < 2 || argc > 3) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - wchar_t *event_name = NULL; - if (3 == argc) - event_name = argv[2]; - - BOOL manual_reset = FALSE; - BOOL initial_state = FALSE; - if (L't' == argv[0][0]) - manual_reset = TRUE; - if (L't' == argv[1][0]) - initial_state = TRUE; - - base::win::ScopedHandle event_create(::CreateEvent( - NULL, manual_reset, initial_state, event_name)); - DWORD error_create = ::GetLastError(); - base::win::ScopedHandle event_open; - if (event_name) - event_open.Set(::OpenEvent(EVENT_ALL_ACCESS, FALSE, event_name)); - - if (event_create.IsValid()) { - DWORD wait = ::WaitForSingleObject(event_create.Get(), 0); - if (initial_state && WAIT_OBJECT_0 != wait) - return SBOX_TEST_FAILED; - - if (!initial_state && WAIT_TIMEOUT != wait) - return SBOX_TEST_FAILED; - } - - if (event_name) { - // Both event_open and event_create have to be valid. - if (event_open.IsValid() && event_create.IsValid()) - return SBOX_TEST_SUCCEEDED; - - if ((event_open.IsValid() && !event_create.IsValid()) || - (!event_open.IsValid() && event_create.IsValid())) { - return SBOX_TEST_FAILED; - } - } else { - // Only event_create has to be valid. - if (event_create.Get()) - return SBOX_TEST_SUCCEEDED; - } - - if (ERROR_ACCESS_DENIED == error_create || - ERROR_BAD_PATHNAME == error_create) - return SBOX_TEST_DENIED; - - return SBOX_TEST_FAILED; -} - -// Tests the creation of events using all the possible combinations. -TEST(SyncPolicyTest, TestEvent) { - TestRunner runner; - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC, - TargetPolicy::EVENTS_ALLOW_ANY, - L"test1")); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC, - TargetPolicy::EVENTS_ALLOW_ANY, - L"test2")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f t")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t t")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f test1")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f test2")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f t test1")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t t test2")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f f test3")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t f test4")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f t test3")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t t test4")); -} - -// Tests opening events with read only access. -TEST(SyncPolicyTest, TestEventReadOnly) { - TestRunner runner; - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC, - TargetPolicy::EVENTS_ALLOW_READONLY, - L"test1")); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC, - TargetPolicy::EVENTS_ALLOW_READONLY, - L"test2")); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC, - TargetPolicy::EVENTS_ALLOW_READONLY, - L"test5")); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC, - TargetPolicy::EVENTS_ALLOW_READONLY, - L"test6")); - - base::win::ScopedHandle handle1(::CreateEvent(NULL, FALSE, FALSE, L"test1")); - base::win::ScopedHandle handle2(::CreateEvent(NULL, FALSE, FALSE, L"test2")); - base::win::ScopedHandle handle3(::CreateEvent(NULL, FALSE, FALSE, L"test3")); - base::win::ScopedHandle handle4(::CreateEvent(NULL, FALSE, FALSE, L"test4")); - - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen f f")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_CreateOpen t f")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test1")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Event_Open s test2")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test3")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open s test4")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f f test5")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t f test6")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen f t test5")); - EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_CreateOpen t t test6")); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/sync_policy_test.h b/security/sandbox/chromium/sandbox/win/src/sync_policy_test.h deleted file mode 100644 index 4f354b35b..000000000 --- a/security/sandbox/chromium/sandbox/win/src/sync_policy_test.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_SYNC_POLICY_TEST_H_ -#define SANDBOX_WIN_SRC_SYNC_POLICY_TEST_H_ - -#include "sandbox/win/tests/common/controller.h" - -namespace sandbox { - -// Opens the named event received on argv[1]. The requested access is -// EVENT_ALL_ACCESS if argv[0] starts with 'f', or SYNCHRONIZE otherwise. -SBOX_TESTS_COMMAND int Event_Open(int argc, wchar_t **argv); - -} // namespace sandbox - -#endif // SANDBOX_WIN_SRC_SYNC_POLICY_TEST_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/target_interceptions.cc b/security/sandbox/chromium/sandbox/win/src/target_interceptions.cc deleted file mode 100644 index e6b0dcf78..000000000 --- a/security/sandbox/chromium/sandbox/win/src/target_interceptions.cc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/target_interceptions.h" - -#include "sandbox/win/src/interception_agent.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/target_services.h" - -namespace sandbox { - -SANDBOX_INTERCEPT NtExports g_nt; - -// Hooks NtMapViewOfSection to detect the load of DLLs. If hot patching is -// required for this dll, this functions patches it. -NTSTATUS WINAPI TargetNtMapViewOfSection( - NtMapViewOfSectionFunction orig_MapViewOfSection, HANDLE section, - HANDLE process, PVOID *base, ULONG_PTR zero_bits, SIZE_T commit_size, - PLARGE_INTEGER offset, PSIZE_T view_size, SECTION_INHERIT inherit, - ULONG allocation_type, ULONG protect) { - NTSTATUS ret = orig_MapViewOfSection(section, process, base, zero_bits, - commit_size, offset, view_size, inherit, - allocation_type, protect); - - static int s_load_count = 0; - if (1 == s_load_count) { - SandboxFactory::GetTargetServices()->GetState()->SetKernel32Loaded(); - s_load_count = 2; - } - - do { - if (!NT_SUCCESS(ret)) - break; - - if (!InitHeap()) - break; - - if (!IsSameProcess(process)) - break; - - if (!IsValidImageSection(section, base, offset, view_size)) - break; - - UINT image_flags; - UNICODE_STRING* module_name = - GetImageInfoFromModule(reinterpret_cast<HMODULE>(*base), &image_flags); - UNICODE_STRING* file_name = GetBackingFilePath(*base); - - if ((!module_name) && (image_flags & MODULE_HAS_CODE)) { - // If the module has no exports we retrieve the module name from the - // full path of the mapped section. - module_name = ExtractModuleName(file_name); - } - - InterceptionAgent* agent = InterceptionAgent::GetInterceptionAgent(); - - if (agent) { - if (!agent->OnDllLoad(file_name, module_name, *base)) { - // Interception agent is demanding to un-map the module. - g_nt.UnmapViewOfSection(process, *base); - ret = STATUS_UNSUCCESSFUL; - } - } - - if (module_name) - operator delete(module_name, NT_ALLOC); - - if (file_name) - operator delete(file_name, NT_ALLOC); - - } while (false); - - if (!s_load_count) - s_load_count = 1; - - return ret; -} - -NTSTATUS WINAPI TargetNtUnmapViewOfSection( - NtUnmapViewOfSectionFunction orig_UnmapViewOfSection, HANDLE process, - PVOID base) { - NTSTATUS ret = orig_UnmapViewOfSection(process, base); - - if (!NT_SUCCESS(ret)) - return ret; - - if (!IsSameProcess(process)) - return ret; - - InterceptionAgent* agent = InterceptionAgent::GetInterceptionAgent(); - - if (agent) - agent->OnDllUnload(base); - - return ret; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/target_interceptions.h b/security/sandbox/chromium/sandbox/win/src/target_interceptions.h deleted file mode 100644 index f4805fec5..000000000 --- a/security/sandbox/chromium/sandbox/win/src/target_interceptions.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_types.h" - -#ifndef SANDBOX_SRC_TARGET_INTERCEPTIONS_H__ -#define SANDBOX_SRC_TARGET_INTERCEPTIONS_H__ - -namespace sandbox { - -extern "C" { - -// Interception of NtMapViewOfSection on the child process. -// It should never be called directly. This function provides the means to -// detect dlls being loaded, so we can patch them if needed. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtMapViewOfSection( - NtMapViewOfSectionFunction orig_MapViewOfSection, HANDLE section, - HANDLE process, PVOID *base, ULONG_PTR zero_bits, SIZE_T commit_size, - PLARGE_INTEGER offset, PSIZE_T view_size, SECTION_INHERIT inherit, - ULONG allocation_type, ULONG protect); - -// Interception of NtUnmapViewOfSection on the child process. -// It should never be called directly. This function provides the means to -// detect dlls being unloaded, so we can clean up our interceptions. -SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtUnmapViewOfSection( - NtUnmapViewOfSectionFunction orig_UnmapViewOfSection, HANDLE process, - PVOID base); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_SRC_TARGET_INTERCEPTIONS_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.cc b/security/sandbox/chromium/sandbox/win/src/target_process.cc deleted file mode 100644 index e27655e7e..000000000 --- a/security/sandbox/chromium/sandbox/win/src/target_process.cc +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/target_process.h" - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/win/pe_image.h" -#include "base/win/startup_information.h" -#include "base/win/windows_version.h" -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/policy_low_level.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sharedmem_ipc_server.h" -#include "sandbox/win/src/win_utils.h" - -namespace { - -void CopyPolicyToTarget(const void* source, size_t size, void* dest) { - if (!source || !size) - return; - memcpy(dest, source, size); - sandbox::PolicyGlobal* policy = - reinterpret_cast<sandbox::PolicyGlobal*>(dest); - - size_t offset = reinterpret_cast<size_t>(source); - - for (size_t i = 0; i < sandbox::kMaxServiceCount; i++) { - size_t buffer = reinterpret_cast<size_t>(policy->entry[i]); - if (buffer) { - buffer -= offset; - policy->entry[i] = reinterpret_cast<sandbox::PolicyBuffer*>(buffer); - } - } -} - -} // namespace - -namespace sandbox { - -SANDBOX_INTERCEPT HANDLE g_shared_section; -SANDBOX_INTERCEPT size_t g_shared_IPC_size; -SANDBOX_INTERCEPT size_t g_shared_policy_size; - -// Returns the address of the main exe module in memory taking in account -// address space layout randomization. -void* GetBaseAddress(const wchar_t* exe_name, void* entry_point) { - HMODULE exe = ::LoadLibrary(exe_name); - if (NULL == exe) - return exe; - - base::win::PEImage pe(exe); - if (!pe.VerifyMagic()) { - ::FreeLibrary(exe); - return exe; - } - PIMAGE_NT_HEADERS nt_header = pe.GetNTHeaders(); - char* base = reinterpret_cast<char*>(entry_point) - - nt_header->OptionalHeader.AddressOfEntryPoint; - - ::FreeLibrary(exe); - return base; -} - -TargetProcess::TargetProcess(base::win::ScopedHandle initial_token, - base::win::ScopedHandle lockdown_token, - base::win::ScopedHandle lowbox_token, - HANDLE job, - ThreadProvider* thread_pool) - // This object owns everything initialized here except thread_pool and - // the job_ handle. The Job handle is closed by BrokerServices and results - // eventually in a call to our dtor. - : lockdown_token_(lockdown_token.Pass()), - initial_token_(initial_token.Pass()), - lowbox_token_(lowbox_token.Pass()), - job_(job), - thread_pool_(thread_pool), - base_address_(NULL) {} - -TargetProcess::~TargetProcess() { - DWORD exit_code = 0; - // Give a chance to the process to die. In most cases the JOB_KILL_ON_CLOSE - // will take effect only when the context changes. As far as the testing went, - // this wait was enough to switch context and kill the processes in the job. - // If this process is already dead, the function will return without waiting. - // TODO(nsylvain): If the process is still alive at the end, we should kill - // it. http://b/893891 - // For now, this wait is there only to do a best effort to prevent some leaks - // from showing up in purify. - if (sandbox_process_info_.IsValid()) { - ::WaitForSingleObject(sandbox_process_info_.process_handle(), 50); - // At this point, the target process should have been killed. Check. - if (!::GetExitCodeProcess(sandbox_process_info_.process_handle(), - &exit_code) || (STILL_ACTIVE == exit_code)) { - // Something went wrong. We don't know if the target is in a state where - // it can manage to do another IPC call. If it can, and we've destroyed - // the |ipc_server_|, it will crash the broker. So we intentionally leak - // that. - if (shared_section_.IsValid()) - shared_section_.Take(); - ignore_result(ipc_server_.release()); - sandbox_process_info_.TakeProcessHandle(); - return; - } - } - - // ipc_server_ references our process handle, so make sure the former is shut - // down before the latter is closed (by ScopedProcessInformation). - ipc_server_.reset(); -} - -// Creates the target (child) process suspended and assigns it to the job -// object. -DWORD TargetProcess::Create(const wchar_t* exe_path, - const wchar_t* command_line, - bool inherit_handles, - const base::win::StartupInformation& startup_info, - base::win::ScopedProcessInformation* target_info) { - if (lowbox_token_.IsValid() && - base::win::GetVersion() < base::win::VERSION_WIN8) { - // We don't allow lowbox_token below Windows 8. - return ERROR_INVALID_PARAMETER; - } - - exe_name_.reset(_wcsdup(exe_path)); - - // the command line needs to be writable by CreateProcess(). - scoped_ptr<wchar_t, base::FreeDeleter> cmd_line(_wcsdup(command_line)); - - // Start the target process suspended. - DWORD flags = - CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS; - - if (startup_info.has_extended_startup_info()) - flags |= EXTENDED_STARTUPINFO_PRESENT; - - if (job_ && base::win::GetVersion() < base::win::VERSION_WIN8) { - // Windows 8 implements nested jobs, but for older systems we need to - // break out of any job we're in to enforce our restrictions. - flags |= CREATE_BREAKAWAY_FROM_JOB; - } - - PROCESS_INFORMATION temp_process_info = {}; - if (!::CreateProcessAsUserW(lockdown_token_.Get(), exe_path, cmd_line.get(), - NULL, // No security attribute. - NULL, // No thread attribute. - inherit_handles, flags, - NULL, // Use the environment of the caller. - NULL, // Use current directory of the caller. - startup_info.startup_info(), - &temp_process_info)) { - return ::GetLastError(); - } - base::win::ScopedProcessInformation process_info(temp_process_info); - - DWORD win_result = ERROR_SUCCESS; - - if (job_) { - // Assign the suspended target to the windows job object. - if (!::AssignProcessToJobObject(job_, process_info.process_handle())) { - win_result = ::GetLastError(); - ::TerminateProcess(process_info.process_handle(), 0); - return win_result; - } - } - - if (initial_token_.IsValid()) { - // Change the token of the main thread of the new process for the - // impersonation token with more rights. This allows the target to start; - // otherwise it will crash too early for us to help. - HANDLE temp_thread = process_info.thread_handle(); - if (!::SetThreadToken(&temp_thread, initial_token_.Get())) { - win_result = ::GetLastError(); - // It might be a security breach if we let the target run outside the job - // so kill it before it causes damage. - ::TerminateProcess(process_info.process_handle(), 0); - return win_result; - } - initial_token_.Close(); - } - - CONTEXT context; - context.ContextFlags = CONTEXT_ALL; - if (!::GetThreadContext(process_info.thread_handle(), &context)) { - win_result = ::GetLastError(); - ::TerminateProcess(process_info.process_handle(), 0); - return win_result; - } - -#if defined(_WIN64) - void* entry_point = reinterpret_cast<void*>(context.Rcx); -#else -#pragma warning(push) -#pragma warning(disable: 4312) - // This cast generates a warning because it is 32 bit specific. - void* entry_point = reinterpret_cast<void*>(context.Eax); -#pragma warning(pop) -#endif // _WIN64 - - if (!target_info->DuplicateFrom(process_info)) { - win_result = ::GetLastError(); // This may or may not be correct. - ::TerminateProcess(process_info.process_handle(), 0); - return win_result; - } - - if (lowbox_token_.IsValid()) { - PROCESS_ACCESS_TOKEN process_access_token; - process_access_token.thread = process_info.thread_handle(); - process_access_token.token = lowbox_token_.Get(); - - NtSetInformationProcess SetInformationProcess = NULL; - ResolveNTFunctionPtr("NtSetInformationProcess", &SetInformationProcess); - - NTSTATUS status = SetInformationProcess( - process_info.process_handle(), - static_cast<PROCESS_INFORMATION_CLASS>(NtProcessInformationAccessToken), - &process_access_token, sizeof(process_access_token)); - if (!NT_SUCCESS(status)) { - win_result = ERROR_INVALID_TOKEN; - ::TerminateProcess(process_info.process_handle(), 0); // exit code - return win_result; - } - } - - base_address_ = GetBaseAddress(exe_path, entry_point); - sandbox_process_info_.Set(process_info.Take()); - return win_result; -} - -ResultCode TargetProcess::TransferVariable(const char* name, void* address, - size_t size) { - if (!sandbox_process_info_.IsValid()) - return SBOX_ERROR_UNEXPECTED_CALL; - - void* child_var = address; - -#if SANDBOX_EXPORTS - HMODULE module = ::LoadLibrary(exe_name_.get()); - if (NULL == module) - return SBOX_ERROR_GENERIC; - - child_var = ::GetProcAddress(module, name); - ::FreeLibrary(module); - - if (NULL == child_var) - return SBOX_ERROR_GENERIC; - - size_t offset = reinterpret_cast<char*>(child_var) - - reinterpret_cast<char*>(module); - child_var = reinterpret_cast<char*>(MainModule()) + offset; -#endif - - SIZE_T written; - if (!::WriteProcessMemory(sandbox_process_info_.process_handle(), - child_var, address, size, &written)) - return SBOX_ERROR_GENERIC; - - if (written != size) - return SBOX_ERROR_GENERIC; - - return SBOX_ALL_OK; -} - -// Construct the IPC server and the IPC dispatcher. When the target does -// an IPC it will eventually call the dispatcher. -DWORD TargetProcess::Init(Dispatcher* ipc_dispatcher, - void* policy, - uint32_t shared_IPC_size, - uint32_t shared_policy_size) { - // We need to map the shared memory on the target. This is necessary for - // any IPC that needs to take place, even if the target has not yet hit - // the main( ) function or even has initialized the CRT. So here we set - // the handle to the shared section. The target on the first IPC must do - // the rest, which boils down to calling MapViewofFile() - - // We use this single memory pool for IPC and for policy. - DWORD shared_mem_size = static_cast<DWORD>(shared_IPC_size + - shared_policy_size); - shared_section_.Set(::CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, - PAGE_READWRITE | SEC_COMMIT, - 0, shared_mem_size, NULL)); - if (!shared_section_.IsValid()) { - return ::GetLastError(); - } - - DWORD access = FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY; - HANDLE target_shared_section; - if (!::DuplicateHandle(::GetCurrentProcess(), shared_section_.Get(), - sandbox_process_info_.process_handle(), - &target_shared_section, access, FALSE, 0)) { - return ::GetLastError(); - } - - void* shared_memory = ::MapViewOfFile(shared_section_.Get(), - FILE_MAP_WRITE|FILE_MAP_READ, - 0, 0, 0); - if (NULL == shared_memory) { - return ::GetLastError(); - } - - CopyPolicyToTarget(policy, shared_policy_size, - reinterpret_cast<char*>(shared_memory) + shared_IPC_size); - - ResultCode ret; - // Set the global variables in the target. These are not used on the broker. - g_shared_section = target_shared_section; - ret = TransferVariable("g_shared_section", &g_shared_section, - sizeof(g_shared_section)); - g_shared_section = NULL; - if (SBOX_ALL_OK != ret) { - return (SBOX_ERROR_GENERIC == ret)? - ::GetLastError() : ERROR_INVALID_FUNCTION; - } - g_shared_IPC_size = shared_IPC_size; - ret = TransferVariable("g_shared_IPC_size", &g_shared_IPC_size, - sizeof(g_shared_IPC_size)); - g_shared_IPC_size = 0; - if (SBOX_ALL_OK != ret) { - return (SBOX_ERROR_GENERIC == ret) ? - ::GetLastError() : ERROR_INVALID_FUNCTION; - } - g_shared_policy_size = shared_policy_size; - ret = TransferVariable("g_shared_policy_size", &g_shared_policy_size, - sizeof(g_shared_policy_size)); - g_shared_policy_size = 0; - if (SBOX_ALL_OK != ret) { - return (SBOX_ERROR_GENERIC == ret) ? - ::GetLastError() : ERROR_INVALID_FUNCTION; - } - - ipc_server_.reset( - new SharedMemIPCServer(sandbox_process_info_.process_handle(), - sandbox_process_info_.process_id(), - thread_pool_, ipc_dispatcher)); - - if (!ipc_server_->Init(shared_memory, shared_IPC_size, kIPCChannelSize)) - return ERROR_NOT_ENOUGH_MEMORY; - - // After this point we cannot use this handle anymore. - ::CloseHandle(sandbox_process_info_.TakeThreadHandle()); - - return ERROR_SUCCESS; -} - -void TargetProcess::Terminate() { - if (!sandbox_process_info_.IsValid()) - return; - - ::TerminateProcess(sandbox_process_info_.process_handle(), 0); -} - -TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { - TargetProcess* target = - new TargetProcess(base::win::ScopedHandle(), base::win::ScopedHandle(), - base::win::ScopedHandle(), NULL, NULL); - PROCESS_INFORMATION process_info = {}; - process_info.hProcess = process; - target->sandbox_process_info_.Set(process_info); - target->base_address_ = base_address; - return target; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.h b/security/sandbox/chromium/sandbox/win/src/target_process.h deleted file mode 100644 index c00f2cea8..000000000 --- a/security/sandbox/chromium/sandbox/win/src/target_process.h +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_TARGET_PROCESS_H_ -#define SANDBOX_WIN_SRC_TARGET_PROCESS_H_ - -#include <windows.h> -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/win/scoped_handle.h" -#include "base/win/scoped_process_information.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace base { -namespace win { - -class StartupInformation; - -}; // namespace win -}; // namespace base - -namespace sandbox { - -class AttributeList; -class SharedMemIPCServer; -class ThreadProvider; - -// TargetProcess models a target instance (child process). Objects of this -// class are owned by the Policy used to create them. -class TargetProcess { - public: - // The constructor takes ownership of |initial_token|, |lockdown_token| - // and |lowbox_token|. - TargetProcess(base::win::ScopedHandle initial_token, - base::win::ScopedHandle lockdown_token, - base::win::ScopedHandle lowbox_token, - HANDLE job, - ThreadProvider* thread_pool); - ~TargetProcess(); - - // TODO(cpu): Currently there does not seem to be a reason to implement - // reference counting for this class since is internal, but kept the - // the same interface so the interception framework does not need to be - // touched at this point. - void AddRef() {} - void Release() {} - - // Creates the new target process. The process is created suspended. - DWORD Create(const wchar_t* exe_path, - const wchar_t* command_line, - bool inherit_handles, - const base::win::StartupInformation& startup_info, - base::win::ScopedProcessInformation* target_info); - - // Destroys the target process. - void Terminate(); - - // Creates the IPC objects such as the BrokerDispatcher and the - // IPC server. The IPC server uses the services of the thread_pool. - DWORD Init(Dispatcher* ipc_dispatcher, - void* policy, - uint32_t shared_IPC_size, - uint32_t shared_policy_size); - - // Returns the handle to the target process. - HANDLE Process() const { - return sandbox_process_info_.process_handle(); - } - - // Returns the handle to the job object that the target process belongs to. - HANDLE Job() const { - return job_; - } - - // Returns the address of the target main exe. This is used by the - // interceptions framework. - HMODULE MainModule() const { - return reinterpret_cast<HMODULE>(base_address_); - } - - // Returns the name of the executable. - const wchar_t* Name() const { - return exe_name_.get(); - } - - // Returns the process id. - DWORD ProcessId() const { - return sandbox_process_info_.process_id(); - } - - // Returns the handle to the main thread. - HANDLE MainThread() const { - return sandbox_process_info_.thread_handle(); - } - - // Transfers a 32-bit variable between the broker and the target. - ResultCode TransferVariable(const char* name, void* address, size_t size); - - private: - // Details of the target process. - base::win::ScopedProcessInformation sandbox_process_info_; - // The token associated with the process. It provides the core of the - // sbox security. - base::win::ScopedHandle lockdown_token_; - // The token given to the initial thread so that the target process can - // start. It has more powers than the lockdown_token. - base::win::ScopedHandle initial_token_; - // The lowbox token associated with the process. This token is set after the - // process creation. - base::win::ScopedHandle lowbox_token_; - // Kernel handle to the shared memory used by the IPC server. - base::win::ScopedHandle shared_section_; - // Job object containing the target process. - HANDLE job_; - // Reference to the IPC subsystem. - scoped_ptr<SharedMemIPCServer> ipc_server_; - // Provides the threads used by the IPC. This class does not own this pointer. - ThreadProvider* thread_pool_; - // Base address of the main executable - void* base_address_; - // Full name of the target executable. - scoped_ptr<wchar_t, base::FreeDeleter> exe_name_; - - // Function used for testing. - friend TargetProcess* MakeTestTargetProcess(HANDLE process, - HMODULE base_address); - - DISALLOW_IMPLICIT_CONSTRUCTORS(TargetProcess); -}; - -// Creates a mock TargetProcess used for testing interceptions. -// TODO(cpu): It seems that this method is not going to be used anymore. -TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address); - - -} // namespace sandbox - -#endif // SANDBOX_WIN_SRC_TARGET_PROCESS_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc deleted file mode 100644 index 7537245b6..000000000 --- a/security/sandbox/chromium/sandbox/win/src/target_services.cc +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/target_services.h" - -#include <new> - -#include <process.h> -#include <stdint.h> - -#include "base/win/windows_version.h" -#include "sandbox/win/src/crosscall_client.h" -#include "sandbox/win/src/handle_closer_agent.h" -#include "sandbox/win/src/handle_interception.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/process_mitigations.h" -#include "sandbox/win/src/restricted_token_utils.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sharedmem_ipc_client.h" - -namespace { - -// Flushing a cached key is triggered by just opening the key and closing the -// resulting handle. RegDisablePredefinedCache() is the documented way to flush -// HKCU so do not use it with this function. -bool FlushRegKey(HKEY root) { - HKEY key; - if (ERROR_SUCCESS == ::RegOpenKeyExW(root, NULL, 0, MAXIMUM_ALLOWED, &key)) { - if (ERROR_SUCCESS != ::RegCloseKey(key)) - return false; - } - return true; -} - -// This function forces advapi32.dll to release some internally cached handles -// that were made during calls to RegOpenkey and RegOpenKeyEx if it is called -// with a more restrictive token. Returns true if the flushing is succesful -// although this behavior is undocumented and there is no guarantee that in -// fact this will happen in future versions of windows. -bool FlushCachedRegHandles() { - return (FlushRegKey(HKEY_LOCAL_MACHINE) && - FlushRegKey(HKEY_CLASSES_ROOT) && - FlushRegKey(HKEY_USERS)); -} - -// Checks if we have handle entries pending and runs the closer. -// Updates is_csrss_connected based on which handle types are closed. -bool CloseOpenHandles(bool* is_csrss_connected) { - if (sandbox::HandleCloserAgent::NeedsHandlesClosed()) { - sandbox::HandleCloserAgent handle_closer; - handle_closer.InitializeHandlesToClose(is_csrss_connected); - if (!handle_closer.CloseHandles()) - return false; - } - - return true; -} - -// GetUserDefaultLocaleName is not available on WIN XP. So we'll -// load it on-the-fly. -const wchar_t kKernel32DllName[] = L"kernel32.dll"; -typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameFunction; - -// Warm up language subsystems before the sandbox is turned on. -// Tested on Win8.1 x64: -// This needs to happen after RevertToSelf() is called, because (at least) in -// the case of GetUserDefaultLCID() it checks the TEB to see if the process is -// impersonating (TEB!IsImpersonating). If it is, the cached locale information -// is not used, nor is it set. Therefore, calls after RevertToSelf() will not -// have warmed-up values to use. -bool WarmupWindowsLocales() { - // NOTE(liamjm): When last checked (Win 8.1 x64) it wasn't necessary to - // warmup all of these functions, but let's not assume that. - ::GetUserDefaultLangID(); - ::GetUserDefaultLCID(); - if (base::win::GetVersion() >= base::win::VERSION_VISTA) { - static GetUserDefaultLocaleNameFunction GetUserDefaultLocaleName_func = - NULL; - if (!GetUserDefaultLocaleName_func) { - HMODULE kernel32_dll = ::GetModuleHandle(kKernel32DllName); - if (!kernel32_dll) { - return false; - } - GetUserDefaultLocaleName_func = - reinterpret_cast<GetUserDefaultLocaleNameFunction>( - GetProcAddress(kernel32_dll, "GetUserDefaultLocaleName")); - if (!GetUserDefaultLocaleName_func) { - return false; - } - } - wchar_t localeName[LOCALE_NAME_MAX_LENGTH] = {0}; - return (0 != GetUserDefaultLocaleName_func( - localeName, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t))); - } - return true; -} - -// Used as storage for g_target_services, because other allocation facilities -// are not available early. We can't use a regular function static because on -// VS2015, because the CRT tries to acquire a lock to guard initialization, but -// this code runs before the CRT is initialized. -char g_target_services_memory[sizeof(sandbox::TargetServicesBase)]; -sandbox::TargetServicesBase* g_target_services = nullptr; - -} // namespace - -namespace sandbox { - -SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level = - INTEGRITY_LEVEL_LAST; -SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations = 0; - -TargetServicesBase::TargetServicesBase() { -} - -ResultCode TargetServicesBase::Init() { - process_state_.SetInitCalled(); - return SBOX_ALL_OK; -} - -// Failure here is a breach of security so the process is terminated. -void TargetServicesBase::LowerToken() { - if (ERROR_SUCCESS != - SetProcessIntegrityLevel(g_shared_delayed_integrity_level)) - ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_INTEGRITY); - process_state_.SetRevertedToSelf(); - // If the client code as called RegOpenKey, advapi32.dll has cached some - // handles. The following code gets rid of them. - if (!::RevertToSelf()) - ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_DROPTOKEN); - if (!FlushCachedRegHandles()) - ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_FLUSHANDLES); - if (ERROR_SUCCESS != ::RegDisablePredefinedCache()) - ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CACHEDISABLE); - if (!WarmupWindowsLocales()) - ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_WARMUP); - bool is_csrss_connected = true; - if (!CloseOpenHandles(&is_csrss_connected)) - ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CLOSEHANDLES); - process_state_.SetCsrssConnected(is_csrss_connected); - // Enabling mitigations must happen last otherwise handle closing breaks - if (g_shared_delayed_mitigations && - !ApplyProcessMitigationsToCurrentProcess(g_shared_delayed_mitigations)) - ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_MITIGATION); -} - -ProcessState* TargetServicesBase::GetState() { - return &process_state_; -} - -TargetServicesBase* TargetServicesBase::GetInstance() { - // Leak on purpose TargetServicesBase. - if (!g_target_services) - g_target_services = new (g_target_services_memory) TargetServicesBase; - return g_target_services; -} - -// The broker services a 'test' IPC service with the IPC_PING_TAG tag. -bool TargetServicesBase::TestIPCPing(int version) { - void* memory = GetGlobalIPCMemory(); - if (NULL == memory) { - return false; - } - SharedMemIPCClient ipc(memory); - CrossCallReturn answer = {0}; - - if (1 == version) { - uint32_t tick1 = ::GetTickCount(); - uint32_t cookie = 717115; - ResultCode code = CrossCall(ipc, IPC_PING1_TAG, cookie, &answer); - - if (SBOX_ALL_OK != code) { - return false; - } - // We should get two extended returns values from the IPC, one is the - // tick count on the broker and the other is the cookie times two. - if ((answer.extended_count != 2)) { - return false; - } - // We test the first extended answer to be within the bounds of the tick - // count only if there was no tick count wraparound. - uint32_t tick2 = ::GetTickCount(); - if (tick2 >= tick1) { - if ((answer.extended[0].unsigned_int < tick1) || - (answer.extended[0].unsigned_int > tick2)) { - return false; - } - } - - if (answer.extended[1].unsigned_int != cookie * 2) { - return false; - } - } else if (2 == version) { - uint32_t cookie = 717111; - InOutCountedBuffer counted_buffer(&cookie, sizeof(cookie)); - ResultCode code = CrossCall(ipc, IPC_PING2_TAG, counted_buffer, &answer); - - if (SBOX_ALL_OK != code) { - return false; - } - if (cookie != 717111 * 3) { - return false; - } - } else { - return false; - } - return true; -} - -ProcessState::ProcessState() : process_state_(0), csrss_connected_(true) { -} - -bool ProcessState::IsKernel32Loaded() const { - return process_state_ != 0; -} - -bool ProcessState::InitCalled() const { - return process_state_ > 1; -} - -bool ProcessState::RevertedToSelf() const { - return process_state_ > 2; -} - -bool ProcessState::IsCsrssConnected() const { - return csrss_connected_; -} - -void ProcessState::SetKernel32Loaded() { - if (!process_state_) - process_state_ = 1; -} - -void ProcessState::SetInitCalled() { - if (process_state_ < 2) - process_state_ = 2; -} - -void ProcessState::SetRevertedToSelf() { - if (process_state_ < 3) - process_state_ = 3; -} - -void ProcessState::SetCsrssConnected(bool csrss_connected) { - csrss_connected_ = csrss_connected; -} - - -ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle, - DWORD target_process_id, - HANDLE* target_handle, - DWORD desired_access, - DWORD options) { - return sandbox::DuplicateHandleProxy(source_handle, target_process_id, - target_handle, desired_access, options); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.h b/security/sandbox/chromium/sandbox/win/src/target_services.h deleted file mode 100644 index 37169485d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/target_services.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_TARGET_SERVICES_H__ -#define SANDBOX_SRC_TARGET_SERVICES_H__ - -#include "base/macros.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/win_utils.h" - -namespace sandbox { - -class ProcessState { - public: - ProcessState(); - // Returns true if kernel32.dll has been loaded. - bool IsKernel32Loaded() const; - // Returns true if main has been called. - bool InitCalled() const; - // Returns true if LowerToken has been called. - bool RevertedToSelf() const; - // Returns true if Csrss is connected. - bool IsCsrssConnected() const; - // Set the current state. - void SetKernel32Loaded(); - void SetInitCalled(); - void SetRevertedToSelf(); - void SetCsrssConnected(bool csrss_connected); - - private: - int process_state_; - bool csrss_connected_; - DISALLOW_COPY_AND_ASSIGN(ProcessState); -}; - -// This class is an implementation of the TargetServices. -// Look in the documentation of sandbox::TargetServices for more info. -// Do NOT add a destructor to this class without changing the implementation of -// the factory method. -class TargetServicesBase : public TargetServices { - public: - TargetServicesBase(); - - // Public interface of TargetServices. - ResultCode Init() override; - void LowerToken() override; - ProcessState* GetState() override; - ResultCode DuplicateHandle(HANDLE source_handle, - DWORD target_process_id, - HANDLE* target_handle, - DWORD desired_access, - DWORD options) override; - - // Factory method. - static TargetServicesBase* GetInstance(); - - // Sends a simple IPC Message that has a well-known answer. Returns true - // if the IPC was successful and false otherwise. There are 2 versions of - // this test: 1 and 2. The first one send a simple message while the - // second one send a message with an in/out param. - bool TestIPCPing(int version); - - private: - ProcessState process_state_; - DISALLOW_COPY_AND_ASSIGN(TargetServicesBase); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_TARGET_SERVICES_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/threadpool_unittest.cc b/security/sandbox/chromium/sandbox/win/src/threadpool_unittest.cc deleted file mode 100644 index d32fdda5b..000000000 --- a/security/sandbox/chromium/sandbox/win/src/threadpool_unittest.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdint.h> - -#include "sandbox/win/src/win2k_threadpool.h" -#include "testing/gtest/include/gtest/gtest.h" - -void __stdcall EmptyCallBack(void*, unsigned char) { -} - -void __stdcall TestCallBack(void* context, unsigned char) { - HANDLE event = reinterpret_cast<HANDLE>(context); - ::SetEvent(event); -} - -namespace sandbox { - -// Test that register and unregister work, part 1. -TEST(IPCTest, ThreadPoolRegisterTest1) { - Win2kThreadPool thread_pool; - - EXPECT_EQ(0u, thread_pool.OutstandingWaits()); - - HANDLE event1 = ::CreateEventW(NULL, FALSE, FALSE, NULL); - HANDLE event2 = ::CreateEventW(NULL, FALSE, FALSE, NULL); - - uint32_t context = 0; - EXPECT_FALSE(thread_pool.RegisterWait(0, event1, EmptyCallBack, &context)); - EXPECT_EQ(0u, thread_pool.OutstandingWaits()); - - EXPECT_TRUE(thread_pool.RegisterWait(this, event1, EmptyCallBack, &context)); - EXPECT_EQ(1u, thread_pool.OutstandingWaits()); - EXPECT_TRUE(thread_pool.RegisterWait(this, event2, EmptyCallBack, &context)); - EXPECT_EQ(2u, thread_pool.OutstandingWaits()); - - EXPECT_TRUE(thread_pool.UnRegisterWaits(this)); - EXPECT_EQ(0u, thread_pool.OutstandingWaits()); - - EXPECT_EQ(TRUE, ::CloseHandle(event1)); - EXPECT_EQ(TRUE, ::CloseHandle(event2)); -} - -// Test that register and unregister work, part 2. -TEST(IPCTest, ThreadPoolRegisterTest2) { - Win2kThreadPool thread_pool; - - HANDLE event1 = ::CreateEventW(NULL, FALSE, FALSE, NULL); - HANDLE event2 = ::CreateEventW(NULL, FALSE, FALSE, NULL); - - uint32_t context = 0; - uint32_t c1 = 0; - uint32_t c2 = 0; - - EXPECT_TRUE(thread_pool.RegisterWait(&c1, event1, EmptyCallBack, &context)); - EXPECT_EQ(1u, thread_pool.OutstandingWaits()); - EXPECT_TRUE(thread_pool.RegisterWait(&c2, event2, EmptyCallBack, &context)); - EXPECT_EQ(2u, thread_pool.OutstandingWaits()); - - EXPECT_TRUE(thread_pool.UnRegisterWaits(&c2)); - EXPECT_EQ(1u, thread_pool.OutstandingWaits()); - EXPECT_TRUE(thread_pool.UnRegisterWaits(&c2)); - EXPECT_EQ(1u, thread_pool.OutstandingWaits()); - - EXPECT_TRUE(thread_pool.UnRegisterWaits(&c1)); - EXPECT_EQ(0u, thread_pool.OutstandingWaits()); - - EXPECT_EQ(TRUE, ::CloseHandle(event1)); - EXPECT_EQ(TRUE, ::CloseHandle(event2)); -} - -// Test that the thread pool has at least a thread that services an event. -// Test that when the event is un-registered is no longer serviced. -TEST(IPCTest, ThreadPoolSignalAndWaitTest) { - Win2kThreadPool thread_pool; - - // The events are auto reset and start not signaled. - HANDLE event1 = ::CreateEventW(NULL, FALSE, FALSE, NULL); - HANDLE event2 = ::CreateEventW(NULL, FALSE, FALSE, NULL); - - EXPECT_TRUE(thread_pool.RegisterWait(this, event1, TestCallBack, event2)); - - EXPECT_EQ(WAIT_OBJECT_0, ::SignalObjectAndWait(event1, event2, 5000, FALSE)); - EXPECT_EQ(WAIT_OBJECT_0, ::SignalObjectAndWait(event1, event2, 5000, FALSE)); - - EXPECT_TRUE(thread_pool.UnRegisterWaits(this)); - EXPECT_EQ(0u, thread_pool.OutstandingWaits()); - - EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT), - ::SignalObjectAndWait(event1, event2, 1000, FALSE)); - - EXPECT_EQ(TRUE, ::CloseHandle(event1)); - EXPECT_EQ(TRUE, ::CloseHandle(event2)); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc deleted file mode 100644 index e6e224b4d..000000000 --- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/top_level_dispatcher.h" - -#include <stdint.h> -#include <string.h> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/filesystem_dispatcher.h" -#include "sandbox/win/src/handle_dispatcher.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/named_pipe_dispatcher.h" -#include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" -#include "sandbox/win/src/process_thread_dispatcher.h" -#include "sandbox/win/src/registry_dispatcher.h" -#include "sandbox/win/src/sandbox_policy_base.h" -#include "sandbox/win/src/sync_dispatcher.h" - -namespace sandbox { - -TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) { - // Initialize the IPC dispatcher array. - memset(ipc_targets_, 0, sizeof(ipc_targets_)); - Dispatcher* dispatcher; - - dispatcher = new FilesystemDispatcher(policy_); - ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher; - ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher; - ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher; - ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher; - ipc_targets_[IPC_NTQUERYFULLATTRIBUTESFILE_TAG] = dispatcher; - filesystem_dispatcher_.reset(dispatcher); - - dispatcher = new NamedPipeDispatcher(policy_); - ipc_targets_[IPC_CREATENAMEDPIPEW_TAG] = dispatcher; - named_pipe_dispatcher_.reset(dispatcher); - - dispatcher = new ThreadProcessDispatcher(policy_); - ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher; - ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher; - ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher; - ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher; - ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher; - thread_process_dispatcher_.reset(dispatcher); - - dispatcher = new SyncDispatcher(policy_); - ipc_targets_[IPC_CREATEEVENT_TAG] = dispatcher; - ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher; - sync_dispatcher_.reset(dispatcher); - - dispatcher = new RegistryDispatcher(policy_); - ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher; - ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher; - registry_dispatcher_.reset(dispatcher); - - dispatcher = new HandleDispatcher(policy_); - ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher; - handle_dispatcher_.reset(dispatcher); - - dispatcher = new ProcessMitigationsWin32KDispatcher(policy_); - ipc_targets_[IPC_GDI_GDIDLLINITIALIZE_TAG] = dispatcher; - ipc_targets_[IPC_GDI_GETSTOCKOBJECT_TAG] = dispatcher; - ipc_targets_[IPC_USER_REGISTERCLASSW_TAG] = dispatcher; - process_mitigations_win32k_dispatcher_.reset(dispatcher); -} - -TopLevelDispatcher::~TopLevelDispatcher() {} - -// When an IPC is ready in any of the targets we get called. We manage an array -// of IPC dispatchers which are keyed on the IPC tag so we normally delegate -// to the appropriate dispatcher unless we can handle the IPC call ourselves. -Dispatcher* TopLevelDispatcher::OnMessageReady(IPCParams* ipc, - CallbackGeneric* callback) { - DCHECK(callback); - static const IPCParams ping1 = {IPC_PING1_TAG, {UINT32_TYPE}}; - static const IPCParams ping2 = {IPC_PING2_TAG, {INOUTPTR_TYPE}}; - - if (ping1.Matches(ipc) || ping2.Matches(ipc)) { - *callback = reinterpret_cast<CallbackGeneric>( - static_cast<Callback1>(&TopLevelDispatcher::Ping)); - return this; - } - - Dispatcher* dispatcher = GetDispatcher(ipc->ipc_tag); - if (!dispatcher) { - NOTREACHED(); - return NULL; - } - return dispatcher->OnMessageReady(ipc, callback); -} - -// Delegate to the appropriate dispatcher. -bool TopLevelDispatcher::SetupService(InterceptionManager* manager, - int service) { - if (IPC_PING1_TAG == service || IPC_PING2_TAG == service) - return true; - - Dispatcher* dispatcher = GetDispatcher(service); - if (!dispatcher) { - NOTREACHED(); - return false; - } - return dispatcher->SetupService(manager, service); -} - -// We service IPC_PING_TAG message which is a way to test a round trip of the -// IPC subsystem. We receive a integer cookie and we are expected to return the -// cookie times two (or three) and the current tick count. -bool TopLevelDispatcher::Ping(IPCInfo* ipc, void* arg1) { - switch (ipc->ipc_tag) { - case IPC_PING1_TAG: { - IPCInt ipc_int(arg1); - uint32_t cookie = ipc_int.As32Bit(); - ipc->return_info.extended_count = 2; - ipc->return_info.extended[0].unsigned_int = ::GetTickCount(); - ipc->return_info.extended[1].unsigned_int = 2 * cookie; - return true; - } - case IPC_PING2_TAG: { - CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1); - if (sizeof(uint32_t) != io_buffer->Size()) - return false; - - uint32_t* cookie = reinterpret_cast<uint32_t*>(io_buffer->Buffer()); - *cookie = (*cookie) * 3; - return true; - } - default: - return false; - } -} - -Dispatcher* TopLevelDispatcher::GetDispatcher(int ipc_tag) { - if (ipc_tag >= IPC_LAST_TAG || ipc_tag <= IPC_UNUSED_TAG) - return NULL; - - return ipc_targets_[ipc_tag]; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h deleted file mode 100644 index c9306de1c..000000000 --- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_TOP_LEVEL_DISPATCHER_H__ -#define SANDBOX_SRC_TOP_LEVEL_DISPATCHER_H__ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/crosscall_server.h" -#include "sandbox/win/src/interception.h" -#include "sandbox/win/src/ipc_tags.h" -#include "sandbox/win/src/sandbox_policy_base.h" - -namespace sandbox { - -// Top level dispatcher which hands requests to the appropriate service -// dispatchers. -class TopLevelDispatcher : public Dispatcher { - public: - // |policy| must outlive this class. - explicit TopLevelDispatcher(PolicyBase* policy); - ~TopLevelDispatcher() override; - - Dispatcher* OnMessageReady(IPCParams* ipc, - CallbackGeneric* callback) override; - bool SetupService(InterceptionManager* manager, int service) override; - - private: - // Test IPC provider. - bool Ping(IPCInfo* ipc, void* cookie); - - // Returns a dispatcher from ipc_targets_. - Dispatcher* GetDispatcher(int ipc_tag); - - PolicyBase* policy_; - scoped_ptr<Dispatcher> filesystem_dispatcher_; - scoped_ptr<Dispatcher> named_pipe_dispatcher_; - scoped_ptr<Dispatcher> thread_process_dispatcher_; - scoped_ptr<Dispatcher> sync_dispatcher_; - scoped_ptr<Dispatcher> registry_dispatcher_; - scoped_ptr<Dispatcher> handle_dispatcher_; - scoped_ptr<Dispatcher> process_mitigations_win32k_dispatcher_; - Dispatcher* ipc_targets_[IPC_LAST_TAG]; - - DISALLOW_COPY_AND_ASSIGN(TopLevelDispatcher); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_TOP_LEVEL_DISPATCHER_H__ diff --git a/security/sandbox/chromium/sandbox/win/src/unload_dll_test.cc b/security/sandbox/chromium/sandbox/win/src/unload_dll_test.cc deleted file mode 100644 index 7e398f686..000000000 --- a/security/sandbox/chromium/sandbox/win/src/unload_dll_test.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/sandbox.h" -#include "sandbox/win/src/sandbox_factory.h" -#include "sandbox/win/src/target_services.h" -#include "sandbox/win/tests/common/controller.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sandbox { - -// Loads and or unloads a DLL passed in the second parameter of argv. -// The first parameter of argv is 'L' = load, 'U' = unload or 'B' for both. -SBOX_TESTS_COMMAND int UseOneDLL(int argc, wchar_t **argv) { - if (argc != 2) - return SBOX_TEST_FAILED_TO_RUN_TEST; - int rv = SBOX_TEST_FAILED_TO_RUN_TEST; - - wchar_t option = (argv[0])[0]; - if ((option == L'L') || (option == L'B')) { - HMODULE module1 = ::LoadLibraryW(argv[1]); - rv = (module1 == NULL) ? SBOX_TEST_FAILED : SBOX_TEST_SUCCEEDED; - } - - if ((option == L'U') || (option == L'B')) { - HMODULE module2 = ::GetModuleHandleW(argv[1]); - rv = ::FreeLibrary(module2) ? SBOX_TEST_SUCCEEDED : SBOX_TEST_FAILED; - } - return rv; -} - -// Opens an event passed as the first parameter of argv. -SBOX_TESTS_COMMAND int SimpleOpenEvent(int argc, wchar_t **argv) { - if (argc != 1) - return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - - base::win::ScopedHandle event_open(::OpenEvent(SYNCHRONIZE, FALSE, argv[0])); - return event_open.Get() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_FAILED; -} - -TEST(UnloadDllTest, BaselineAvicapDll) { - TestRunner runner; - runner.SetTestState(BEFORE_REVERT); - runner.SetTimeout(2000); - // Add a sync rule, because that ensures that the interception agent has - // more than one item in its internal table. - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC, - TargetPolicy::EVENTS_ALLOW_ANY, L"t0001")); - - // Note for the puzzled: avicap32.dll is a 64-bit dll in 64-bit versions of - // windows so this test and the others just work. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"UseOneDLL L avicap32.dll")); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"UseOneDLL B avicap32.dll")); -} - -TEST(UnloadDllTest, UnloadAviCapDllNoPatching) { - TestRunner runner; - runner.SetTestState(BEFORE_REVERT); - runner.SetTimeout(2000); - sandbox::TargetPolicy* policy = runner.GetPolicy(); - policy->AddDllToUnload(L"avicap32.dll"); - EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL L avicap32.dll")); - EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL B avicap32.dll")); -} - -TEST(UnloadDllTest, UnloadAviCapDllWithPatching) { - TestRunner runner; - runner.SetTimeout(2000); - runner.SetTestState(BEFORE_REVERT); - sandbox::TargetPolicy* policy = runner.GetPolicy(); - policy->AddDllToUnload(L"avicap32.dll"); - - base::win::ScopedHandle handle1(::CreateEvent( - NULL, FALSE, FALSE, L"tst0001")); - - // Add a couple of rules that ensures that the interception agent add EAT - // patching on the client which makes sure that the unload dll record does - // not interact badly with them. - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY, - TargetPolicy::REG_ALLOW_ANY, - L"HKEY_LOCAL_MACHINE\\Software\\Microsoft")); - EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_SYNC, - TargetPolicy::EVENTS_ALLOW_ANY, L"tst0001")); - - EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL L avicap32.dll")); - - runner.SetTestState(AFTER_REVERT); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"SimpleOpenEvent tst0001")); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/win2k_threadpool.cc b/security/sandbox/chromium/sandbox/win/src/win2k_threadpool.cc deleted file mode 100644 index 35de38a0f..000000000 --- a/security/sandbox/chromium/sandbox/win/src/win2k_threadpool.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/win2k_threadpool.h" - -#include <stddef.h> - -#include "sandbox/win/src/win_utils.h" - -namespace sandbox { - -Win2kThreadPool::Win2kThreadPool() { - ::InitializeCriticalSection(&lock_); -} - -bool Win2kThreadPool::RegisterWait(const void* cookie, HANDLE waitable_object, - CrossCallIPCCallback callback, - void* context) { - if (0 == cookie) { - return false; - } - HANDLE pool_object = NULL; - // create a wait for a kernel object, with no timeout - if (!::RegisterWaitForSingleObject(&pool_object, waitable_object, callback, - context, INFINITE, WT_EXECUTEDEFAULT)) { - return false; - } - PoolObject pool_obj = {cookie, pool_object}; - AutoLock lock(&lock_); - pool_objects_.push_back(pool_obj); - return true; -} - -bool Win2kThreadPool::UnRegisterWaits(void* cookie) { - if (0 == cookie) { - return false; - } - AutoLock lock(&lock_); - bool success = true; - PoolObjects::iterator it = pool_objects_.begin(); - while (it != pool_objects_.end()) { - if (it->cookie == cookie) { - HANDLE wait = it->wait; - it = pool_objects_.erase(it); - success &= (::UnregisterWaitEx(wait, INVALID_HANDLE_VALUE) != 0); - } else { - ++it; - } - } - return success; -} - -size_t Win2kThreadPool::OutstandingWaits() { - AutoLock lock(&lock_); - return pool_objects_.size(); -} - -Win2kThreadPool::~Win2kThreadPool() { - // Here we used to unregister all the pool wait handles. Now, following the - // rest of the code we avoid lengthy or blocking calls given that the process - // is being torn down. - ::DeleteCriticalSection(&lock_); -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/win2k_threadpool.h b/security/sandbox/chromium/sandbox/win/src/win2k_threadpool.h deleted file mode 100644 index c4d539dd7..000000000 --- a/security/sandbox/chromium/sandbox/win/src/win2k_threadpool.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_WIN2K_THREADPOOL_H_ -#define SANDBOX_SRC_WIN2K_THREADPOOL_H_ - -#include <stddef.h> - -#include <algorithm> -#include <list> -#include "base/macros.h" -#include "sandbox/win/src/crosscall_server.h" - -namespace sandbox { - -// Win2kThreadPool a simple implementation of a thread provider as required -// for the sandbox IPC subsystem. See sandbox\crosscall_server.h for the details -// and requirements of this interface. -// -// Implementing the thread provider as a thread pool is desirable in the case -// of shared memory IPC because it can generate a large number of waitable -// events: as many as channels. A thread pool does not create a thread per -// event, instead maintains a few idle threads but can create more if the need -// arises. -// -// This implementation simply thunks to the nice thread pool API of win2k. -class Win2kThreadPool : public ThreadProvider { - public: - Win2kThreadPool(); - ~Win2kThreadPool() override; - - bool RegisterWait(const void* cookie, - HANDLE waitable_object, - CrossCallIPCCallback callback, - void* context) override; - - bool UnRegisterWaits(void* cookie) override; - - // Returns the total number of wait objects associated with - // the thread pool. - size_t OutstandingWaits(); - - private: - // record to keep track of a wait and its associated cookie. - struct PoolObject { - const void* cookie; - HANDLE wait; - }; - // The list of pool wait objects. - typedef std::list<PoolObject> PoolObjects; - PoolObjects pool_objects_; - // This lock protects the list of pool wait objects. - CRITICAL_SECTION lock_; - - DISALLOW_COPY_AND_ASSIGN(Win2kThreadPool); -}; - -} // namespace sandbox - -#endif // SANDBOX_SRC_WIN2K_THREADPOOL_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/sandbox/chromium/sandbox/win/src/win_utils.cc deleted file mode 100644 index 1e4675f8e..000000000 --- a/security/sandbox/chromium/sandbox/win/src/win_utils.cc +++ /dev/null @@ -1,437 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/win_utils.h" - -#include <stddef.h> - -#include <map> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_util.h" -#include "base/win/pe_image.h" -#include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/sandbox_nt_util.h" - -namespace { - -// Holds the information about a known registry key. -struct KnownReservedKey { - const wchar_t* name; - HKEY key; -}; - -// Contains all the known registry key by name and by handle. -const KnownReservedKey kKnownKey[] = { - { L"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT }, - { L"HKEY_CURRENT_USER", HKEY_CURRENT_USER }, - { L"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE}, - { L"HKEY_USERS", HKEY_USERS}, - { L"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA}, - { L"HKEY_PERFORMANCE_TEXT", HKEY_PERFORMANCE_TEXT}, - { L"HKEY_PERFORMANCE_NLSTEXT", HKEY_PERFORMANCE_NLSTEXT}, - { L"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG}, - { L"HKEY_DYN_DATA", HKEY_DYN_DATA} -}; - -// These functions perform case independent path comparisons. -bool EqualPath(const base::string16& first, const base::string16& second) { - return _wcsicmp(first.c_str(), second.c_str()) == 0; -} - -bool EqualPath(const base::string16& first, size_t first_offset, - const base::string16& second, size_t second_offset) { - return _wcsicmp(first.c_str() + first_offset, - second.c_str() + second_offset) == 0; -} - -bool EqualPath(const base::string16& first, - const wchar_t* second, size_t second_len) { - return _wcsnicmp(first.c_str(), second, second_len) == 0; -} - -bool EqualPath(const base::string16& first, size_t first_offset, - const wchar_t* second, size_t second_len) { - return _wcsnicmp(first.c_str() + first_offset, second, second_len) == 0; -} - -// Returns true if |path| starts with "\??\" and returns a path without that -// component. -bool IsNTPath(const base::string16& path, base::string16* trimmed_path ) { - if ((path.size() < sandbox::kNTPrefixLen) || - (0 != path.compare(0, sandbox::kNTPrefixLen, sandbox::kNTPrefix))) { - *trimmed_path = path; - return false; - } - - *trimmed_path = path.substr(sandbox::kNTPrefixLen); - return true; -} - -// Returns true if |path| starts with "\Device\" and returns a path without that -// component. -bool IsDevicePath(const base::string16& path, base::string16* trimmed_path ) { - if ((path.size() < sandbox::kNTDevicePrefixLen) || - (!EqualPath(path, sandbox::kNTDevicePrefix, - sandbox::kNTDevicePrefixLen))) { - *trimmed_path = path; - return false; - } - - *trimmed_path = path.substr(sandbox::kNTDevicePrefixLen); - return true; -} - -bool StartsWithDriveLetter(const base::string16& path) { - if (path.size() < 3) - return false; - - if (path[1] != L':' || path[2] != L'\\') - return false; - - return (path[0] >= 'a' && path[0] <= 'z') || - (path[0] >= 'A' && path[0] <= 'Z'); -} - -const wchar_t kNTDotPrefix[] = L"\\\\.\\"; -const size_t kNTDotPrefixLen = arraysize(kNTDotPrefix) - 1; - -// Removes "\\\\.\\" from the path. -void RemoveImpliedDevice(base::string16* path) { - if (0 == path->compare(0, kNTDotPrefixLen, kNTDotPrefix)) - *path = path->substr(kNTDotPrefixLen); -} - -} // namespace - -namespace sandbox { - -// Returns true if the provided path points to a pipe. -bool IsPipe(const base::string16& path) { - size_t start = 0; - if (0 == path.compare(0, sandbox::kNTPrefixLen, sandbox::kNTPrefix)) - start = sandbox::kNTPrefixLen; - - const wchar_t kPipe[] = L"pipe\\"; - if (path.size() < start + arraysize(kPipe) - 1) - return false; - - return EqualPath(path, start, kPipe, arraysize(kPipe) - 1); -} - -HKEY GetReservedKeyFromName(const base::string16& name) { - for (size_t i = 0; i < arraysize(kKnownKey); ++i) { - if (name == kKnownKey[i].name) - return kKnownKey[i].key; - } - - return NULL; -} - -bool ResolveRegistryName(base::string16 name, base::string16* resolved_name) { - for (size_t i = 0; i < arraysize(kKnownKey); ++i) { - if (name.find(kKnownKey[i].name) == 0) { - HKEY key; - DWORD disposition; - if (ERROR_SUCCESS != ::RegCreateKeyEx(kKnownKey[i].key, L"", 0, NULL, 0, - MAXIMUM_ALLOWED, NULL, &key, - &disposition)) - return false; - - bool result = GetPathFromHandle(key, resolved_name); - ::RegCloseKey(key); - - if (!result) - return false; - - *resolved_name += name.substr(wcslen(kKnownKey[i].name)); - return true; - } - } - - return false; -} - -// |full_path| can have any of the following forms: -// \??\c:\some\foo\bar -// \Device\HarddiskVolume0\some\foo\bar -// \??\HarddiskVolume0\some\foo\bar -// \??\UNC\SERVER\Share\some\foo\bar -DWORD IsReparsePoint(const base::string16& full_path) { - // Check if it's a pipe. We can't query the attributes of a pipe. - if (IsPipe(full_path)) - return ERROR_NOT_A_REPARSE_POINT; - - base::string16 path; - bool nt_path = IsNTPath(full_path, &path); - bool has_drive = StartsWithDriveLetter(path); - bool is_device_path = IsDevicePath(path, &path); - - if (!has_drive && !is_device_path && !nt_path) - return ERROR_INVALID_NAME; - - if (!has_drive) { - // Add Win32 device namespace prefix, required for some Windows APIs. - path.insert(0, kNTDotPrefix); - } - - // Ensure that volume path matches start of path. - wchar_t vol_path[MAX_PATH]; - if (!::GetVolumePathNameW(path.c_str(), vol_path, MAX_PATH)) { - // This will fail if this is a device that isn't volume related, which can't - // then be a reparse point. - return is_device_path ? ERROR_NOT_A_REPARSE_POINT : ERROR_INVALID_NAME; - } - - // vol_path includes a trailing slash, so reduce size for path and loop check. - size_t vol_path_len = wcslen(vol_path) - 1; - if (!EqualPath(path, vol_path, vol_path_len)) { - return ERROR_INVALID_NAME; - } - - do { - DWORD attributes = ::GetFileAttributes(path.c_str()); - if (INVALID_FILE_ATTRIBUTES == attributes) { - DWORD error = ::GetLastError(); - if (error != ERROR_FILE_NOT_FOUND && - error != ERROR_PATH_NOT_FOUND && - error != ERROR_INVALID_FUNCTION && - error != ERROR_INVALID_NAME) { - // Unexpected error. - NOTREACHED_NT(); - return error; - } - } else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) { - // This is a reparse point. - return ERROR_SUCCESS; - } - - path.resize(path.rfind(L'\\')); - } while (path.size() > vol_path_len); // Skip root dir. - - return ERROR_NOT_A_REPARSE_POINT; -} - -// We get a |full_path| of the forms accepted by IsReparsePoint(), and the name -// we'll get from |handle| will be \device\harddiskvolume1\some\foo\bar. -bool SameObject(HANDLE handle, const wchar_t* full_path) { - // Check if it's a pipe. - if (IsPipe(full_path)) - return true; - - base::string16 actual_path; - if (!GetPathFromHandle(handle, &actual_path)) - return false; - - base::string16 path(full_path); - DCHECK_NT(!path.empty()); - - // This may end with a backslash. - if (path.back() == L'\\') { - path.pop_back(); - } - - // Perfect match (case-insensitive check). - if (EqualPath(actual_path, path)) - return true; - - bool nt_path = IsNTPath(path, &path); - bool has_drive = StartsWithDriveLetter(path); - - if (!has_drive && nt_path) { - base::string16 simple_actual_path; - if (IsDevicePath(path, &path)) { - if (IsDevicePath(actual_path, &simple_actual_path)) { - // Perfect match (case-insensitive check). - return (EqualPath(simple_actual_path, path)); - } else { - return false; - } - } else { - // Add Win32 device namespace for GetVolumePathName. - path.insert(0, kNTDotPrefix); - } - } - - // Get the volume path in the same format as actual_path. - wchar_t vol_path[MAX_PATH]; - if (!::GetVolumePathName(path.c_str(), vol_path, MAX_PATH)) { - return false; - } - size_t vol_path_len = wcslen(vol_path); - base::string16 nt_vol; - if (!GetNtPathFromWin32Path(vol_path, &nt_vol)) { - return false; - } - - // The two paths should be the same length. - if (nt_vol.size() + path.size() - vol_path_len != actual_path.size()) { - return false; - } - - // Check the volume matches. - if (!EqualPath(actual_path, nt_vol.c_str(), nt_vol.size())) { - return false; - } - - // Check the path after the volume matches. - if (!EqualPath(actual_path, nt_vol.size(), path, vol_path_len)) { - return false; - } - - return true; -} - -// Paths like \Device\HarddiskVolume0\some\foo\bar are assumed to be already -// expanded. -bool ConvertToLongPath(base::string16* path) { - if (IsPipe(*path)) - return true; - - base::string16 temp_path; - if (IsDevicePath(*path, &temp_path)) - return false; - - bool is_nt_path = IsNTPath(temp_path, &temp_path); - bool added_implied_device = false; - if (!StartsWithDriveLetter(temp_path) && is_nt_path) { - temp_path = base::string16(kNTDotPrefix) + temp_path; - added_implied_device = true; - } - - DWORD size = MAX_PATH; - scoped_ptr<wchar_t[]> long_path_buf(new wchar_t[size]); - - DWORD return_value = ::GetLongPathName(temp_path.c_str(), long_path_buf.get(), - size); - while (return_value >= size) { - size *= 2; - long_path_buf.reset(new wchar_t[size]); - return_value = ::GetLongPathName(temp_path.c_str(), long_path_buf.get(), - size); - } - - DWORD last_error = ::GetLastError(); - if (0 == return_value && (ERROR_FILE_NOT_FOUND == last_error || - ERROR_PATH_NOT_FOUND == last_error || - ERROR_INVALID_NAME == last_error)) { - // The file does not exist, but maybe a sub path needs to be expanded. - base::string16::size_type last_slash = temp_path.rfind(L'\\'); - if (base::string16::npos == last_slash) - return false; - - base::string16 begin = temp_path.substr(0, last_slash); - base::string16 end = temp_path.substr(last_slash); - if (!ConvertToLongPath(&begin)) - return false; - - // Ok, it worked. Let's reset the return value. - temp_path = begin + end; - return_value = 1; - } else if (0 != return_value) { - temp_path = long_path_buf.get(); - } - - if (return_value != 0) { - if (added_implied_device) - RemoveImpliedDevice(&temp_path); - - if (is_nt_path) { - *path = kNTPrefix; - *path += temp_path; - } else { - *path = temp_path; - } - - return true; - } - - return false; -} - -bool GetPathFromHandle(HANDLE handle, base::string16* path) { - NtQueryObjectFunction NtQueryObject = NULL; - ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject); - - OBJECT_NAME_INFORMATION initial_buffer; - OBJECT_NAME_INFORMATION* name = &initial_buffer; - ULONG size = sizeof(initial_buffer); - // Query the name information a first time to get the size of the name. - // Windows XP requires that the size of the buffer passed in here be != 0. - NTSTATUS status = NtQueryObject(handle, ObjectNameInformation, name, size, - &size); - - scoped_ptr<BYTE[]> name_ptr; - if (size) { - name_ptr.reset(new BYTE[size]); - name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(name_ptr.get()); - - // Query the name information a second time to get the name of the - // object referenced by the handle. - status = NtQueryObject(handle, ObjectNameInformation, name, size, &size); - } - - if (STATUS_SUCCESS != status) - return false; - - path->assign(name->ObjectName.Buffer, name->ObjectName.Length / - sizeof(name->ObjectName.Buffer[0])); - return true; -} - -bool GetNtPathFromWin32Path(const base::string16& path, - base::string16* nt_path) { - HANDLE file = ::CreateFileW(path.c_str(), 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (file == INVALID_HANDLE_VALUE) - return false; - bool rv = GetPathFromHandle(file, nt_path); - ::CloseHandle(file); - return rv; -} - -bool WriteProtectedChildMemory(HANDLE child_process, void* address, - const void* buffer, size_t length) { - // First, remove the protections. - DWORD old_protection; - if (!::VirtualProtectEx(child_process, address, length, - PAGE_WRITECOPY, &old_protection)) - return false; - - SIZE_T written; - bool ok = ::WriteProcessMemory(child_process, address, buffer, length, - &written) && (length == written); - - // Always attempt to restore the original protection. - if (!::VirtualProtectEx(child_process, address, length, - old_protection, &old_protection)) - return false; - - return ok; -} - -}; // namespace sandbox - -void ResolveNTFunctionPtr(const char* name, void* ptr) { - static volatile HMODULE ntdll = NULL; - - if (!ntdll) { - HMODULE ntdll_local = ::GetModuleHandle(sandbox::kNtdllName); - // Use PEImage to sanity-check that we have a valid ntdll handle. - base::win::PEImage ntdll_peimage(ntdll_local); - CHECK_NT(ntdll_peimage.VerifyMagic()); - // Race-safe way to set static ntdll. - ::InterlockedCompareExchangePointer( - reinterpret_cast<PVOID volatile*>(&ntdll), ntdll_local, NULL); - - } - - CHECK_NT(ntdll); - FARPROC* function_ptr = reinterpret_cast<FARPROC*>(ptr); - *function_ptr = ::GetProcAddress(ntdll, name); - CHECK_NT(*function_ptr); -} diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.h b/security/sandbox/chromium/sandbox/win/src/win_utils.h deleted file mode 100644 index f7895c1b8..000000000 --- a/security/sandbox/chromium/sandbox/win/src/win_utils.h +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_WIN_UTILS_H_ -#define SANDBOX_SRC_WIN_UTILS_H_ - -#include <windows.h> -#include <stddef.h> -#include <string> - -#include "base/macros.h" -#include "base/strings/string16.h" - -namespace sandbox { - -// Prefix for path used by NT calls. -const wchar_t kNTPrefix[] = L"\\??\\"; -const size_t kNTPrefixLen = arraysize(kNTPrefix) - 1; - -const wchar_t kNTDevicePrefix[] = L"\\Device\\"; -const size_t kNTDevicePrefixLen = arraysize(kNTDevicePrefix) - 1; - -// Automatically acquires and releases a lock when the object is -// is destroyed. -class AutoLock { - public: - // Acquires the lock. - explicit AutoLock(CRITICAL_SECTION *lock) : lock_(lock) { - ::EnterCriticalSection(lock); - }; - - // Releases the lock; - ~AutoLock() { - ::LeaveCriticalSection(lock_); - }; - - private: - CRITICAL_SECTION *lock_; - DISALLOW_IMPLICIT_CONSTRUCTORS(AutoLock); -}; - -// Basic implementation of a singleton which calls the destructor -// when the exe is shutting down or the DLL is being unloaded. -template <typename Derived> -class SingletonBase { - public: - static Derived* GetInstance() { - static Derived* instance = NULL; - if (NULL == instance) { - instance = new Derived(); - // Microsoft CRT extension. In an exe this this called after - // winmain returns, in a dll is called in DLL_PROCESS_DETACH - _onexit(OnExit); - } - return instance; - } - - private: - // this is the function that gets called by the CRT when the - // process is shutting down. - static int __cdecl OnExit() { - delete GetInstance(); - return 0; - } -}; - -// Convert a short path (C:\path~1 or \\??\\c:\path~1) to the long version of -// the path. If the path is not a valid filesystem path, the function returns -// false and argument is not modified. -bool ConvertToLongPath(base::string16* path); - -// Returns ERROR_SUCCESS if the path contains a reparse point, -// ERROR_NOT_A_REPARSE_POINT if there's no reparse point in this path, or an -// error code when the function fails. -// This function is not smart. It looks for each element in the path and -// returns true if any of them is a reparse point. -DWORD IsReparsePoint(const base::string16& full_path); - -// Returns true if the handle corresponds to the object pointed by this path. -bool SameObject(HANDLE handle, const wchar_t* full_path); - -// Resolves a handle to an nt path. Returns true if the handle can be resolved. -bool GetPathFromHandle(HANDLE handle, base::string16* path); - -// Resolves a win32 path to an nt path using GetPathFromHandle. The path must -// exist. Returs true if the translation was succesful. -bool GetNtPathFromWin32Path(const base::string16& path, - base::string16* nt_path); - -// Translates a reserved key name to its handle. -// For example "HKEY_LOCAL_MACHINE" returns HKEY_LOCAL_MACHINE. -// Returns NULL if the name does not represent any reserved key name. -HKEY GetReservedKeyFromName(const base::string16& name); - -// Resolves a user-readable registry path to a system-readable registry path. -// For example, HKEY_LOCAL_MACHINE\\Software\\microsoft is translated to -// \\registry\\machine\\software\\microsoft. Returns false if the path -// cannot be resolved. -bool ResolveRegistryName(base::string16 name, base::string16* resolved_name); - -// Writes |length| bytes from the provided |buffer| into the address space of -// |child_process|, at the specified |address|, preserving the original write -// protection attributes. Returns true on success. -bool WriteProtectedChildMemory(HANDLE child_process, void* address, - const void* buffer, size_t length); - -// Returns true if the provided path points to a pipe. -bool IsPipe(const base::string16& path); - -} // namespace sandbox - -// Resolves a function name in NTDLL to a function pointer. The second parameter -// is a pointer to the function pointer. -void ResolveNTFunctionPtr(const char* name, void* ptr); - -#endif // SANDBOX_SRC_WIN_UTILS_H_ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils_unittest.cc b/security/sandbox/chromium/sandbox/win/src/win_utils_unittest.cc deleted file mode 100644 index fb72eb338..000000000 --- a/security/sandbox/chromium/sandbox/win/src/win_utils_unittest.cc +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <windows.h> - -#include "base/win/scoped_handle.h" -#include "sandbox/win/src/win_utils.h" -#include "sandbox/win/tests/common/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(WinUtils, IsReparsePoint) { - using sandbox::IsReparsePoint; - - // Create a temp file because we need write access to it. - wchar_t temp_directory[MAX_PATH]; - wchar_t my_folder[MAX_PATH]; - ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, my_folder), 0u); - - // Delete the file and create a directory instead. - ASSERT_TRUE(::DeleteFile(my_folder)); - ASSERT_TRUE(::CreateDirectory(my_folder, NULL)); - - EXPECT_EQ(static_cast<DWORD>(ERROR_NOT_A_REPARSE_POINT), - IsReparsePoint(my_folder)); - - base::string16 not_found = base::string16(my_folder) + L"\\foo\\bar"; - EXPECT_EQ(static_cast<DWORD>(ERROR_NOT_A_REPARSE_POINT), - IsReparsePoint(not_found)); - - base::string16 new_file = base::string16(my_folder) + L"\\foo"; - EXPECT_EQ(static_cast<DWORD>(ERROR_NOT_A_REPARSE_POINT), - IsReparsePoint(new_file)); - - // Replace the directory with a reparse point to %temp%. - HANDLE dir = ::CreateFile(my_folder, FILE_ALL_ACCESS, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - EXPECT_NE(INVALID_HANDLE_VALUE, dir); - - base::string16 temp_dir_nt = base::string16(L"\\??\\") + temp_directory; - EXPECT_TRUE(SetReparsePoint(dir, temp_dir_nt.c_str())); - - EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), IsReparsePoint(new_file)); - - EXPECT_TRUE(DeleteReparsePoint(dir)); - EXPECT_TRUE(::CloseHandle(dir)); - EXPECT_TRUE(::RemoveDirectory(my_folder)); -} - -TEST(WinUtils, SameObject) { - using sandbox::SameObject; - - // Create a temp file because we need write access to it. - wchar_t temp_directory[MAX_PATH]; - wchar_t my_folder[MAX_PATH]; - ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); - ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, my_folder), 0u); - - // Delete the file and create a directory instead. - ASSERT_TRUE(::DeleteFile(my_folder)); - ASSERT_TRUE(::CreateDirectory(my_folder, NULL)); - - base::string16 folder(my_folder); - base::string16 file_name = folder + L"\\foo.txt"; - const ULONG kSharing = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; - base::win::ScopedHandle file(CreateFile( - file_name.c_str(), GENERIC_WRITE, kSharing, NULL, CREATE_ALWAYS, - FILE_FLAG_DELETE_ON_CLOSE, NULL)); - - EXPECT_TRUE(file.IsValid()); - base::string16 file_name_nt1 = base::string16(L"\\??\\") + file_name; - base::string16 file_name_nt2 = - base::string16(L"\\??\\") + folder + L"\\FOO.txT"; - EXPECT_TRUE(SameObject(file.Get(), file_name_nt1.c_str())); - EXPECT_TRUE(SameObject(file.Get(), file_name_nt2.c_str())); - - file.Close(); - EXPECT_TRUE(::RemoveDirectory(my_folder)); -} - -TEST(WinUtils, IsPipe) { - using sandbox::IsPipe; - - base::string16 pipe_name = L"\\??\\pipe\\mypipe"; - EXPECT_TRUE(IsPipe(pipe_name)); - - pipe_name = L"\\??\\PiPe\\mypipe"; - EXPECT_TRUE(IsPipe(pipe_name)); - - pipe_name = L"\\??\\pipe"; - EXPECT_FALSE(IsPipe(pipe_name)); - - pipe_name = L"\\??\\_pipe_\\mypipe"; - EXPECT_FALSE(IsPipe(pipe_name)); - - pipe_name = L"\\??\\ABCD\\mypipe"; - EXPECT_FALSE(IsPipe(pipe_name)); - - - // Written as two strings to prevent trigraph '?' '?' '/'. - pipe_name = L"/?" L"?/pipe/mypipe"; - EXPECT_FALSE(IsPipe(pipe_name)); - - pipe_name = L"\\XX\\pipe\\mypipe"; - EXPECT_FALSE(IsPipe(pipe_name)); - - pipe_name = L"\\Device\\NamedPipe\\mypipe"; - EXPECT_FALSE(IsPipe(pipe_name)); -} diff --git a/security/sandbox/chromium/sandbox/win/src/window.cc b/security/sandbox/chromium/sandbox/win/src/window.cc deleted file mode 100644 index cfbf280d9..000000000 --- a/security/sandbox/chromium/sandbox/win/src/window.cc +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/window.h" - -#include <aclapi.h> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/src/acl.h" -#include "sandbox/win/src/sid.h" - -namespace { - -// Gets the security attributes of a window object referenced by |handle|. The -// lpSecurityDescriptor member of the SECURITY_ATTRIBUTES parameter returned -// must be freed using LocalFree by the caller. -bool GetSecurityAttributes(HANDLE handle, SECURITY_ATTRIBUTES* attributes) { - attributes->bInheritHandle = FALSE; - attributes->nLength = sizeof(SECURITY_ATTRIBUTES); - - PACL dacl = NULL; - DWORD result = ::GetSecurityInfo(handle, SE_WINDOW_OBJECT, - DACL_SECURITY_INFORMATION, NULL, NULL, &dacl, - NULL, &attributes->lpSecurityDescriptor); - if (ERROR_SUCCESS == result) - return true; - - return false; -} - -} - -namespace sandbox { - -ResultCode CreateAltWindowStation(HWINSTA* winsta) { - // Get the security attributes from the current window station; we will - // use this as the base security attributes for the new window station. - SECURITY_ATTRIBUTES attributes = {0}; - if (!GetSecurityAttributes(::GetProcessWindowStation(), &attributes)) { - return SBOX_ERROR_CANNOT_CREATE_WINSTATION; - } - - // Create the window station using NULL for the name to ask the os to - // generate it. - *winsta = ::CreateWindowStationW( - NULL, 0, GENERIC_READ | WINSTA_CREATEDESKTOP, &attributes); - LocalFree(attributes.lpSecurityDescriptor); - - if (*winsta) - return SBOX_ALL_OK; - - return SBOX_ERROR_CANNOT_CREATE_WINSTATION; -} - -ResultCode CreateAltDesktop(HWINSTA winsta, HDESK* desktop) { - base::string16 desktop_name = L"sbox_alternate_desktop_"; - - // Append the current PID to the desktop name. - wchar_t buffer[16]; - _snwprintf_s(buffer, sizeof(buffer) / sizeof(wchar_t), L"0x%X", - ::GetCurrentProcessId()); - desktop_name += buffer; - - // Get the security attributes from the current desktop, we will use this as - // the base security attributes for the new desktop. - SECURITY_ATTRIBUTES attributes = {0}; - if (!GetSecurityAttributes(GetThreadDesktop(GetCurrentThreadId()), - &attributes)) { - return SBOX_ERROR_CANNOT_CREATE_DESKTOP; - } - - // Back up the current window station, in case we need to switch it. - HWINSTA current_winsta = ::GetProcessWindowStation(); - - if (winsta) { - // We need to switch to the alternate window station before creating the - // desktop. - if (!::SetProcessWindowStation(winsta)) { - ::LocalFree(attributes.lpSecurityDescriptor); - return SBOX_ERROR_CANNOT_CREATE_DESKTOP; - } - } - - // Create the destkop. - *desktop = ::CreateDesktop(desktop_name.c_str(), - NULL, - NULL, - 0, - DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | - READ_CONTROL | WRITE_DAC | WRITE_OWNER, - &attributes); - ::LocalFree(attributes.lpSecurityDescriptor); - - if (winsta) { - // Revert to the right window station. - if (!::SetProcessWindowStation(current_winsta)) { - return SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION; - } - } - - if (*desktop) { - // Replace the DACL on the new Desktop with a reduced privilege version. - // We can soft fail on this for now, as it's just an extra mitigation. - static const ACCESS_MASK kDesktopDenyMask = WRITE_DAC | WRITE_OWNER | - DELETE | - DESKTOP_CREATEMENU | - DESKTOP_CREATEWINDOW | - DESKTOP_HOOKCONTROL | - DESKTOP_JOURNALPLAYBACK | - DESKTOP_JOURNALRECORD | - DESKTOP_SWITCHDESKTOP; - AddKnownSidToObject(*desktop, SE_WINDOW_OBJECT, Sid(WinRestrictedCodeSid), - DENY_ACCESS, kDesktopDenyMask); - return SBOX_ALL_OK; - } - - return SBOX_ERROR_CANNOT_CREATE_DESKTOP; -} - -base::string16 GetWindowObjectName(HANDLE handle) { - // Get the size of the name. - DWORD size = 0; - ::GetUserObjectInformation(handle, UOI_NAME, NULL, 0, &size); - - if (!size) { - NOTREACHED(); - return base::string16(); - } - - // Create the buffer that will hold the name. - scoped_ptr<wchar_t[]> name_buffer(new wchar_t[size]); - - // Query the name of the object. - if (!::GetUserObjectInformation(handle, UOI_NAME, name_buffer.get(), size, - &size)) { - NOTREACHED(); - return base::string16(); - } - - return base::string16(name_buffer.get()); -} - -base::string16 GetFullDesktopName(HWINSTA winsta, HDESK desktop) { - if (!desktop) { - NOTREACHED(); - return base::string16(); - } - - base::string16 name; - if (winsta) { - name = GetWindowObjectName(winsta); - name += L'\\'; - } - - name += GetWindowObjectName(desktop); - return name; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/src/window.h b/security/sandbox/chromium/sandbox/win/src/window.h deleted file mode 100644 index 62fe7c474..000000000 --- a/security/sandbox/chromium/sandbox/win/src/window.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_SRC_WINDOW_H_ -#define SANDBOX_SRC_WINDOW_H_ - -#include <windows.h> -#include <string> - -#include "base/strings/string16.h" -#include "sandbox/win/src/sandbox_types.h" - -namespace sandbox { - - // Creates a window station. The name is generated by the OS. The security - // descriptor is based on the security descriptor of the current window - // station. - ResultCode CreateAltWindowStation(HWINSTA* winsta); - - // Creates a desktop. The name is a static string followed by the pid of the - // current process. The security descriptor on the new desktop is based on the - // security descriptor of the desktop associated with the current thread. - // If a winsta is specified, the function will switch to it before creating - // the desktop. If the functions fails the switch back to the current winsta, - // the function will return SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION. - ResultCode CreateAltDesktop(HWINSTA winsta, HDESK* desktop); - - // Returns the name of a desktop or a window station. - base::string16 GetWindowObjectName(HANDLE handle); - - // Returns the name of the desktop referenced by |desktop|. If a window - // station is specified, the name is prepended with the window station name, - // followed by a backslash. This name can be used as the lpDesktop parameter - // to CreateProcess. - base::string16 GetFullDesktopName(HWINSTA winsta, HDESK desktop); - -} // namespace sandbox - -#endif // SANDBOX_SRC_WINDOW_H_ diff --git a/security/sandbox/chromium/sandbox/win/wow_helper/service64_resolver.cc b/security/sandbox/chromium/sandbox/win/wow_helper/service64_resolver.cc deleted file mode 100644 index 0424d9fdd..000000000 --- a/security/sandbox/chromium/sandbox/win/wow_helper/service64_resolver.cc +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/wow_helper/service64_resolver.h" - -#include <limits.h> -#include <stddef.h> - -#include "base/bit_cast.h" -#include "base/memory/scoped_ptr.h" -#include "sandbox/win/wow_helper/target_code.h" - -namespace { -#pragma pack(push, 1) - -const BYTE kMovEax = 0xB8; -const BYTE kMovEdx = 0xBA; -const USHORT kCallPtrEdx = 0x12FF; -const BYTE kRet = 0xC2; -const BYTE kNop = 0x90; -const USHORT kJmpEdx = 0xE2FF; -const USHORT kXorEcx = 0xC933; -const ULONG kLeaEdx = 0x0424548D; -const ULONG kCallFs1 = 0xC015FF64; -const ULONG kCallFs2Ret = 0xC2000000; -const BYTE kPopEdx = 0x5A; -const BYTE kPushEdx = 0x52; -const BYTE kPush32 = 0x68; - -const ULONG kMmovR10EcxMovEax = 0xB8D18B4C; -const USHORT kSyscall = 0x050F; -const BYTE kRetNp = 0xC3; -const BYTE kPad = 0x66; -const USHORT kNop16 = 0x9066; -const BYTE kRelJmp = 0xE9; - -const ULONG kXorRaxMovEax = 0xB8C03148; -const ULONG kSaveRcx = 0x10488948; -const ULONG kMovRcxRaxJmp = 0xE9C88B48; - -// Service code for 64 bit systems. -struct ServiceEntry { - // this struct contains roughly the following code: - // mov r10,rcx - // mov eax,52h - // syscall - // ret - // xchg ax,ax - // xchg ax,ax - - ULONG mov_r10_ecx_mov_eax; // = 4C 8B D1 B8 - ULONG service_id; - USHORT syscall; // = 0F 05 - BYTE ret; // = C3 - BYTE pad; // = 66 - USHORT xchg_ax_ax1; // = 66 90 - USHORT xchg_ax_ax2; // = 66 90 -}; - -struct Redirected { - // this struct contains roughly the following code: - // jmp relative_32 - // xchg ax,ax // 3 byte nop - - Redirected() { - jmp = kRelJmp; - relative = 0; - pad = kPad; - xchg_ax_ax = kNop16; - }; - BYTE jmp; // = E9 - ULONG relative; - BYTE pad; // = 66 - USHORT xchg_ax_ax; // = 66 90 -}; - -struct InternalThunk { - // this struct contains roughly the following code: - // xor rax,rax - // mov eax, 0x00080000 // Thunk storage. - // mov [rax]PatchInfo.service, rcx // Save first argument. - // mov rcx, rax - // jmp relative_to_interceptor - - InternalThunk() { - xor_rax_mov_eax = kXorRaxMovEax; - patch_info = 0; - save_rcx = kSaveRcx; - mov_rcx_rax_jmp = kMovRcxRaxJmp; - relative = 0; - }; - ULONG xor_rax_mov_eax; // = 48 31 C0 B8 - ULONG patch_info; - ULONG save_rcx; // = 48 89 48 10 - ULONG mov_rcx_rax_jmp; // = 48 8b c8 e9 - ULONG relative; -}; - -struct ServiceFullThunk { - sandbox::PatchInfo patch_info; - ServiceEntry original; - InternalThunk internal_thunk; -}; - -#pragma pack(pop) - -// Simple utility function to write to a buffer on the child, if the memery has -// write protection attributes. -// Arguments: -// child_process (in): process to write to. -// address (out): memory position on the child to write to. -// buffer (in): local buffer with the data to write . -// length (in): number of bytes to write. -// Returns true on success. -bool WriteProtectedChildMemory(HANDLE child_process, - void* address, - const void* buffer, - size_t length) { - // first, remove the protections - DWORD old_protection; - if (!::VirtualProtectEx(child_process, address, length, - PAGE_WRITECOPY, &old_protection)) - return false; - - SIZE_T written; - bool ok = ::WriteProcessMemory(child_process, address, buffer, length, - &written) && (length == written); - - // always attempt to restore the original protection - if (!::VirtualProtectEx(child_process, address, length, - old_protection, &old_protection)) - return false; - - return ok; -} - -// Get pointers to the functions that we need from ntdll.dll. -NTSTATUS ResolveNtdll(sandbox::PatchInfo* patch_info) { - wchar_t* ntdll_name = L"ntdll.dll"; - HMODULE ntdll = ::GetModuleHandle(ntdll_name); - if (!ntdll) - return STATUS_PROCEDURE_NOT_FOUND; - - void* signal = ::GetProcAddress(ntdll, "NtSignalAndWaitForSingleObject"); - if (!signal) - return STATUS_PROCEDURE_NOT_FOUND; - - patch_info->signal_and_wait = - reinterpret_cast<NtSignalAndWaitForSingleObjectFunction>(signal); - - return STATUS_SUCCESS; -} - -}; // namespace - -namespace sandbox { - -NTSTATUS ResolverThunk::Init(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes) { - if (NULL == thunk_storage || 0 == storage_bytes || - NULL == target_module || NULL == target_name) - return STATUS_INVALID_PARAMETER; - - if (storage_bytes < GetThunkSize()) - return STATUS_BUFFER_TOO_SMALL; - - NTSTATUS ret = STATUS_SUCCESS; - if (NULL == interceptor_entry_point) { - ret = ResolveInterceptor(interceptor_module, interceptor_name, - &interceptor_entry_point); - if (!NT_SUCCESS(ret)) - return ret; - } - - ret = ResolveTarget(target_module, target_name, &target_); - if (!NT_SUCCESS(ret)) - return ret; - - interceptor_ = interceptor_entry_point; - - return ret; -} - -NTSTATUS ResolverThunk::ResolveInterceptor(const void* interceptor_module, - const char* interceptor_name, - const void** address) { - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS ResolverThunk::ResolveTarget(const void* module, - const char* function_name, - void** address) { - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS Service64ResolverThunk::Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used) { - NTSTATUS ret = Init(target_module, interceptor_module, target_name, - interceptor_name, interceptor_entry_point, - thunk_storage, storage_bytes); - if (!NT_SUCCESS(ret)) - return ret; - - size_t thunk_bytes = GetThunkSize(); - scoped_ptr<char[]> thunk_buffer(new char[thunk_bytes]); - ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>( - thunk_buffer.get()); - - if (!IsFunctionAService(&thunk->original)) - return STATUS_UNSUCCESSFUL; - - ret = PerformPatch(thunk, thunk_storage); - - if (NULL != storage_used) - *storage_used = thunk_bytes; - - return ret; -} - -NTSTATUS Service64ResolverThunk::ResolveInterceptor( - const void* interceptor_module, - const char* interceptor_name, - const void** address) { - // After all, we are using a locally mapped version of the exe, so the - // action is the same as for a target function. - return ResolveTarget(interceptor_module, interceptor_name, - const_cast<void**>(address)); -} - -// In this case all the work is done from the parent, so resolve is -// just a simple GetProcAddress. -NTSTATUS Service64ResolverThunk::ResolveTarget(const void* module, - const char* function_name, - void** address) { - if (NULL == module) - return STATUS_UNSUCCESSFUL; - - *address = ::GetProcAddress(bit_cast<HMODULE>(module), function_name); - - if (NULL == *address) - return STATUS_UNSUCCESSFUL; - - return STATUS_SUCCESS; -} - -size_t Service64ResolverThunk::GetThunkSize() const { - return sizeof(ServiceFullThunk); -} - -bool Service64ResolverThunk::IsFunctionAService(void* local_thunk) const { - ServiceEntry function_code; - SIZE_T read; - if (!::ReadProcessMemory(process_, target_, &function_code, - sizeof(function_code), &read)) - return false; - - if (sizeof(function_code) != read) - return false; - - if (kMmovR10EcxMovEax != function_code.mov_r10_ecx_mov_eax || - kSyscall != function_code.syscall || kRetNp != function_code.ret) - return false; - - // Save the verified code - memcpy(local_thunk, &function_code, sizeof(function_code)); - - return true; -} - -NTSTATUS Service64ResolverThunk::PerformPatch(void* local_thunk, - void* remote_thunk) { - ServiceFullThunk* full_local_thunk = reinterpret_cast<ServiceFullThunk*>( - local_thunk); - ServiceFullThunk* full_remote_thunk = reinterpret_cast<ServiceFullThunk*>( - remote_thunk); - - // If the source or target are above 4GB we cannot do this relative jump. - if (reinterpret_cast<ULONG_PTR>(full_remote_thunk) > - static_cast<ULONG_PTR>(ULONG_MAX)) - return STATUS_CONFLICTING_ADDRESSES; - - if (reinterpret_cast<ULONG_PTR>(target_) > static_cast<ULONG_PTR>(ULONG_MAX)) - return STATUS_CONFLICTING_ADDRESSES; - - // Patch the original code. - Redirected local_service; - Redirected* remote_service = reinterpret_cast<Redirected*>(target_); - ULONG_PTR diff = reinterpret_cast<BYTE*>(&full_remote_thunk->internal_thunk) - - &remote_service->pad; - local_service.relative = static_cast<ULONG>(diff); - - // Setup the PatchInfo structure. - SIZE_T actual; - if (!::ReadProcessMemory(process_, remote_thunk, local_thunk, - sizeof(PatchInfo), &actual)) - return STATUS_UNSUCCESSFUL; - if (sizeof(PatchInfo) != actual) - return STATUS_UNSUCCESSFUL; - - full_local_thunk->patch_info.orig_MapViewOfSection = reinterpret_cast< - NtMapViewOfSectionFunction>(&full_remote_thunk->original); - full_local_thunk->patch_info.patch_location = target_; - NTSTATUS ret = ResolveNtdll(&full_local_thunk->patch_info); - if (!NT_SUCCESS(ret)) - return ret; - - // Setup the thunk. The jump out is performed from right after the end of the - // thunk (full_remote_thunk + 1). - InternalThunk my_thunk; - ULONG_PTR patch_info = reinterpret_cast<ULONG_PTR>(remote_thunk); - my_thunk.patch_info = static_cast<ULONG>(patch_info); - diff = reinterpret_cast<const BYTE*>(interceptor_) - - reinterpret_cast<BYTE*>(full_remote_thunk + 1); - my_thunk.relative = static_cast<ULONG>(diff); - - memcpy(&full_local_thunk->internal_thunk, &my_thunk, sizeof(my_thunk)); - - // copy the local thunk buffer to the child - if (!::WriteProcessMemory(process_, remote_thunk, local_thunk, - sizeof(ServiceFullThunk), &actual)) - return STATUS_UNSUCCESSFUL; - - if (sizeof(ServiceFullThunk) != actual) - return STATUS_UNSUCCESSFUL; - - // and now change the function to intercept, on the child - if (!::WriteProtectedChildMemory(process_, target_, &local_service, - sizeof(local_service))) - return STATUS_UNSUCCESSFUL; - - return STATUS_SUCCESS; -} - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/wow_helper/service64_resolver.h b/security/sandbox/chromium/sandbox/win/wow_helper/service64_resolver.h deleted file mode 100644 index 32ee46f8e..000000000 --- a/security/sandbox/chromium/sandbox/win/wow_helper/service64_resolver.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WOW_HELPER_SERVICE64_RESOLVER_H__ -#define SANDBOX_WOW_HELPER_SERVICE64_RESOLVER_H__ - -#include <stddef.h> - -#include "base/macros.h" -#include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/resolver.h" - -namespace sandbox { - -// This is the concrete resolver used to perform service-call type functions -// inside ntdll.dll (64-bit). -class Service64ResolverThunk : public ResolverThunk { - public: - // The service resolver needs a child process to write to. - explicit Service64ResolverThunk(HANDLE process) - : process_(process), ntdll_base_(NULL) {} - virtual ~Service64ResolverThunk() {} - - // Implementation of Resolver::Setup. - virtual NTSTATUS Setup(const void* target_module, - const void* interceptor_module, - const char* target_name, - const char* interceptor_name, - const void* interceptor_entry_point, - void* thunk_storage, - size_t storage_bytes, - size_t* storage_used); - - // Implementation of Resolver::ResolveInterceptor. - virtual NTSTATUS ResolveInterceptor(const void* module, - const char* function_name, - const void** address); - - // Implementation of Resolver::ResolveTarget. - virtual NTSTATUS ResolveTarget(const void* module, - const char* function_name, - void** address); - - // Implementation of Resolver::GetThunkSize. - virtual size_t GetThunkSize() const; - - protected: - // The unit test will use this member to allow local patch on a buffer. - HMODULE ntdll_base_; - - // Handle of the child process. - HANDLE process_; - - private: - // Returns true if the code pointer by target_ corresponds to the expected - // type of function. Saves that code on the first part of the thunk pointed - // by local_thunk (should be directly accessible from the parent). - virtual bool IsFunctionAService(void* local_thunk) const; - - // Performs the actual patch of target_. - // local_thunk must be already fully initialized, and the first part must - // contain the original code. The real type of this buffer is ServiceFullThunk - // (yes, private). remote_thunk (real type ServiceFullThunk), must be - // allocated on the child, and will contain the thunk data, after this call. - // Returns the apropriate status code. - virtual NTSTATUS PerformPatch(void* local_thunk, void* remote_thunk); - - DISALLOW_COPY_AND_ASSIGN(Service64ResolverThunk); -}; - -} // namespace sandbox - - -#endif // SANDBOX_WOW_HELPER_SERVICE64_RESOLVER_H__ diff --git a/security/sandbox/chromium/sandbox/win/wow_helper/target_code.cc b/security/sandbox/chromium/sandbox/win/wow_helper/target_code.cc deleted file mode 100644 index ce44eeba2..000000000 --- a/security/sandbox/chromium/sandbox/win/wow_helper/target_code.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/wow_helper/target_code.h" - -namespace sandbox { - -// Hooks NtMapViewOfSection to detect the load of dlls. -#pragma code_seg(push, code, ".TargetCode$A") -NTSTATUS WINAPI TargetNtMapViewOfSection( - PatchInfo *patch_info, HANDLE process, PVOID *base, ULONG_PTR zero_bits, - SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size, - SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect) { - NTSTATUS ret = patch_info->orig_MapViewOfSection(patch_info->section, process, - base, zero_bits, commit_size, - offset, view_size, inherit, - allocation_type, protect); - - LARGE_INTEGER timeout; - timeout.QuadPart = -(5 * 10000000); // 5 seconds. - - // The wait is alertable. - patch_info->signal_and_wait(patch_info->dll_load, patch_info->continue_load, - TRUE, &timeout); - - return ret; -} -#pragma code_seg(pop, code) - -// Marks the end of the code to copy to the target process. -#pragma code_seg(push, code, ".TargetCode$B") -NTSTATUS WINAPI TargetEnd() { - return STATUS_SUCCESS; -} -#pragma code_seg(pop, code) - -} // namespace sandbox diff --git a/security/sandbox/chromium/sandbox/win/wow_helper/target_code.h b/security/sandbox/chromium/sandbox/win/wow_helper/target_code.h deleted file mode 100644 index c198a852e..000000000 --- a/security/sandbox/chromium/sandbox/win/wow_helper/target_code.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WOW_HELPER_TARGET_CODE_H__ -#define SANDBOX_WOW_HELPER_TARGET_CODE_H__ - -#include "sandbox/win/src/nt_internals.h" - -namespace sandbox { - -extern "C" { - -// Holds the information needed for the interception of NtMapViewOfSection. -// Changes of this structure must be synchronized with changes of PatchInfo32 -// on sandbox/win/src/wow64.cc. -struct PatchInfo { - HANDLE dll_load; // Event to signal the broker. - HANDLE continue_load; // Event to wait for the broker. - HANDLE section; // First argument of the call. - NtMapViewOfSectionFunction orig_MapViewOfSection; - NtSignalAndWaitForSingleObjectFunction signal_and_wait; - void* patch_location; -}; - -// Interception of NtMapViewOfSection on the child process. -// It should never be called directly. This function provides the means to -// detect dlls being loaded, so we can patch them if needed. -NTSTATUS WINAPI TargetNtMapViewOfSection( - PatchInfo* patch_info, HANDLE process, PVOID* base, ULONG_PTR zero_bits, - SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size, - SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect); - -// Marker of the end of TargetNtMapViewOfSection. -NTSTATUS WINAPI TargetEnd(); - -} // extern "C" - -} // namespace sandbox - -#endif // SANDBOX_WOW_HELPER_TARGET_CODE_H__ diff --git a/security/sandbox/chromium/sandbox/win/wow_helper/wow_helper.cc b/security/sandbox/chromium/sandbox/win/wow_helper/wow_helper.cc deleted file mode 100644 index af76cbc13..000000000 --- a/security/sandbox/chromium/sandbox/win/wow_helper/wow_helper.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Wow_helper.exe is a simple Win32 64-bit executable designed to help to -// sandbox a 32 bit application running on a 64 bit OS. The basic idea is to -// perform a 64 bit interception of the target process and notify the 32-bit -// broker process whenever a DLL is being loaded. This allows the broker to -// setup the interceptions (32-bit) properly on the target. - -#include <windows.h> -#include <stddef.h> - -#include <string> - -#include "sandbox/win/wow_helper/service64_resolver.h" -#include "sandbox/win/wow_helper/target_code.h" - -namespace sandbox { - -// Performs the interception of NtMapViewOfSection on the 64-bit version of -// ntdll.dll. 'thunk' is the buffer on the address space of process 'child', -// that will be used to store the information about the patch. -int PatchNtdll(HANDLE child, void* thunk, size_t thunk_bytes) { - wchar_t* ntdll_name = L"ntdll.dll"; - HMODULE ntdll_base = ::GetModuleHandle(ntdll_name); - if (!ntdll_base) - return 100; - - Service64ResolverThunk resolver(child); - size_t used = resolver.GetThunkSize(); - char* code = reinterpret_cast<char*>(thunk) + used; - NTSTATUS ret = resolver.Setup(ntdll_base, NULL, "NtMapViewOfSection", NULL, - code, thunk, thunk_bytes, NULL); - if (!NT_SUCCESS(ret)) - return 101; - - size_t size = reinterpret_cast<char*>(&TargetEnd) - - reinterpret_cast<char*>(&TargetNtMapViewOfSection); - - if (size + used > thunk_bytes) - return 102; - - SIZE_T written; - if (!::WriteProcessMemory(child, code, &TargetNtMapViewOfSection, size, - &written)) - return 103; - - if (size != written) - return 104; - - return 0; -} - -} // namespace sandbox - -// We must receive two arguments: the process id of the target to intercept and -// the address of a page of memory on that process that will be used for the -// interception. We receive the address because the broker will cleanup the -// patch when the work is performed. -// -// It should be noted that we don't wait until the real work is done; this -// program quits as soon as the 64-bit interception is performed. -int wWinMain(HINSTANCE, HINSTANCE, wchar_t* command_line, int) { - static_assert(sizeof(void*) > sizeof(DWORD), "unsupported 32 bits"); - if (!command_line) - return 1; - - wchar_t* next; - DWORD process_id = wcstoul(command_line, &next, 0); - if (!process_id) - return 2; - - DWORD access = PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE; - HANDLE child = ::OpenProcess(access, FALSE, process_id); - if (!child) - return 3; - - DWORD buffer = wcstoul(next, NULL, 0); - if (!buffer) - return 4; - - void* thunk = reinterpret_cast<void*>(static_cast<ULONG_PTR>(buffer)); - - const size_t kPageSize = 4096; - return sandbox::PatchNtdll(child, thunk, kPageSize); -} |