Home | History | Annotate | Download | only in syscall_broker
      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