1 // Copyright 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 "sandbox/linux/syscall_broker/broker_policy.h" 6 7 #include <fcntl.h> 8 #include <stddef.h> 9 #include <stdint.h> 10 #include <string.h> 11 12 #include <string> 13 #include <vector> 14 15 #include "base/logging.h" 16 #include "sandbox/linux/syscall_broker/broker_common.h" 17 18 namespace sandbox { 19 namespace syscall_broker { 20 21 BrokerPolicy::BrokerPolicy(int denied_errno, 22 const std::vector<BrokerFilePermission>& permissions) 23 : denied_errno_(denied_errno), 24 permissions_(permissions), 25 num_of_permissions_(permissions.size()) { 26 // The spec guarantees vectors store their elements contiguously 27 // so set up a pointer to array of element so it can be used 28 // in async signal safe code instead of vector operations. 29 if (num_of_permissions_ > 0) { 30 permissions_array_ = &permissions_[0]; 31 } else { 32 permissions_array_ = NULL; 33 } 34 } 35 36 BrokerPolicy::~BrokerPolicy() { 37 } 38 39 // Check if calling access() should be allowed on |requested_filename| with 40 // mode |requested_mode|. 41 // Note: access() being a system call to check permissions, this can get a bit 42 // confusing. We're checking if calling access() should even be allowed with 43 // the same policy we would use for open(). 44 // If |file_to_access| is not NULL, we will return the matching pointer from 45 // the whitelist. For paranoia a caller should then use |file_to_access|. See 46 // GetFileNameIfAllowedToOpen() for more explanation. 47 // return true if calling access() on this file should be allowed, false 48 // otherwise. 49 // Async signal safe if and only if |file_to_access| is NULL. 50 bool BrokerPolicy::GetFileNameIfAllowedToAccess( 51 const char* requested_filename, 52 int requested_mode, 53 const char** file_to_access) const { 54 if (file_to_access && *file_to_access) { 55 // Make sure that callers never pass a non-empty string. In case callers 56 // wrongly forget to check the return value and look at the string 57 // instead, this could catch bugs. 58 RAW_LOG(FATAL, "*file_to_access should be NULL"); 59 return false; 60 } 61 for (size_t i = 0; i < num_of_permissions_; i++) { 62 if (permissions_array_[i].CheckAccess(requested_filename, requested_mode, 63 file_to_access)) { 64 return true; 65 } 66 } 67 return false; 68 } 69 70 // Check if |requested_filename| can be opened with flags |requested_flags|. 71 // If |file_to_open| is not NULL, we will return the matching pointer from the 72 // whitelist. For paranoia, a caller should then use |file_to_open| rather 73 // than |requested_filename|, so that it never attempts to open an 74 // attacker-controlled file name, even if an attacker managed to fool the 75 // string comparison mechanism. 76 // Return true if opening should be allowed, false otherwise. 77 // Async signal safe if and only if |file_to_open| is NULL. 78 bool BrokerPolicy::GetFileNameIfAllowedToOpen(const char* requested_filename, 79 int requested_flags, 80 const char** file_to_open, 81 bool* unlink_after_open) const { 82 if (file_to_open && *file_to_open) { 83 // Make sure that callers never pass a non-empty string. In case callers 84 // wrongly forget to check the return value and look at the string 85 // instead, this could catch bugs. 86 RAW_LOG(FATAL, "*file_to_open should be NULL"); 87 return false; 88 } 89 for (size_t i = 0; i < num_of_permissions_; i++) { 90 if (permissions_array_[i].CheckOpen(requested_filename, requested_flags, 91 file_to_open, unlink_after_open)) { 92 return true; 93 } 94 } 95 return false; 96 } 97 98 } // namespace syscall_broker 99 100 } // namespace sandbox 101