1 // Copyright (c) 2012 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 <set> 6 #include <string> 7 8 #include "base/basictypes.h" 9 #include "base/files/file_path.h" 10 #include "content/browser/child_process_security_policy_impl.h" 11 #include "content/public/common/url_constants.h" 12 #include "content/test/test_content_browser_client.h" 13 #include "storage/browser/fileapi/file_permission_policy.h" 14 #include "storage/browser/fileapi/file_system_url.h" 15 #include "storage/browser/fileapi/isolated_context.h" 16 #include "storage/common/fileapi/file_system_types.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 #include "url/gurl.h" 19 20 namespace content { 21 namespace { 22 23 const int kRendererID = 42; 24 const int kWorkerRendererID = kRendererID + 1; 25 26 #if defined(FILE_PATH_USES_DRIVE_LETTERS) 27 #define TEST_PATH(x) FILE_PATH_LITERAL("c:") FILE_PATH_LITERAL(x) 28 #else 29 #define TEST_PATH(x) FILE_PATH_LITERAL(x) 30 #endif 31 32 class ChildProcessSecurityPolicyTestBrowserClient 33 : public TestContentBrowserClient { 34 public: 35 ChildProcessSecurityPolicyTestBrowserClient() {} 36 37 virtual bool IsHandledURL(const GURL& url) OVERRIDE { 38 return schemes_.find(url.scheme()) != schemes_.end(); 39 } 40 41 void ClearSchemes() { 42 schemes_.clear(); 43 } 44 45 void AddScheme(const std::string& scheme) { 46 schemes_.insert(scheme); 47 } 48 49 private: 50 std::set<std::string> schemes_; 51 }; 52 53 } // namespace 54 55 class ChildProcessSecurityPolicyTest : public testing::Test { 56 public: 57 ChildProcessSecurityPolicyTest() : old_browser_client_(NULL) { 58 } 59 60 virtual void SetUp() { 61 old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_); 62 63 // Claim to always handle chrome:// URLs because the CPSP's notion of 64 // allowing WebUI bindings is hard-wired to this particular scheme. 65 test_browser_client_.AddScheme(kChromeUIScheme); 66 67 // Claim to always handle file:// URLs like the browser would. 68 // net::URLRequest::IsHandledURL() no longer claims support for default 69 // protocols as this is the responsibility of the browser (which is 70 // responsible for adding the appropriate ProtocolHandler). 71 test_browser_client_.AddScheme(url::kFileScheme); 72 } 73 74 virtual void TearDown() { 75 test_browser_client_.ClearSchemes(); 76 SetBrowserClientForTesting(old_browser_client_); 77 } 78 79 protected: 80 void RegisterTestScheme(const std::string& scheme) { 81 test_browser_client_.AddScheme(scheme); 82 } 83 84 void GrantPermissionsForFile(ChildProcessSecurityPolicyImpl* p, 85 int child_id, 86 const base::FilePath& file, 87 int permissions) { 88 p->GrantPermissionsForFile(child_id, file, permissions); 89 } 90 91 void CheckHasNoFileSystemPermission(ChildProcessSecurityPolicyImpl* p, 92 const std::string& child_id) { 93 EXPECT_FALSE(p->CanReadFileSystem(kRendererID, child_id)); 94 EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, child_id)); 95 EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, child_id)); 96 EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, child_id)); 97 } 98 99 void CheckHasNoFileSystemFilePermission(ChildProcessSecurityPolicyImpl* p, 100 const base::FilePath& file, 101 const storage::FileSystemURL& url) { 102 EXPECT_FALSE(p->CanReadFile(kRendererID, file)); 103 EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file)); 104 EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url)); 105 EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url)); 106 EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url)); 107 EXPECT_FALSE(p->CanCreateReadWriteFileSystemFile(kRendererID, url)); 108 EXPECT_FALSE(p->CanCopyIntoFileSystemFile(kRendererID, url)); 109 EXPECT_FALSE(p->CanDeleteFileSystemFile(kRendererID, url)); 110 } 111 112 private: 113 ChildProcessSecurityPolicyTestBrowserClient test_browser_client_; 114 ContentBrowserClient* old_browser_client_; 115 }; 116 117 118 TEST_F(ChildProcessSecurityPolicyTest, IsWebSafeSchemeTest) { 119 ChildProcessSecurityPolicyImpl* p = 120 ChildProcessSecurityPolicyImpl::GetInstance(); 121 122 EXPECT_TRUE(p->IsWebSafeScheme(url::kHttpScheme)); 123 EXPECT_TRUE(p->IsWebSafeScheme(url::kHttpsScheme)); 124 EXPECT_TRUE(p->IsWebSafeScheme(url::kFtpScheme)); 125 EXPECT_TRUE(p->IsWebSafeScheme(url::kDataScheme)); 126 EXPECT_TRUE(p->IsWebSafeScheme("feed")); 127 EXPECT_TRUE(p->IsWebSafeScheme(url::kBlobScheme)); 128 EXPECT_TRUE(p->IsWebSafeScheme(url::kFileSystemScheme)); 129 130 EXPECT_FALSE(p->IsWebSafeScheme("registered-web-safe-scheme")); 131 p->RegisterWebSafeScheme("registered-web-safe-scheme"); 132 EXPECT_TRUE(p->IsWebSafeScheme("registered-web-safe-scheme")); 133 134 EXPECT_FALSE(p->IsWebSafeScheme(kChromeUIScheme)); 135 } 136 137 TEST_F(ChildProcessSecurityPolicyTest, IsPseudoSchemeTest) { 138 ChildProcessSecurityPolicyImpl* p = 139 ChildProcessSecurityPolicyImpl::GetInstance(); 140 141 EXPECT_TRUE(p->IsPseudoScheme(url::kAboutScheme)); 142 EXPECT_TRUE(p->IsPseudoScheme(url::kJavaScriptScheme)); 143 EXPECT_TRUE(p->IsPseudoScheme(kViewSourceScheme)); 144 145 EXPECT_FALSE(p->IsPseudoScheme("registered-pseudo-scheme")); 146 p->RegisterPseudoScheme("registered-pseudo-scheme"); 147 EXPECT_TRUE(p->IsPseudoScheme("registered-pseudo-scheme")); 148 149 EXPECT_FALSE(p->IsPseudoScheme(kChromeUIScheme)); 150 } 151 152 TEST_F(ChildProcessSecurityPolicyTest, StandardSchemesTest) { 153 ChildProcessSecurityPolicyImpl* p = 154 ChildProcessSecurityPolicyImpl::GetInstance(); 155 156 p->Add(kRendererID); 157 158 // Safe 159 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("http://www.google.com/"))); 160 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("https://www.paypal.com/"))); 161 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("ftp://ftp.gnu.org/"))); 162 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("data:text/html,<b>Hi</b>"))); 163 EXPECT_TRUE(p->CanRequestURL(kRendererID, 164 GURL("view-source:http://www.google.com/"))); 165 EXPECT_TRUE(p->CanRequestURL( 166 kRendererID, GURL("filesystem:http://localhost/temporary/a.gif"))); 167 168 // Dangerous 169 EXPECT_FALSE(p->CanRequestURL(kRendererID, 170 GURL("file:///etc/passwd"))); 171 EXPECT_FALSE(p->CanRequestURL(kRendererID, 172 GURL("chrome://foo/bar"))); 173 174 p->Remove(kRendererID); 175 } 176 177 TEST_F(ChildProcessSecurityPolicyTest, AboutTest) { 178 ChildProcessSecurityPolicyImpl* p = 179 ChildProcessSecurityPolicyImpl::GetInstance(); 180 181 p->Add(kRendererID); 182 183 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("about:blank"))); 184 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("about:BlAnK"))); 185 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("aBouT:BlAnK"))); 186 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("aBouT:blank"))); 187 188 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:memory"))); 189 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:crash"))); 190 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:cache"))); 191 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:hang"))); 192 193 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("aBoUt:memory"))); 194 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:CrASh"))); 195 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("abOuT:cAChe"))); 196 197 // Requests for about: pages should be denied. 198 p->GrantRequestURL(kRendererID, GURL("about:crash")); 199 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:crash"))); 200 201 // These requests for chrome:// pages should be granted. 202 GURL chrome_url("chrome://foo"); 203 p->GrantRequestURL(kRendererID, chrome_url); 204 EXPECT_TRUE(p->CanRequestURL(kRendererID, chrome_url)); 205 206 p->Remove(kRendererID); 207 } 208 209 TEST_F(ChildProcessSecurityPolicyTest, JavaScriptTest) { 210 ChildProcessSecurityPolicyImpl* p = 211 ChildProcessSecurityPolicyImpl::GetInstance(); 212 213 p->Add(kRendererID); 214 215 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("javascript:alert('xss')"))); 216 p->GrantRequestURL(kRendererID, GURL("javascript:alert('xss')")); 217 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("javascript:alert('xss')"))); 218 219 p->Remove(kRendererID); 220 } 221 222 TEST_F(ChildProcessSecurityPolicyTest, RegisterWebSafeSchemeTest) { 223 ChildProcessSecurityPolicyImpl* p = 224 ChildProcessSecurityPolicyImpl::GetInstance(); 225 226 p->Add(kRendererID); 227 228 // Currently, "asdf" is destined for ShellExecute, so it is allowed. 229 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("asdf:rockers"))); 230 231 // Once we register "asdf", we default to deny. 232 RegisterTestScheme("asdf"); 233 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("asdf:rockers"))); 234 235 // We can allow new schemes by adding them to the whitelist. 236 p->RegisterWebSafeScheme("asdf"); 237 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("asdf:rockers"))); 238 239 // Cleanup. 240 p->Remove(kRendererID); 241 } 242 243 TEST_F(ChildProcessSecurityPolicyTest, CanServiceCommandsTest) { 244 ChildProcessSecurityPolicyImpl* p = 245 ChildProcessSecurityPolicyImpl::GetInstance(); 246 247 p->Add(kRendererID); 248 249 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd"))); 250 p->GrantRequestURL(kRendererID, GURL("file:///etc/passwd")); 251 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd"))); 252 253 // We should forget our state if we repeat a renderer id. 254 p->Remove(kRendererID); 255 p->Add(kRendererID); 256 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd"))); 257 p->Remove(kRendererID); 258 } 259 260 TEST_F(ChildProcessSecurityPolicyTest, ViewSource) { 261 ChildProcessSecurityPolicyImpl* p = 262 ChildProcessSecurityPolicyImpl::GetInstance(); 263 264 p->Add(kRendererID); 265 266 // View source is determined by the embedded scheme. 267 EXPECT_TRUE(p->CanRequestURL(kRendererID, 268 GURL("view-source:http://www.google.com/"))); 269 EXPECT_FALSE(p->CanRequestURL(kRendererID, 270 GURL("view-source:file:///etc/passwd"))); 271 EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd"))); 272 EXPECT_FALSE(p->CanRequestURL( 273 kRendererID, GURL("view-source:view-source:http://www.google.com/"))); 274 275 p->GrantRequestURL(kRendererID, GURL("view-source:file:///etc/passwd")); 276 // View source needs to be able to request the embedded scheme. 277 EXPECT_TRUE(p->CanRequestURL(kRendererID, 278 GURL("view-source:file:///etc/passwd"))); 279 EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd"))); 280 281 p->Remove(kRendererID); 282 } 283 284 TEST_F(ChildProcessSecurityPolicyTest, SpecificFile) { 285 ChildProcessSecurityPolicyImpl* p = 286 ChildProcessSecurityPolicyImpl::GetInstance(); 287 288 p->Add(kRendererID); 289 290 GURL icon_url("file:///tmp/foo.png"); 291 GURL sensitive_url("file:///etc/passwd"); 292 EXPECT_FALSE(p->CanRequestURL(kRendererID, icon_url)); 293 EXPECT_FALSE(p->CanRequestURL(kRendererID, sensitive_url)); 294 295 p->GrantRequestSpecificFileURL(kRendererID, icon_url); 296 EXPECT_TRUE(p->CanRequestURL(kRendererID, icon_url)); 297 EXPECT_FALSE(p->CanRequestURL(kRendererID, sensitive_url)); 298 299 p->GrantRequestURL(kRendererID, icon_url); 300 EXPECT_TRUE(p->CanRequestURL(kRendererID, icon_url)); 301 EXPECT_TRUE(p->CanRequestURL(kRendererID, sensitive_url)); 302 303 p->Remove(kRendererID); 304 } 305 306 TEST_F(ChildProcessSecurityPolicyTest, FileSystemGrantsTest) { 307 ChildProcessSecurityPolicyImpl* p = 308 ChildProcessSecurityPolicyImpl::GetInstance(); 309 310 p->Add(kRendererID); 311 std::string read_id = 312 storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( 313 storage::kFileSystemTypeTest, "read_filesystem", base::FilePath()); 314 std::string read_write_id = 315 storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( 316 storage::kFileSystemTypeTest, 317 "read_write_filesystem", 318 base::FilePath()); 319 std::string copy_into_id = 320 storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( 321 storage::kFileSystemTypeTest, 322 "copy_into_filesystem", 323 base::FilePath()); 324 std::string delete_from_id = 325 storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( 326 storage::kFileSystemTypeTest, 327 "delete_from_filesystem", 328 base::FilePath()); 329 330 // Test initially having no permissions. 331 CheckHasNoFileSystemPermission(p, read_id); 332 CheckHasNoFileSystemPermission(p, read_write_id); 333 CheckHasNoFileSystemPermission(p, copy_into_id); 334 CheckHasNoFileSystemPermission(p, delete_from_id); 335 336 // Testing varying combinations of grants and checks. 337 p->GrantReadFileSystem(kRendererID, read_id); 338 EXPECT_TRUE(p->CanReadFileSystem(kRendererID, read_id)); 339 EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_id)); 340 EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_id)); 341 EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, read_id)); 342 343 p->GrantReadFileSystem(kRendererID, read_write_id); 344 p->GrantWriteFileSystem(kRendererID, read_write_id); 345 EXPECT_TRUE(p->CanReadFileSystem(kRendererID, read_write_id)); 346 EXPECT_TRUE(p->CanReadWriteFileSystem(kRendererID, read_write_id)); 347 EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_write_id)); 348 EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, read_write_id)); 349 350 p->GrantCopyIntoFileSystem(kRendererID, copy_into_id); 351 EXPECT_FALSE(p->CanReadFileSystem(kRendererID, copy_into_id)); 352 EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, copy_into_id)); 353 EXPECT_TRUE(p->CanCopyIntoFileSystem(kRendererID, copy_into_id)); 354 EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, copy_into_id)); 355 356 p->GrantDeleteFromFileSystem(kRendererID, delete_from_id); 357 EXPECT_FALSE(p->CanReadFileSystem(kRendererID, delete_from_id)); 358 EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, delete_from_id)); 359 EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, delete_from_id)); 360 EXPECT_TRUE(p->CanDeleteFromFileSystem(kRendererID, delete_from_id)); 361 362 // Test revoke permissions on renderer ID removal. 363 p->Remove(kRendererID); 364 CheckHasNoFileSystemPermission(p, read_id); 365 CheckHasNoFileSystemPermission(p, read_write_id); 366 CheckHasNoFileSystemPermission(p, copy_into_id); 367 CheckHasNoFileSystemPermission(p, delete_from_id); 368 369 // Test having no permissions upon re-adding same renderer ID. 370 p->Add(kRendererID); 371 CheckHasNoFileSystemPermission(p, read_id); 372 CheckHasNoFileSystemPermission(p, read_write_id); 373 CheckHasNoFileSystemPermission(p, copy_into_id); 374 CheckHasNoFileSystemPermission(p, delete_from_id); 375 376 // Cleanup. 377 p->Remove(kRendererID); 378 storage::IsolatedContext::GetInstance()->RevokeFileSystem(read_id); 379 storage::IsolatedContext::GetInstance()->RevokeFileSystem(read_write_id); 380 storage::IsolatedContext::GetInstance()->RevokeFileSystem(copy_into_id); 381 storage::IsolatedContext::GetInstance()->RevokeFileSystem(delete_from_id); 382 } 383 384 TEST_F(ChildProcessSecurityPolicyTest, FilePermissionGrantingAndRevoking) { 385 ChildProcessSecurityPolicyImpl* p = 386 ChildProcessSecurityPolicyImpl::GetInstance(); 387 388 p->RegisterFileSystemPermissionPolicy( 389 storage::kFileSystemTypeTest, 390 storage::FILE_PERMISSION_USE_FILE_PERMISSION); 391 392 p->Add(kRendererID); 393 base::FilePath file(TEST_PATH("/dir/testfile")); 394 file = file.NormalizePathSeparators(); 395 storage::FileSystemURL url = storage::FileSystemURL::CreateForTest( 396 GURL("http://foo/"), storage::kFileSystemTypeTest, file); 397 398 // Test initially having no permissions. 399 CheckHasNoFileSystemFilePermission(p, file, url); 400 401 // Testing every combination of permissions granting and revoking. 402 p->GrantReadFile(kRendererID, file); 403 EXPECT_TRUE(p->CanReadFile(kRendererID, file)); 404 EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file)); 405 EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url)); 406 EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url)); 407 EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url)); 408 EXPECT_FALSE(p->CanCreateReadWriteFileSystemFile(kRendererID, url)); 409 EXPECT_FALSE(p->CanCopyIntoFileSystemFile(kRendererID, url)); 410 EXPECT_FALSE(p->CanDeleteFileSystemFile(kRendererID, url)); 411 p->RevokeAllPermissionsForFile(kRendererID, file); 412 CheckHasNoFileSystemFilePermission(p, file, url); 413 414 p->GrantCreateReadWriteFile(kRendererID, file); 415 EXPECT_TRUE(p->CanReadFile(kRendererID, file)); 416 EXPECT_TRUE(p->CanCreateReadWriteFile(kRendererID, file)); 417 EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url)); 418 EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url)); 419 EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url)); 420 EXPECT_TRUE(p->CanCreateReadWriteFileSystemFile(kRendererID, url)); 421 EXPECT_TRUE(p->CanCopyIntoFileSystemFile(kRendererID, url)); 422 EXPECT_TRUE(p->CanDeleteFileSystemFile(kRendererID, url)); 423 p->RevokeAllPermissionsForFile(kRendererID, file); 424 CheckHasNoFileSystemFilePermission(p, file, url); 425 426 // Test revoke permissions on renderer ID removal. 427 p->GrantCreateReadWriteFile(kRendererID, file); 428 EXPECT_TRUE(p->CanReadFile(kRendererID, file)); 429 EXPECT_TRUE(p->CanCreateReadWriteFile(kRendererID, file)); 430 EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url)); 431 EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url)); 432 EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url)); 433 EXPECT_TRUE(p->CanCreateReadWriteFileSystemFile(kRendererID, url)); 434 EXPECT_TRUE(p->CanCopyIntoFileSystemFile(kRendererID, url)); 435 EXPECT_TRUE(p->CanDeleteFileSystemFile(kRendererID, url)); 436 p->Remove(kRendererID); 437 CheckHasNoFileSystemFilePermission(p, file, url); 438 439 // Test having no permissions upon re-adding same renderer ID. 440 p->Add(kRendererID); 441 CheckHasNoFileSystemFilePermission(p, file, url); 442 443 // Cleanup. 444 p->Remove(kRendererID); 445 } 446 447 TEST_F(ChildProcessSecurityPolicyTest, FilePermissions) { 448 base::FilePath granted_file = base::FilePath(TEST_PATH("/home/joe")); 449 base::FilePath sibling_file = base::FilePath(TEST_PATH("/home/bob")); 450 base::FilePath child_file = base::FilePath(TEST_PATH("/home/joe/file")); 451 base::FilePath parent_file = base::FilePath(TEST_PATH("/home")); 452 base::FilePath parent_slash_file = base::FilePath(TEST_PATH("/home/")); 453 base::FilePath child_traversal1 = 454 base::FilePath(TEST_PATH("/home/joe/././file")); 455 base::FilePath child_traversal2 = base::FilePath( 456 TEST_PATH("/home/joe/file/../otherfile")); 457 base::FilePath evil_traversal1 = 458 base::FilePath(TEST_PATH("/home/joe/../../etc/passwd")); 459 base::FilePath evil_traversal2 = base::FilePath( 460 TEST_PATH("/home/joe/./.././../etc/passwd")); 461 base::FilePath self_traversal = 462 base::FilePath(TEST_PATH("/home/joe/../joe/file")); 463 base::FilePath relative_file = base::FilePath(FILE_PATH_LITERAL("home/joe")); 464 465 ChildProcessSecurityPolicyImpl* p = 466 ChildProcessSecurityPolicyImpl::GetInstance(); 467 468 // Grant permissions for a file. 469 p->Add(kRendererID); 470 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 471 base::File::FLAG_OPEN)); 472 473 GrantPermissionsForFile(p, kRendererID, granted_file, 474 base::File::FLAG_OPEN | 475 base::File::FLAG_OPEN_TRUNCATED | 476 base::File::FLAG_READ | 477 base::File::FLAG_WRITE); 478 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file, 479 base::File::FLAG_OPEN | 480 base::File::FLAG_OPEN_TRUNCATED | 481 base::File::FLAG_READ | 482 base::File::FLAG_WRITE)); 483 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file, 484 base::File::FLAG_OPEN | 485 base::File::FLAG_READ)); 486 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 487 base::File::FLAG_CREATE)); 488 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 0)); 489 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 490 base::File::FLAG_CREATE | 491 base::File::FLAG_OPEN_TRUNCATED | 492 base::File::FLAG_READ | 493 base::File::FLAG_WRITE)); 494 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, sibling_file, 495 base::File::FLAG_OPEN | 496 base::File::FLAG_READ)); 497 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, parent_file, 498 base::File::FLAG_OPEN | 499 base::File::FLAG_READ)); 500 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_file, 501 base::File::FLAG_OPEN | 502 base::File::FLAG_READ)); 503 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_traversal1, 504 base::File::FLAG_OPEN | 505 base::File::FLAG_READ)); 506 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_traversal2, 507 base::File::FLAG_OPEN | 508 base::File::FLAG_READ)); 509 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, evil_traversal1, 510 base::File::FLAG_OPEN | 511 base::File::FLAG_READ)); 512 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, evil_traversal2, 513 base::File::FLAG_OPEN | 514 base::File::FLAG_READ)); 515 // CPSP doesn't allow this case for the sake of simplicity. 516 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, self_traversal, 517 base::File::FLAG_OPEN | 518 base::File::FLAG_READ)); 519 p->Remove(kRendererID); 520 521 // Grant permissions for the directory the file is in. 522 p->Add(kRendererID); 523 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 524 base::File::FLAG_OPEN)); 525 GrantPermissionsForFile(p, kRendererID, parent_file, 526 base::File::FLAG_OPEN | 527 base::File::FLAG_READ); 528 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file, 529 base::File::FLAG_OPEN)); 530 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 531 base::File::FLAG_READ | 532 base::File::FLAG_WRITE)); 533 p->Remove(kRendererID); 534 535 // Grant permissions for the directory the file is in (with trailing '/'). 536 p->Add(kRendererID); 537 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 538 base::File::FLAG_OPEN)); 539 GrantPermissionsForFile(p, kRendererID, parent_slash_file, 540 base::File::FLAG_OPEN | 541 base::File::FLAG_READ); 542 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file, 543 base::File::FLAG_OPEN)); 544 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 545 base::File::FLAG_READ | 546 base::File::FLAG_WRITE)); 547 548 // Grant permissions for the file (should overwrite the permissions granted 549 // for the directory). 550 GrantPermissionsForFile(p, kRendererID, granted_file, 551 base::File::FLAG_TEMPORARY); 552 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 553 base::File::FLAG_OPEN)); 554 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file, 555 base::File::FLAG_TEMPORARY)); 556 557 // Revoke all permissions for the file (it should inherit its permissions 558 // from the directory again). 559 p->RevokeAllPermissionsForFile(kRendererID, granted_file); 560 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file, 561 base::File::FLAG_OPEN | 562 base::File::FLAG_READ)); 563 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 564 base::File::FLAG_TEMPORARY)); 565 p->Remove(kRendererID); 566 567 // Grant file permissions for the file to main thread renderer process, 568 // make sure its worker thread renderer process inherits those. 569 p->Add(kRendererID); 570 GrantPermissionsForFile(p, kRendererID, granted_file, 571 base::File::FLAG_OPEN | 572 base::File::FLAG_READ); 573 EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file, 574 base::File::FLAG_OPEN | 575 base::File::FLAG_READ)); 576 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 577 base::File::FLAG_WRITE)); 578 p->AddWorker(kWorkerRendererID, kRendererID); 579 EXPECT_TRUE(p->HasPermissionsForFile(kWorkerRendererID, granted_file, 580 base::File::FLAG_OPEN | 581 base::File::FLAG_READ)); 582 EXPECT_FALSE(p->HasPermissionsForFile(kWorkerRendererID, granted_file, 583 base::File::FLAG_WRITE)); 584 p->Remove(kRendererID); 585 EXPECT_FALSE(p->HasPermissionsForFile(kWorkerRendererID, granted_file, 586 base::File::FLAG_OPEN | 587 base::File::FLAG_READ)); 588 p->Remove(kWorkerRendererID); 589 590 p->Add(kRendererID); 591 GrantPermissionsForFile(p, kRendererID, relative_file, 592 base::File::FLAG_OPEN); 593 EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, relative_file, 594 base::File::FLAG_OPEN)); 595 p->Remove(kRendererID); 596 } 597 598 TEST_F(ChildProcessSecurityPolicyTest, CanServiceWebUIBindings) { 599 ChildProcessSecurityPolicyImpl* p = 600 ChildProcessSecurityPolicyImpl::GetInstance(); 601 602 GURL url("chrome://thumb/http://www.google.com/"); 603 604 p->Add(kRendererID); 605 606 EXPECT_FALSE(p->HasWebUIBindings(kRendererID)); 607 EXPECT_FALSE(p->CanRequestURL(kRendererID, url)); 608 p->GrantWebUIBindings(kRendererID); 609 EXPECT_TRUE(p->HasWebUIBindings(kRendererID)); 610 EXPECT_TRUE(p->CanRequestURL(kRendererID, url)); 611 612 p->Remove(kRendererID); 613 } 614 615 TEST_F(ChildProcessSecurityPolicyTest, RemoveRace) { 616 ChildProcessSecurityPolicyImpl* p = 617 ChildProcessSecurityPolicyImpl::GetInstance(); 618 619 GURL url("file:///etc/passwd"); 620 base::FilePath file(TEST_PATH("/etc/passwd")); 621 622 p->Add(kRendererID); 623 624 p->GrantRequestURL(kRendererID, url); 625 p->GrantReadFile(kRendererID, file); 626 p->GrantWebUIBindings(kRendererID); 627 628 EXPECT_TRUE(p->CanRequestURL(kRendererID, url)); 629 EXPECT_TRUE(p->CanReadFile(kRendererID, file)); 630 EXPECT_TRUE(p->HasWebUIBindings(kRendererID)); 631 632 p->Remove(kRendererID); 633 634 // Renderers are added and removed on the UI thread, but the policy can be 635 // queried on the IO thread. The ChildProcessSecurityPolicy needs to be 636 // prepared to answer policy questions about renderers who no longer exist. 637 638 // In this case, we default to secure behavior. 639 EXPECT_FALSE(p->CanRequestURL(kRendererID, url)); 640 EXPECT_FALSE(p->CanReadFile(kRendererID, file)); 641 EXPECT_FALSE(p->HasWebUIBindings(kRendererID)); 642 } 643 644 } // namespace content 645