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

Side by Side Diff: sandbox/linux/services/broker_process.cc

Issue 18337010: Avoid std::string copying in GetFileNameInWhitelist. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 5 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sandbox/linux/services/broker_process.h" 5 #include "sandbox/linux/services/broker_process.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <sys/socket.h> 8 #include <sys/socket.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <sys/syscall.h> 10 #include <sys/syscall.h>
11 #include <sys/types.h> 11 #include <sys/types.h>
12 #include <unistd.h> 12 #include <unistd.h>
13 13
14 #include <algorithm> 14 #include <algorithm>
15 #include <string> 15 #include <string>
16 #include <vector> 16 #include <vector>
17 17
18 #include "base/basictypes.h" 18 #include "base/basictypes.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/pickle.h" 20 #include "base/pickle.h"
21 #include "base/posix/eintr_wrapper.h" 21 #include "base/posix/eintr_wrapper.h"
22 #include "base/posix/unix_domain_socket_linux.h" 22 #include "base/posix/unix_domain_socket_linux.h"
23 #include "build/build_config.h" 23 #include "build/build_config.h"
24 #include "sandbox/linux/services/broker_process_utils.h"
24 #include "sandbox/linux/services/linux_syscalls.h" 25 #include "sandbox/linux/services/linux_syscalls.h"
25 26
26 #if defined(OS_ANDROID) && !defined(MSG_CMSG_CLOEXEC) 27 #if defined(OS_ANDROID) && !defined(MSG_CMSG_CLOEXEC)
27 #define MSG_CMSG_CLOEXEC 0x40000000 28 #define MSG_CMSG_CLOEXEC 0x40000000
28 #endif 29 #endif
29 30
30 namespace { 31 namespace {
31 32
32 static const size_t kMaxMessageLength = 4096; 33 static const size_t kMaxMessageLength = 4096;
33 34
(...skipping 12 matching lines...) Expand all
46 // Since we have to account for buggy userland (see crbug.com/237283), we will 47 // Since we have to account for buggy userland (see crbug.com/237283), we will
47 // open(2) the file with O_CLOEXEC in the broker process if necessary, in 48 // open(2) the file with O_CLOEXEC in the broker process if necessary, in
48 // addition to calling recvmsg(2) with MSG_CMSG_CLOEXEC. 49 // addition to calling recvmsg(2) with MSG_CMSG_CLOEXEC.
49 static const int kCurrentProcessOpenFlagsMask = O_CLOEXEC; 50 static const int kCurrentProcessOpenFlagsMask = O_CLOEXEC;
50 51
51 // Check whether |requested_filename| is in |allowed_file_names|. 52 // Check whether |requested_filename| is in |allowed_file_names|.
52 // See GetFileNameIfAllowedToOpen() for an explanation of |file_to_open|. 53 // See GetFileNameIfAllowedToOpen() for an explanation of |file_to_open|.
53 // async signal safe if |file_to_open| is NULL. 54 // async signal safe if |file_to_open| is NULL.
54 // TODO(jln): assert signal safety. 55 // TODO(jln): assert signal safety.
55 bool GetFileNameInWhitelist(const std::vector<std::string>& allowed_file_names, 56 bool GetFileNameInWhitelist(const std::vector<std::string>& allowed_file_names,
56 const std::string& requested_filename, 57 const char* requested_filename,
57 const char** file_to_open) { 58 const char** file_to_open) {
58 if (file_to_open && *file_to_open) { 59 if (file_to_open && *file_to_open) {
59 // Make sure that callers never pass a non-empty string. In case callers 60 // Make sure that callers never pass a non-empty string. In case callers
60 // wrongly forget to check the return value and look at the string 61 // wrongly forget to check the return value and look at the string
61 // instead, this could catch bugs. 62 // instead, this could catch bugs.
62 RAW_LOG(FATAL, "*file_to_open should be NULL"); 63 RAW_LOG(FATAL, "*file_to_open should be NULL");
63 return false; 64 return false;
64 } 65 }
65 std::vector<std::string>::const_iterator it; 66 const char* found_filename =
66 it = std::find(allowed_file_names.begin(), allowed_file_names.end(), 67 sandbox::BrokerProcessUtils::Find(requested_filename, allowed_file_names);
67 requested_filename); 68
68 if (it < allowed_file_names.end()) { // requested_filename was found? 69 if (found_filename) { // |requested_filename| was found?
69 if (file_to_open) 70 if (file_to_open)
70 *file_to_open = it->c_str(); 71 *file_to_open = found_filename;
71 return true; 72 return true;
72 } 73 }
73 return false; 74 return false;
74 } 75 }
75 76
76 // We maintain a list of flags that have been reviewed for "sanity" and that 77 // We maintain a list of flags that have been reviewed for "sanity" and that
77 // we're ok to allow in the broker. 78 // we're ok to allow in the broker.
78 // I.e. here is where we wouldn't add O_RESET_FILE_SYSTEM. 79 // I.e. here is where we wouldn't add O_RESET_FILE_SYSTEM.
79 bool IsAllowedOpenFlags(int flags) { 80 bool IsAllowedOpenFlags(int flags) {
80 // First, check the access mode 81 // First, check the access mode
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 387 }
387 388
388 // Perform access(2) on |requested_filename| with mode |mode| if allowed by our 389 // Perform access(2) on |requested_filename| with mode |mode| if allowed by our
389 // policy. Write the syscall return value (-errno) to |write_pickle|. 390 // policy. Write the syscall return value (-errno) to |write_pickle|.
390 void BrokerProcess::AccessFileForIPC(const std::string& requested_filename, 391 void BrokerProcess::AccessFileForIPC(const std::string& requested_filename,
391 int mode, Pickle* write_pickle) const { 392 int mode, Pickle* write_pickle) const {
392 DCHECK(write_pickle); 393 DCHECK(write_pickle);
393 const char* file_to_access = NULL; 394 const char* file_to_access = NULL;
394 const bool safe_to_access_file = GetFileNameIfAllowedToAccess( 395 const bool safe_to_access_file = GetFileNameIfAllowedToAccess(
395 requested_filename.c_str(), mode, &file_to_access); 396 requested_filename.c_str(), mode, &file_to_access);
397
396 if (safe_to_access_file) { 398 if (safe_to_access_file) {
397 CHECK(file_to_access); 399 CHECK(file_to_access);
398 int access_ret = access(file_to_access, mode); 400 int access_ret = access(file_to_access, mode);
399 int access_errno = errno; 401 int access_errno = errno;
400 if (!access_ret) 402 if (!access_ret)
401 write_pickle->WriteInt(0); 403 write_pickle->WriteInt(0);
402 else 404 else
403 write_pickle->WriteInt(-access_errno); 405 write_pickle->WriteInt(-access_errno);
404 } else { 406 } else {
405 write_pickle->WriteInt(-EPERM); 407 write_pickle->WriteInt(-EPERM);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 // mode |requested_mode|. 442 // mode |requested_mode|.
441 // Note: access() being a system call to check permissions, this can get a bit 443 // Note: access() being a system call to check permissions, this can get a bit
442 // confusing. We're checking if calling access() should even be allowed with 444 // confusing. We're checking if calling access() should even be allowed with
443 // the same policy we would use for open(). 445 // the same policy we would use for open().
444 // If |file_to_access| is not NULL, we will return the matching pointer from 446 // If |file_to_access| is not NULL, we will return the matching pointer from
445 // the whitelist. For paranoia a caller should then use |file_to_access|. See 447 // the whitelist. For paranoia a caller should then use |file_to_access|. See
446 // GetFileNameIfAllowedToOpen() fore more explanation. 448 // GetFileNameIfAllowedToOpen() fore more explanation.
447 // return true if calling access() on this file should be allowed, false 449 // return true if calling access() on this file should be allowed, false
448 // otherwise. 450 // otherwise.
449 // Async signal safe if and only if |file_to_access| is NULL. 451 // Async signal safe if and only if |file_to_access| is NULL.
450 bool BrokerProcess::GetFileNameIfAllowedToAccess(const char* requested_filename, 452 bool BrokerProcess::GetFileNameIfAllowedToAccess(
451 int requested_mode, const char** file_to_access) const { 453 const char* requested_filename, int requested_mode,
jln (very slow on Chromium) 2013/07/08 22:36:51 Why the re-indent?
Jorge Lucangeli Obes 2013/07/09 03:52:12 Done.
454 const char** file_to_access) const {
452 // First, check if |requested_mode| is existence, ability to read or ability 455 // First, check if |requested_mode| is existence, ability to read or ability
453 // to write. We do not support X_OK. 456 // to write. We do not support X_OK.
454 if (requested_mode != F_OK && 457 if (requested_mode != F_OK &&
455 requested_mode & ~(R_OK | W_OK)) { 458 requested_mode & ~(R_OK | W_OK)) {
456 return false; 459 return false;
457 } 460 }
458 switch (requested_mode) { 461 switch (requested_mode) {
459 case F_OK: 462 case F_OK:
460 // We allow to check for file existence if we can either read or write. 463 // We allow to check for file existence if we can either read or write.
461 return GetFileNameInWhitelist(allowed_r_files_, requested_filename, 464 return GetFileNameInWhitelist(allowed_r_files_, requested_filename,
(...skipping 20 matching lines...) Expand all
482 } 485 }
483 486
484 // Check if |requested_filename| can be opened with flags |requested_flags|. 487 // Check if |requested_filename| can be opened with flags |requested_flags|.
485 // If |file_to_open| is not NULL, we will return the matching pointer from the 488 // If |file_to_open| is not NULL, we will return the matching pointer from the
486 // whitelist. For paranoia, a caller should then use |file_to_open| rather 489 // whitelist. For paranoia, a caller should then use |file_to_open| rather
487 // than |requested_filename|, so that it never attempts to open an 490 // than |requested_filename|, so that it never attempts to open an
488 // attacker-controlled file name, even if an attacker managed to fool the 491 // attacker-controlled file name, even if an attacker managed to fool the
489 // string comparison mechanism. 492 // string comparison mechanism.
490 // Return true if opening should be allowed, false otherwise. 493 // Return true if opening should be allowed, false otherwise.
491 // Async signal safe if and only if |file_to_open| is NULL. 494 // Async signal safe if and only if |file_to_open| is NULL.
492 bool BrokerProcess::GetFileNameIfAllowedToOpen(const char* requested_filename, 495 bool BrokerProcess::GetFileNameIfAllowedToOpen(
493 int requested_flags, const char** file_to_open) const { 496 const char* requested_filename, int requested_flags,
497 const char** file_to_open) const {
jln (very slow on Chromium) 2013/07/08 22:36:51 Why the re-indent?
Jorge Lucangeli Obes 2013/07/09 03:52:12 Done.
494 if (!IsAllowedOpenFlags(requested_flags)) { 498 if (!IsAllowedOpenFlags(requested_flags)) {
495 return false; 499 return false;
496 } 500 }
497 switch (requested_flags & O_ACCMODE) { 501 switch (requested_flags & O_ACCMODE) {
498 case O_RDONLY: 502 case O_RDONLY:
499 return GetFileNameInWhitelist(allowed_r_files_, requested_filename, 503 return GetFileNameInWhitelist(allowed_r_files_, requested_filename,
500 file_to_open); 504 file_to_open);
501 case O_WRONLY: 505 case O_WRONLY:
502 return GetFileNameInWhitelist(allowed_w_files_, requested_filename, 506 return GetFileNameInWhitelist(allowed_w_files_, requested_filename,
503 file_to_open); 507 file_to_open);
504 case O_RDWR: 508 case O_RDWR:
505 { 509 {
506 bool allowed_for_read_and_write = 510 bool allowed_for_read_and_write =
507 GetFileNameInWhitelist(allowed_r_files_, requested_filename, NULL) && 511 GetFileNameInWhitelist(allowed_r_files_, requested_filename, NULL) &&
508 GetFileNameInWhitelist(allowed_w_files_, requested_filename, 512 GetFileNameInWhitelist(allowed_w_files_, requested_filename,
509 file_to_open); 513 file_to_open);
510 return allowed_for_read_and_write; 514 return allowed_for_read_and_write;
511 } 515 }
512 default: 516 default:
513 return false; 517 return false;
514 } 518 }
515 } 519 }
516 520
517 } // namespace sandbox. 521 } // namespace sandbox.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698