Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1013)

Side by Side Diff: base/memory/shared_memory_win_unittest.cc

Issue 1677163003: base: Create file mappings with reduced access control permissions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments from mark. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/memory/shared_memory_win.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 <windows.h>
6 #include <sddl.h>
7
8 #include "base/command_line.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/memory/shared_memory.h"
11 #include "base/process/process.h"
12 #include "base/rand_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/test/multiprocess_test.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/win/scoped_handle.h"
18 #include "testing/multiprocess_func_list.h"
19
20 namespace base {
21 namespace {
22 const char* kHandleSwitchName = "shared_memory_win_test_switch";
23
24 // Creates a process token with a low integrity SID.
25 win::ScopedHandle CreateLowIntegritySID() {
26 HANDLE process_token_raw = nullptr;
27 BOOL success = ::OpenProcessToken(GetCurrentProcess(),
28 TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT |
29 TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY,
30 &process_token_raw);
31 if (!success)
32 return base::win::ScopedHandle();
33 win::ScopedHandle process_token(process_token_raw);
34
35 HANDLE lowered_process_token_raw = nullptr;
36 success =
37 ::DuplicateTokenEx(process_token.Get(), 0, NULL, SecurityImpersonation,
38 TokenPrimary, &lowered_process_token_raw);
39 if (!success)
40 return base::win::ScopedHandle();
41 win::ScopedHandle lowered_process_token(lowered_process_token_raw);
42
43 // Low integrity SID
44 WCHAR integrity_sid_string[20] = L"S-1-16-4096";
45 PSID integrity_sid = nullptr;
46 success = ::ConvertStringSidToSid(integrity_sid_string, &integrity_sid);
47 if (!success)
48 return base::win::ScopedHandle();
49
50 TOKEN_MANDATORY_LABEL TIL = {0};
Nico 2016/02/19 03:33:01 FAILED: ninja -t msvc -e environment.x86 -- C:\b\b
51 TIL.Label.Attributes = SE_GROUP_INTEGRITY;
52 TIL.Label.Sid = integrity_sid;
53 success = ::SetTokenInformation(
54 lowered_process_token.Get(), TokenIntegrityLevel, &TIL,
55 sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(integrity_sid));
56 if (!success)
57 return base::win::ScopedHandle();
58 return lowered_process_token;
59 }
60
61 // Reads a HANDLE from the pipe as a raw int, least significant digit first.
62 win::ScopedHandle ReadHandleFromPipe(HANDLE pipe) {
63 // Read from parent pipe.
64 const size_t buf_size = 1000;
65 char buffer[buf_size];
66 memset(buffer, 0, buf_size);
67 DWORD bytes_read;
68 BOOL success = ReadFile(pipe, buffer, buf_size, &bytes_read, NULL);
69
70 if (!success || bytes_read == 0) {
71 LOG(ERROR) << "Failed to read handle from pipe.";
72 return win::ScopedHandle();
73 }
74
75 int handle_as_int = 0;
76 int power_of_ten = 1;
77 for (unsigned int i = 0; i < bytes_read; ++i) {
78 handle_as_int += buffer[i] * power_of_ten;
79 power_of_ten *= 10;
80 }
81
82 return win::ScopedHandle(reinterpret_cast<HANDLE>(handle_as_int));
83 }
84
85 // Writes a HANDLE to a pipe as a raw int, least significant digit first.
86 void WriteHandleToPipe(HANDLE pipe, HANDLE handle) {
87 uint32_t handle_as_int = reinterpret_cast<uint32_t>(handle);
brucedawson 2016/02/20 00:49:52 VC++ 2015 prefers double casts for the truncation-
88
89 scoped_ptr<char, base::FreeDeleter> buffer(static_cast<char*>(malloc(1000)));
90 size_t index = 0;
91 while (handle_as_int > 0) {
92 buffer.get()[index] = handle_as_int % 10;
93 handle_as_int /= 10;
94 ++index;
95 }
96
97 ::ConnectNamedPipe(pipe, nullptr);
98 DWORD written;
99 ASSERT_TRUE(::WriteFile(pipe, buffer.get(), index, &written, NULL));
100 }
101
102 // Creates a communication pipe with the given name.
103 win::ScopedHandle CreateCommunicationPipe(const std::wstring& name) {
104 return win::ScopedHandle(CreateNamedPipe(name.c_str(), // pipe name
105 PIPE_ACCESS_DUPLEX, PIPE_WAIT, 255,
106 1000, 1000, 0, NULL));
107 }
108
109 // Generates a random name for a communication pipe.
110 std::wstring CreateCommunicationPipeName() {
111 uint64_t rand_values[4];
112 RandBytes(&rand_values, sizeof(rand_values));
113 std::wstring child_pipe_name = StringPrintf(
114 L"\\\\.\\pipe\\SharedMemoryWinTest_%016llx%016llx%016llx%016llx",
115 rand_values[0], rand_values[1], rand_values[2], rand_values[3]);
116 return child_pipe_name;
117 }
118
119 class SharedMemoryWinTest : public base::MultiProcessTest {
120 protected:
121 CommandLine MakeCmdLine(const std::string& procname) override {
122 CommandLine line = base::MultiProcessTest::MakeCmdLine(procname);
123 line.AppendSwitchASCII(kHandleSwitchName, communication_pipe_name_);
124 return line;
125 }
126
127 std::string communication_pipe_name_;
128 };
129
130 MULTIPROCESS_TEST_MAIN(LowerPermissions) {
131 std::string handle_name =
132 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kHandleSwitchName);
133 std::wstring handle_name16 = SysUTF8ToWide(handle_name);
134 win::ScopedHandle parent_pipe(
135 ::CreateFile(handle_name16.c_str(), // pipe name
136 GENERIC_READ,
137 0, // no sharing
138 NULL, // default security attributes
139 OPEN_EXISTING, // opens existing pipe
140 0, // default attributes
141 NULL)); // no template file
142 if (parent_pipe.Get() == INVALID_HANDLE_VALUE) {
143 LOG(ERROR) << "Failed to open communication pipe.";
144 return 1;
145 }
146
147 win::ScopedHandle received_handle = ReadHandleFromPipe(parent_pipe.Get());
148 if (!received_handle.Get()) {
149 LOG(ERROR) << "Failed to read handle from pipe.";
150 return 1;
151 }
152
153 // Attempting to add the WRITE_DAC permission should fail.
154 HANDLE duped_handle;
155 BOOL success = ::DuplicateHandle(GetCurrentProcess(), received_handle.Get(),
156 GetCurrentProcess(), &duped_handle,
157 FILE_MAP_READ | WRITE_DAC, FALSE, 0);
158 if (success) {
159 LOG(ERROR) << "Should not have been able to add WRITE_DAC permission.";
160 return 1;
161 }
162
163 // Attempting to add the FILE_MAP_WRITE permission should fail.
164 success = ::DuplicateHandle(GetCurrentProcess(), received_handle.Get(),
165 GetCurrentProcess(), &duped_handle,
166 FILE_MAP_READ | FILE_MAP_WRITE, FALSE, 0);
167 if (success) {
168 LOG(ERROR) << "Should not have been able to add FILE_MAP_WRITE permission.";
169 return 1;
170 }
171
172 // Attempting to duplicate the HANDLE with the same permissions should
173 // succeed.
174 success = ::DuplicateHandle(GetCurrentProcess(), received_handle.Get(),
175 GetCurrentProcess(), &duped_handle, FILE_MAP_READ,
176 FALSE, 0);
177 if (!success) {
178 LOG(ERROR) << "Failed to duplicate handle.";
179 return 4;
180 }
181 ::CloseHandle(duped_handle);
182 return 0;
183 }
184
185 TEST_F(SharedMemoryWinTest, LowerPermissions) {
186 std::wstring communication_pipe_name = CreateCommunicationPipeName();
187 communication_pipe_name_ = SysWideToUTF8(communication_pipe_name);
188
189 win::ScopedHandle communication_pipe =
190 CreateCommunicationPipe(communication_pipe_name);
191 ASSERT_TRUE(communication_pipe.Get());
192
193 win::ScopedHandle lowered_process_token = CreateLowIntegritySID();
194 ASSERT_TRUE(lowered_process_token.Get());
195
196 base::LaunchOptions options;
197 options.as_user = lowered_process_token.Get();
198 base::Process process = SpawnChildWithOptions("LowerPermissions", options);
199 ASSERT_TRUE(process.IsValid());
200
201 SharedMemory memory;
202 memory.CreateAndMapAnonymous(1001);
203
204 // Duplicate into child process, giving only FILE_MAP_READ permissions.
205 HANDLE raw_handle = nullptr;
206 ::DuplicateHandle(::GetCurrentProcess(), memory.handle().GetHandle(),
207 process.Handle(), &raw_handle,
208 FILE_MAP_READ | SECTION_QUERY, FALSE, 0);
209 ASSERT_TRUE(raw_handle);
210
211 WriteHandleToPipe(communication_pipe.Get(), raw_handle);
212
213 int exit_code;
214 EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
215 &exit_code));
216 EXPECT_EQ(0, exit_code);
217 }
218
219 } // namespace
220 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/shared_memory_win.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698