Commit message: None
CVE: CVE-2012-5138
Vulnerability description: Google Chrome before 23.0.1271.95 does not properly handle file paths, which has unspecified impact and attack vectors.

Project: Chrome

void ChildProcessSecurityPolicyImpl::AddChild(int child_id) {
  if (security_state_.count(child_id) != 0) {
    NOTREACHED() << "Add child process at most once.";
    return;
  }

  security_state_[child_id] = new SecurityState();
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::CanAccessCookiesForOrigin(
    int child_id, const GURL& gurl) {
  base::AutoLock lock(lock_);
  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return false;
  return state->second->CanAccessCookiesForOrigin(gurl);
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::CanReadDirectory(
    int child_id, const FilePath& directory) {
  return HasPermissionsForFile(child_id,
                               directory,
                               kEnumerateDirectoryPermissions);
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::CanReadFile(int child_id,
                                                 const FilePath& file) {
  return HasPermissionsForFile(child_id, file, kReadFilePermissions);
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::CanReadFileSystem(
    int child_id, const std::string& filesystem_id) {
  return HasPermissionsForFileSystem(child_id,
                                     filesystem_id,
                                     kReadFilePermissions);
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::CanReadRawCookies(int child_id) {
  base::AutoLock lock(lock_);

  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return false;

  return state->second->can_read_raw_cookies();
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::CanReadWriteFileSystem(
    int child_id, const std::string& filesystem_id) {
  return HasPermissionsForFileSystem(child_id,
                                     filesystem_id,
                                     kReadFilePermissions |
                                     kWriteFilePermissions);
}

Project: Chrome

  bool CanRequestURL(const GURL& url) {
    SchemeMap::const_iterator judgment(scheme_policy_.find(url.scheme()));
    if (judgment != scheme_policy_.end())
      return judgment->second;

    if (url.SchemeIs(chrome::kFileScheme)) {
      FilePath path;
      if (net::FileURLToFilePath(url, &path))
        return request_file_set_.find(path) != request_file_set_.end();
    }

    return false;  // Unmentioned schemes are disallowed.
  }

Project: Chrome

  bool CanSendCookiesForOrigin(const GURL& gurl) {
    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    if (!command_line.HasSwitch(switches::kEnableStrictSiteIsolation))
      return true;

    if (origin_lock_.is_empty())
      return true;
    GURL site_gurl = SiteInstanceImpl::GetSiteForURL(NULL, gurl);
    return origin_lock_ == site_gurl;
  }

Project: Chrome

ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
  RegisterWebSafeScheme(chrome::kHttpScheme);
  RegisterWebSafeScheme(chrome::kHttpsScheme);
  RegisterWebSafeScheme(chrome::kFtpScheme);
  RegisterWebSafeScheme(chrome::kDataScheme);
  RegisterWebSafeScheme("feed");
  RegisterWebSafeScheme(chrome::kBlobScheme);
  RegisterWebSafeScheme(chrome::kFileSystemScheme);

  RegisterPseudoScheme(chrome::kAboutScheme);
  RegisterPseudoScheme(chrome::kJavaScriptScheme);
  RegisterPseudoScheme(chrome::kViewSourceScheme);
}

Project: Chrome

ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() {
  return ChildProcessSecurityPolicyImpl::GetInstance();
}

Project: Chrome

ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() {
  return Singleton<ChildProcessSecurityPolicyImpl>::get();
}

Project: Chrome

  void GrantPermissionsForFile(const FilePath& file, int permissions) {
    FilePath stripped = file.StripTrailingSeparators();
    file_permissions_[stripped] |= permissions;
    UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.FilePermissionPathLength",
                         stripped.value().size());
  }

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
    int child_id, const FilePath& file, int permissions) {
  base::AutoLock lock(lock_);

  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantPermissionsForFile(file, permissions);
}

Project: Chrome

  void GrantPermissionsForFileSystem(const std::string& filesystem_id,
                                     int permissions) {
    if (filesystem_permissions_.find(filesystem_id) ==
        filesystem_permissions_.end())
      fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id);
    filesystem_permissions_[filesystem_id] = permissions;
  }

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantPermissionsForFileSystem(
    int child_id,
    const std::string& filesystem_id,
    int permission) {
  base::AutoLock lock(lock_);

  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;
  state->second->GrantPermissionsForFileSystem(filesystem_id, permission);
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantReadDirectory(
    int child_id, const FilePath& directory) {
  GrantPermissionsForFile(child_id, directory, kEnumerateDirectoryPermissions);
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id,
                                                   const FilePath& file) {
  GrantPermissionsForFile(child_id, file, kReadFilePermissions);
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantReadRawCookies(int child_id) {
  base::AutoLock lock(lock_);

  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantReadRawCookies();
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantReadWriteFileSystem(
    int child_id, const std::string& filesystem_id) {
  GrantPermissionsForFileSystem(child_id, filesystem_id,
                                kReadFilePermissions |
                                kWriteFilePermissions);
}

Project: Chrome

  void GrantRequestOfSpecificFile(const FilePath &file) {
    request_file_set_.insert(file.StripTrailingSeparators());
  }

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL(
    int child_id,
    const GURL& url) {
  if (!url.SchemeIs(chrome::kFileScheme))
    return;

  {
    base::AutoLock lock(lock_);
    SecurityStateMap::iterator state = security_state_.find(child_id);
    if (state == security_state_.end())
      return;

    FilePath path;
    if (net::FileURLToFilePath(url, &path))
        state->second->GrantRequestOfSpecificFile(path);
  }
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantRequestURL(
    int child_id, const GURL& url) {

  if (!url.is_valid())
    return;  // Can't grant the capability to request invalid URLs.

  if (IsWebSafeScheme(url.scheme()))
    return;  // The scheme has already been whitelisted for every child process.

  if (IsPseudoScheme(url.scheme())) {
    if (url.SchemeIs(chrome::kViewSourceScheme)) {
      GrantRequestURL(child_id, GURL(url.path()));
    }

    return;  // Can't grant the capability to request pseudo schemes.
  }

  {
    base::AutoLock lock(lock_);
    SecurityStateMap::iterator state = security_state_.find(child_id);
    if (state == security_state_.end())
      return;

    state->second->GrantScheme(url.scheme());
  }
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantScheme(int child_id,
                                                 const std::string& scheme) {
  base::AutoLock lock(lock_);

  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantScheme(scheme);
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::GrantWebUIBindings(int child_id) {
  base::AutoLock lock(lock_);

  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return;

  state->second->GrantBindings(BINDINGS_POLICY_WEB_UI);

  state->second->GrantScheme(chrome::kChromeUIScheme);

  state->second->GrantScheme(chrome::kFileScheme);
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
    int child_id, const FilePath& file, int permissions) {
  base::AutoLock lock(lock_);
  bool result = ChildProcessHasPermissionsForFile(child_id, file, permissions);
  if (!result) {
    WorkerToMainProcessMap::iterator iter = worker_map_.find(child_id);
    if (iter != worker_map_.end() && iter->second != 0) {
      result = ChildProcessHasPermissionsForFile(iter->second,
                                                 file,
                                                 permissions);
    }
  }
  return result;
}

Project: Chrome

  bool HasPermissionsForFileSystem(const std::string& filesystem_id,
                                   int permissions) {
    if (filesystem_permissions_.find(filesystem_id) ==
        filesystem_permissions_.end())
      return false;
    return (filesystem_permissions_[filesystem_id] & permissions) ==
        permissions;
  }

Project: Chrome

bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
    int child_id,
    const std::string& filesystem_id,
    int permission) {
  base::AutoLock lock(lock_);

  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return false;
  return state->second->HasPermissionsForFileSystem(filesystem_id, permission);
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
  base::AutoLock lock(lock_);

  SecurityStateMap::iterator state = security_state_.find(child_id);
  if (state == security_state_.end())
    return false;

  return state->second->has_web_ui_bindings();
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::IsDisabledScheme(
    const std::string& scheme) {
  base::AutoLock lock(lock_);
  return disabled_schemes_.find(scheme) != disabled_schemes_.end();
}

Project: Chrome

bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
    const std::string& scheme) {
  base::AutoLock lock(lock_);

  return (web_safe_schemes_.find(scheme) != web_safe_schemes_.end());
}

Project: Chrome

  void LockToOrigin(const GURL& gurl) {
    origin_lock_ = gurl;
  }

Project: Chrome

void ChildProcessSecurityPolicyImpl::LockToOrigin(int child_id,
                                                  const GURL& gurl) {
  DCHECK(SiteInstanceImpl::GetSiteForURL(NULL, gurl) == gurl);
  base::AutoLock lock(lock_);
  SecurityStateMap::iterator state = security_state_.find(child_id);
  DCHECK(state != security_state_.end());
  state->second->LockToOrigin(gurl);
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::RegisterDisabledSchemes(
    const std::set<std::string>& schemes) {
  base::AutoLock lock(lock_);
  disabled_schemes_ = schemes;
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme(
    const std::string& scheme) {
  base::AutoLock lock(lock_);
  DCHECK(web_safe_schemes_.count(scheme) == 0) << "Add schemes at most once.";
  DCHECK(pseudo_schemes_.count(scheme) == 0) << "Web-safe implies not pseudo.";

  web_safe_schemes_.insert(scheme);
}

Project: Chrome

void ChildProcessSecurityPolicyImpl::Remove(int child_id) {
  base::AutoLock lock(lock_);
  if (!security_state_.count(child_id))
    return;  // May be called multiple times.

  delete security_state_[child_id];
  security_state_.erase(child_id);
  worker_map_.erase(child_id);
}

Project: Chrome

  void RevokeAllPermissionsForFile(const FilePath& file) {
    FilePath stripped = file.StripTrailingSeparators();
    file_permissions_.erase(stripped);
    request_file_set_.erase(stripped);
  }

Project: Chrome

  bool has_web_ui_bindings() const {
    return enabled_bindings_ & BINDINGS_POLICY_WEB_UI;
  }

Project: Chrome

ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() {
  web_safe_schemes_.clear();
  pseudo_schemes_.clear();
  STLDeleteContainerPairSecondPointers(security_state_.begin(),
                                       security_state_.end());
  security_state_.clear();
}

Project: Chrome

  ~SecurityState() {
    scheme_policy_.clear();
    fileapi::IsolatedContext* isolated_context =
        fileapi::IsolatedContext::GetInstance();
    for (FileSystemMap::iterator iter = filesystem_permissions_.begin();
         iter != filesystem_permissions_.end();
         ++iter) {
      isolated_context->RemoveReference(iter->first);
    }
    UMA_HISTOGRAM_COUNTS("ChildProcessSecurityPolicy.PerChildFilePermissions",
                         file_permissions_.size());
  }

Project: Chrome

  void AddScheme(const std::string& scheme) {
    schemes_.insert(scheme);
  }

Project: Chrome

  ChildProcessSecurityPolicyTest() : old_browser_client_(NULL) {
  }

Project: Chrome

  ChildProcessSecurityPolicyTestBrowserClient() {}

Project: Chrome

  virtual bool IsHandledURL(const GURL& url) {
    return schemes_.find(url.scheme()) != schemes_.end();
  }

Project: Chrome

  void RegisterTestScheme(const std::string& scheme) {
    test_browser_client_.AddScheme(scheme);
  }

Project: Chrome

  virtual void SetUp() {
    old_browser_client_ = GetContentClient()->browser();
    GetContentClient()->set_browser_for_testing(&test_browser_client_);

    test_browser_client_.AddScheme("chrome");
  }

Project: Chrome

  virtual void TearDown() {
    test_browser_client_.ClearSchemes();
    GetContentClient()->set_browser_for_testing(old_browser_client_);
  }