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
BrokerPolicy(int denied_errno,const std::vector<BrokerFilePermission> & permissions)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
~BrokerPolicy()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.
GetFileNameIfAllowedToAccess(const char * requested_filename,int requested_mode,const char ** file_to_access) const50 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.
GetFileNameIfAllowedToOpen(const char * requested_filename,int requested_flags,const char ** file_to_open,bool * unlink_after_open) const78 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