Index: sandbox/linux/syscall_broker/broker_policy.cc |
diff --git a/sandbox/linux/syscall_broker/broker_policy.cc b/sandbox/linux/syscall_broker/broker_policy.cc |
index ee9a658319d992a585a911c8d030382716b14a85..d9f69e3b8111f27dcfdab1c86cac1d7af1bd11b6 100644 |
--- a/sandbox/linux/syscall_broker/broker_policy.cc |
+++ b/sandbox/linux/syscall_broker/broker_policy.cc |
@@ -17,76 +17,19 @@ |
namespace sandbox { |
namespace syscall_broker { |
-namespace { |
- |
-// We maintain a list of flags that have been reviewed for "sanity" and that |
-// we're ok to allow in the broker. |
-// I.e. here is where we wouldn't add O_RESET_FILE_SYSTEM. |
-bool IsAllowedOpenFlags(int flags) { |
- // First, check the access mode. |
- const int access_mode = flags & O_ACCMODE; |
- if (access_mode != O_RDONLY && access_mode != O_WRONLY && |
- access_mode != O_RDWR) { |
- return false; |
- } |
- |
- // We only support a 2-parameters open, so we forbid O_CREAT. |
- if (flags & O_CREAT) { |
- return false; |
- } |
- |
- // Some flags affect the behavior of the current process. We don't support |
- // them and don't allow them for now. |
- if (flags & kCurrentProcessOpenFlagsMask) |
- return false; |
- |
- // Now check that all the flags are known to us. |
- const int creation_and_status_flags = flags & ~O_ACCMODE; |
- |
- const int known_flags = O_APPEND | O_ASYNC | O_CLOEXEC | O_CREAT | O_DIRECT | |
- O_DIRECTORY | O_EXCL | O_LARGEFILE | O_NOATIME | |
- O_NOCTTY | O_NOFOLLOW | O_NONBLOCK | O_NDELAY | |
- O_SYNC | O_TRUNC; |
- |
- const int unknown_flags = ~known_flags; |
- const bool has_unknown_flags = creation_and_status_flags & unknown_flags; |
- return !has_unknown_flags; |
-} |
- |
-// Needs to be async signal safe if |file_to_open| is NULL. |
-// TODO(jln): assert signal safety. |
-bool GetFileNameInWhitelist(const std::vector<std::string>& allowed_file_names, |
- const char* requested_filename, |
- const char** file_to_open) { |
- if (file_to_open && *file_to_open) { |
- // Make sure that callers never pass a non-empty string. In case callers |
- // wrongly forget to check the return value and look at the string |
- // instead, this could catch bugs. |
- RAW_LOG(FATAL, "*file_to_open should be NULL"); |
- return false; |
- } |
- |
- // Look for |requested_filename| in |allowed_file_names|. |
- // We don't use ::find() because it takes a std::string and |
- // the conversion allocates memory. |
- for (const auto& allowed_file_name : allowed_file_names) { |
- if (strcmp(requested_filename, allowed_file_name.c_str()) == 0) { |
- if (file_to_open) |
- *file_to_open = allowed_file_name.c_str(); |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-} // namespace |
- |
BrokerPolicy::BrokerPolicy(int denied_errno, |
- const std::vector<std::string>& allowed_r_files, |
- const std::vector<std::string>& allowed_w_files) |
+ const std::vector<BrokerFilePermission>& permissions) |
: denied_errno_(denied_errno), |
- allowed_r_files_(allowed_r_files), |
- allowed_w_files_(allowed_w_files) { |
+ permissions_(permissions), |
+ num_of_permissions_(permissions.size()) { |
+ // The spec guarantees vectors store their elements contiguously |
+ // so set up a pointer to array of element so it can be used |
+ // in async signal safe code instead of vector operations. |
+ if (num_of_permissions_ > 0) { |
+ permissions_array_ = &permissions_[0]; |
+ } else { |
+ permissions_array_ = NULL; |
+ } |
} |
BrokerPolicy::~BrokerPolicy() { |
@@ -107,34 +50,20 @@ bool BrokerPolicy::GetFileNameIfAllowedToAccess( |
const char* requested_filename, |
int requested_mode, |
const char** file_to_access) const { |
- // First, check if |requested_mode| is existence, ability to read or ability |
- // to write. We do not support X_OK. |
- if (requested_mode != F_OK && requested_mode & ~(R_OK | W_OK)) { |
+ if (file_to_access && *file_to_access) { |
+ // Make sure that callers never pass a non-empty string. In case callers |
+ // wrongly forget to check the return value and look at the string |
+ // instead, this could catch bugs. |
+ RAW_LOG(FATAL, "*file_to_access should be NULL"); |
return false; |
} |
- switch (requested_mode) { |
- case F_OK: |
- // We allow to check for file existence if we can either read or write. |
- return GetFileNameInWhitelist( |
- allowed_r_files_, requested_filename, file_to_access) || |
- GetFileNameInWhitelist( |
- allowed_w_files_, requested_filename, file_to_access); |
- case R_OK: |
- return GetFileNameInWhitelist( |
- allowed_r_files_, requested_filename, file_to_access); |
- case W_OK: |
- return GetFileNameInWhitelist( |
- allowed_w_files_, requested_filename, file_to_access); |
- case R_OK | W_OK: { |
- bool allowed_for_read_and_write = |
- GetFileNameInWhitelist(allowed_r_files_, requested_filename, NULL) && |
- GetFileNameInWhitelist( |
- allowed_w_files_, requested_filename, file_to_access); |
- return allowed_for_read_and_write; |
+ for (size_t i = 0; i < num_of_permissions_; i++) { |
+ if (permissions_array_[i].CheckAccess(requested_filename, requested_mode, |
+ file_to_access)) { |
+ return true; |
} |
- default: |
- return false; |
} |
+ return false; |
} |
// Check if |requested_filename| can be opened with flags |requested_flags|. |
@@ -147,27 +76,22 @@ bool BrokerPolicy::GetFileNameIfAllowedToAccess( |
// Async signal safe if and only if |file_to_open| is NULL. |
bool BrokerPolicy::GetFileNameIfAllowedToOpen(const char* requested_filename, |
int requested_flags, |
- const char** file_to_open) const { |
- if (!IsAllowedOpenFlags(requested_flags)) { |
+ const char** file_to_open, |
+ bool* unlink_after_open) const { |
+ if (file_to_open && *file_to_open) { |
+ // Make sure that callers never pass a non-empty string. In case callers |
+ // wrongly forget to check the return value and look at the string |
+ // instead, this could catch bugs. |
+ RAW_LOG(FATAL, "*file_to_open should be NULL"); |
return false; |
} |
- switch (requested_flags & O_ACCMODE) { |
- case O_RDONLY: |
- return GetFileNameInWhitelist( |
- allowed_r_files_, requested_filename, file_to_open); |
- case O_WRONLY: |
- return GetFileNameInWhitelist( |
- allowed_w_files_, requested_filename, file_to_open); |
- case O_RDWR: { |
- bool allowed_for_read_and_write = |
- GetFileNameInWhitelist(allowed_r_files_, requested_filename, NULL) && |
- GetFileNameInWhitelist( |
- allowed_w_files_, requested_filename, file_to_open); |
- return allowed_for_read_and_write; |
+ for (size_t i = 0; i < num_of_permissions_; i++) { |
+ if (permissions_array_[i].CheckOpen(requested_filename, requested_flags, |
+ file_to_open, unlink_after_open)) { |
+ return true; |
} |
- default: |
- return false; |
} |
+ return false; |
} |
} // namespace syscall_broker |