Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2014 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 
      5 #include "base/win/windows_version.h"
      6 #include "sandbox/win/src/handle_closer.h"
      7 #include "sandbox/win/src/sandbox.h"
      8 #include "sandbox/win/src/sandbox_policy.h"
      9 #include "sandbox/win/src/sandbox_factory.h"
     10 #include "sandbox/win/tests/common/controller.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 namespace sandbox {
     14 
     15 
     16 SBOX_TESTS_COMMAND int NamedPipe_Create(int argc, wchar_t **argv) {
     17   if (argc < 1 || argc > 2) {
     18     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
     19   }
     20   if ((NULL == argv) || (NULL == argv[0])) {
     21     return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
     22   }
     23 
     24   HANDLE pipe = ::CreateNamedPipeW(argv[0],
     25                                    PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
     26                                    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, 4096,
     27                                    4096, 2000, NULL);
     28   if (INVALID_HANDLE_VALUE == pipe)
     29     return SBOX_TEST_DENIED;
     30 
     31   // The second parameter allows us to enforce a whitelist for where the
     32   // pipe should be in the object namespace after creation.
     33   if (argc == 2) {
     34     base::string16 handle_name;
     35     if (GetHandleName(pipe, &handle_name)) {
     36       if (handle_name.compare(0, wcslen(argv[1]), argv[1]) != 0)
     37         return SBOX_TEST_FAILED;
     38     } else {
     39       return SBOX_TEST_FAILED;
     40     }
     41   }
     42 
     43   OVERLAPPED overlapped = {0};
     44   overlapped.hEvent = ::CreateEvent(NULL, TRUE, TRUE, NULL);
     45   BOOL result = ::ConnectNamedPipe(pipe, &overlapped);
     46 
     47   if (!result) {
     48     DWORD error = ::GetLastError();
     49     if (ERROR_PIPE_CONNECTED != error &&
     50         ERROR_IO_PENDING != error) {
     51           return SBOX_TEST_FAILED;
     52     }
     53   }
     54 
     55   if (!::CloseHandle(pipe))
     56     return SBOX_TEST_FAILED;
     57 
     58   ::CloseHandle(overlapped.hEvent);
     59   return SBOX_TEST_SUCCEEDED;
     60 }
     61 
     62 // Tests if we can create a pipe in the sandbox.
     63 TEST(NamedPipePolicyTest, CreatePipe) {
     64   TestRunner runner;
     65   // TODO(nsylvain): This policy is wrong because "*" is a valid char in a
     66   // namedpipe name. Here we apply it like a wildcard. http://b/893603
     67   EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
     68                              TargetPolicy::NAMEDPIPES_ALLOW_ANY,
     69                              L"\\\\.\\pipe\\test*"));
     70 
     71   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
     72             runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
     73 
     74   // On XP, the sandbox can create a pipe without any help but it fails on
     75   // Vista+, this is why we do not test the "denied" case.
     76   if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
     77     EXPECT_EQ(SBOX_TEST_DENIED,
     78               runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
     79   }
     80 }
     81 
     82 // Tests if we can create a pipe with a path traversal in the sandbox.
     83 TEST(NamedPipePolicyTest, CreatePipeTraversal) {
     84   TestRunner runner;
     85   // TODO(nsylvain): This policy is wrong because "*" is a valid char in a
     86   // namedpipe name. Here we apply it like a wildcard. http://b/893603
     87   EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
     88                              TargetPolicy::NAMEDPIPES_ALLOW_ANY,
     89                               L"\\\\.\\pipe\\test*"));
     90 
     91   // On XP, the sandbox can create a pipe without any help but it fails on
     92   // Vista+, this is why we do not test the "denied" case.
     93   if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
     94     EXPECT_EQ(SBOX_TEST_DENIED,
     95               runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\..\\bleh"));
     96     EXPECT_EQ(SBOX_TEST_DENIED,
     97               runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/../bleh"));
     98     EXPECT_EQ(SBOX_TEST_DENIED,
     99               runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\../bleh"));
    100     EXPECT_EQ(SBOX_TEST_DENIED,
    101               runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/..\\bleh"));
    102   }
    103 }
    104 
    105 // This tests that path canonicalization is actually disabled if we use \\?\
    106 // syntax.
    107 TEST(NamedPipePolicyTest, CreatePipeCanonicalization) {
    108   // "For file I/O, the "\\?\" prefix to a path string tells the Windows APIs to
    109   // disable all string parsing and to send the string that follows it straight
    110   // to the file system."
    111   // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
    112   wchar_t* argv[2] = { L"\\\\?\\pipe\\test\\..\\bleh",
    113                        L"\\Device\\NamedPipe\\test" };
    114   EXPECT_EQ(SBOX_TEST_SUCCEEDED, NamedPipe_Create(2, argv));
    115 }
    116 
    117 // The same test as CreatePipe but this time using strict interceptions.
    118 TEST(NamedPipePolicyTest, CreatePipeStrictInterceptions) {
    119   TestRunner runner;
    120   runner.GetPolicy()->SetStrictInterceptions();
    121 
    122   // TODO(nsylvain): This policy is wrong because "*" is a valid char in a
    123   // namedpipe name. Here we apply it like a wildcard. http://b/893603
    124   EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
    125                              TargetPolicy::NAMEDPIPES_ALLOW_ANY,
    126                               L"\\\\.\\pipe\\test*"));
    127 
    128   EXPECT_EQ(SBOX_TEST_SUCCEEDED,
    129             runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
    130 
    131   // On XP, the sandbox can create a pipe without any help but it fails on
    132   // Vista+, this is why we do not test the "denied" case.
    133   if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
    134     EXPECT_EQ(SBOX_TEST_DENIED,
    135               runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
    136   }
    137 }
    138 
    139 }  // namespace sandbox
    140