policy_opcodes_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "sandbox/win/src/policy_engine_opcodes.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include "sandbox/win/src/policy_engine_params.h"
  8. #include "sandbox/win/src/sandbox_nt_types.h"
  9. #include "sandbox/win/src/sandbox_nt_util.h"
  10. #include "sandbox/win/src/sandbox_types.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. namespace sandbox {
  13. const size_t kOpcodeMemory = 1024;
  14. TEST(PolicyEngineTest, ParameterSetTest) {
  15. void* pv1 = reinterpret_cast<void*>(0x477EAA5);
  16. const void* pv2 = reinterpret_cast<void*>(0x987654);
  17. ParameterSet pset1 = ParamPickerMake(pv1);
  18. ParameterSet pset2 = ParamPickerMake(pv2);
  19. // Test that we can store and retrieve a void pointer:
  20. const void* result1 = 0;
  21. uint32_t result2 = 0;
  22. EXPECT_TRUE(pset1.Get(&result1));
  23. EXPECT_TRUE(pv1 == result1);
  24. EXPECT_FALSE(pset1.Get(&result2));
  25. EXPECT_TRUE(pset2.Get(&result1));
  26. EXPECT_TRUE(pv2 == result1);
  27. EXPECT_FALSE(pset2.Get(&result2));
  28. // Test that we can store and retrieve a uint32_t:
  29. uint32_t number = 12747;
  30. ParameterSet pset3 = ParamPickerMake(number);
  31. EXPECT_FALSE(pset3.Get(&result1));
  32. EXPECT_TRUE(pset3.Get(&result2));
  33. EXPECT_EQ(number, result2);
  34. // Test that we can store and retrieve a string:
  35. const wchar_t* txt = L"S231L";
  36. ParameterSet pset4 = ParamPickerMake(txt);
  37. const wchar_t* result3 = nullptr;
  38. EXPECT_TRUE(pset4.Get(&result3));
  39. EXPECT_EQ(0, wcscmp(txt, result3));
  40. }
  41. TEST(PolicyEngineTest, OpcodeConstraints) {
  42. // Test that PolicyOpcode has no virtual functions
  43. // because these objects are copied over to other processes
  44. // so they cannot have vtables.
  45. EXPECT_FALSE(__is_polymorphic(PolicyOpcode));
  46. // Keep developers from adding smarts to the opcodes which should
  47. // be pretty much a bag of bytes with a OO interface.
  48. EXPECT_TRUE(__has_trivial_destructor(PolicyOpcode));
  49. EXPECT_TRUE(__has_trivial_constructor(PolicyOpcode));
  50. EXPECT_TRUE(__has_trivial_copy(PolicyOpcode));
  51. }
  52. TEST(PolicyEngineTest, TrueFalseOpcodes) {
  53. void* dummy = nullptr;
  54. ParameterSet ppb1 = ParamPickerMake(dummy);
  55. char memory[kOpcodeMemory];
  56. OpcodeFactory opcode_maker(memory, sizeof(memory));
  57. // This opcode always evaluates to true.
  58. PolicyOpcode* op1 = opcode_maker.MakeOpAlwaysFalse(kPolNone);
  59. ASSERT_NE(nullptr, op1);
  60. EXPECT_EQ(EVAL_FALSE, op1->Evaluate(&ppb1, 1, nullptr));
  61. EXPECT_FALSE(op1->IsAction());
  62. // This opcode always evaluates to false.
  63. PolicyOpcode* op2 = opcode_maker.MakeOpAlwaysTrue(kPolNone);
  64. ASSERT_NE(nullptr, op2);
  65. EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 1, nullptr));
  66. // Nulls not allowed on the params.
  67. EXPECT_EQ(EVAL_ERROR, op2->Evaluate(nullptr, 0, nullptr));
  68. EXPECT_EQ(EVAL_ERROR, op2->Evaluate(nullptr, 1, nullptr));
  69. // True and False opcodes do not 'require' a number of parameters
  70. EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 0, nullptr));
  71. EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 1, nullptr));
  72. // Test Inverting the logic. Note that inversion is done outside
  73. // any particular opcode evaluation so no need to repeat for all
  74. // opcodes.
  75. PolicyOpcode* op3 = opcode_maker.MakeOpAlwaysFalse(kPolNegateEval);
  76. ASSERT_NE(nullptr, op3);
  77. EXPECT_EQ(EVAL_TRUE, op3->Evaluate(&ppb1, 1, nullptr));
  78. PolicyOpcode* op4 = opcode_maker.MakeOpAlwaysTrue(kPolNegateEval);
  79. ASSERT_NE(nullptr, op4);
  80. EXPECT_EQ(EVAL_FALSE, op4->Evaluate(&ppb1, 1, nullptr));
  81. // Test that we clear the match context
  82. PolicyOpcode* op5 = opcode_maker.MakeOpAlwaysTrue(kPolClearContext);
  83. ASSERT_NE(nullptr, op5);
  84. MatchContext context;
  85. context.position = 1;
  86. context.options = kPolUseOREval;
  87. EXPECT_EQ(EVAL_TRUE, op5->Evaluate(&ppb1, 1, &context));
  88. EXPECT_EQ(0u, context.position);
  89. MatchContext context2;
  90. EXPECT_EQ(context2.options, context.options);
  91. }
  92. TEST(PolicyEngineTest, OpcodeMakerCase1) {
  93. // Testing that the opcode maker does not overrun the
  94. // supplied buffer. It should only be able to make 'count' opcodes.
  95. void* dummy = nullptr;
  96. ParameterSet ppb1 = ParamPickerMake(dummy);
  97. char memory[kOpcodeMemory];
  98. OpcodeFactory opcode_maker(memory, sizeof(memory));
  99. size_t count = sizeof(memory) / sizeof(PolicyOpcode);
  100. for (size_t ix = 0; ix != count; ++ix) {
  101. PolicyOpcode* op = opcode_maker.MakeOpAlwaysFalse(kPolNone);
  102. ASSERT_NE(nullptr, op);
  103. EXPECT_EQ(EVAL_FALSE, op->Evaluate(&ppb1, 1, nullptr));
  104. }
  105. // There should be no room more another opcode:
  106. PolicyOpcode* op1 = opcode_maker.MakeOpAlwaysFalse(kPolNone);
  107. ASSERT_EQ(nullptr, op1);
  108. }
  109. TEST(PolicyEngineTest, OpcodeMakerCase2) {
  110. // Testing that the opcode maker does not overrun the
  111. // supplied buffer. It should only be able to make 'count' opcodes.
  112. // The difference with the previous test is that this opcodes allocate
  113. // the string 'txt2' inside the same buffer.
  114. const wchar_t* txt1 = L"1234";
  115. const wchar_t txt2[] = L"123";
  116. ParameterSet ppb1 = ParamPickerMake(txt1);
  117. MatchContext mc1;
  118. char memory[kOpcodeMemory];
  119. OpcodeFactory opcode_maker(memory, sizeof(memory));
  120. size_t count = sizeof(memory) / (sizeof(PolicyOpcode) + sizeof(txt2));
  121. // Test that it does not overrun the buffer.
  122. for (size_t ix = 0; ix != count; ++ix) {
  123. PolicyOpcode* op = opcode_maker.MakeOpWStringMatch(
  124. 0, txt2, 0, CASE_SENSITIVE, kPolClearContext);
  125. ASSERT_NE(nullptr, op);
  126. EXPECT_EQ(EVAL_TRUE, op->Evaluate(&ppb1, 1, &mc1));
  127. }
  128. // There should be no room more another opcode:
  129. PolicyOpcode* op1 =
  130. opcode_maker.MakeOpWStringMatch(0, txt2, 0, CASE_SENSITIVE, kPolNone);
  131. ASSERT_EQ(nullptr, op1);
  132. }
  133. TEST(PolicyEngineTest, IntegerOpcodes) {
  134. const wchar_t* txt = L"abcdef";
  135. uint32_t num1 = 42;
  136. uint32_t num2 = 113377;
  137. ParameterSet pp_wrong1 = ParamPickerMake(txt);
  138. ParameterSet pp_num1 = ParamPickerMake(num1);
  139. ParameterSet pp_num2 = ParamPickerMake(num2);
  140. char memory[kOpcodeMemory];
  141. OpcodeFactory opcode_maker(memory, sizeof(memory));
  142. // Test basic match for uint32s 42 == 42 and 42 != 113377.
  143. PolicyOpcode* op_m42 = opcode_maker.MakeOpNumberMatch(0, 42UL, kPolNone);
  144. ASSERT_NE(nullptr, op_m42);
  145. EXPECT_EQ(EVAL_TRUE, op_m42->Evaluate(&pp_num1, 1, nullptr));
  146. EXPECT_EQ(EVAL_FALSE, op_m42->Evaluate(&pp_num2, 1, nullptr));
  147. EXPECT_EQ(EVAL_ERROR, op_m42->Evaluate(&pp_wrong1, 1, nullptr));
  148. // Test basic match for void pointers.
  149. const void* vp = nullptr;
  150. ParameterSet pp_num3 = ParamPickerMake(vp);
  151. PolicyOpcode* op_vp_null =
  152. opcode_maker.MakeOpVoidPtrMatch(0, nullptr, kPolNone);
  153. ASSERT_NE(nullptr, op_vp_null);
  154. EXPECT_EQ(EVAL_TRUE, op_vp_null->Evaluate(&pp_num3, 1, nullptr));
  155. EXPECT_EQ(EVAL_FALSE, op_vp_null->Evaluate(&pp_num1, 1, nullptr));
  156. EXPECT_EQ(EVAL_ERROR, op_vp_null->Evaluate(&pp_wrong1, 1, nullptr));
  157. // Basic range test [41 43] (inclusive).
  158. PolicyOpcode* op_range1 =
  159. opcode_maker.MakeOpNumberMatchRange(0, 41, 43, kPolNone);
  160. ASSERT_NE(nullptr, op_range1);
  161. EXPECT_EQ(EVAL_TRUE, op_range1->Evaluate(&pp_num1, 1, nullptr));
  162. EXPECT_EQ(EVAL_FALSE, op_range1->Evaluate(&pp_num2, 1, nullptr));
  163. EXPECT_EQ(EVAL_ERROR, op_range1->Evaluate(&pp_wrong1, 1, nullptr));
  164. }
  165. TEST(PolicyEngineTest, LogicalOpcodes) {
  166. char memory[kOpcodeMemory];
  167. OpcodeFactory opcode_maker(memory, sizeof(memory));
  168. uint32_t num1 = 0x10100702;
  169. ParameterSet pp_num1 = ParamPickerMake(num1);
  170. PolicyOpcode* op_and1 =
  171. opcode_maker.MakeOpNumberAndMatch(0, 0x00100000, kPolNone);
  172. ASSERT_NE(nullptr, op_and1);
  173. EXPECT_EQ(EVAL_TRUE, op_and1->Evaluate(&pp_num1, 1, nullptr));
  174. PolicyOpcode* op_and2 =
  175. opcode_maker.MakeOpNumberAndMatch(0, 0x00000001, kPolNone);
  176. ASSERT_NE(nullptr, op_and2);
  177. EXPECT_EQ(EVAL_FALSE, op_and2->Evaluate(&pp_num1, 1, nullptr));
  178. }
  179. TEST(PolicyEngineTest, WCharOpcodes1) {
  180. const wchar_t* txt1 = L"the quick fox jumps over the lazy dog";
  181. const wchar_t txt2[] = L"the quick";
  182. const wchar_t txt3[] = L" fox jumps";
  183. const wchar_t txt4[] = L"the lazy dog";
  184. const wchar_t txt5[] = L"jumps over";
  185. const wchar_t txt6[] = L"g";
  186. ParameterSet pp_tc1 = ParamPickerMake(txt1);
  187. char memory[kOpcodeMemory];
  188. OpcodeFactory opcode_maker(memory, sizeof(memory));
  189. PolicyOpcode* op1 =
  190. opcode_maker.MakeOpWStringMatch(0, txt2, 0, CASE_SENSITIVE, kPolNone);
  191. ASSERT_NE(nullptr, op1);
  192. // Simplest substring match from pos 0. It should be a successful match
  193. // and the match context should be updated.
  194. MatchContext mc1;
  195. EXPECT_EQ(EVAL_TRUE, op1->Evaluate(&pp_tc1, 1, &mc1));
  196. EXPECT_TRUE(_countof(txt2) == mc1.position + 1);
  197. // Matching again should fail and the context should be unmodified.
  198. EXPECT_EQ(EVAL_FALSE, op1->Evaluate(&pp_tc1, 1, &mc1));
  199. EXPECT_TRUE(_countof(txt2) == mc1.position + 1);
  200. // Using the same match context we should continue where we left
  201. // in the previous successful match,
  202. PolicyOpcode* op3 =
  203. opcode_maker.MakeOpWStringMatch(0, txt3, 0, CASE_SENSITIVE, kPolNone);
  204. ASSERT_NE(nullptr, op3);
  205. EXPECT_EQ(EVAL_TRUE, op3->Evaluate(&pp_tc1, 1, &mc1));
  206. EXPECT_TRUE(_countof(txt3) + _countof(txt2) == mc1.position + 2);
  207. // We now keep on matching but now we skip 6 characters which means
  208. // we skip the string ' over '. And we zero the match context. This is
  209. // the primitive that we use to build '??'.
  210. PolicyOpcode* op4 = opcode_maker.MakeOpWStringMatch(
  211. 0, txt4, 6, CASE_SENSITIVE, kPolClearContext);
  212. ASSERT_NE(nullptr, op4);
  213. EXPECT_EQ(EVAL_TRUE, op4->Evaluate(&pp_tc1, 1, &mc1));
  214. EXPECT_EQ(0u, mc1.position);
  215. // Test that we can properly match the last part of the string
  216. PolicyOpcode* op4b = opcode_maker.MakeOpWStringMatch(
  217. 0, txt4, kSeekToEnd, CASE_SENSITIVE, kPolClearContext);
  218. ASSERT_NE(nullptr, op4b);
  219. EXPECT_EQ(EVAL_TRUE, op4b->Evaluate(&pp_tc1, 1, &mc1));
  220. EXPECT_EQ(0u, mc1.position);
  221. // Test matching 'jumps over' over the entire string. This is the
  222. // primitive we build '*' from.
  223. PolicyOpcode* op5 = opcode_maker.MakeOpWStringMatch(0, txt5, kSeekForward,
  224. CASE_SENSITIVE, kPolNone);
  225. ASSERT_NE(nullptr, op5);
  226. EXPECT_EQ(EVAL_TRUE, op5->Evaluate(&pp_tc1, 1, &mc1));
  227. EXPECT_EQ(24u, mc1.position);
  228. // Test that we don't match because it is not at the end of the string
  229. PolicyOpcode* op5b = opcode_maker.MakeOpWStringMatch(
  230. 0, txt5, kSeekToEnd, CASE_SENSITIVE, kPolNone);
  231. ASSERT_NE(nullptr, op5b);
  232. EXPECT_EQ(EVAL_FALSE, op5b->Evaluate(&pp_tc1, 1, &mc1));
  233. EXPECT_EQ(24u, mc1.position);
  234. // Test that we function if the string does not fit. In this case we
  235. // try to match 'the lazy dog' against 'he lazy dog'.
  236. PolicyOpcode* op6 =
  237. opcode_maker.MakeOpWStringMatch(0, txt4, 2, CASE_SENSITIVE, kPolNone);
  238. ASSERT_NE(nullptr, op6);
  239. EXPECT_EQ(EVAL_FALSE, op6->Evaluate(&pp_tc1, 1, &mc1));
  240. // Testing matching against 'g' which should be the last char.
  241. MatchContext mc2;
  242. PolicyOpcode* op7 = opcode_maker.MakeOpWStringMatch(0, txt6, kSeekForward,
  243. CASE_SENSITIVE, kPolNone);
  244. ASSERT_NE(nullptr, op7);
  245. EXPECT_EQ(EVAL_TRUE, op7->Evaluate(&pp_tc1, 1, &mc2));
  246. EXPECT_EQ(37u, mc2.position);
  247. // Trying to match again should fail since we are in the last char.
  248. // This also covers a couple of boundary conditions.
  249. EXPECT_EQ(EVAL_FALSE, op7->Evaluate(&pp_tc1, 1, &mc2));
  250. EXPECT_EQ(37u, mc2.position);
  251. }
  252. TEST(PolicyEngineTest, WCharOpcodes2) {
  253. const wchar_t* path1 = L"c:\\documents and settings\\Microsoft\\BLAH.txt";
  254. const wchar_t txt1[] = L"Settings\\microsoft";
  255. ParameterSet pp_tc1 = ParamPickerMake(path1);
  256. char memory[kOpcodeMemory];
  257. OpcodeFactory opcode_maker(memory, sizeof(memory));
  258. MatchContext mc1;
  259. // Testing case-insensitive does not buy us much since it this option
  260. // is just passed to the Microsoft API that we use normally, but just for
  261. // coverage, here it is:
  262. PolicyOpcode* op1s = opcode_maker.MakeOpWStringMatch(
  263. 0, txt1, kSeekForward, CASE_SENSITIVE, kPolNone);
  264. ASSERT_NE(nullptr, op1s);
  265. PolicyOpcode* op1i = opcode_maker.MakeOpWStringMatch(
  266. 0, txt1, kSeekForward, CASE_INSENSITIVE, kPolNone);
  267. ASSERT_NE(nullptr, op1i);
  268. EXPECT_EQ(EVAL_FALSE, op1s->Evaluate(&pp_tc1, 1, &mc1));
  269. EXPECT_EQ(EVAL_TRUE, op1i->Evaluate(&pp_tc1, 1, &mc1));
  270. EXPECT_EQ(35u, mc1.position);
  271. }
  272. TEST(PolicyEngineTest, ActionOpcodes) {
  273. char memory[kOpcodeMemory];
  274. OpcodeFactory opcode_maker(memory, sizeof(memory));
  275. MatchContext mc1;
  276. void* dummy = nullptr;
  277. ParameterSet ppb1 = ParamPickerMake(dummy);
  278. PolicyOpcode* op1 = opcode_maker.MakeOpAction(ASK_BROKER, kPolNone);
  279. ASSERT_NE(nullptr, op1);
  280. EXPECT_TRUE(op1->IsAction());
  281. EXPECT_EQ(ASK_BROKER, op1->Evaluate(&ppb1, 1, &mc1));
  282. }
  283. } // namespace sandbox