summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-28 01:09:19 +0000
committerdumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-28 01:09:19 +0000
commite54edc37fb21741c9e5cacf6ff330da03332391e (patch)
tree019296a52bdf4d5b2a3e7a2e65158ce4e26c3986 /chrome
parentf05327a72316227c3439026f5b7ec4ac876530d4 (diff)
downloadchromium_src-e54edc37fb21741c9e5cacf6ff330da03332391e.zip
chromium_src-e54edc37fb21741c9e5cacf6ff330da03332391e.tar.gz
chromium_src-e54edc37fb21741c9e5cacf6ff330da03332391e.tar.bz2
Change ChildProcessSecurityPolicy to store a list of allowed flags for
each file. BUG=none TEST=none Review URL: http://codereview.chromium.org/3431032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60742 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/child_process_security_policy.cc55
-rw-r--r--chrome/browser/child_process_security_policy.h16
-rw-r--r--chrome/browser/child_process_security_policy_unittest.cc89
-rw-r--r--chrome/browser/plugin_process_host.cc2
-rw-r--r--chrome/browser/renderer_host/blob_dispatcher_host.cc2
-rw-r--r--chrome/browser/renderer_host/redirect_to_file_resource_handler.cc2
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc4
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.cc2
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc8
9 files changed, 143 insertions, 37 deletions
diff --git a/chrome/browser/child_process_security_policy.cc b/chrome/browser/child_process_security_policy.cc
index 54ee31e..5068e57 100644
--- a/chrome/browser/child_process_security_policy.cc
+++ b/chrome/browser/child_process_security_policy.cc
@@ -6,6 +6,7 @@
#include "base/file_path.h"
#include "base/logging.h"
+#include "base/platform_file.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "chrome/common/bindings_policy.h"
@@ -13,6 +14,12 @@
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request.h"
+const int kReadFilePermissions =
+ base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_EXCLUSIVE_READ |
+ base::PLATFORM_FILE_ASYNC;
+
// The SecurityState class is used to maintain per-renderer security state
// information.
class ChildProcessSecurityPolicy::SecurityState {
@@ -34,9 +41,9 @@ class ChildProcessSecurityPolicy::SecurityState {
scheme_policy_[scheme] = false;
}
- // Grant permission to upload the specified file to the web.
- void GrantUploadFile(const FilePath& file) {
- uploadable_files_.insert(file);
+ // Grant certain permissions to a file.
+ void GrantPermissionsForFile(const FilePath& file, int permissions) {
+ file_permissions_[file.StripTrailingSeparators()] |= permissions;
}
void GrantBindings(int bindings) {
@@ -62,10 +69,18 @@ class ChildProcessSecurityPolicy::SecurityState {
return judgment->second;
}
- // Determine whether permission has been granted to upload file.
- // Files that have not been granted default to being denied.
- bool CanUploadFile(const FilePath& file) {
- return uploadable_files_.find(file) != uploadable_files_.end();
+ // Determine if the certain permissions have been granted to a file.
+ bool HasPermissionsForFile(const FilePath& file, int permissions) {
+ FilePath current_path = file.StripTrailingSeparators();
+ FilePath last_path;
+ while (current_path != last_path) {
+ if (file_permissions_.find(current_path) != file_permissions_.end())
+ return (file_permissions_[current_path] & permissions) == permissions;
+ last_path = current_path;
+ current_path = current_path.DirName();
+ }
+
+ return false;
}
bool has_dom_ui_bindings() const {
@@ -82,7 +97,7 @@ class ChildProcessSecurityPolicy::SecurityState {
private:
typedef std::map<std::string, bool> SchemeMap;
- typedef std::set<FilePath> FileSet;
+ typedef std::map<FilePath, int> FileMap; // bit-set of PlatformFileFlags
// Maps URL schemes to whether permission has been granted or revoked:
// |true| means the scheme has been granted.
@@ -92,7 +107,7 @@ class ChildProcessSecurityPolicy::SecurityState {
SchemeMap scheme_policy_;
// The set of files the renderer is permited to upload to the web.
- FileSet uploadable_files_;
+ FileMap file_permissions_;
int enabled_bindings_;
@@ -215,15 +230,20 @@ void ChildProcessSecurityPolicy::GrantRequestURL(
}
}
-void ChildProcessSecurityPolicy::GrantUploadFile(int renderer_id,
- const FilePath& file) {
+void ChildProcessSecurityPolicy::GrantReadFile(int renderer_id,
+ const FilePath& file) {
+ GrantPermissionsForFile(renderer_id, file, kReadFilePermissions);
+}
+
+void ChildProcessSecurityPolicy::GrantPermissionsForFile(
+ int renderer_id, const FilePath& file, int permissions) {
AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(renderer_id);
if (state == security_state_.end())
return;
- state->second->GrantUploadFile(file);
+ state->second->GrantPermissionsForFile(file, permissions);
}
void ChildProcessSecurityPolicy::GrantScheme(int renderer_id,
@@ -336,15 +356,20 @@ bool ChildProcessSecurityPolicy::CanRequestURL(
}
}
-bool ChildProcessSecurityPolicy::CanUploadFile(int renderer_id,
- const FilePath& file) {
+bool ChildProcessSecurityPolicy::CanReadFile(int renderer_id,
+ const FilePath& file) {
+ return HasPermissionsForFile(renderer_id, file, kReadFilePermissions);
+}
+
+bool ChildProcessSecurityPolicy::HasPermissionsForFile(
+ int renderer_id, const FilePath& file, int permissions) {
AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(renderer_id);
if (state == security_state_.end())
return false;
- return state->second->CanUploadFile(file);
+ return state->second->HasPermissionsForFile(file, permissions);
}
bool ChildProcessSecurityPolicy::HasDOMUIBindings(int renderer_id) {
diff --git a/chrome/browser/child_process_security_policy.h b/chrome/browser/child_process_security_policy.h
index 6440fee..6ae4f30 100644
--- a/chrome/browser/child_process_security_policy.h
+++ b/chrome/browser/child_process_security_policy.h
@@ -69,7 +69,13 @@ class ChildProcessSecurityPolicy {
// Whenever the user picks a file from a <input type="file"> element, the
// browser should call this function to grant the renderer the capability to
// upload the file to the web.
- void GrantUploadFile(int renderer_id, const FilePath& file);
+ void GrantReadFile(int renderer_id, const FilePath& file);
+
+ // Grants certain permissions to a file. |permissions| must be a bit-set of
+ // base::PlatformFileFlags.
+ void GrantPermissionsForFile(int renderer_id,
+ const FilePath& file,
+ int permissions);
// Grants the renderer process the capability to access URLs of the provided
// scheme.
@@ -100,7 +106,13 @@ class ChildProcessSecurityPolicy {
// Before servicing a renderer's request to upload a file to the web, the
// browser should call this method to determine whether the renderer has the
// capability to upload the requested file.
- bool CanUploadFile(int renderer_id, const FilePath& file);
+ bool CanReadFile(int renderer_id, const FilePath& file);
+
+ // Determins if certain permissions were granted for a file. |permissions|
+ // must be a bit-set of base::PlatformFileFlags.
+ bool HasPermissionsForFile(int renderer_id,
+ const FilePath& file,
+ int permissions);
// Returns true if the specified renderer_id has been granted DOMUIBindings.
// The browser should check this property before assuming the renderer is
diff --git a/chrome/browser/child_process_security_policy_unittest.cc b/chrome/browser/child_process_security_policy_unittest.cc
index 46279c7..949265d 100644
--- a/chrome/browser/child_process_security_policy_unittest.cc
+++ b/chrome/browser/child_process_security_policy_unittest.cc
@@ -6,6 +6,7 @@
#include "base/basictypes.h"
#include "base/file_path.h"
+#include "base/platform_file.h"
#include "chrome/browser/child_process_security_policy.h"
#include "chrome/common/url_constants.h"
#include "net/url_request/url_request.h"
@@ -185,30 +186,98 @@ TEST_F(ChildProcessSecurityPolicyTest, ViewSource) {
p->Remove(kRendererID);
}
-TEST_F(ChildProcessSecurityPolicyTest, CanUploadFiles) {
+TEST_F(ChildProcessSecurityPolicyTest, CanReadFiles) {
ChildProcessSecurityPolicy* p = ChildProcessSecurityPolicy::GetInstance();
p->Add(kRendererID);
- EXPECT_FALSE(p->CanUploadFile(kRendererID,
+ EXPECT_FALSE(p->CanReadFile(kRendererID,
FilePath(FILE_PATH_LITERAL("/etc/passwd"))));
- p->GrantUploadFile(kRendererID, FilePath(FILE_PATH_LITERAL("/etc/passwd")));
- EXPECT_TRUE(p->CanUploadFile(kRendererID,
+ p->GrantReadFile(kRendererID, FilePath(FILE_PATH_LITERAL("/etc/passwd")));
+ EXPECT_TRUE(p->CanReadFile(kRendererID,
FilePath(FILE_PATH_LITERAL("/etc/passwd"))));
- EXPECT_FALSE(p->CanUploadFile(kRendererID,
+ EXPECT_FALSE(p->CanReadFile(kRendererID,
FilePath(FILE_PATH_LITERAL("/etc/shadow"))));
p->Remove(kRendererID);
p->Add(kRendererID);
- EXPECT_FALSE(p->CanUploadFile(kRendererID,
+ EXPECT_FALSE(p->CanReadFile(kRendererID,
FilePath(FILE_PATH_LITERAL("/etc/passwd"))));
- EXPECT_FALSE(p->CanUploadFile(kRendererID,
+ EXPECT_FALSE(p->CanReadFile(kRendererID,
FilePath(FILE_PATH_LITERAL("/etc/shadow"))));
p->Remove(kRendererID);
}
+TEST_F(ChildProcessSecurityPolicyTest, FilePermissions) {
+ ChildProcessSecurityPolicy* p = ChildProcessSecurityPolicy::GetInstance();
+
+ // Grant permissions for a file.
+ p->Add(kRendererID);
+ FilePath file = FilePath(FILE_PATH_LITERAL("/etc/passwd"));
+ EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN));
+
+ p->GrantPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE |
+ base::PLATFORM_FILE_TRUNCATE);
+ EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE |
+ base::PLATFORM_FILE_TRUNCATE));
+ EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_READ));
+ EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_CREATE));
+ EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_CREATE |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE |
+ base::PLATFORM_FILE_TRUNCATE));
+ p->Remove(kRendererID);
+
+ // Grant permissions for the directory the file is in.
+ p->Add(kRendererID);
+ EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN));
+ p->GrantPermissionsForFile(kRendererID, FilePath(FILE_PATH_LITERAL("/etc")),
+ base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_READ);
+ EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN));
+ EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE));
+ p->Remove(kRendererID);
+
+ // Grant permissions for the directory the file is in (with trailing '/').
+ p->Add(kRendererID);
+ EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN));
+ p->GrantPermissionsForFile(kRendererID, FilePath(FILE_PATH_LITERAL("/etc/")),
+ base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_READ);
+ EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN));
+ EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE));
+
+ // Grant permissions for the file (should overwrite the permissions granted
+ // for the directory).
+ p->GrantPermissionsForFile(kRendererID, file, base::PLATFORM_FILE_TEMPORARY);
+ EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_OPEN));
+ EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, file,
+ base::PLATFORM_FILE_TEMPORARY));
+ p->Remove(kRendererID);
+}
+
TEST_F(ChildProcessSecurityPolicyTest, CanServiceInspectElement) {
ChildProcessSecurityPolicy* p = ChildProcessSecurityPolicy::GetInstance();
@@ -248,11 +317,11 @@ TEST_F(ChildProcessSecurityPolicyTest, RemoveRace) {
p->Add(kRendererID);
p->GrantRequestURL(kRendererID, url);
- p->GrantUploadFile(kRendererID, file);
+ p->GrantReadFile(kRendererID, file);
p->GrantDOMUIBindings(kRendererID);
EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
- EXPECT_TRUE(p->CanUploadFile(kRendererID, file));
+ EXPECT_TRUE(p->CanReadFile(kRendererID, file));
EXPECT_TRUE(p->HasDOMUIBindings(kRendererID));
p->Remove(kRendererID);
@@ -263,6 +332,6 @@ TEST_F(ChildProcessSecurityPolicyTest, RemoveRace) {
// In this case, we default to secure behavior.
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
- EXPECT_FALSE(p->CanUploadFile(kRendererID, file));
+ EXPECT_FALSE(p->CanReadFile(kRendererID, file));
EXPECT_FALSE(p->HasDOMUIBindings(kRendererID));
}
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc
index 2032a84..093b975 100644
--- a/chrome/browser/plugin_process_host.cc
+++ b/chrome/browser/plugin_process_host.cc
@@ -379,7 +379,7 @@ void PluginProcessHost::OnAccessFiles(int renderer_id,
for (size_t i = 0; i < files.size(); ++i) {
const FilePath path = FilePath::FromWStringHack(UTF8ToWide(files[i]));
- if (!policy->CanUploadFile(renderer_id, path)) {
+ if (!policy->CanReadFile(renderer_id, path)) {
LOG(INFO) << "Denied unauthorized request for file " << files[i];
*allowed = false;
return;
diff --git a/chrome/browser/renderer_host/blob_dispatcher_host.cc b/chrome/browser/renderer_host/blob_dispatcher_host.cc
index 28a3435..8fdafe5 100644
--- a/chrome/browser/renderer_host/blob_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/blob_dispatcher_host.cc
@@ -58,7 +58,7 @@ bool BlobDispatcherHost::CheckPermission(
blob_data->items().begin();
iter != blob_data->items().end(); ++iter) {
if (iter->type() == webkit_blob::BlobData::TYPE_FILE) {
- if (!policy->CanUploadFile(process_id_, iter->file_path()))
+ if (!policy->CanReadFile(process_id_, iter->file_path()))
return false;
}
}
diff --git a/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc b/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc
index b1470b1..a2509fb 100644
--- a/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc
+++ b/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc
@@ -163,7 +163,7 @@ void RedirectToFileResourceHandler::DidCreateTemporaryFile(
file_stream_.reset(new net::FileStream(file_handle.ReleaseValue(),
base::PLATFORM_FILE_WRITE |
base::PLATFORM_FILE_ASYNC));
- ChildProcessSecurityPolicy::GetInstance()->GrantUploadFile(
+ ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
process_id_, file_path);
host_->StartDeferredRequest(process_id_, request_id_);
}
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 1d1117b..9ca53bd 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -463,7 +463,7 @@ void RenderViewHost::DragTargetDragEnter(
FilePath path = FilePath::FromWStringHack(UTF16ToWideHack(*iter));
policy->GrantRequestURL(process()->id(),
net::FilePathToFileURL(path));
- policy->GrantUploadFile(process()->id(), path);
+ policy->GrantReadFile(process()->id(), path);
}
Send(new ViewMsg_DragTargetDragEnter(routing_id(), drop_data, client_pt,
screen_pt, operations_allowed));
@@ -675,7 +675,7 @@ void RenderViewHost::FilesSelectedInChooser(
// Grant the security access requested to the given files.
for (std::vector<FilePath>::const_iterator file = files.begin();
file != files.end(); ++file) {
- ChildProcessSecurityPolicy::GetInstance()->GrantUploadFile(
+ ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
process()->id(), *file);
}
Send(new ViewMsg_RunFileChooserResponse(routing_id(), files));
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc
index 899f077..8085d93 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc
@@ -153,7 +153,7 @@ bool ShouldServiceRequest(ChildProcessInfo::ProcessType process_type,
std::vector<net::UploadData::Element>::const_iterator iter;
for (iter = uploads->begin(); iter != uploads->end(); ++iter) {
if (iter->type() == net::UploadData::TYPE_FILE &&
- !policy->CanUploadFile(child_id, iter->file_path())) {
+ !policy->CanReadFile(child_id, iter->file_path())) {
NOTREACHED() << "Denied unauthorized upload of "
<< iter->file_path().value();
return false;
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 8641c6c..21264f2 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -1449,7 +1449,7 @@ void ResourceMessageFilter::OnGetFileSize(const FilePath& path,
IPC::Message* reply_msg) {
// Get file size only when the child process has been granted permission to
// upload the file.
- if (!ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) {
+ if (!ChildProcessSecurityPolicy::GetInstance()->CanReadFile(id(), path)) {
ViewHostMsg_GetFileSize::WriteReplyParams(
reply_msg, static_cast<int64>(-1));
Send(reply_msg);
@@ -1469,7 +1469,7 @@ void ResourceMessageFilter::OnGetFileModificationTime(const FilePath& path,
IPC::Message* reply_msg) {
// Get file modification time only when the child process has been granted
// permission to upload the file.
- if (!ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) {
+ if (!ChildProcessSecurityPolicy::GetInstance()->CanReadFile(id(), path)) {
ViewHostMsg_GetFileModificationTime::WriteReplyParams(reply_msg,
base::Time());
Send(reply_msg);
@@ -1508,7 +1508,7 @@ void ResourceMessageFilter::OnOpenFile(const FilePath& path,
// Open the file only when the child process has been granted permission to
// upload the file.
// TODO(jianli): Do we need separate permission to control opening the file?
- if (!ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) {
+ if (!ChildProcessSecurityPolicy::GetInstance()->CanReadFile(id(), path)) {
ViewHostMsg_OpenFile::WriteReplyParams(
reply_msg,
#if defined(OS_WIN)
@@ -1702,7 +1702,7 @@ void ResourceMessageFilter::OnAsyncOpenFile(const IPC::Message& msg,
int message_id) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- if (!ChildProcessSecurityPolicy::GetInstance()->CanUploadFile(id(), path)) {
+ if (!ChildProcessSecurityPolicy::GetInstance()->CanReadFile(id(), path)) {
IPC::Message* reply = new ViewMsg_AsyncOpenFile_ACK(
msg.routing_id(), base::PLATFORM_FILE_ERROR_ACCESS_DENIED,
IPC::InvalidPlatformFileForTransit(), message_id);