security/sandbox/win/src/policy_opcodes_unittest.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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.
     5 #include "sandbox/win/src/sandbox_types.h"
     6 #include "sandbox/win/src/sandbox_nt_types.h"
     7 #include "sandbox/win/src/policy_engine_params.h"
     8 #include "sandbox/win/src/policy_engine_opcodes.h"
     9 #include "testing/gtest/include/gtest/gtest.h"
    12 #define INIT_GLOBAL_RTL(member) \
    13   g_nt.##member = reinterpret_cast<##member##Function>( \
    14   ::GetProcAddress(ntdll, #member)); \
    15   if (NULL == g_nt.##member) \
    16   return false
    18 namespace sandbox {
    20 SANDBOX_INTERCEPT NtExports g_nt;
    22 bool SetupNtdllImports() {
    23     HMODULE ntdll = ::GetModuleHandle(kNtdllName);
    25     INIT_GLOBAL_RTL(RtlAllocateHeap);
    26     INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString);
    27     INIT_GLOBAL_RTL(RtlCompareUnicodeString);
    28     INIT_GLOBAL_RTL(RtlCreateHeap);
    29     INIT_GLOBAL_RTL(RtlDestroyHeap);
    30     INIT_GLOBAL_RTL(RtlFreeHeap);
    31     INIT_GLOBAL_RTL(_strnicmp);
    32     INIT_GLOBAL_RTL(strlen);
    33     INIT_GLOBAL_RTL(wcslen);
    35   return true;
    36 }
    38 TEST(PolicyEngineTest, ParameterSetTest) {
    39   void* pv1 = reinterpret_cast<void*>(0x477EAA5);
    40   const void* pv2 = reinterpret_cast<void*>(0x987654);
    41   ParameterSet pset1 = ParamPickerMake(pv1);
    42   ParameterSet pset2 = ParamPickerMake(pv2);
    44   // Test that we can store and retrieve a void pointer:
    45   const void* result1 =0;
    46   unsigned long result2 = 0;
    47   EXPECT_TRUE(pset1.Get(&result1));
    48   EXPECT_TRUE(pv1 == result1);
    49   EXPECT_FALSE(pset1.Get(&result2));
    50   EXPECT_TRUE(pset2.Get(&result1));
    51   EXPECT_TRUE(pv2 == result1);
    52   EXPECT_FALSE(pset2.Get(&result2));
    54   // Test that we can store and retrieve a ulong:
    55   unsigned long number = 12747;
    56   ParameterSet pset3 = ParamPickerMake(number);
    57   EXPECT_FALSE(pset3.Get(&result1));
    58   EXPECT_TRUE(pset3.Get(&result2));
    59   EXPECT_EQ(number, result2);
    61   // Test that we can store and retrieve a string:
    62   const wchar_t* txt = L"S231L";
    63   ParameterSet pset4 = ParamPickerMake(txt);
    64   const wchar_t* result3 = NULL;
    65   EXPECT_TRUE(pset4.Get(&result3));
    66   EXPECT_EQ(0, wcscmp(txt, result3));
    67 }
    69 TEST(PolicyEngineTest, OpcodeConstraints) {
    70   // Test that PolicyOpcode has no virtual functions
    71   // because these objects are copied over to other processes
    72   // so they cannot have vtables.
    73   EXPECT_FALSE(__is_polymorphic(PolicyOpcode));
    74   // Keep developers from adding smarts to the opcodes which should
    75   // be pretty much a bag of bytes with a OO interface.
    76   EXPECT_TRUE(__has_trivial_destructor(PolicyOpcode));
    77   EXPECT_TRUE(__has_trivial_constructor(PolicyOpcode));
    78   EXPECT_TRUE(__has_trivial_copy(PolicyOpcode));
    79 }
    81 TEST(PolicyEngineTest, TrueFalseOpcodes) {
    82   void* dummy = NULL;
    83   ParameterSet ppb1 = ParamPickerMake(dummy);
    84   char memory[1024];
    85   OpcodeFactory opcode_maker(memory, sizeof(memory));
    87   // This opcode always evaluates to true.
    88   PolicyOpcode* op1 = opcode_maker.MakeOpAlwaysFalse(kPolNone);
    89   EXPECT_EQ(EVAL_FALSE, op1->Evaluate(&ppb1, 1, NULL));
    90   EXPECT_FALSE(op1->IsAction());
    92   // This opcode always evaluates to false.
    93   PolicyOpcode* op2 = opcode_maker.MakeOpAlwaysTrue(kPolNone);
    94   EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 1, NULL));
    96   // Nulls not allowed on the params.
    97   EXPECT_EQ(EVAL_ERROR, op2->Evaluate(NULL, 0, NULL));
    98   EXPECT_EQ(EVAL_ERROR, op2->Evaluate(NULL, 1, NULL));
   100   // True and False opcodes do not 'require' a number of parameters
   101   EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 0, NULL));
   102   EXPECT_EQ(EVAL_TRUE, op2->Evaluate(&ppb1, 1, NULL));
   104   // Test Inverting the logic. Note that inversion is done outside
   105   // any particular opcode evaluation so no need to repeat for all
   106   // opcodes.
   107   PolicyOpcode* op3 = opcode_maker.MakeOpAlwaysFalse(kPolNegateEval);
   108   EXPECT_EQ(EVAL_TRUE, op3->Evaluate(&ppb1, 1, NULL));
   109   PolicyOpcode* op4 = opcode_maker.MakeOpAlwaysTrue(kPolNegateEval);
   110   EXPECT_EQ(EVAL_FALSE, op4->Evaluate(&ppb1, 1, NULL));
   112   // Test that we clear the match context
   113   PolicyOpcode* op5 = opcode_maker.MakeOpAlwaysTrue(kPolClearContext);
   114   MatchContext context;
   115   context.position = 1;
   116   context.options = kPolUseOREval;
   117   EXPECT_EQ(EVAL_TRUE, op5->Evaluate(&ppb1, 1, &context));
   118   EXPECT_EQ(0, context.position);
   119   MatchContext context2;
   120   EXPECT_EQ(context2.options, context.options);
   121 }
   123 TEST(PolicyEngineTest, OpcodeMakerCase1) {
   124   // Testing that the opcode maker does not overrun the
   125   // supplied buffer. It should only be able to make 'count' opcodes.
   126   void* dummy = NULL;
   127   ParameterSet ppb1 = ParamPickerMake(dummy);
   129   char memory[256];
   130   OpcodeFactory opcode_maker(memory, sizeof(memory));
   131   size_t count = sizeof(memory) / sizeof(PolicyOpcode);
   133   for (size_t ix =0; ix != count; ++ix) {
   134      PolicyOpcode* op = opcode_maker.MakeOpAlwaysFalse(kPolNone);
   135      ASSERT_TRUE(NULL != op);
   136      EXPECT_EQ(EVAL_FALSE, op->Evaluate(&ppb1, 1, NULL));
   137   }
   138   // There should be no room more another opcode:
   139   PolicyOpcode* op1 = opcode_maker.MakeOpAlwaysFalse(kPolNone);
   140   ASSERT_TRUE(NULL == op1);
   141 }
   143 TEST(PolicyEngineTest, OpcodeMakerCase2) {
   144   SetupNtdllImports();
   145   // Testing that the opcode maker does not overrun the
   146   // supplied buffer. It should only be able to make 'count' opcodes.
   147   // The difference with the previous test is that this opcodes allocate
   148   // the string 'txt2' inside the same buffer.
   149   const wchar_t* txt1 = L"1234";
   150   const wchar_t txt2[] = L"123";
   152   ParameterSet ppb1 = ParamPickerMake(txt1);
   153   MatchContext mc1;
   155   char memory[256];
   156   OpcodeFactory opcode_maker(memory, sizeof(memory));
   157   size_t count = sizeof(memory) / (sizeof(PolicyOpcode) + sizeof(txt2));
   159   // Test that it does not overrun the buffer.
   160   for (size_t ix =0; ix != count; ++ix) {
   161     PolicyOpcode* op = opcode_maker.MakeOpWStringMatch(0, txt2, 0,
   162                                                        CASE_SENSITIVE,
   163                                                        kPolClearContext);
   164     ASSERT_TRUE(NULL != op);
   165     EXPECT_EQ(EVAL_TRUE, op->Evaluate(&ppb1, 1, &mc1));
   166   }
   168   // There should be no room more another opcode:
   169   PolicyOpcode* op1 = opcode_maker.MakeOpWStringMatch(0, txt2, 0,
   170                                                       CASE_SENSITIVE,
   171                                                       kPolNone);
   172   ASSERT_TRUE(NULL == op1);
   173 }
   175 TEST(PolicyEngineTest, IntegerOpcodes) {
   176   const wchar_t* txt = L"abcdef";
   177   unsigned long num1 = 42;
   178   unsigned long num2 = 113377;
   180   ParameterSet pp_wrong1 = ParamPickerMake(txt);
   181   ParameterSet pp_num1 = ParamPickerMake(num1);
   182   ParameterSet pp_num2 = ParamPickerMake(num2);
   184   char memory[128];
   185   OpcodeFactory opcode_maker(memory, sizeof(memory));
   187   // Test basic match for unsigned longs 42 == 42 and 42 != 113377.
   188   PolicyOpcode* op_m42 = opcode_maker.MakeOpNumberMatch(0, unsigned long(42),
   189                                                         kPolNone);
   190   EXPECT_EQ(EVAL_TRUE, op_m42->Evaluate(&pp_num1, 1, NULL));
   191   EXPECT_EQ(EVAL_FALSE, op_m42->Evaluate(&pp_num2, 1, NULL));
   192   EXPECT_EQ(EVAL_ERROR, op_m42->Evaluate(&pp_wrong1, 1, NULL));
   194   // Test basic match for void pointers.
   195   const void* vp = NULL;
   196   ParameterSet pp_num3 = ParamPickerMake(vp);
   197   PolicyOpcode* op_vp_null = opcode_maker.MakeOpVoidPtrMatch(0, NULL,
   198                                                              kPolNone);
   199   EXPECT_EQ(EVAL_TRUE, op_vp_null->Evaluate(&pp_num3, 1, NULL));
   200   EXPECT_EQ(EVAL_FALSE, op_vp_null->Evaluate(&pp_num1, 1, NULL));
   201   EXPECT_EQ(EVAL_ERROR, op_vp_null->Evaluate(&pp_wrong1, 1, NULL));
   203   // Basic range test [41 43] (inclusive).
   204   PolicyOpcode* op_range1 = opcode_maker.MakeOpUlongMatchRange(0, 41, 43,
   205                                                                kPolNone);
   206   EXPECT_EQ(EVAL_TRUE, op_range1->Evaluate(&pp_num1, 1, NULL));
   207   EXPECT_EQ(EVAL_FALSE, op_range1->Evaluate(&pp_num2, 1, NULL));
   208   EXPECT_EQ(EVAL_ERROR, op_range1->Evaluate(&pp_wrong1, 1, NULL));
   209 }
   211 TEST(PolicyEngineTest, LogicalOpcodes) {
   212   char memory[128];
   213   OpcodeFactory opcode_maker(memory, sizeof(memory));
   215   unsigned long num1 = 0x10100702;
   216   ParameterSet pp_num1 = ParamPickerMake(num1);
   218   PolicyOpcode* op_and1 = opcode_maker.MakeOpUlongAndMatch(0, 0x00100000,
   219                                                            kPolNone);
   220   EXPECT_EQ(EVAL_TRUE, op_and1->Evaluate(&pp_num1, 1, NULL));
   221   PolicyOpcode* op_and2 = opcode_maker.MakeOpUlongAndMatch(0, 0x00000001,
   222                                                            kPolNone);
   223   EXPECT_EQ(EVAL_FALSE, op_and2->Evaluate(&pp_num1, 1, NULL));
   224 }
   226 TEST(PolicyEngineTest, WCharOpcodes1) {
   227   SetupNtdllImports();
   229   const wchar_t* txt1 = L"the quick fox jumps over the lazy dog";
   230   const wchar_t txt2[] = L"the quick";
   231   const wchar_t txt3[] = L" fox jumps";
   232   const wchar_t txt4[] = L"the lazy dog";
   233   const wchar_t txt5[] = L"jumps over";
   234   const wchar_t txt6[] = L"g";
   236   ParameterSet pp_tc1 = ParamPickerMake(txt1);
   237   char memory[512];
   238   OpcodeFactory opcode_maker(memory, sizeof(memory));
   240   PolicyOpcode* op1 = opcode_maker.MakeOpWStringMatch(0, txt2, 0,
   241                                                       CASE_SENSITIVE,
   242                                                       kPolNone);
   244   // Simplest substring match from pos 0. It should be a successful match
   245   // and the match context should be updated.
   246   MatchContext mc1;
   247   EXPECT_EQ(EVAL_TRUE, op1->Evaluate(&pp_tc1, 1, &mc1));
   248   EXPECT_TRUE(_countof(txt2) == mc1.position + 1);
   250   // Matching again should fail and the context should be unmodified.
   251   EXPECT_EQ(EVAL_FALSE, op1->Evaluate(&pp_tc1, 1, &mc1));
   252   EXPECT_TRUE(_countof(txt2) == mc1.position + 1);
   254   // Using the same match context we should continue where we left
   255   // in the previous successful match,
   256   PolicyOpcode* op3 = opcode_maker.MakeOpWStringMatch(0, txt3, 0,
   257                                                       CASE_SENSITIVE,
   258                                                       kPolNone);
   259   EXPECT_EQ(EVAL_TRUE, op3->Evaluate(&pp_tc1, 1, &mc1));
   260   EXPECT_TRUE(_countof(txt3) + _countof(txt2) == mc1.position + 2);
   262   // We now keep on matching but now we skip 6 characters which means
   263   // we skip the string ' over '. And we zero the match context. This is
   264   // the primitive that we use to build '??'.
   265   PolicyOpcode* op4 = opcode_maker.MakeOpWStringMatch(0, txt4, 6,
   266                                                       CASE_SENSITIVE,
   267                                                       kPolClearContext);
   268   EXPECT_EQ(EVAL_TRUE, op4->Evaluate(&pp_tc1, 1, &mc1));
   269   EXPECT_EQ(0, mc1.position);
   271   // Test that we can properly match the last part of the string
   272   PolicyOpcode* op4b = opcode_maker.MakeOpWStringMatch(0, txt4, kSeekToEnd,
   273                                                        CASE_SENSITIVE,
   274                                                        kPolClearContext);
   275   EXPECT_EQ(EVAL_TRUE, op4b->Evaluate(&pp_tc1, 1, &mc1));
   276   EXPECT_EQ(0, mc1.position);
   278   // Test matching 'jumps over' over the entire string. This is the
   279   // primitive we build '*' from.
   280   PolicyOpcode* op5 = opcode_maker.MakeOpWStringMatch(0, txt5, kSeekForward,
   281                                                       CASE_SENSITIVE, kPolNone);
   282   EXPECT_EQ(EVAL_TRUE, op5->Evaluate(&pp_tc1, 1, &mc1));
   283   EXPECT_EQ(24, mc1.position);
   285   // Test that we don't match because it is not at the end of the string
   286   PolicyOpcode* op5b = opcode_maker.MakeOpWStringMatch(0, txt5, kSeekToEnd,
   287                                                        CASE_SENSITIVE,
   288                                                        kPolNone);
   289   EXPECT_EQ(EVAL_FALSE, op5b->Evaluate(&pp_tc1, 1, &mc1));
   291   // Test that we function if the string does not fit. In this case we
   292   // try to match 'the lazy dog' against 'he lazy dog'.
   293   PolicyOpcode* op6 = opcode_maker.MakeOpWStringMatch(0, txt4, 2,
   294                                                       CASE_SENSITIVE, kPolNone);
   295   EXPECT_EQ(24, mc1.position);
   297   // Testing matching against 'g' which should be the last char.
   298   MatchContext mc2;
   299   PolicyOpcode* op7 = opcode_maker.MakeOpWStringMatch(0, txt6, kSeekForward,
   300                                                       CASE_SENSITIVE, kPolNone);
   301   EXPECT_EQ(EVAL_TRUE, op7->Evaluate(&pp_tc1, 1, &mc2));
   303   // Trying to match again should fail since we are in the last char.
   304   // This also covers a couple of boundary conditions.
   305   EXPECT_EQ(EVAL_FALSE, op7->Evaluate(&pp_tc1, 1, &mc2));
   306 }
   308 TEST(PolicyEngineTest, WCharOpcodes2) {
   309   SetupNtdllImports();
   311   const wchar_t* path1 = L"c:\\documents and settings\\Microsoft\\BLAH.txt";
   312   const wchar_t txt1[] = L"Settings\\microsoft";
   313   ParameterSet pp_tc1 = ParamPickerMake(path1);
   315   char memory[256];
   316   OpcodeFactory opcode_maker(memory, sizeof(memory));
   317   MatchContext mc1;
   319   // Testing case-insensitive does not buy us much since it this option
   320   // is just passed to the Microsoft API that we use normally, but just for
   321   // coverage, here it is:
   322   PolicyOpcode* op1s = opcode_maker.MakeOpWStringMatch(0, txt1, kSeekForward,
   323                                                       CASE_SENSITIVE, kPolNone);
   324   PolicyOpcode* op1i = opcode_maker.MakeOpWStringMatch(0, txt1, kSeekForward,
   325                                                        CASE_INSENSITIVE,
   326                                                        kPolNone);
   327   EXPECT_EQ(EVAL_FALSE, op1s->Evaluate(&pp_tc1, 1, &mc1));
   328   EXPECT_EQ(EVAL_TRUE, op1i->Evaluate(&pp_tc1, 1, &mc1));
   329   EXPECT_EQ(35, mc1.position);
   330 }
   332 TEST(PolicyEngineTest, ActionOpcodes) {
   333   char memory[256];
   334   OpcodeFactory opcode_maker(memory, sizeof(memory));
   335   MatchContext mc1;
   336   void* dummy = NULL;
   337   ParameterSet ppb1 = ParamPickerMake(dummy);
   339   PolicyOpcode* op1 = opcode_maker.MakeOpAction(ASK_BROKER, kPolNone);
   340   EXPECT_TRUE(op1->IsAction());
   341   EXPECT_EQ(ASK_BROKER, op1->Evaluate(&ppb1, 1, &mc1));
   342 }
   344 }  // namespace sandbox

mercurial