• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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