diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-20 11:51:53 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-20 11:51:53 +0000 |
commit | 809d34b1007ff081775a3923356421b973724c33 (patch) | |
tree | 6ffe487c929268b7928d1ae6f61a7520bee7acd2 | |
parent | 87738f7d5cdb54e524520144f28baa78e38098e2 (diff) | |
download | chromium_src-809d34b1007ff081775a3923356421b973724c33.zip chromium_src-809d34b1007ff081775a3923356421b973724c33.tar.gz chromium_src-809d34b1007ff081775a3923356421b973724c33.tar.bz2 |
Enable sandbox in local discovery utility process.
Local discovery in sandbox works only on Windows, linux requires --no-sandbox.
BUG=245391
Review URL: https://chromiumcodereview.appspot.com/19737002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@212781 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/chrome_main_delegate.cc | 5 | ||||
-rw-r--r-- | chrome/browser/local_discovery/service_discovery_host_client.cc | 3 | ||||
-rw-r--r-- | chrome/utility/chrome_content_utility_client.cc | 6 | ||||
-rw-r--r-- | chrome/utility/chrome_content_utility_client.h | 2 | ||||
-rw-r--r-- | chrome/utility/local_discovery/service_discovery_message_handler.cc | 155 | ||||
-rw-r--r-- | chrome/utility/local_discovery/service_discovery_message_handler.h | 5 | ||||
-rw-r--r-- | content/browser/utility_process_host_impl.cc | 11 | ||||
-rw-r--r-- | content/browser/utility_process_host_impl.h | 4 | ||||
-rw-r--r-- | content/public/browser/utility_process_host.h | 3 | ||||
-rw-r--r-- | content/public/common/content_switches.cc | 3 | ||||
-rw-r--r-- | content/public/common/content_switches.h | 1 |
11 files changed, 185 insertions, 13 deletions
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index ab692b6..4077d3c 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc @@ -636,6 +636,11 @@ void ChromeMainDelegate::PreSandboxStartup() { // only do this when ResourcesBundle has been initialized). SetMacProcessName(command_line); #endif // defined(OS_MACOSX) + +#if !defined(CHROME_MULTIPLE_DLL_BROWSER) + if (process_type == switches::kUtilityProcess) + chrome::ChromeContentUtilityClient::PreSandboxStartup(); +#endif } #if defined(OS_POSIX) && !defined(OS_MACOSX) diff --git a/chrome/browser/local_discovery/service_discovery_host_client.cc b/chrome/browser/local_discovery/service_discovery_host_client.cc index 2d6db4b..42b5a22 100644 --- a/chrome/browser/local_discovery/service_discovery_host_client.cc +++ b/chrome/browser/local_discovery/service_discovery_host_client.cc @@ -163,8 +163,7 @@ void ServiceDiscoveryHostClient::StartOnIOThread() { this, base::MessageLoopProxy::current().get())->AsWeakPtr(); if (utility_host_) { utility_host_->EnableZygote(); - // TODO(vitalybuka): enable sandbox. http://crbug.com/245391 - utility_host_->DisableSandbox(); + utility_host_->EnableMDns(); utility_host_->StartBatchMode(); } } diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc index 967352b..b5db0fd 100644 --- a/chrome/utility/chrome_content_utility_client.cc +++ b/chrome/utility/chrome_content_utility_client.cc @@ -151,6 +151,12 @@ bool ChromeContentUtilityClient::OnMessageReceived( return handled; } +void ChromeContentUtilityClient::PreSandboxStartup() { +#if defined(ENABLE_MDNS) + local_discovery::ServiceDiscoveryMessageHandler::PreSandboxStartup(); +#endif // ENABLE_MDNS +} + void ChromeContentUtilityClient::OnUnpackExtension( const base::FilePath& extension_path, const std::string& extension_id, diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h index 0495029..c155cf5 100644 --- a/chrome/utility/chrome_content_utility_client.h +++ b/chrome/utility/chrome_content_utility_client.h @@ -41,6 +41,8 @@ class ChromeContentUtilityClient : public content::ContentUtilityClient { virtual void UtilityThreadStarted() OVERRIDE; virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + static void PreSandboxStartup(); + private: // IPC message handlers. void OnUnpackExtension(const base::FilePath& extension_path, diff --git a/chrome/utility/local_discovery/service_discovery_message_handler.cc b/chrome/utility/local_discovery/service_discovery_message_handler.cc index e401226..2630c80 100644 --- a/chrome/utility/local_discovery/service_discovery_message_handler.cc +++ b/chrome/utility/local_discovery/service_discovery_message_handler.cc @@ -4,10 +4,121 @@ #include "chrome/utility/local_discovery/service_discovery_message_handler.h" +#include "base/command_line.h" #include "chrome/common/local_discovery/local_discovery_messages.h" #include "chrome/utility/local_discovery/service_discovery_client_impl.h" +#include "content/public/common/content_switches.h" #include "content/public/utility/utility_thread.h" +#if defined(OS_WIN) + +#include "base/lazy_instance.h" +#include "net/base/winsock_init.h" +#include "net/base/winsock_util.h" + +#endif // OS_WIN + +namespace { + +bool NeedsSockets() { + return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox) && + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUtilityProcessEnableMDns); +} + +#if defined(OS_WIN) + +class SocketFactory : public net::PlatformSocketFactory { + public: + SocketFactory() + : socket_v4_(NULL), + socket_v6_(NULL) { + net::EnsureWinsockInit(); + socket_v4_ = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, + WSA_FLAG_OVERLAPPED); + socket_v6_ = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, + WSA_FLAG_OVERLAPPED); + } + + void Reset() { + if (socket_v4_ != INVALID_SOCKET) { + closesocket(socket_v4_); + socket_v4_ = INVALID_SOCKET; + } + if (socket_v6_ != INVALID_SOCKET) { + closesocket(socket_v6_); + socket_v6_ = INVALID_SOCKET; + } + } + + virtual ~SocketFactory() { + Reset(); + } + + virtual SOCKET CreateSocket(int family, int type, int protocol) OVERRIDE { + SOCKET result = INVALID_SOCKET; + if (type != SOCK_DGRAM && protocol != IPPROTO_UDP) { + NOTREACHED(); + } else if (family == AF_INET) { + std::swap(result, socket_v4_); + } else if (family == AF_INET6) { + std::swap(result, socket_v6_); + } + return result; + } + + SOCKET socket_v4_; + SOCKET socket_v6_; + + DISALLOW_COPY_AND_ASSIGN(SocketFactory); +}; + +base::LazyInstance<SocketFactory> + g_local_discovery_socket_factory = LAZY_INSTANCE_INITIALIZER; + +class ScopedSocketFactorySetter { + public: + ScopedSocketFactorySetter() { + if (NeedsSockets()) { + net::PlatformSocketFactory::SetInstance( + &g_local_discovery_socket_factory.Get()); + } + } + + ~ScopedSocketFactorySetter() { + if (NeedsSockets()) { + net::PlatformSocketFactory::SetInstance(NULL); + g_local_discovery_socket_factory.Get().Reset(); + } + } + + static void Initialize() { + if (NeedsSockets()) { + g_local_discovery_socket_factory.Get(); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedSocketFactorySetter); +}; + +#else // OS_WIN + +class ScopedSocketFactorySetter { + public: + ScopedSocketFactorySetter() {} + + static void Initialize() { + // TODO(vitalybuka) : implement socket access from sandbox for other + // platforms. + DCHECK(!NeedsSockets()); + } +}; + +#endif // OS_WIN + +} // namespace + namespace local_discovery { ServiceDiscoveryMessageHandler::ServiceDiscoveryMessageHandler() { @@ -16,13 +127,28 @@ ServiceDiscoveryMessageHandler::ServiceDiscoveryMessageHandler() { ServiceDiscoveryMessageHandler::~ServiceDiscoveryMessageHandler() { } -void ServiceDiscoveryMessageHandler::Initialize() { - if (!service_discovery_client_) { - mdns_client_ = net::MDnsClient::CreateDefault(); - mdns_client_->StartListening(); - service_discovery_client_.reset( - new local_discovery::ServiceDiscoveryClientImpl(mdns_client_.get())); +void ServiceDiscoveryMessageHandler::PreSandboxStartup() { + ScopedSocketFactorySetter::Initialize(); +} + +bool ServiceDiscoveryMessageHandler::Initialize() { + if (service_discovery_client_) + return true; + + if (mdns_client_) // We tried but failed before. + return false; + + mdns_client_ = net::MDnsClient::CreateDefault(); + { + // Temporarily redirect network code to use pre-created sockets. + ScopedSocketFactorySetter socket_factory_setter; + if (!mdns_client_->StartListening()) + return false; } + + service_discovery_client_.reset( + new local_discovery::ServiceDiscoveryClientImpl(mdns_client_.get())); + return true; } bool ServiceDiscoveryMessageHandler::OnMessageReceived( @@ -42,7 +168,8 @@ bool ServiceDiscoveryMessageHandler::OnMessageReceived( void ServiceDiscoveryMessageHandler::OnStartWatcher( uint64 id, const std::string& service_type) { - Initialize(); + if (!Initialize()) + return; DCHECK(!ContainsKey(service_watchers_, id)); scoped_ptr<ServiceWatcher> watcher( service_discovery_client_->CreateServiceWatcher( @@ -54,12 +181,16 @@ void ServiceDiscoveryMessageHandler::OnStartWatcher( } void ServiceDiscoveryMessageHandler::OnDiscoverServices(uint64 id, - bool force_update) { + bool force_update) { + if (!service_discovery_client_) + return; DCHECK(ContainsKey(service_watchers_, id)); service_watchers_[id]->DiscoverNewServices(force_update); } void ServiceDiscoveryMessageHandler::OnDestroyWatcher(uint64 id) { + if (!service_discovery_client_) + return; DCHECK(ContainsKey(service_watchers_, id)); service_watchers_.erase(id); } @@ -67,7 +198,8 @@ void ServiceDiscoveryMessageHandler::OnDestroyWatcher(uint64 id) { void ServiceDiscoveryMessageHandler::OnResolveService( uint64 id, const std::string& service_name) { - Initialize(); + if (!Initialize()) + return; DCHECK(!ContainsKey(service_resolvers_, id)); scoped_ptr<ServiceResolver> resolver( service_discovery_client_->CreateServiceResolver( @@ -79,6 +211,8 @@ void ServiceDiscoveryMessageHandler::OnResolveService( } void ServiceDiscoveryMessageHandler::OnDestroyResolver(uint64 id) { + if (!service_discovery_client_) + return; DCHECK(ContainsKey(service_resolvers_, id)); service_resolvers_.erase(id); } @@ -87,6 +221,7 @@ void ServiceDiscoveryMessageHandler::OnServiceUpdated( uint64 id, ServiceWatcher::UpdateType update, const std::string& name) { + DCHECK(service_discovery_client_); content::UtilityThread::Get()->Send( new LocalDiscoveryHostMsg_WatcherCallback(id, update, name)); } @@ -95,8 +230,10 @@ void ServiceDiscoveryMessageHandler::OnServiceResolved( uint64 id, ServiceResolver::RequestStatus status, const ServiceDescription& description) { + DCHECK(service_discovery_client_); content::UtilityThread::Get()->Send( new LocalDiscoveryHostMsg_ResolverCallback(id, status, description)); } } // namespace local_discovery + diff --git a/chrome/utility/local_discovery/service_discovery_message_handler.h b/chrome/utility/local_discovery/service_discovery_message_handler.h index 8b4bd1a..c1b9130 100644 --- a/chrome/utility/local_discovery/service_discovery_message_handler.h +++ b/chrome/utility/local_discovery/service_discovery_message_handler.h @@ -28,12 +28,14 @@ class ServiceDiscoveryMessageHandler : public chrome::UtilityMessageHandler { // UtilityMessageHandler implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + static void PreSandboxStartup(); + private: typedef std::map<uint64, linked_ptr<ServiceWatcher> > ServiceWatchers; typedef std::map<uint64, linked_ptr<ServiceResolver> > ServiceResolvers; // Lazy initializes ServiceDiscoveryClient. - void Initialize(); + bool Initialize(); // IPC message handlers. void OnStartWatcher(uint64 id, const std::string& service_type); @@ -62,3 +64,4 @@ class ServiceDiscoveryMessageHandler : public chrome::UtilityMessageHandler { } // namespace local_discovery #endif // CHROME_UTILITY_LOCAL_DISCOVERY_SERVICE_DISCOVERY_MESSAGE_HANDLER_H_ + diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc index bf65674..6e9dfa7 100644 --- a/content/browser/utility_process_host_impl.cc +++ b/content/browser/utility_process_host_impl.cc @@ -111,6 +111,7 @@ UtilityProcessHostImpl::UtilityProcessHostImpl( : client_(client), client_task_runner_(client_task_runner), is_batch_mode_(false), + is_mdns_enabled_(false), no_sandbox_(false), #if defined(OS_LINUX) child_flags_(ChildProcessHost::CHILD_ALLOW_SELF), @@ -123,7 +124,8 @@ UtilityProcessHostImpl::UtilityProcessHostImpl( UtilityProcessHostImpl::~UtilityProcessHostImpl() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DCHECK(!is_batch_mode_); + if (is_batch_mode_) + EndBatchMode(); } bool UtilityProcessHostImpl::Send(IPC::Message* message) { @@ -150,6 +152,10 @@ void UtilityProcessHostImpl::SetExposedDir(const base::FilePath& dir) { exposed_dir_ = dir; } +void UtilityProcessHostImpl::EnableMDns() { + is_mdns_enabled_ = true; +} + void UtilityProcessHostImpl::DisableSandbox() { no_sandbox_ = true; } @@ -244,6 +250,9 @@ bool UtilityProcessHostImpl::StartProcess() { cmd_line->AppendSwitchPath(switches::kUtilityProcessAllowedDir, exposed_dir_); #endif + if (is_mdns_enabled_) + cmd_line->AppendSwitch(switches::kUtilityProcessEnableMDns); + bool use_zygote = false; #if defined(OS_LINUX) diff --git a/content/browser/utility_process_host_impl.h b/content/browser/utility_process_host_impl.h index 779bc02..45d2b3f 100644 --- a/content/browser/utility_process_host_impl.h +++ b/content/browser/utility_process_host_impl.h @@ -37,6 +37,7 @@ class CONTENT_EXPORT UtilityProcessHostImpl virtual bool StartBatchMode() OVERRIDE; virtual void EndBatchMode() OVERRIDE; virtual void SetExposedDir(const base::FilePath& dir) OVERRIDE; + virtual void EnableMDns() OVERRIDE; virtual void DisableSandbox() OVERRIDE; virtual void EnableZygote() OVERRIDE; virtual const ChildProcessData& GetData() OVERRIDE; @@ -64,6 +65,9 @@ class CONTENT_EXPORT UtilityProcessHostImpl base::FilePath exposed_dir_; + // Whether utility process needs perform presandbox initialization for MDns. + bool is_mdns_enabled_; + // Whether to pass switches::kNoSandbox to the child. bool no_sandbox_; diff --git a/content/public/browser/utility_process_host.h b/content/public/browser/utility_process_host.h index 5f280c6..efd06b81e 100644 --- a/content/public/browser/utility_process_host.h +++ b/content/public/browser/utility_process_host.h @@ -50,6 +50,9 @@ class UtilityProcessHost : public IPC::Sender, // the operation. virtual void SetExposedDir(const base::FilePath& dir) = 0; + // Allows a mdns to use network in sandbox. + virtual void EnableMDns() = 0; + // Make the process run without a sandbox. virtual void DisableSandbox() = 0; diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index bc6d2b8..36089c9 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -795,6 +795,9 @@ const char kUtilityProcess[] = "utility"; // specifies the directory that can be accessed. const char kUtilityProcessAllowedDir[] = "utility-allowed-dir"; +// Allows MDns to access network in sandboxed process. +const char kUtilityProcessEnableMDns[] = "utility-enable-mdns"; + // Will add kWaitForDebugger to every child processes. If a value is passed, it // will be used as a filter to determine if the child process should have the // kWaitForDebugger flag passed on or not. diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 1e11290..d0c66bb 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -236,6 +236,7 @@ CONTENT_EXPORT extern const char kUserAgent[]; extern const char kUtilityCmdPrefix[]; CONTENT_EXPORT extern const char kUtilityProcess[]; extern const char kUtilityProcessAllowedDir[]; +CONTENT_EXPORT extern const char kUtilityProcessEnableMDns[]; CONTENT_EXPORT extern const char kWaitForDebuggerChildren[]; extern const char kWebCoreLogChannels[]; CONTENT_EXPORT extern const char kWorkerProcess[]; |