Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | #ifndef SANDBOX_SRC_POLICY_ENGINE_PARAMS_H__ |
michael@0 | 6 | #define SANDBOX_SRC_POLICY_ENGINE_PARAMS_H__ |
michael@0 | 7 | |
michael@0 | 8 | #include "base/basictypes.h" |
michael@0 | 9 | #include "sandbox/win/src/internal_types.h" |
michael@0 | 10 | #include "sandbox/win/src/nt_internals.h" |
michael@0 | 11 | #include "sandbox/win/src/sandbox_nt_util.h" |
michael@0 | 12 | |
michael@0 | 13 | // This header defines the classes that allow the low level policy to select |
michael@0 | 14 | // the input parameters. In order to better make sense of this header is |
michael@0 | 15 | // recommended that you check policy_engine_opcodes.h first. |
michael@0 | 16 | |
michael@0 | 17 | namespace sandbox { |
michael@0 | 18 | |
michael@0 | 19 | // Models the set of interesting parameters of an intercepted system call |
michael@0 | 20 | // normally you don't create objects of this class directly, instead you |
michael@0 | 21 | // use the POLPARAMS_XXX macros. |
michael@0 | 22 | // For example, if an intercepted function has the following signature: |
michael@0 | 23 | // |
michael@0 | 24 | // NTSTATUS NtOpenFileFunction (PHANDLE FileHandle, |
michael@0 | 25 | // ACCESS_MASK DesiredAccess, |
michael@0 | 26 | // POBJECT_ATTRIBUTES ObjectAttributes, |
michael@0 | 27 | // PIO_STATUS_BLOCK IoStatusBlock, |
michael@0 | 28 | // ULONG ShareAccess, |
michael@0 | 29 | // ULONG OpenOptions); |
michael@0 | 30 | // |
michael@0 | 31 | // You could say that the following parameters are of interest to policy: |
michael@0 | 32 | // |
michael@0 | 33 | // POLPARAMS_BEGIN(open_params) |
michael@0 | 34 | // POLPARAM(DESIRED_ACCESS) |
michael@0 | 35 | // POLPARAM(OBJECT_NAME) |
michael@0 | 36 | // POLPARAM(SECURITY_DESCRIPTOR) |
michael@0 | 37 | // POLPARAM(IO_STATUS) |
michael@0 | 38 | // POLPARAM(OPEN_OPTIONS) |
michael@0 | 39 | // POLPARAMS_END; |
michael@0 | 40 | // |
michael@0 | 41 | // and the actual code will use this for defining the parameters: |
michael@0 | 42 | // |
michael@0 | 43 | // CountedParameterSet<open_params> p; |
michael@0 | 44 | // p[open_params::DESIRED_ACCESS] = ParamPickerMake(DesiredAccess); |
michael@0 | 45 | // p[open_params::OBJECT_NAME] = |
michael@0 | 46 | // ParamPickerMake(ObjectAttributes->ObjectName); |
michael@0 | 47 | // p[open_params::SECURITY_DESCRIPTOR] = |
michael@0 | 48 | // ParamPickerMake(ObjectAttributes->SecurityDescriptor); |
michael@0 | 49 | // p[open_params::IO_STATUS] = ParamPickerMake(IoStatusBlock); |
michael@0 | 50 | // p[open_params::OPEN_OPTIONS] = ParamPickerMake(OpenOptions); |
michael@0 | 51 | // |
michael@0 | 52 | // These will create an stack-allocated array of ParameterSet objects which |
michael@0 | 53 | // have each 1) the address of the parameter 2) a numeric id that encodes the |
michael@0 | 54 | // original C++ type. This allows the policy to treat any set of supported |
michael@0 | 55 | // argument types uniformily and with some type safety. |
michael@0 | 56 | // |
michael@0 | 57 | // TODO(cpu): support not fully implemented yet for unicode string and will |
michael@0 | 58 | // probably add other types as well. |
michael@0 | 59 | class ParameterSet { |
michael@0 | 60 | public: |
michael@0 | 61 | ParameterSet() : real_type_(INVALID_TYPE), address_(NULL) {} |
michael@0 | 62 | |
michael@0 | 63 | // Retrieve the stored parameter. If the type does not match ulong fail. |
michael@0 | 64 | bool Get(unsigned long* destination) const { |
michael@0 | 65 | if (ULONG_TYPE != real_type_) { |
michael@0 | 66 | return false; |
michael@0 | 67 | } |
michael@0 | 68 | *destination = Void2TypePointerCopy<unsigned long>(); |
michael@0 | 69 | return true; |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | // Retrieve the stored parameter. If the type does not match void* fail. |
michael@0 | 73 | bool Get(const void** destination) const { |
michael@0 | 74 | if (VOIDPTR_TYPE != real_type_) { |
michael@0 | 75 | return false; |
michael@0 | 76 | } |
michael@0 | 77 | *destination = Void2TypePointerCopy<void*>(); |
michael@0 | 78 | return true; |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | // Retrieve the stored parameter. If the type does not match wchar_t* fail. |
michael@0 | 82 | bool Get(const wchar_t** destination) const { |
michael@0 | 83 | if (WCHAR_TYPE != real_type_) { |
michael@0 | 84 | return false; |
michael@0 | 85 | } |
michael@0 | 86 | *destination = Void2TypePointerCopy<const wchar_t*>(); |
michael@0 | 87 | return true; |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | // False if the parameter is not properly initialized. |
michael@0 | 91 | bool IsValid() const { |
michael@0 | 92 | return INVALID_TYPE != real_type_; |
michael@0 | 93 | } |
michael@0 | 94 | |
michael@0 | 95 | protected: |
michael@0 | 96 | // The constructor can only be called by derived types, which should |
michael@0 | 97 | // safely provide the real_type and the address of the argument. |
michael@0 | 98 | ParameterSet(ArgType real_type, const void* address) |
michael@0 | 99 | : real_type_(real_type), address_(address) { |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | private: |
michael@0 | 103 | // This template provides the same functionality as bits_cast but |
michael@0 | 104 | // it works with pointer while the former works only with references. |
michael@0 | 105 | template <typename T> |
michael@0 | 106 | T Void2TypePointerCopy() const { |
michael@0 | 107 | return *(reinterpret_cast<const T*>(address_)); |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | ArgType real_type_; |
michael@0 | 111 | const void* address_; |
michael@0 | 112 | }; |
michael@0 | 113 | |
michael@0 | 114 | // To safely infer the type, we use a set of template specializations |
michael@0 | 115 | // in ParameterSetEx with a template function ParamPickerMake to do the |
michael@0 | 116 | // parameter type deduction. |
michael@0 | 117 | |
michael@0 | 118 | // Base template class. Not implemented so using unsupported types should |
michael@0 | 119 | // fail to compile. |
michael@0 | 120 | template <typename T> |
michael@0 | 121 | class ParameterSetEx : public ParameterSet { |
michael@0 | 122 | public: |
michael@0 | 123 | ParameterSetEx(const void* address); |
michael@0 | 124 | }; |
michael@0 | 125 | |
michael@0 | 126 | template<> |
michael@0 | 127 | class ParameterSetEx<void const*> : public ParameterSet { |
michael@0 | 128 | public: |
michael@0 | 129 | ParameterSetEx(const void* address) |
michael@0 | 130 | : ParameterSet(VOIDPTR_TYPE, address) {} |
michael@0 | 131 | }; |
michael@0 | 132 | |
michael@0 | 133 | template<> |
michael@0 | 134 | class ParameterSetEx<void*> : public ParameterSet { |
michael@0 | 135 | public: |
michael@0 | 136 | ParameterSetEx(const void* address) |
michael@0 | 137 | : ParameterSet(VOIDPTR_TYPE, address) {} |
michael@0 | 138 | }; |
michael@0 | 139 | |
michael@0 | 140 | |
michael@0 | 141 | template<> |
michael@0 | 142 | class ParameterSetEx<wchar_t*> : public ParameterSet { |
michael@0 | 143 | public: |
michael@0 | 144 | ParameterSetEx(const void* address) |
michael@0 | 145 | : ParameterSet(WCHAR_TYPE, address) {} |
michael@0 | 146 | }; |
michael@0 | 147 | |
michael@0 | 148 | template<> |
michael@0 | 149 | class ParameterSetEx<wchar_t const*> : public ParameterSet { |
michael@0 | 150 | public: |
michael@0 | 151 | ParameterSetEx(const void* address) |
michael@0 | 152 | : ParameterSet(WCHAR_TYPE, address) {} |
michael@0 | 153 | }; |
michael@0 | 154 | |
michael@0 | 155 | |
michael@0 | 156 | template<> |
michael@0 | 157 | class ParameterSetEx<unsigned long> : public ParameterSet { |
michael@0 | 158 | public: |
michael@0 | 159 | ParameterSetEx(const void* address) |
michael@0 | 160 | : ParameterSet(ULONG_TYPE, address) {} |
michael@0 | 161 | }; |
michael@0 | 162 | |
michael@0 | 163 | template<> |
michael@0 | 164 | class ParameterSetEx<UNICODE_STRING> : public ParameterSet { |
michael@0 | 165 | public: |
michael@0 | 166 | ParameterSetEx(const void* address) |
michael@0 | 167 | : ParameterSet(UNISTR_TYPE, address) {} |
michael@0 | 168 | }; |
michael@0 | 169 | |
michael@0 | 170 | template <typename T> |
michael@0 | 171 | ParameterSet ParamPickerMake(T& parameter) { |
michael@0 | 172 | return ParameterSetEx<T>(¶meter); |
michael@0 | 173 | }; |
michael@0 | 174 | |
michael@0 | 175 | struct CountedParameterSetBase { |
michael@0 | 176 | int count; |
michael@0 | 177 | ParameterSet parameters[1]; |
michael@0 | 178 | }; |
michael@0 | 179 | |
michael@0 | 180 | // This template defines the actual list of policy parameters for a given |
michael@0 | 181 | // interception. |
michael@0 | 182 | // Warning: This template stores the address to the actual variables, in |
michael@0 | 183 | // other words, the values are not copied. |
michael@0 | 184 | template <typename T> |
michael@0 | 185 | struct CountedParameterSet { |
michael@0 | 186 | CountedParameterSet() : count(T::PolParamLast) {} |
michael@0 | 187 | |
michael@0 | 188 | ParameterSet& operator[](typename T::Args n) { |
michael@0 | 189 | return parameters[n]; |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | CountedParameterSetBase* GetBase() { |
michael@0 | 193 | return reinterpret_cast<CountedParameterSetBase*>(this); |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | int count; |
michael@0 | 197 | ParameterSet parameters[T::PolParamLast]; |
michael@0 | 198 | }; |
michael@0 | 199 | |
michael@0 | 200 | } // namespace sandbox |
michael@0 | 201 | |
michael@0 | 202 | #endif // SANDBOX_SRC_POLICY_ENGINE_PARAMS_H__ |