예제 #1
0
 def test_restricted_path_function_allowed(self):
   fake_function = self.mox.CreateMockAnything()
   fake_function('foo', bar='baz').AndReturn(1)
   stubs.FakeFile.is_file_accessible('foo').AndReturn(True)
   self.mox.ReplayAll()
   restricted_path_fake_function = stubs.RestrictedPathFunction(fake_function)
   self.assertEqual(1, restricted_path_fake_function('foo', bar='baz'))
   self.mox.VerifyAll()
예제 #2
0
def _install_open_hooks():
  """Install open hooks for sandbox."""
  if _open_hooks:
    for install_open_hook in _open_hooks:
      install_open_hook()
    # Assume installed open hooks don't enforce the sandbox path restrictions
    # and install a final hook to do that (the goal of hooks is to allow
    # alternate open techniques, not to circumvent the sandbox). It does mean
    # that open requests that make it to FakeFile have their path checked
    # twice but that doesn't break anything.
    __builtin__.open = stubs.RestrictedPathFunction(__builtin__.open, IOError)
예제 #3
0
 def test_restricted_path_function_not_allowed(self):
   fake_function = self.mox.CreateMockAnything()
   stubs.FakeFile.is_file_accessible('foo').AndReturn(False)
   self.mox.ReplayAll()
   restricted_path_fake_function = stubs.RestrictedPathFunction(fake_function)
   with self.assertRaises(OSError) as cm:
     restricted_path_fake_function('foo', bar='baz')
   self.mox.VerifyAll()
   e = cm.exception
   self.assertEqual(errno.EACCES, e.errno)
   self.assertEqual('path not accessible', e.strerror)
   self.assertEqual('foo', e.filename)
예제 #4
0
                    del module_dict[symbol]


_MODULE_OVERRIDE_POLICIES = {
    'os':
    ModuleOverridePolicy(
        default_stub=stubs.os_error_not_implemented,
        whitelist=[
            'altsep', 'curdir', 'defpath', 'devnull', 'environ', 'error',
            'fstat', 'getcwd', 'getcwdu', 'getenv', '_get_exports_list',
            'name', 'open', 'pardir', 'path', 'pathsep', 'sep',
            'stat_float_times', 'stat_result', 'strerror', 'sys', 'walk'
        ],
        overrides={
            'access': stubs.fake_access,
            'listdir': stubs.RestrictedPathFunction(os.listdir),
            # Alias lstat() to stat() to match the behavior in production.
            'lstat': stubs.RestrictedPathFunction(os.stat),
            'open': stubs.fake_open,
            'stat': stubs.RestrictedPathFunction(os.stat),
            'uname': stubs.fake_uname,
            'getpid': stubs.return_minus_one,
            'getppid': stubs.return_minus_one,
            'getpgrp': stubs.return_minus_one,
            'getgid': stubs.return_minus_one,
            'getegid': stubs.return_minus_one,
            'geteuid': stubs.return_minus_one,
            'getuid': stubs.return_minus_one,
            'urandom': stubs.fake_urandom,
            'system': stubs.return_minus_one,
        },
예제 #5
0
def enable_sandbox(config):
  """Enable the sandbox based on the configuration.

  This includes installing import hooks to restrict access to C modules and
  stub out functions that are not implemented in production, replacing the file
  builtins with read-only versions and add enabled libraries to the path.

  Args:
    config: The runtime_config_pb2.Config to use to configure the sandbox.
  """

  devnull = open(os.path.devnull)
  modules = [os, traceback, google]
  c_module = _find_shared_object_c_module()
  if c_module:
    modules.append(c_module)
  module_paths = [module.__file__ for module in modules]
  module_paths.extend([os.path.realpath(module.__file__) for module in modules])
  python_lib_paths = [config.application_root]
  for path in sys.path:
    if any(module_path.startswith(path) for module_path in module_paths):
      python_lib_paths.append(path)
  python_lib_paths.extend(_enable_libraries(config.libraries))
  for name in list(sys.modules):
    if not _should_keep_module(name):
      _removed_modules.append(sys.modules[name])
      del sys.modules[name]
  path_override_hook = PathOverrideImportHook(
      set(_THIRD_PARTY_LIBRARY_NAME_OVERRIDES.get(lib.name, lib.name)
          for lib in config.libraries).intersection(_C_MODULES))
  python_lib_paths.extend(path_override_hook.extra_sys_paths)
  stubs.FakeFile.set_allowed_paths(config.application_root,
                                   python_lib_paths[1:] +
                                   path_override_hook.extra_accessible_paths)
  stubs.FakeFile.set_skip_files(config.skip_files)
  stubs.FakeFile.set_static_files(config.static_files)
  __builtin__.file = stubs.FakeFile
  __builtin__.open = stubs.FakeFile
  types.FileType = stubs.FakeFile
  if _open_hooks:
    for install_open_hook in _open_hooks:
      install_open_hook()
    # Assume installed open hooks don't enforce the sandbox path restrictions
    # and install a final hook to do that (the goal of hooks is to allow
    # alternate open techniques, not to circumvent the sandbox). It does mean
    # that open requests that make it to FakeFile have their path checked
    # twice but that doesn't break anything.
    __builtin__.open = stubs.RestrictedPathFunction(__builtin__.open, IOError)
  sys.platform = 'linux3'
  enabled_library_regexes = [
      NAME_TO_CMODULE_WHITELIST_REGEX[lib.name] for lib in config.libraries
      if lib.name in NAME_TO_CMODULE_WHITELIST_REGEX]
  sys.meta_path = [
      StubModuleImportHook(),
      ModuleOverrideImportHook(_MODULE_OVERRIDE_POLICIES),
      CModuleImportHook(enabled_library_regexes),
      path_override_hook,
      PyCryptoRandomImportHook,
      PathRestrictingImportHook(enabled_library_regexes)
      ]
  sys.path_importer_cache = {}
  sys.path = python_lib_paths[:]

  thread = __import__('thread')
  __import__('%s.threading' % dist27.__name__)
  threading = sys.modules['%s.threading' % dist27.__name__]
  thread.start_new_thread = _make_request_id_aware_start_new_thread(
      thread.start_new_thread)
  # This import needs to be after enabling the sandbox so it imports the
  # sandboxed version of the logging module.
  from google.appengine.runtime import runtime
  runtime.PatchStartNewThread(thread)
  threading._start_new_thread = thread.start_new_thread

  os.chdir(config.application_root)
  sandboxed_os = __import__('os')
  request_environment.PatchOsEnviron(sandboxed_os)
  os.__dict__.update(sandboxed_os.__dict__)
  _init_logging(config.stderr_log_level)
  pdb_sandbox.install(config)
  sys.stdin = devnull
  sys.stdout = sys.stderr