// 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 "base/basictypes.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(unsigned long* destination) const { if (ULONG_TYPE != real_type_) { return false; } *destination = Void2TypePointerCopy<unsigned long>(); return true; } // Retrieve the stored parameter. If the type does not match void* fail. bool Get(const void** destination) const { if (VOIDPTR_TYPE != real_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 (WCHAR_TYPE != real_type_) { return false; } *destination = Void2TypePointerCopy<const wchar_t*>(); return true; } // False if the parameter is not properly initialized. bool IsValid() const { return INVALID_TYPE != real_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<unsigned long> : public ParameterSet { public: ParameterSetEx(const void* address) : ParameterSet(ULONG_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__