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)) # Note that the above code (see _find_shared_object_c_module) imports modules # that must be pruned so please use care if you move the call to # _prune_sys_modules. _prune_sys_modules() path_override_hook = PathOverrideImportHook( THIRD_PARTY_C_MODULES.get_importable_module_names(config)) python_lib_paths.extend(path_override_hook.extra_sys_paths) if not config.vm: _install_fake_file(config, python_lib_paths, path_override_hook) _install_open_hooks() # NOTE(user): The sys.platform was a hack needed to solve # b/7482060. After python version 2.7.4 this is no longer needed. def was_created_before(ver1, ver2): """Returns true if the integer tuple ver1 is less than the tuple ver2.""" if ver1[0] != ver2[0]: return ver1[0] < ver2[0] elif ver1[1] != ver2[1]: return ver1[1] < ver2[1] else: return ver1[2] < ver2[2] if was_created_before(sys.version_info, (2, 7, 4)): sys.platform = 'linux3' _install_import_hooks(config, path_override_hook) sys.path_importer_cache = {} if not config.vm: sys.path = python_lib_paths[:] else: # Use anything present on the sys.path if the runtime is on a vm. # This lets users use deps installed with pip. sys.path.extend(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
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)) # Note that the above code (see _find_shared_object_c_module) imports modules # that must be pruned so please use care if you move the call to # _prune_sys_modules. _prune_sys_modules() path_override_hook = PathOverrideImportHook( THIRD_PARTY_C_MODULES.get_importable_module_names(config)) python_lib_paths.extend(path_override_hook.extra_sys_paths) if not config.vm: _install_fake_file(config, python_lib_paths, path_override_hook) _install_open_hooks() # NOTE(user): The sys.platform was a hack needed to solve # b/7482060. After python version 2.7.4 this is no longer needed. def was_created_before(ver1, ver2): """Returns true if the integer tuple ver1 is less than the tuple ver2.""" if ver1[0] != ver2[0]: return ver1[0] < ver2[0] elif ver1[1] != ver2[1]: return ver1[1] < ver2[1] else: return ver1[2] < ver2[2] if was_created_before(sys.version_info, (2, 7, 4)): sys.platform = 'linux3' _install_import_hooks(config, path_override_hook) sys.path_importer_cache = {} if not config.vm: sys.path = python_lib_paths[:] else: # Use anything present on the sys.path if the runtime is on a vm. # This lets users use deps installed with pip. sys.path.extend(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