diff options
author | tsepez@chromium.org <tsepez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-08 19:31:34 +0000 |
---|---|---|
committer | tsepez@chromium.org <tsepez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-08 19:31:34 +0000 |
commit | 6136d0622a9bc8cd3e5d339e31708bc31e420847 (patch) | |
tree | abaaa069776336379fa026f90173c98b4163ff5b | |
parent | ca71ec7b50d002c0b16e5fea5003c38ce13d9788 (diff) | |
download | chromium_src-6136d0622a9bc8cd3e5d339e31708bc31e420847.zip chromium_src-6136d0622a9bc8cd3e5d339e31708bc31e420847.tar.gz chromium_src-6136d0622a9bc8cd3e5d339e31708bc31e420847.tar.bz2 |
Check that the files the renderer wants to preserve as part of a session restore are already available to the renderer.
The fix involves cracking open the WebHistoryItem, extracting its file paths,
and checking them against ChildProcessSecurityPolicy for the messages
ViewHostMsg_UpdateState and ViewHostMsg_FrameNavigate.
BUG=237263
R=darin@chromium.org
Review URL: https://codereview.chromium.org/14727006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@198965 0039d316-1c4b-4281-b951-d872f2087c98
5 files changed, 122 insertions, 11 deletions
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 8424da9..d3363f5 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc @@ -67,6 +67,7 @@ #include "ui/shell_dialogs/selected_file_info.h" #include "ui/snapshot/snapshot.h" #include "webkit/fileapi/isolated_context.h" +#include "webkit/glue/glue_serialize.h" #include "webkit/glue/webdropdata.h" #include "webkit/glue/webkit_glue.h" @@ -1224,11 +1225,25 @@ void RenderViewHostImpl::OnNavigate(const IPC::Message& msg) { FilterURL(policy, process, true, &validated_params.password_form.origin); FilterURL(policy, process, true, &validated_params.password_form.action); + // Without this check, the renderer can trick the browser into using + // filenames it can't access in a future session restore. + if (!CanAccessFilesOfSerializedState(validated_params.content_state)) { + GetProcess()->ReceivedBadMessage(); + return; + } + delegate_->DidNavigate(this, validated_params); } void RenderViewHostImpl::OnUpdateState(int32 page_id, const std::string& state) { + // Without this check, the renderer can trick the browser into using + // filenames it can't access in a future session restore. + if (!CanAccessFilesOfSerializedState(state)) { + GetProcess()->ReceivedBadMessage(); + return; + } + delegate_->UpdateState(this, page_id, state); } @@ -2042,4 +2057,18 @@ void RenderViewHostImpl::ClearPowerSaveBlockers() { STLDeleteValues(&power_save_blockers_); } +bool RenderViewHostImpl::CanAccessFilesOfSerializedState( + const std::string& state) const { + ChildProcessSecurityPolicyImpl* policy = + ChildProcessSecurityPolicyImpl::GetInstance(); + const std::vector<base::FilePath>& file_paths = + webkit_glue::FilePathsFromHistoryState(state); + for (std::vector<base::FilePath>::const_iterator file = file_paths.begin(); + file != file_paths.end(); ++file) { + if (!policy->CanReadFile(GetProcess()->GetID(), *file)) + return false; + } + return true; +} + } // namespace content diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index baa4b2e..a03ba43 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h @@ -562,6 +562,8 @@ class CONTENT_EXPORT RenderViewHostImpl void ClearPowerSaveBlockers(); + bool CanAccessFilesOfSerializedState(const std::string& state) const; + // Our delegate, which wants to know about changes in the RenderView. RenderViewHostDelegate* delegate_; diff --git a/content/browser/renderer_host/render_view_host_unittest.cc b/content/browser/renderer_host/render_view_host_unittest.cc index 7c5898e..38bb777 100644 --- a/content/browser/renderer_host/render_view_host_unittest.cc +++ b/content/browser/renderer_host/render_view_host_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/path_service.h" #include "base/utf_string_conversions.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/renderer_host/test_render_view_host.h" @@ -261,4 +262,41 @@ TEST_F(RenderViewHostTest, BadMessageHandlerInputEventAck) { #endif +TEST_F(RenderViewHostTest, MessageWithBadHistoryItemFiles) { + base::FilePath file_path; + EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path)); + file_path = file_path.AppendASCII("foo"); + EXPECT_EQ(0, process()->bad_msg_count()); + test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path); + EXPECT_EQ(1, process()->bad_msg_count()); + + ChildProcessSecurityPolicyImpl::GetInstance()->GrantPermissionsForFile( + process()->GetID(), file_path, + base::PLATFORM_FILE_OPEN | + base::PLATFORM_FILE_READ | + base::PLATFORM_FILE_EXCLUSIVE_READ | + base::PLATFORM_FILE_ASYNC); + test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path); + EXPECT_EQ(1, process()->bad_msg_count()); +} + +TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) { + GURL url("http://www.google.com"); + base::FilePath file_path; + EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path)); + file_path = file_path.AppendASCII("bar"); + EXPECT_EQ(0, process()->bad_msg_count()); + test_rvh()->SendNavigateWithFile(1, url, file_path); + EXPECT_EQ(1, process()->bad_msg_count()); + + ChildProcessSecurityPolicyImpl::GetInstance()->GrantPermissionsForFile( + process()->GetID(), file_path, + base::PLATFORM_FILE_OPEN | + base::PLATFORM_FILE_READ | + base::PLATFORM_FILE_EXCLUSIVE_READ | + base::PLATFORM_FILE_ASYNC); + test_rvh()->SendNavigateWithFile(process()->GetID(), url, file_path); + EXPECT_EQ(1, process()->bad_msg_count()); +} + } // namespace content diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc index 0e1792a..6f5310f 100644 --- a/content/browser/renderer_host/test_render_view_host.cc +++ b/content/browser/renderer_host/test_render_view_host.cc @@ -289,21 +289,27 @@ void TestRenderViewHost::SendNavigateWithOriginalRequestURL( int page_id, const GURL& url, const GURL& original_request_url) { OnDidStartProvisionalLoadForFrame(0, -1, true, url); SendNavigateWithParameters(page_id, url, PAGE_TRANSITION_LINK, - original_request_url, 200); + original_request_url, 200, 0); +} + +void TestRenderViewHost::SendNavigateWithFile( + int page_id, const GURL& url, const base::FilePath& file_path) { + SendNavigateWithParameters(page_id, url, PAGE_TRANSITION_LINK, + url, 200, &file_path); } void TestRenderViewHost::SendNavigateWithTransitionAndResponseCode( int page_id, const GURL& url, PageTransition transition, int response_code) { OnDidStartProvisionalLoadForFrame(0, -1, true, url); - SendNavigateWithParameters(page_id, url, transition, url, response_code); + SendNavigateWithParameters(page_id, url, transition, url, response_code, 0); } void TestRenderViewHost::SendNavigateWithParameters( int page_id, const GURL& url, PageTransition transition, - const GURL& original_request_url, int response_code) { + const GURL& original_request_url, int response_code, + const base::FilePath* file_path_for_history_item) { ViewHostMsg_FrameNavigate_Params params; - params.page_id = page_id; params.frame_id = 0; params.url = url; @@ -324,9 +330,23 @@ void TestRenderViewHost::SendNavigateWithParameters( params.socket_address.set_port(80); params.was_fetched_via_proxy = simulate_fetch_via_proxy_; params.history_list_was_cleared = simulate_history_list_was_cleared_; - params.content_state = webkit_glue::CreateHistoryStateForURL(GURL(url)); params.original_request_url = original_request_url; + WebKit::WebHTTPBody http_body; + http_body.initialize(); + + WebKit::WebHistoryItem history_item; + history_item.initialize(); + history_item.setURLString(WebKit::WebString::fromUTF8(url.spec())); + if (file_path_for_history_item) { + const char char_data[] = "data"; + http_body.appendData(WebKit::WebData(char_data, arraysize(char_data)-1)); + http_body.appendFile(WebKit::WebString::fromUTF8( + file_path_for_history_item->MaybeAsASCII())); + history_item.setHTTPBody(http_body); + } + params.content_state = webkit_glue::HistoryItemToString(history_item); + ViewHostMsg_FrameNavigate msg(1, params); OnNavigate(msg); } @@ -360,6 +380,22 @@ void TestRenderViewHost::TestOnStartDragging( event_info); } +void TestRenderViewHost::TestOnUpdateStateWithFile( + int process_id, + const base::FilePath& file_path) { + WebKit::WebHTTPBody http_body; + http_body.initialize(); + const char char_data[] = "data"; + http_body.appendData(WebKit::WebData(char_data, arraysize(char_data)-1)); + http_body.appendFile(WebKit::WebString::fromUTF8(file_path.MaybeAsASCII())); + + WebKit::WebHistoryItem history_item; + history_item.initialize(); + history_item.setURLString("http://www.google.com"); + history_item.setHTTPBody(http_body); + OnUpdateState(process_id, webkit_glue::HistoryItemToString(history_item)); +} + void TestRenderViewHost::set_simulate_fetch_via_proxy(bool proxy) { simulate_fetch_via_proxy_ = proxy; } diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h index a6ec555..68634d4 100644 --- a/content/browser/renderer_host/test_render_view_host.h +++ b/content/browser/renderer_host/test_render_view_host.h @@ -246,6 +246,11 @@ class TestRenderViewHost void SendNavigateWithOriginalRequestURL( int page_id, const GURL& url, const GURL& original_request_url); + void SendNavigateWithFile( + int page_id, const GURL& url, const base::FilePath& file_path); + + void TestOnUpdateStateWithFile( + int process_id, const base::FilePath& file_path); void TestOnStartDragging(const WebDropData& drop_data); @@ -307,12 +312,13 @@ class TestRenderViewHost // Calls OnNavigate on the RenderViewHost with the given information. // Sets the rest of the parameters in the message to the "typical" values. // This is a helper function for simulating the most common types of loads. - void SendNavigateWithParameters(int page_id, - const GURL& url, - PageTransition transition, - const GURL& original_request_url, - int response_code); - + void SendNavigateWithParameters( + int page_id, + const GURL& url, + PageTransition transition, + const GURL& original_request_url, + int response_code, + const base::FilePath* file_path_for_history_item); // Tracks if the caller thinks if it created the RenderView. This is so we can // respond to IsRenderViewLive appropriately. |